summaryrefslogtreecommitdiffstats
path: root/lldb/utils/test/lldb-disasm.py
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/utils/test/lldb-disasm.py')
-rwxr-xr-xlldb/utils/test/lldb-disasm.py294
1 files changed, 294 insertions, 0 deletions
diff --git a/lldb/utils/test/lldb-disasm.py b/lldb/utils/test/lldb-disasm.py
new file mode 100755
index 00000000000..339e8e7caba
--- /dev/null
+++ b/lldb/utils/test/lldb-disasm.py
@@ -0,0 +1,294 @@
+#!/usr/bin/env python
+
+"""
+Run lldb to disassemble all the available functions for an executable image.
+
+"""
+
+from __future__ import print_function
+
+import os
+import re
+import sys
+from optparse import OptionParser
+
+
+def setupSysPath():
+ """
+ Add LLDB.framework/Resources/Python and the test dir to the sys.path.
+ """
+ # Get the directory containing the current script.
+ scriptPath = sys.path[0]
+ if not scriptPath.endswith(os.path.join('utils', 'test')):
+ print("This script expects to reside in lldb's utils/test directory.")
+ sys.exit(-1)
+
+ # This is our base name component.
+ base = os.path.abspath(os.path.join(scriptPath, os.pardir, os.pardir))
+
+ # This is for the goodies in the test directory under base.
+ sys.path.append(os.path.join(base, 'test'))
+
+ # These are for xcode build directories.
+ xcode3_build_dir = ['build']
+ xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
+ dbg = ['Debug']
+ rel = ['Release']
+ bai = ['BuildAndIntegration']
+ python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
+
+ dbgPath = os.path.join(
+ base, *(xcode3_build_dir + dbg + python_resource_dir))
+ dbgPath2 = os.path.join(
+ base, *(xcode4_build_dir + dbg + python_resource_dir))
+ relPath = os.path.join(
+ base, *(xcode3_build_dir + rel + python_resource_dir))
+ relPath2 = os.path.join(
+ base, *(xcode4_build_dir + rel + python_resource_dir))
+ baiPath = os.path.join(
+ base, *(xcode3_build_dir + bai + python_resource_dir))
+ baiPath2 = os.path.join(
+ base, *(xcode4_build_dir + bai + python_resource_dir))
+
+ lldbPath = None
+ if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
+ lldbPath = dbgPath
+ elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
+ lldbPath = dbgPath2
+ elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
+ lldbPath = relPath
+ elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
+ lldbPath = relPath2
+ elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
+ lldbPath = baiPath
+ elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
+ lldbPath = baiPath2
+
+ if not lldbPath:
+ print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ')
+ print(relPath + ', or ' + baiPath)
+ sys.exit(-1)
+
+ # 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
+
+
+def run_command(ci, cmd, res, echo=True):
+ if echo:
+ print("run command:", cmd)
+ ci.HandleCommand(cmd, res)
+ if res.Succeeded():
+ if echo:
+ print("run_command output:", res.GetOutput())
+ else:
+ if echo:
+ print("run command failed!")
+ print("run_command error:", res.GetError())
+
+
+def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
+ symbols_to_disassemble,
+ re_symbol_pattern,
+ quiet_disassembly):
+ import lldb
+ import atexit
+ import re
+
+ # Create the debugger instance now.
+ dbg = lldb.SBDebugger.Create()
+ if not dbg:
+ raise Exception('Invalid debugger instance')
+
+ # Register an exit callback.
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+
+ # We want our debugger to be synchronous.
+ dbg.SetAsync(False)
+
+ # Get the command interpreter from the debugger.
+ ci = dbg.GetCommandInterpreter()
+ if not ci:
+ raise Exception('Could not get the command interpreter')
+
+ # And the associated result object.
+ res = lldb.SBCommandReturnObject()
+
+ # 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, not quiet_disassembly)
+
+ # Now issue the file command.
+ run_command(ci, 'file %s' % exe, res, not quiet_disassembly)
+
+ # Create a target.
+ #target = dbg.CreateTarget(exe)
+ target = dbg.GetSelectedTarget()
+ stream = lldb.SBStream()
+
+ def IsCodeType(symbol):
+ """Check whether an SBSymbol represents code."""
+ return symbol.GetType() == lldb.eSymbolTypeCode
+
+ # Define a generator for the symbols to disassemble.
+ def symbol_iter(num, symbols, re_symbol_pattern, target, verbose):
+ # If we specify the symbols to disassemble, ignore symbol table dump.
+ if symbols:
+ for i in range(len(symbols)):
+ if verbose:
+ print("symbol:", symbols[i])
+ yield symbols[i]
+ else:
+ limited = True if num != -1 else False
+ if limited:
+ count = 0
+ if re_symbol_pattern:
+ pattern = re.compile(re_symbol_pattern)
+ stream = lldb.SBStream()
+ for m in target.module_iter():
+ if verbose:
+ print("module:", m)
+ for s in m:
+ if limited and count >= num:
+ return
+ # If a regexp symbol pattern is supplied, consult it.
+ if re_symbol_pattern:
+ # If the pattern does not match, look for the next
+ # symbol.
+ if not pattern.match(s.GetName()):
+ continue
+
+ # If we come here, we're ready to disassemble the symbol.
+ if verbose:
+ print("symbol:", s.GetName())
+ if IsCodeType(s):
+ if limited:
+ count = count + 1
+ if verbose:
+ print("returning symbol:", s.GetName())
+ yield s.GetName()
+ if verbose:
+ print("start address:", s.GetStartAddress())
+ print("end address:", s.GetEndAddress())
+ s.GetDescription(stream)
+ print("symbol description:", stream.GetData())
+ stream.Clear()
+
+ # 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, not quiet_disassembly)
+
+
+def main():
+ # This is to set up the Python path to include the pexpect-2.4 dir.
+ # Remember to update this when/if things change.
+ scriptPath = sys.path[0]
+ sys.path.append(
+ os.path.join(
+ scriptPath,
+ os.pardir,
+ os.pardir,
+ 'test',
+ 'pexpect-2.4'))
+
+ parser = OptionParser(usage="""\
+Run lldb to disassemble all the available functions for an executable image.
+
+Usage: %prog [options]
+""")
+ parser.add_option(
+ '-C',
+ '--lldb-command',
+ type='string',
+ action='append',
+ metavar='COMMAND',
+ default=[],
+ dest='lldb_commands',
+ help='Command(s) lldb executes after starting up (can be empty)')
+ parser.add_option(
+ '-e',
+ '--executable',
+ type='string',
+ action='store',
+ dest='executable',
+ help="""Mandatory: the executable to do disassembly on.""")
+ parser.add_option(
+ '-o',
+ '--options',
+ type='string',
+ action='store',
+ dest='disassemble_options',
+ help="""Mandatory: the options passed to lldb's 'disassemble' command.""")
+ parser.add_option(
+ '-q',
+ '--quiet-disassembly',
+ action='store_true',
+ default=False,
+ dest='quiet_disassembly',
+ help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
+ parser.add_option(
+ '-n',
+ '--num-symbols',
+ type='int',
+ action='store',
+ default=-1,
+ dest='num_symbols',
+ help="""The number of symbols to disassemble, if specified.""")
+ parser.add_option(
+ '-p',
+ '--symbol_pattern',
+ type='string',
+ action='store',
+ dest='re_symbol_pattern',
+ help="""The regular expression of symbols to invoke lldb's 'disassemble' command.""")
+ parser.add_option(
+ '-s',
+ '--symbol',
+ type='string',
+ action='append',
+ metavar='SYMBOL',
+ default=[],
+ dest='symbols_to_disassemble',
+ help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
+
+ opts, args = parser.parse_args()
+
+ lldb_commands = opts.lldb_commands
+
+ if not opts.executable or not opts.disassemble_options:
+ parser.print_help()
+ sys.exit(1)
+
+ executable = opts.executable
+ disassemble_options = opts.disassemble_options
+ quiet_disassembly = opts.quiet_disassembly
+ num_symbols = opts.num_symbols
+ symbols_to_disassemble = opts.symbols_to_disassemble
+ re_symbol_pattern = opts.re_symbol_pattern
+
+ # We have parsed the options.
+ 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,
+ num_symbols,
+ symbols_to_disassemble,
+ re_symbol_pattern,
+ quiet_disassembly)
+
+if __name__ == '__main__':
+ main()
OpenPOWER on IntegriCloud