blob: 9cc4370e60457b82eae8971033a906fb6ab38828 [file] [log] [blame]
Johnny Chen1605cf62010-09-08 22:54:46 +00001"""
Johnny Chenb51d87d2010-10-07 21:38:28 +00002This LLDB module contains miscellaneous utilities.
Johnny Chen1605cf62010-09-08 22:54:46 +00003"""
4
5import lldb
Johnny Chen0bfa8592011-03-23 20:28:59 +00006import os, sys
Johnny Chened5f04e2010-10-15 23:33:18 +00007import StringIO
Johnny Chen1605cf62010-09-08 22:54:46 +00008
Johnny Chen0bfa8592011-03-23 20:28:59 +00009def is_exe(fpath):
10 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
11
Johnny Chen0bfa8592011-03-23 20:28:59 +000012def which(program):
Johnny Chen0b4dfac2011-04-18 18:34:09 +000013 """Find the full path to a program, or return None."""
Johnny Chen0bfa8592011-03-23 20:28:59 +000014 fpath, fname = os.path.split(program)
15 if fpath:
16 if is_exe(program):
17 return program
18 else:
19 for path in os.environ["PATH"].split(os.pathsep):
20 exe_file = os.path.join(path, program)
21 if is_exe(exe_file):
22 return exe_file
23 return None
24
Johnny Chen77356a02011-03-03 01:41:57 +000025# ===========================================
26# Iterator for lldb aggregate data structures
27# ===========================================
28
29def lldb_iter(obj, getsize, getelem):
30 """A generator adaptor for lldb aggregate data structures.
31
32 API clients pass in an aggregate object or a container of it, the name of
33 the method to get the size of the aggregate, and the name of the method to
34 get the element by index.
35
36 Example usages:
37
38 1. Pass an aggregate as the first argument:
39
40 def disassemble_instructions (insts):
41 from lldbutil import lldb_iter
42 for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
43 print i
44
45 2. Pass a container of aggregate which provides APIs to get to the size and
46 the element of the aggregate:
47
48 # Module is a container of symbol table
49 module = target.FindModule(filespec)
50 for symbol in lldb_iter(module, 'GetNumSymbols', 'GetSymbolAtIndex'):
51 name = symbol.GetName()
52 ...
53 """
54 size = getattr(obj, getsize)
55 elem = getattr(obj, getelem)
56 for i in range(size()):
57 yield elem(i)
58
59
Johnny Chen51ed1b62011-03-03 19:14:00 +000060# ===================================================
61# Disassembly for an SBFunction or an SBSymbol object
62# ===================================================
63
64def disassemble(target, function_or_symbol):
65 """Disassemble the function or symbol given a target.
66
67 It returns the disassembly content in a string object.
68 """
69 buf = StringIO.StringIO()
70 insts = function_or_symbol.GetInstructions(target)
71 for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
72 print >> buf, i
73 return buf.getvalue()
74
75
Johnny Chen4c70f282011-03-02 01:36:45 +000076# ==========================================================
77# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
78# ==========================================================
79
80def int_to_bytearray(val, bytesize):
81 """Utility function to convert an integer into a bytearray.
82
Johnny Chend2765fc2011-03-02 20:54:22 +000083 It returns the bytearray in the little endian format. It is easy to get the
84 big endian format, just do ba.reverse() on the returned object.
Johnny Chen4c70f282011-03-02 01:36:45 +000085 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000086 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +000087
88 if bytesize == 1:
89 return bytearray([val])
90
91 # Little endian followed by a format character.
92 template = "<%c"
93 if bytesize == 2:
94 fmt = template % 'h'
95 elif bytesize == 4:
96 fmt = template % 'i'
97 elif bytesize == 4:
98 fmt = template % 'q'
99 else:
100 return None
101
Johnny Chenf4c0d1d2011-03-30 17:54:35 +0000102 packed = struct.pack(fmt, val)
Johnny Chen4c70f282011-03-02 01:36:45 +0000103 return bytearray(map(ord, packed))
104
105def bytearray_to_int(bytes, bytesize):
106 """Utility function to convert a bytearray into an integer.
107
Johnny Chend2765fc2011-03-02 20:54:22 +0000108 It interprets the bytearray in the little endian format. For a big endian
109 bytearray, just do ba.reverse() on the object before passing it in.
Johnny Chen4c70f282011-03-02 01:36:45 +0000110 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +0000111 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +0000112
113 if bytesize == 1:
114 return ba[0]
115
116 # Little endian followed by a format character.
117 template = "<%c"
118 if bytesize == 2:
119 fmt = template % 'h'
120 elif bytesize == 4:
121 fmt = template % 'i'
122 elif bytesize == 4:
123 fmt = template % 'q'
124 else:
125 return None
126
Johnny Chenf4c0d1d2011-03-30 17:54:35 +0000127 unpacked = struct.unpack(fmt, str(bytes))
Johnny Chen4c70f282011-03-02 01:36:45 +0000128 return unpacked[0]
129
130
Johnny Chen77356a02011-03-03 01:41:57 +0000131# ===========================================================
132# Returns the list of stopped thread(s) given an lldb process
133# ===========================================================
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000134
Johnny Chen77356a02011-03-03 01:41:57 +0000135def get_stopped_threads(process, reason):
136 """Returns the thread(s) with the specified stop reason in a list."""
137 threads = []
138 for t in lldb_iter(process, 'GetNumThreads', 'GetThreadAtIndex'):
139 if t.GetStopReason() == reason:
140 threads.append(t)
141 return threads
Johnny Chen164bf882010-10-09 01:31:09 +0000142
Johnny Chen77356a02011-03-03 01:41:57 +0000143def get_stopped_thread(process, reason):
144 """A convenience function which returns the first thread with the given stop
145 reason or None.
Johnny Chen164bf882010-10-09 01:31:09 +0000146
Johnny Chendeaf8842010-12-08 19:19:08 +0000147 Example usages:
148
Johnny Chen77356a02011-03-03 01:41:57 +0000149 1. Get the stopped thread due to a breakpoint condition
Johnny Chen164bf882010-10-09 01:31:09 +0000150
Johnny Chen77356a02011-03-03 01:41:57 +0000151 ...
152 from lldbutil import get_stopped_thread
153 thread = get_stopped_thread(self.process, lldb.eStopReasonPlanComplete)
154 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition")
155 ...
Johnny Chendeaf8842010-12-08 19:19:08 +0000156
Johnny Chen77356a02011-03-03 01:41:57 +0000157 2. Get the thread stopped due to a breakpoint
Johnny Chendeaf8842010-12-08 19:19:08 +0000158
Johnny Chen77356a02011-03-03 01:41:57 +0000159 ...
160 from lldbutil import get_stopped_thread
161 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
162 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint")
163 ...
164
Johnny Chen164bf882010-10-09 01:31:09 +0000165 """
Johnny Chen77356a02011-03-03 01:41:57 +0000166 threads = get_stopped_threads(process, reason)
167 if len(threads) == 0:
168 return None
169 return threads[0]
Johnny Chen164bf882010-10-09 01:31:09 +0000170
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000171# ==============================================================
172# Get the description of an lldb object or None if not available
173# ==============================================================
174def get_description(lldb_obj, option=None):
175 """Calls lldb_obj.GetDescription() and returns a string, or None."""
176 method = getattr(lldb_obj, 'GetDescription')
177 if not method:
178 return None
179 stream = lldb.SBStream()
180 if option is None:
181 success = method(stream)
182 else:
183 success = method(stream, option)
184 if not success:
185 return None
186 return stream.GetData()
187
188
Johnny Chen168a61a2010-10-22 21:31:03 +0000189# =================================================
190# Convert some enum value to its string counterpart
191# =================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000192
193def StateTypeString(enum):
194 """Returns the stateType string given an enum."""
195 if enum == lldb.eStateInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000196 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000197 elif enum == lldb.eStateUnloaded:
Johnny Chen59b84772010-10-18 15:46:54 +0000198 return "unloaded"
Johnny Chen42da4da2011-03-05 01:20:11 +0000199 elif enum == lldb.eStateConnected:
200 return "connected"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000201 elif enum == lldb.eStateAttaching:
Johnny Chen59b84772010-10-18 15:46:54 +0000202 return "attaching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000203 elif enum == lldb.eStateLaunching:
Johnny Chen59b84772010-10-18 15:46:54 +0000204 return "launching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000205 elif enum == lldb.eStateStopped:
Johnny Chen59b84772010-10-18 15:46:54 +0000206 return "stopped"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000207 elif enum == lldb.eStateRunning:
Johnny Chen59b84772010-10-18 15:46:54 +0000208 return "running"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000209 elif enum == lldb.eStateStepping:
Johnny Chen59b84772010-10-18 15:46:54 +0000210 return "stepping"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000211 elif enum == lldb.eStateCrashed:
Johnny Chen59b84772010-10-18 15:46:54 +0000212 return "crashed"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000213 elif enum == lldb.eStateDetached:
Johnny Chen59b84772010-10-18 15:46:54 +0000214 return "detached"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000215 elif enum == lldb.eStateExited:
Johnny Chen59b84772010-10-18 15:46:54 +0000216 return "exited"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000217 elif enum == lldb.eStateSuspended:
Johnny Chen59b84772010-10-18 15:46:54 +0000218 return "suspended"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000219 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000220 raise Exception("Unknown StateType enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000221
222def StopReasonString(enum):
223 """Returns the stopReason string given an enum."""
224 if enum == lldb.eStopReasonInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000225 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000226 elif enum == lldb.eStopReasonNone:
Johnny Chen59b84772010-10-18 15:46:54 +0000227 return "none"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000228 elif enum == lldb.eStopReasonTrace:
Johnny Chen59b84772010-10-18 15:46:54 +0000229 return "trace"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000230 elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000231 return "breakpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000232 elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000233 return "watchpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000234 elif enum == lldb.eStopReasonSignal:
Johnny Chen59b84772010-10-18 15:46:54 +0000235 return "signal"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000236 elif enum == lldb.eStopReasonException:
Johnny Chen59b84772010-10-18 15:46:54 +0000237 return "exception"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000238 elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen59b84772010-10-18 15:46:54 +0000239 return "plancomplete"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000240 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000241 raise Exception("Unknown StopReason enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000242
Johnny Chen2c8d1592010-11-03 21:37:58 +0000243def ValueTypeString(enum):
244 """Returns the valueType string given an enum."""
245 if enum == lldb.eValueTypeInvalid:
246 return "invalid"
247 elif enum == lldb.eValueTypeVariableGlobal:
248 return "global_variable"
249 elif enum == lldb.eValueTypeVariableStatic:
250 return "static_variable"
251 elif enum == lldb.eValueTypeVariableArgument:
252 return "argument_variable"
253 elif enum == lldb.eValueTypeVariableLocal:
254 return "local_variable"
255 elif enum == lldb.eValueTypeRegister:
256 return "register"
257 elif enum == lldb.eValueTypeRegisterSet:
258 return "register_set"
259 elif enum == lldb.eValueTypeConstResult:
260 return "constant_result"
261 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000262 raise Exception("Unknown ValueType enum")
Johnny Chen2c8d1592010-11-03 21:37:58 +0000263
Johnny Chenbe683bc2010-10-07 22:15:58 +0000264
Johnny Chen168a61a2010-10-22 21:31:03 +0000265# ==================================================
266# Utility functions related to Threads and Processes
267# ==================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000268
Johnny Chen69af39d2011-03-09 23:45:56 +0000269def get_caller_symbol(thread):
270 """
271 Returns the symbol name for the call site of the leaf function.
272 """
273 depth = thread.GetNumFrames()
274 if depth <= 1:
275 return None
276 caller = thread.GetFrameAtIndex(1).GetSymbol()
277 if caller:
278 return caller.GetName()
279 else:
280 return None
281
282
Johnny Chen1605cf62010-09-08 22:54:46 +0000283def GetFunctionNames(thread):
284 """
285 Returns a sequence of function names from the stack frames of this thread.
286 """
287 def GetFuncName(i):
288 return thread.GetFrameAtIndex(i).GetFunction().GetName()
289
290 return map(GetFuncName, range(thread.GetNumFrames()))
291
292
Johnny Chenb51d87d2010-10-07 21:38:28 +0000293def GetSymbolNames(thread):
294 """
295 Returns a sequence of symbols for this thread.
296 """
297 def GetSymbol(i):
298 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
299
300 return map(GetSymbol, range(thread.GetNumFrames()))
301
302
303def GetPCAddresses(thread):
304 """
305 Returns a sequence of pc addresses for this thread.
306 """
307 def GetPCAddress(i):
308 return thread.GetFrameAtIndex(i).GetPCAddress()
309
310 return map(GetPCAddress, range(thread.GetNumFrames()))
311
312
Johnny Chen1605cf62010-09-08 22:54:46 +0000313def GetFilenames(thread):
314 """
315 Returns a sequence of file names from the stack frames of this thread.
316 """
317 def GetFilename(i):
318 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
319
320 return map(GetFilename, range(thread.GetNumFrames()))
321
322
323def GetLineNumbers(thread):
324 """
325 Returns a sequence of line numbers from the stack frames of this thread.
326 """
327 def GetLineNumber(i):
328 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
329
330 return map(GetLineNumber, range(thread.GetNumFrames()))
331
332
333def GetModuleNames(thread):
334 """
335 Returns a sequence of module names from the stack frames of this thread.
336 """
337 def GetModuleName(i):
338 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
339
340 return map(GetModuleName, range(thread.GetNumFrames()))
341
342
Johnny Chen88866ac2010-09-09 00:55:07 +0000343def GetStackFrames(thread):
344 """
345 Returns a sequence of stack frames for this thread.
346 """
347 def GetStackFrame(i):
348 return thread.GetFrameAtIndex(i)
349
350 return map(GetStackFrame, range(thread.GetNumFrames()))
351
352
Johnny Chen30425e92010-10-07 18:52:48 +0000353def PrintStackTrace(thread, string_buffer = False):
Johnny Chen1605cf62010-09-08 22:54:46 +0000354 """Prints a simple stack trace of this thread."""
Johnny Chen30425e92010-10-07 18:52:48 +0000355
Johnny Chened5f04e2010-10-15 23:33:18 +0000356 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000357 target = thread.GetProcess().GetTarget()
358
Johnny Chen1605cf62010-09-08 22:54:46 +0000359 depth = thread.GetNumFrames()
360
361 mods = GetModuleNames(thread)
362 funcs = GetFunctionNames(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000363 symbols = GetSymbolNames(thread)
Johnny Chen1605cf62010-09-08 22:54:46 +0000364 files = GetFilenames(thread)
365 lines = GetLineNumbers(thread)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000366 addrs = GetPCAddresses(thread)
Johnny Chen30425e92010-10-07 18:52:48 +0000367
Johnny Chenad5fd402010-10-25 19:13:52 +0000368 if thread.GetStopReason() != lldb.eStopReasonInvalid:
369 desc = "stop reason=" + StopReasonString(thread.GetStopReason())
370 else:
371 desc = ""
372 print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
373 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen1605cf62010-09-08 22:54:46 +0000374
Johnny Chenb51d87d2010-10-07 21:38:28 +0000375 for i in range(depth):
376 frame = thread.GetFrameAtIndex(i)
377 function = frame.GetFunction()
Johnny Chen1605cf62010-09-08 22:54:46 +0000378
Johnny Chenb51d87d2010-10-07 21:38:28 +0000379 load_addr = addrs[i].GetLoadAddress(target)
380 if not function.IsValid():
381 file_addr = addrs[i].GetFileAddress()
382 print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
383 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
384 else:
385 print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
386 num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
387
388 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000389 return output.getvalue()
Johnny Chenb51d87d2010-10-07 21:38:28 +0000390
391
392def PrintStackTraces(process, string_buffer = False):
393 """Prints the stack traces of all the threads."""
394
Johnny Chened5f04e2010-10-15 23:33:18 +0000395 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000396
397 print >> output, "Stack traces for " + repr(process)
398
399 for i in range(process.GetNumThreads()):
400 print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
Johnny Chen30425e92010-10-07 18:52:48 +0000401
402 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000403 return output.getvalue()
Jim Inghame41494a2011-04-16 00:01:13 +0000404
405def GetThreadsStoppedAtBreakpoint (process, bkpt):
Johnny Chen37ac00b2011-04-18 18:32:09 +0000406 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
Jim Inghame41494a2011-04-16 00:01:13 +0000407 stopped_threads = []
408 threads = []
409
410 stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
411
412 if len(stopped_threads) == 0:
413 return threads
414
415 for thread in stopped_threads:
416 # Make sure we've hit our breakpoint...
417 break_id = thread.GetStopReasonDataAtIndex (0)
418 if break_id == bkpt.GetID():
419 threads.append(thread)
420
421 return threads
422
423def ContinueToBreakpoint (process, bkpt):
Johnny Chen37ac00b2011-04-18 18:32:09 +0000424 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
Jim Inghame41494a2011-04-16 00:01:13 +0000425 process.Continue()
426 if process.GetState() != lldb.eStateStopped:
427 return None
428 else:
429 return GetThreadsStoppedAtBreakpoint (process, bkpt)
430