blob: 1069bf477af2062e78cefc115182348c1eea72c6 [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
Kate Stoneb9c1b512016-09-06 20:57:50 +000013
Johnny Chen5e28aa52011-03-28 22:40:32 +000014def setupSysPath():
15 """
Johnny Chen4044fdc2011-03-28 22:48:25 +000016 Add LLDB.framework/Resources/Python and the test dir to the sys.path.
Johnny Chen5e28aa52011-03-28 22:40:32 +000017 """
18 # Get the directory containing the current script.
19 scriptPath = sys.path[0]
20 if not scriptPath.endswith(os.path.join('utils', 'test')):
21 print "This script expects to reside in lldb's utils/test directory."
22 sys.exit(-1)
23
24 # This is our base name component.
25 base = os.path.abspath(os.path.join(scriptPath, os.pardir, os.pardir))
26
27 # This is for the goodies in the test directory under base.
Kate Stoneb9c1b512016-09-06 20:57:50 +000028 sys.path.append(os.path.join(base, 'test'))
Johnny Chen5e28aa52011-03-28 22:40:32 +000029
30 # These are for xcode build directories.
31 xcode3_build_dir = ['build']
32 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
33 dbg = ['Debug']
34 rel = ['Release']
35 bai = ['BuildAndIntegration']
36 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
37
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 dbgPath = os.path.join(
39 base, *(xcode3_build_dir + dbg + python_resource_dir))
40 dbgPath2 = os.path.join(
41 base, *(xcode4_build_dir + dbg + python_resource_dir))
42 relPath = os.path.join(
43 base, *(xcode3_build_dir + rel + python_resource_dir))
44 relPath2 = os.path.join(
45 base, *(xcode4_build_dir + rel + python_resource_dir))
46 baiPath = os.path.join(
47 base, *(xcode3_build_dir + bai + python_resource_dir))
48 baiPath2 = os.path.join(
49 base, *(xcode4_build_dir + bai + python_resource_dir))
Johnny Chen5e28aa52011-03-28 22:40:32 +000050
51 lldbPath = None
52 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
53 lldbPath = dbgPath
54 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
55 lldbPath = dbgPath2
56 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
57 lldbPath = relPath
58 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
59 lldbPath = relPath2
60 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
61 lldbPath = baiPath
62 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
63 lldbPath = baiPath2
64
65 if not lldbPath:
66 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
67 print relPath + ', or ' + baiPath
68 sys.exit(-1)
69
70 # This is to locate the lldb.py module. Insert it right after sys.path[0].
71 sys.path[1:1] = [lldbPath]
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 # print "sys.path:", sys.path
Johnny Chen5e28aa52011-03-28 22:40:32 +000073
74
Johnny Chen758f2882011-08-19 20:51:15 +000075def run_command(ci, cmd, res, echo=True):
76 if echo:
Johnny Chen6454e152011-03-29 01:07:00 +000077 print "run command:", cmd
Johnny Chen5e28aa52011-03-28 22:40:32 +000078 ci.HandleCommand(cmd, res)
79 if res.Succeeded():
Johnny Chen758f2882011-08-19 20:51:15 +000080 if echo:
Johnny Chen6454e152011-03-29 01:07:00 +000081 print "run_command output:", res.GetOutput()
Johnny Chen5e28aa52011-03-28 22:40:32 +000082 else:
Johnny Chen758f2882011-08-19 20:51:15 +000083 if echo:
Johnny Chen6454e152011-03-29 01:07:00 +000084 print "run command failed!"
85 print "run_command error:", res.GetError()
Johnny Chen5e28aa52011-03-28 22:40:32 +000086
Kate Stoneb9c1b512016-09-06 20:57:50 +000087
Johnny Chen293683b2011-08-18 22:46:50 +000088def do_lldb_disassembly(lldb_commands, exe, disassemble_options, num_symbols,
89 symbols_to_disassemble,
90 re_symbol_pattern,
91 quiet_disassembly):
Kate Stoneb9c1b512016-09-06 20:57:50 +000092 import lldb
93 import atexit
94 import re
Johnny Chen5e28aa52011-03-28 22:40:32 +000095
96 # Create the debugger instance now.
97 dbg = lldb.SBDebugger.Create()
Johnny Chen26fc16b2011-05-25 20:47:27 +000098 if not dbg:
Kate Stoneb9c1b512016-09-06 20:57:50 +000099 raise Exception('Invalid debugger instance')
Johnny Chen5e28aa52011-03-28 22:40:32 +0000100
101 # Register an exit callback.
102 atexit.register(lambda: lldb.SBDebugger.Terminate())
103
104 # We want our debugger to be synchronous.
105 dbg.SetAsync(False)
106
107 # Get the command interpreter from the debugger.
108 ci = dbg.GetCommandInterpreter()
109 if not ci:
110 raise Exception('Could not get the command interpreter')
111
112 # And the associated result object.
113 res = lldb.SBCommandReturnObject()
114
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115 # See if there any extra command(s) to execute before we issue the file
116 # command.
Johnny Chen5e28aa52011-03-28 22:40:32 +0000117 for cmd in lldb_commands:
Johnny Chen758f2882011-08-19 20:51:15 +0000118 run_command(ci, cmd, res, not quiet_disassembly)
Johnny Chen5e28aa52011-03-28 22:40:32 +0000119
Johnny Chend16c1052011-03-31 01:34:55 +0000120 # Now issue the file command.
Johnny Chen758f2882011-08-19 20:51:15 +0000121 run_command(ci, 'file %s' % exe, res, not quiet_disassembly)
Johnny Chend16c1052011-03-31 01:34:55 +0000122
Johnny Chen0e43f322011-03-31 01:06:28 +0000123 # Create a target.
Johnny Chend16c1052011-03-31 01:34:55 +0000124 #target = dbg.CreateTarget(exe)
125 target = dbg.GetSelectedTarget()
Johnny Chen0e43f322011-03-31 01:06:28 +0000126 stream = lldb.SBStream()
127
Johnny Chend16c1052011-03-31 01:34:55 +0000128 def IsCodeType(symbol):
129 """Check whether an SBSymbol represents code."""
130 return symbol.GetType() == lldb.eSymbolTypeCode
131
Johnny Chen0e43f322011-03-31 01:06:28 +0000132 # Define a generator for the symbols to disassemble.
Johnny Chen293683b2011-08-18 22:46:50 +0000133 def symbol_iter(num, symbols, re_symbol_pattern, target, verbose):
Johnny Chen0e43f322011-03-31 01:06:28 +0000134 # If we specify the symbols to disassemble, ignore symbol table dump.
135 if symbols:
136 for i in range(len(symbols)):
Johnny Chen758f2882011-08-19 20:51:15 +0000137 if verbose:
138 print "symbol:", symbols[i]
Johnny Chen0e43f322011-03-31 01:06:28 +0000139 yield symbols[i]
140 else:
141 limited = True if num != -1 else False
142 if limited:
143 count = 0
Johnny Chen4c35b712011-08-19 17:28:25 +0000144 if re_symbol_pattern:
145 pattern = re.compile(re_symbol_pattern)
Johnny Chen0e43f322011-03-31 01:06:28 +0000146 stream = lldb.SBStream()
Johnny Chen6cd4d1d2011-04-28 23:34:58 +0000147 for m in target.module_iter():
Johnny Chen758f2882011-08-19 20:51:15 +0000148 if verbose:
149 print "module:", m
Johnny Chen6cd4d1d2011-04-28 23:34:58 +0000150 for s in m:
Johnny Chen0e43f322011-03-31 01:06:28 +0000151 if limited and count >= num:
152 return
Johnny Chen293683b2011-08-18 22:46:50 +0000153 # If a regexp symbol pattern is supplied, consult it.
154 if re_symbol_pattern:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 # If the pattern does not match, look for the next
156 # symbol.
Johnny Chen293683b2011-08-18 22:46:50 +0000157 if not pattern.match(s.GetName()):
158 continue
159
160 # If we come here, we're ready to disassemble the symbol.
Johnny Chen758f2882011-08-19 20:51:15 +0000161 if verbose:
162 print "symbol:", s.GetName()
Johnny Chen0e43f322011-03-31 01:06:28 +0000163 if IsCodeType(s):
164 if limited:
165 count = count + 1
Johnny Chen901209d2011-08-18 22:04:27 +0000166 if verbose:
167 print "returning symbol:", s.GetName()
Johnny Chen0e43f322011-03-31 01:06:28 +0000168 yield s.GetName()
Johnny Chen901209d2011-08-18 22:04:27 +0000169 if verbose:
170 print "start address:", s.GetStartAddress()
171 print "end address:", s.GetEndAddress()
172 s.GetDescription(stream)
173 print "symbol description:", stream.GetData()
174 stream.Clear()
Johnny Chen0e43f322011-03-31 01:06:28 +0000175
Johnny Chen318e7ba2011-03-30 18:47:54 +0000176 # Disassembly time.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177 for symbol in symbol_iter(
178 num_symbols,
179 symbols_to_disassemble,
180 re_symbol_pattern,
181 target,
182 not quiet_disassembly):
Johnny Chen318e7ba2011-03-30 18:47:54 +0000183 cmd = "disassemble %s '%s'" % (disassemble_options, symbol)
Johnny Chen758f2882011-08-19 20:51:15 +0000184 run_command(ci, cmd, res, not quiet_disassembly)
Johnny Chen6454e152011-03-29 01:07:00 +0000185
Johnny Chen5e28aa52011-03-28 22:40:32 +0000186
187def main():
188 # This is to set up the Python path to include the pexpect-2.4 dir.
189 # Remember to update this when/if things change.
190 scriptPath = sys.path[0]
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191 sys.path.append(
192 os.path.join(
193 scriptPath,
194 os.pardir,
195 os.pardir,
196 'test',
197 'pexpect-2.4'))
Johnny Chen5e28aa52011-03-28 22:40:32 +0000198
199 parser = OptionParser(usage="""\
200Run lldb to disassemble all the available functions for an executable image.
201
202Usage: %prog [options]
203""")
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 parser.add_option(
205 '-C',
206 '--lldb-command',
207 type='string',
208 action='append',
209 metavar='COMMAND',
210 default=[],
211 dest='lldb_commands',
212 help='Command(s) lldb executes after starting up (can be empty)')
213 parser.add_option(
214 '-e',
215 '--executable',
216 type='string',
217 action='store',
218 dest='executable',
219 help="""Mandatory: the executable to do disassembly on.""")
220 parser.add_option(
221 '-o',
222 '--options',
223 type='string',
224 action='store',
225 dest='disassemble_options',
226 help="""Mandatory: the options passed to lldb's 'disassemble' command.""")
227 parser.add_option(
228 '-q',
229 '--quiet-disassembly',
230 action='store_true',
231 default=False,
232 dest='quiet_disassembly',
233 help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
234 parser.add_option(
235 '-n',
236 '--num-symbols',
237 type='int',
238 action='store',
239 default=-1,
240 dest='num_symbols',
241 help="""The number of symbols to disassemble, if specified.""")
242 parser.add_option(
243 '-p',
244 '--symbol_pattern',
245 type='string',
246 action='store',
247 dest='re_symbol_pattern',
248 help="""The regular expression of symbols to invoke lldb's 'disassemble' command.""")
249 parser.add_option(
250 '-s',
251 '--symbol',
252 type='string',
253 action='append',
254 metavar='SYMBOL',
255 default=[],
256 dest='symbols_to_disassemble',
257 help="""The symbol(s) to invoke lldb's 'disassemble' command on, if specified.""")
258
Johnny Chen5e28aa52011-03-28 22:40:32 +0000259 opts, args = parser.parse_args()
260
261 lldb_commands = opts.lldb_commands
Johnny Chen5e28aa52011-03-28 22:40:32 +0000262
Johnny Chen6454e152011-03-29 01:07:00 +0000263 if not opts.executable or not opts.disassemble_options:
Johnny Chen5e28aa52011-03-28 22:40:32 +0000264 parser.print_help()
265 sys.exit(1)
Johnny Chen6454e152011-03-29 01:07:00 +0000266
Johnny Chen5e28aa52011-03-28 22:40:32 +0000267 executable = opts.executable
Johnny Chen6454e152011-03-29 01:07:00 +0000268 disassemble_options = opts.disassemble_options
Johnny Chen901209d2011-08-18 22:04:27 +0000269 quiet_disassembly = opts.quiet_disassembly
Johnny Chen293683b2011-08-18 22:46:50 +0000270 num_symbols = opts.num_symbols
Johnny Chen318e7ba2011-03-30 18:47:54 +0000271 symbols_to_disassemble = opts.symbols_to_disassemble
Johnny Chen293683b2011-08-18 22:46:50 +0000272 re_symbol_pattern = opts.re_symbol_pattern
Johnny Chen5e28aa52011-03-28 22:40:32 +0000273
274 # We have parsed the options.
Johnny Chen758f2882011-08-19 20:51:15 +0000275 if not quiet_disassembly:
276 print "lldb commands:", lldb_commands
277 print "executable:", executable
278 print "disassemble options:", disassemble_options
279 print "quiet disassembly output:", quiet_disassembly
280 print "num of symbols to disassemble:", num_symbols
281 print "symbols to disassemble:", symbols_to_disassemble
282 print "regular expression of symbols to disassemble:", re_symbol_pattern
Johnny Chen5e28aa52011-03-28 22:40:32 +0000283
284 setupSysPath()
Johnny Chen901209d2011-08-18 22:04:27 +0000285 do_lldb_disassembly(lldb_commands, executable, disassemble_options,
286 num_symbols,
287 symbols_to_disassemble,
Johnny Chen293683b2011-08-18 22:46:50 +0000288 re_symbol_pattern,
Johnny Chen901209d2011-08-18 22:04:27 +0000289 quiet_disassembly)
Johnny Chen5e28aa52011-03-28 22:40:32 +0000290
291if __name__ == '__main__':
292 main()