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