1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#!/usr/bin/env python
"""
Run lldb disassembler on all the binaries specified by a combination of root dir
and path pattern.
"""
import os, sys, subprocess
import re
from optparse import OptionParser
# The directory of this Python script as well as the lldb-disasm.py workhorse.
scriptPath = None
# The root directory for the SDK symbols.
root_dir = None
# The regular expression pattern to match the desired pathname to the binaries.
path_pattern = None
# And the re-compiled regular expression object.
path_regexp = None
# If specified, number of symbols to disassemble for each qualified binary.
num_symbols = -1
# Command template of the invocation of lldb disassembler.
template = '%s/lldb-disasm.py -C "platform select remote-ios" -o "-n" -q -e %s -n %s'
# Regular expression for detecting file output for Mach-o binary.
mach_o = re.compile('\sMach-O.+binary')
def isbinary(path):
file_output = subprocess.Popen(["file", path],
stdout=subprocess.PIPE).stdout.read()
return (mach_o.search(file_output) is not None)
def walk_and_invoke(sdk_root, path_regexp, suffix, num_symbols):
"""Look for matched file and invoke lldb disassembly on it."""
global scriptPath
for root, dirs, files in os.walk(sdk_root, topdown=False):
for name in files:
path = os.path.join(root, name)
# We're not interested in .h file.
if name.endswith(".h"):
continue
# Neither a symbolically linked file.
if os.path.islink(path):
continue
# We'll be pattern matching based on the path relative to the SDK root.
replaced_path = path.replace(root_dir, "", 1)
# Check regular expression match for the replaced path.
if not path_regexp.search(replaced_path):
continue
# If a suffix is specified, check it, too.
if suffix and not name.endswith(suffix):
continue
if not isbinary(path):
continue
command = template % (scriptPath, path, num_symbols if num_symbols > 0 else 1000)
print "Running %s" % (command)
os.system(command)
def main():
"""Read the root dir and the path spec, invoke lldb-disasm.py on the file."""
global scriptPath
global root_dir
global path_pattern
global path_regexp
global num_symbols
scriptPath = sys.path[0]
parser = OptionParser(usage="""\
Run lldb disassembler on all the binaries specified by a combination of root dir
and path pattern.
""")
parser.add_option('-r', '--root-dir',
type='string', action='store',
dest='root_dir',
help='Mandatory: the root directory for the SDK symbols.')
parser.add_option('-p', '--path-pattern',
type='string', action='store',
dest='path_pattern',
help='Mandatory: regular expression pattern for the desired binaries.')
parser.add_option('-s', '--suffix',
type='string', action='store', default=None,
dest='suffix',
help='Specify the suffix of the binaries to look for.')
parser.add_option('-n', '--num-symbols',
type='int', action='store', default=-1,
dest='num_symbols',
help="""The number of symbols to disassemble, if specified.""")
opts, args = parser.parse_args()
if not opts.root_dir or not opts.path_pattern:
parser.print_help()
sys.exit(1)
# Sanity check the root directory.
root_dir = opts.root_dir
root_dir = os.path.abspath(root_dir)
if not os.path.isdir(root_dir):
parser.print_help()
sys.exit(1)
path_pattern = opts.path_pattern
path_regexp = re.compile(path_pattern)
suffix = opts.suffix
num_symbols = opts.num_symbols
print "Root directory for SDK symbols:", root_dir
print "Regular expression for the binaries:", path_pattern
print "Suffix of the binaries to look for:", suffix
print "num of symbols to disassemble:", num_symbols
walk_and_invoke(root_dir, path_regexp, suffix, num_symbols)
if __name__ == '__main__':
main()
|