blob: fb75bb62c6c6c5c10444ff7b3cb1be609edec943 [file] [log] [blame]
Johnny Chen5e28aa52011-03-28 22:40:32 +00001#!/usr/bin/env python
2
3"""
4Run lldb to disassemble all the available functions for an executable image.
5
6"""
7
8import os
Johnny Chen293683b2011-08-18 22:46:50 +00009import re
Johnny Chen5e28aa52011-03-28 22:40:32 +000010import sys
11from optparse import OptionParser
12
13def setupSysPath():
14 """
Johnny Chen4044fdc2011-03-28 22:48:25 +000015 Add LLDB.framework/Resources/Python and the test dir to the sys.path.
Johnny Chen5e28aa52011-03-28 22:40:32 +000016 """
17 # Get the directory containing the current script.
18 scriptPath = sys.path[0]
19 if not scriptPath.endswith(os.path.join('utils', 'test')):
20 print "This script expects to reside in lldb's utils/test directory."
21 sys.exit(-1)
22
23 # This is our base name component.
24 base = os.path.abspath(os.path.join(scriptPath, os.pardir, os.pardir))
25
26 # This is for the goodies in the test directory under base.
27 sys.path.append(os.path.join(base,'test'))
28
29 # These are for xcode build directories.
30 xcode3_build_dir = ['build']
31 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
32 dbg = ['Debug']
33 rel = ['Release']
34 bai = ['BuildAndIntegration']
35 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
36
37 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
38 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
39 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
40 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
41 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
42 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
43
44 lldbPath = None
45 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
46 lldbPath = dbgPath
47 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
48 lldbPath = dbgPath2
49 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
50 lldbPath = relPath
51 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
52 lldbPath = relPath2
53 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
54 lldbPath = baiPath
55 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
56 lldbPath = baiPath2
57
58 if not lldbPath:
59 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
60 print relPath + ', or ' + baiPath
61 sys.exit(-1)
62
63 # This is to locate the lldb.py module. Insert it right after sys.path[0].
64 sys.path[1:1] = [lldbPath]
65 print "sys.path:", sys.path
66
67
Johnny Chen6454e152011-03-29 01:07:00 +000068def run_command(ci, cmd, res, echoInput=True, echoOutput=True):
69 if echoInput:
70 print "run command:", cmd
Johnny Chen5e28aa52011-03-28 22:40:32 +000071 ci.HandleCommand(cmd, res)
72 if res.Succeeded():
Johnny Chen6454e152011-03-29 01:07:00 +000073 if echoOutput:
74 print "run_command output:", res.GetOutput()
Johnny Chen5e28aa52011-03-28 22:40:32 +000075 else:
Johnny Chen6454e152011-03-29 01:07:00 +000076 if echoOutput:
77 print "run command failed!"
78 print "run_command error:", res.GetError()
Johnny Chen5e28aa52011-03-28 22:40:32 +000079
Johnny Chen293683b2011-08-18 22:46:50 +000080def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
81 symbols_to_disassemble,
82 re_symbol_pattern,
83 quiet_disassembly):
Johnny Chen0e43f322011-03-31 01:06:28 +000084 import lldb, atexit, re
Johnny Chen5e28aa52011-03-28 22:40:32 +000085
86 # Create the debugger instance now.
87 dbg = lldb.SBDebugger.Create()
Johnny Chen26fc16b2011-05-25 20:47:27 +000088 if not dbg:
Johnny Chen5e28aa52011-03-28 22:40:32 +000089 raise Exception('Invalid debugger instance')
90
91 # Register an exit callback.
92 atexit.register(lambda: lldb.SBDebugger.Terminate())
93
94 # We want our debugger to be synchronous.
95 dbg.SetAsync(False)
96
97 # Get the command interpreter from the debugger.
98 ci = dbg.GetCommandInterpreter()
99 if not ci:
100 raise Exception('Could not get the command interpreter')
101
102 # And the associated result object.
103 res = lldb.SBCommandReturnObject()
104
105 # See if there any extra command(s) to execute before we issue the file command.
106 for cmd in lldb_commands:
107 run_command(ci, cmd, res)
108
Johnny Chend16c1052011-03-31 01:34:55 +0000109 # Now issue the file command.
110 run_command(ci, 'file %s' % exe, res)
111
Johnny Chen0e43f322011-03-31 01:06:28 +0000112 # Create a target.
Johnny Chend16c1052011-03-31 01:34:55 +0000113 #target = dbg.CreateTarget(exe)
114 target = dbg.GetSelectedTarget()
Johnny Chen0e43f322011-03-31 01:06:28 +0000115 stream = lldb.SBStream()
116
Johnny Chend16c1052011-03-31 01:34:55 +0000117 def IsCodeType(symbol):
118 """Check whether an SBSymbol represents code."""
119 return symbol.GetType() == lldb.eSymbolTypeCode
120
Johnny Chen0e43f322011-03-31 01:06:28 +0000121 # Define a generator for the symbols to disassemble.
Johnny Chen293683b2011-08-18 22:46:50 +0000122 def symbol_iter(num, symbols, re_symbol_pattern, target, verbose):
Johnny Chen0e43f322011-03-31 01:06:28 +0000123 # If we specify the symbols to disassemble, ignore symbol table dump.
124 if symbols:
125 for i in range(len(symbols)):
126 print "symbol:", symbols[i]
127 yield symbols[i]
128 else:
129 limited = True if num != -1 else False
130 if limited:
131 count = 0
Johnny Chen293683b2011-08-18 22:46:50 +0000132 pattern = re.compile(re_symbol_pattern)
Johnny Chen0e43f322011-03-31 01:06:28 +0000133 stream = lldb.SBStream()
Johnny Chen6cd4d1d2011-04-28 23:34:58 +0000134 for m in target.module_iter():
Johnny Chen0e43f322011-03-31 01:06:28 +0000135 print "module:", m
Johnny Chen6cd4d1d2011-04-28 23:34:58 +0000136 for s in m:
Johnny Chen0e43f322011-03-31 01:06:28 +0000137 if limited and count >= num:
138 return
Johnny Chen293683b2011-08-18 22:46:50 +0000139 # If a regexp symbol pattern is supplied, consult it.
140 if re_symbol_pattern:
141 # If the pattern does not match, look for the next symbol.
142 if not pattern.match(s.GetName()):
143 continue
144
145 # If we come here, we're ready to disassemble the symbol.
Johnny Chen0e43f322011-03-31 01:06:28 +0000146 print "symbol:", s.GetName()
147 if IsCodeType(s):
148 if limited:
149 count = count + 1
Johnny Chen901209d2011-08-18 22:04:27 +0000150 if verbose:
151 print "returning symbol:", s.GetName()
Johnny Chen0e43f322011-03-31 01:06:28 +0000152 yield s.GetName()
Johnny Chen901209d2011-08-18 22:04:27 +0000153 if verbose:
154 print "start address:", s.GetStartAddress()
155 print "end address:", s.GetEndAddress()
156 s.GetDescription(stream)
157 print "symbol description:", stream.GetData()
158 stream.Clear()
Johnny Chen0e43f322011-03-31 01:06:28 +0000159
Johnny Chen318e7ba2011-03-30 18:47:54 +0000160 # Disassembly time.
Johnny Chen293683b2011-08-18 22:46:50 +0000161 for symbol in symbol_iter(num_symbols, symbols_to_disassemble, re_symbol_pattern, target, not quiet_disassembly):
Johnny Chen318e7ba2011-03-30 18:47:54 +0000162 cmd = "disassemble %s '%s'" % (disassemble_options, symbol)
Johnny Chen901209d2011-08-18 22:04:27 +0000163 run_command(ci, cmd, res, True, not quiet_disassembly)
Johnny Chen6454e152011-03-29 01:07:00 +0000164
Johnny Chen5e28aa52011-03-28 22:40:32 +0000165
166def main():
167 # This is to set up the Python path to include the pexpect-2.4 dir.
168 # Remember to update this when/if things change.
169 scriptPath = sys.path[0]
170 sys.path.append(os.path.join(scriptPath, os.pardir, os.pardir, 'test', 'pexpect-2.4'))
171
172 parser = OptionParser(usage="""\
173Run lldb to disassemble all the available functions for an executable image.
174
175Usage: %prog [options]
176""")
177 parser.add_option('-C', '--lldb-command',
178 type='string', action='append', metavar='COMMAND',
179 default=[], dest='lldb_commands',
180 help='Command(s) lldb executes after starting up (can be empty)')
Johnny Chen5e28aa52011-03-28 22:40:32 +0000181 parser.add_option('-e', '--executable',
182 type='string', action='store',
183 dest='executable',
Johnny Chen6454e152011-03-29 01:07:00 +0000184 help="""Mandatory: the executable to do disassembly on.""")
185 parser.add_option('-o', '--options',
186 type='string', action='store',
187 dest='disassemble_options',
188 help="""Mandatory: the options passed to lldb's 'disassemble' command.""")
Johnny Chen901209d2011-08-18 22:04:27 +0000189 parser.add_option('-q', '--quiet-disassembly',
190 action='store_true', default=False,
191 dest='quiet_disassembly',
192 help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
Johnny Chen293683b2011-08-18 22:46:50 +0000193 parser.add_option('-n', '--num-symbols',
194 type='int', action='store', default=-1,
195 dest='num_symbols',
196 help="""The number of symbols to disassemble, if specified.""")
197 parser.add_option('-p', '--symbol_pattern',
198 type='string', action='store',
199 dest='re_symbol_pattern',
200 help="""The regular expression of symbols to invoke lldb's 'disassemble' command.""")
Johnny Chen318e7ba2011-03-30 18:47:54 +0000201 parser.add_option('-s', '--symbol',
202 type='string', action='append', metavar='SYMBOL', default=[],
203 dest='symbols_to_disassemble',
204 help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
205
Johnny Chen5e28aa52011-03-28 22:40:32 +0000206 opts, args = parser.parse_args()
207
208 lldb_commands = opts.lldb_commands
Johnny Chen5e28aa52011-03-28 22:40:32 +0000209
Johnny Chen6454e152011-03-29 01:07:00 +0000210 if not opts.executable or not opts.disassemble_options:
Johnny Chen5e28aa52011-03-28 22:40:32 +0000211 parser.print_help()
212 sys.exit(1)
Johnny Chen6454e152011-03-29 01:07:00 +0000213
Johnny Chen5e28aa52011-03-28 22:40:32 +0000214 executable = opts.executable
Johnny Chen6454e152011-03-29 01:07:00 +0000215 disassemble_options = opts.disassemble_options
Johnny Chen901209d2011-08-18 22:04:27 +0000216 quiet_disassembly = opts.quiet_disassembly
Johnny Chen293683b2011-08-18 22:46:50 +0000217 num_symbols = opts.num_symbols
Johnny Chen318e7ba2011-03-30 18:47:54 +0000218 symbols_to_disassemble = opts.symbols_to_disassemble
Johnny Chen293683b2011-08-18 22:46:50 +0000219 re_symbol_pattern = opts.re_symbol_pattern
Johnny Chen5e28aa52011-03-28 22:40:32 +0000220
221 # We have parsed the options.
222 print "lldb commands:", lldb_commands
Johnny Chen5e28aa52011-03-28 22:40:32 +0000223 print "executable:", executable
Johnny Chen6454e152011-03-29 01:07:00 +0000224 print "disassemble options:", disassemble_options
Johnny Chen901209d2011-08-18 22:04:27 +0000225 print "quiet disassembly output:", quiet_disassembly
Johnny Chen293683b2011-08-18 22:46:50 +0000226 print "num of symbols to disassemble:", num_symbols
Johnny Chen318e7ba2011-03-30 18:47:54 +0000227 print "symbols to disassemble:", symbols_to_disassemble
Johnny Chen293683b2011-08-18 22:46:50 +0000228 print "regular expression of symbols to disassemble:", re_symbol_pattern
Johnny Chen5e28aa52011-03-28 22:40:32 +0000229
230 setupSysPath()
Johnny Chen901209d2011-08-18 22:04:27 +0000231 do_lldb_disassembly(lldb_commands, executable, disassemble_options,
232 num_symbols,
233 symbols_to_disassemble,
Johnny Chen293683b2011-08-18 22:46:50 +0000234 re_symbol_pattern,
Johnny Chen901209d2011-08-18 22:04:27 +0000235 quiet_disassembly)
Johnny Chen5e28aa52011-03-28 22:40:32 +0000236
237if __name__ == '__main__':
238 main()