Home | History | Annotate | Download | only in test
      1 #!/usr/bin/env python
      2 
      3 """
      4 Run lldb disassembler on all the binaries specified by a combination of root dir
      5 and path pattern.
      6 """
      7 
      8 import os, sys, subprocess
      9 import re
     10 from optparse import OptionParser
     11 
     12 # The directory of this Python script as well as the lldb-disasm.py workhorse.
     13 scriptPath = None
     14 
     15 # The root directory for the SDK symbols.
     16 root_dir = None
     17 
     18 # The regular expression pattern to match the desired pathname to the binaries.
     19 path_pattern = None
     20 
     21 # And the re-compiled regular expression object.
     22 path_regexp = None
     23 
     24 # If specified, number of symbols to disassemble for each qualified binary.
     25 num_symbols = -1
     26 
     27 # Command template of the invocation of lldb disassembler.
     28 template = '%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.
     31 mach_o = re.compile('\sMach-O.+binary')
     32 def 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 
     37 def 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 
     67 def 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="""\
     78 Run lldb disassembler on all the binaries specified by a combination of root dir
     79 and 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 
    124 if __name__ == '__main__':
    125     main()
    126