forked from OSchip/llvm-project
Add a Python script to locate each binary file under a root directory which matches some pathname pattern
and to invoke lldb-disasm.py on the binary file to disassemble its symbols. The number of symbols can be specified by, for example, '-n 10000', to specify 10,000 symbols to disassemble for each module. By default, only 1000 symbols from each module are disassembled. Example: utils/test/run-dis.py -r '/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3/Symbols' -p '^/System/Library/.*Frameworks/.*\.framework/[^/]+$' tries to disassemble every public/private frameworks (by default only 1000 symbols are disassembled) under iOS4.3. llvm-svn: 138078
This commit is contained in:
parent
d07e104844
commit
758f288cdd
|
@ -62,18 +62,18 @@ def setupSysPath():
|
|||
|
||||
# This is to locate the lldb.py module. Insert it right after sys.path[0].
|
||||
sys.path[1:1] = [lldbPath]
|
||||
print "sys.path:", sys.path
|
||||
#print "sys.path:", sys.path
|
||||
|
||||
|
||||
def run_command(ci, cmd, res, echoInput=True, echoOutput=True):
|
||||
if echoInput:
|
||||
def run_command(ci, cmd, res, echo=True):
|
||||
if echo:
|
||||
print "run command:", cmd
|
||||
ci.HandleCommand(cmd, res)
|
||||
if res.Succeeded():
|
||||
if echoOutput:
|
||||
if echo:
|
||||
print "run_command output:", res.GetOutput()
|
||||
else:
|
||||
if echoOutput:
|
||||
if echo:
|
||||
print "run command failed!"
|
||||
print "run_command error:", res.GetError()
|
||||
|
||||
|
@ -104,10 +104,10 @@ def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
|
|||
|
||||
# See if there any extra command(s) to execute before we issue the file command.
|
||||
for cmd in lldb_commands:
|
||||
run_command(ci, cmd, res)
|
||||
run_command(ci, cmd, res, not quiet_disassembly)
|
||||
|
||||
# Now issue the file command.
|
||||
run_command(ci, 'file %s' % exe, res)
|
||||
run_command(ci, 'file %s' % exe, res, not quiet_disassembly)
|
||||
|
||||
# Create a target.
|
||||
#target = dbg.CreateTarget(exe)
|
||||
|
@ -123,7 +123,8 @@ def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
|
|||
# If we specify the symbols to disassemble, ignore symbol table dump.
|
||||
if symbols:
|
||||
for i in range(len(symbols)):
|
||||
print "symbol:", symbols[i]
|
||||
if verbose:
|
||||
print "symbol:", symbols[i]
|
||||
yield symbols[i]
|
||||
else:
|
||||
limited = True if num != -1 else False
|
||||
|
@ -133,7 +134,8 @@ def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
|
|||
pattern = re.compile(re_symbol_pattern)
|
||||
stream = lldb.SBStream()
|
||||
for m in target.module_iter():
|
||||
print "module:", m
|
||||
if verbose:
|
||||
print "module:", m
|
||||
for s in m:
|
||||
if limited and count >= num:
|
||||
return
|
||||
|
@ -144,7 +146,8 @@ def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
|
|||
continue
|
||||
|
||||
# If we come here, we're ready to disassemble the symbol.
|
||||
print "symbol:", s.GetName()
|
||||
if verbose:
|
||||
print "symbol:", s.GetName()
|
||||
if IsCodeType(s):
|
||||
if limited:
|
||||
count = count + 1
|
||||
|
@ -161,7 +164,7 @@ def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
|
|||
# Disassembly time.
|
||||
for symbol in symbol_iter(num_symbols, symbols_to_disassemble, re_symbol_pattern, target, not quiet_disassembly):
|
||||
cmd = "disassemble %s '%s'" % (disassemble_options, symbol)
|
||||
run_command(ci, cmd, res, True, not quiet_disassembly)
|
||||
run_command(ci, cmd, res, not quiet_disassembly)
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -220,13 +223,14 @@ Usage: %prog [options]
|
|||
re_symbol_pattern = opts.re_symbol_pattern
|
||||
|
||||
# We have parsed the options.
|
||||
print "lldb commands:", lldb_commands
|
||||
print "executable:", executable
|
||||
print "disassemble options:", disassemble_options
|
||||
print "quiet disassembly output:", quiet_disassembly
|
||||
print "num of symbols to disassemble:", num_symbols
|
||||
print "symbols to disassemble:", symbols_to_disassemble
|
||||
print "regular expression of symbols to disassemble:", re_symbol_pattern
|
||||
if not quiet_disassembly:
|
||||
print "lldb commands:", lldb_commands
|
||||
print "executable:", executable
|
||||
print "disassemble options:", disassemble_options
|
||||
print "quiet disassembly output:", quiet_disassembly
|
||||
print "num of symbols to disassemble:", num_symbols
|
||||
print "symbols to disassemble:", symbols_to_disassemble
|
||||
print "regular expression of symbols to disassemble:", re_symbol_pattern
|
||||
|
||||
setupSysPath()
|
||||
do_lldb_disassembly(lldb_commands, executable, disassemble_options,
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
#!/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 = './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 visit(suffix, dir, names):
|
||||
"""Look for matched file and invoke lldb disassembly on it."""
|
||||
global scriptPath
|
||||
global root_dir
|
||||
global path_pattern
|
||||
global path_regexp
|
||||
global num_symbols
|
||||
|
||||
old_dir = os.getcwd()
|
||||
for name in names:
|
||||
path = os.path.join(dir, name)
|
||||
if os.path.isdir(path):
|
||||
continue
|
||||
if name.endswith(".h"):
|
||||
continue
|
||||
|
||||
replaced_path = path.replace(root_dir, "", 1)
|
||||
if not path_regexp.search(replaced_path):
|
||||
continue
|
||||
if suffix and not name.endswith(suffix):
|
||||
continue
|
||||
if not isbinary(path):
|
||||
continue
|
||||
|
||||
os.chdir(scriptPath)
|
||||
command = template % (path, num_symbols if num_symbols > 0 else 1000)
|
||||
print "Running %s" % (command)
|
||||
os.system(command)
|
||||
|
||||
os.chdir(old_dir)
|
||||
|
||||
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
|
||||
|
||||
os.path.walk(root_dir, visit, suffix)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue