@@ -0,0 +1,1456 @@
+#!/usr/bin/env python%0A%0A%22%22%22A tool for looking for indirect jumps and calls in x86 binaries.%0A%0A   Helpful to verify whether or not retpoline mitigations are catching%0A   all of the indirect branches in a binary and telling you which%0A   functions the remaining ones are in (assembly, etc).%0A%0A   Depends on llvm-objdump being in your path and is tied to the%0A   dump format.%0A%22%22%22%0A%0Aimport os%0Aimport sys%0Aimport re%0Aimport subprocess%0Aimport optparse%0A%0A# Look for indirect calls/jmps in a binary. re: (call%7Cjmp).*%5C* %0Adef look_for_indirect(file):%0A    args = %5B'llvm-objdump'%5D%0A    args.extend(%5B%22-d%22%5D)%0A    args.extend(%5Bfile%5D)%0A%0A    p = subprocess.Popen(args=args, stdin=None, stderr=subprocess.PIPE, stdout=subprocess.PIPE)%0A    (stdout,stderr) = p.communicate()%0A%0A    function = %22%22%0A    for line in stdout.splitlines():%0A        if line.startswith(' ') == False:%0A            function = line%0A        result = re.search('(call%7Cjmp).*%5C*', line)%0A        if result != None:%0A            # TODO: Perhaps use cxxfilt to demangle functions?%0A            print function%0A            print line%0A    return%0A%0A# Compare the debug info between two files.%0Adef main(args):%0A    # No options currently other than the binary.%0A    parser = optparse.OptionParser(%22%25prog %5Boptions%5D %3Cbinary%3E%22)%0A    (opts, args) = parser.parse_args(args)%0A    if len(args) != 2:%0A        parser.error(%22invalid number of arguments: %25s%22 %25 len(args))%0A    look_for_indirect(args%5B1%5D)%0A%0Aif __name__ == '__main__':%0A    main(sys.argv)%0A

Add a wrapper around llvm-objdump to look for indirect calls/jmps in x86 assembly.