blob: 114f637b03cfb8693cce71e7ee7d077cea2f8d80 [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 Chen8a3b54e2011-04-26 23:07:40 +00009# ===================================================
10# Utilities for locating/checking executable programs
11# ===================================================
Johnny Chen979cb5d2011-04-26 22:53:38 +000012
Johnny Chen0bfa8592011-03-23 20:28:59 +000013def is_exe(fpath):
Johnny Chenefdc26a2011-04-26 23:10:15 +000014 """Returns True if fpath is an executable."""
Johnny Chen0bfa8592011-03-23 20:28:59 +000015 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
16
Johnny Chen0bfa8592011-03-23 20:28:59 +000017def which(program):
Johnny Chenefdc26a2011-04-26 23:10:15 +000018 """Returns the full path to a program; None otherwise."""
Johnny Chen0bfa8592011-03-23 20:28:59 +000019 fpath, fname = os.path.split(program)
20 if fpath:
21 if is_exe(program):
22 return program
23 else:
24 for path in os.environ["PATH"].split(os.pathsep):
25 exe_file = os.path.join(path, program)
26 if is_exe(exe_file):
27 return exe_file
28 return None
29
Johnny Chen51ed1b62011-03-03 19:14:00 +000030# ===================================================
31# Disassembly for an SBFunction or an SBSymbol object
32# ===================================================
33
34def disassemble(target, function_or_symbol):
35 """Disassemble the function or symbol given a target.
36
37 It returns the disassembly content in a string object.
38 """
39 buf = StringIO.StringIO()
40 insts = function_or_symbol.GetInstructions(target)
Johnny Chend643c082011-04-28 22:57:01 +000041 for i in insts:
Johnny Chen51ed1b62011-03-03 19:14:00 +000042 print >> buf, i
43 return buf.getvalue()
44
45
Johnny Chen4c70f282011-03-02 01:36:45 +000046# ==========================================================
47# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
48# ==========================================================
49
50def int_to_bytearray(val, bytesize):
51 """Utility function to convert an integer into a bytearray.
52
Johnny Chend2765fc2011-03-02 20:54:22 +000053 It returns the bytearray in the little endian format. It is easy to get the
54 big endian format, just do ba.reverse() on the returned object.
Johnny Chen4c70f282011-03-02 01:36:45 +000055 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000056 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +000057
58 if bytesize == 1:
59 return bytearray([val])
60
61 # Little endian followed by a format character.
62 template = "<%c"
63 if bytesize == 2:
64 fmt = template % 'h'
65 elif bytesize == 4:
66 fmt = template % 'i'
67 elif bytesize == 4:
68 fmt = template % 'q'
69 else:
70 return None
71
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000072 packed = struct.pack(fmt, val)
Johnny Chen4c70f282011-03-02 01:36:45 +000073 return bytearray(map(ord, packed))
74
75def bytearray_to_int(bytes, bytesize):
76 """Utility function to convert a bytearray into an integer.
77
Johnny Chend2765fc2011-03-02 20:54:22 +000078 It interprets the bytearray in the little endian format. For a big endian
79 bytearray, just do ba.reverse() on the object before passing it in.
Johnny Chen4c70f282011-03-02 01:36:45 +000080 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000081 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +000082
83 if bytesize == 1:
84 return ba[0]
85
86 # Little endian followed by a format character.
87 template = "<%c"
88 if bytesize == 2:
89 fmt = template % 'h'
90 elif bytesize == 4:
91 fmt = template % 'i'
92 elif bytesize == 4:
93 fmt = template % 'q'
94 else:
95 return None
96
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000097 unpacked = struct.unpack(fmt, str(bytes))
Johnny Chen4c70f282011-03-02 01:36:45 +000098 return unpacked[0]
99
100
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000101# ==============================================================
102# Get the description of an lldb object or None if not available
103# ==============================================================
Johnny Chenbdc36bd2011-04-25 20:23:05 +0000104def get_description(obj, option=None):
105 """Calls lldb_obj.GetDescription() and returns a string, or None.
106
107 For SBTarget and SBBreakpointLocation lldb objects, an extra option can be
108 passed in to describe the detailed level of description desired:
109 o lldb.eDescriptionLevelBrief
110 o lldb.eDescriptionLevelFull
111 o lldb.eDescriptionLevelVerbose
112 """
113 method = getattr(obj, 'GetDescription')
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000114 if not method:
115 return None
Johnny Chenbdc36bd2011-04-25 20:23:05 +0000116 if isinstance(obj, lldb.SBTarget) or isinstance(obj, lldb.SBBreakpointLocation):
117 if option is None:
118 option = lldb.eDescriptionLevelBrief
119
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000120 stream = lldb.SBStream()
121 if option is None:
122 success = method(stream)
123 else:
124 success = method(stream, option)
125 if not success:
126 return None
127 return stream.GetData()
128
129
Johnny Chen168a61a2010-10-22 21:31:03 +0000130# =================================================
131# Convert some enum value to its string counterpart
132# =================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000133
Johnny Chen47342d52011-04-27 17:43:07 +0000134def state_type_to_str(enum):
Johnny Chenbe683bc2010-10-07 22:15:58 +0000135 """Returns the stateType string given an enum."""
136 if enum == lldb.eStateInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000137 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000138 elif enum == lldb.eStateUnloaded:
Johnny Chen59b84772010-10-18 15:46:54 +0000139 return "unloaded"
Johnny Chen42da4da2011-03-05 01:20:11 +0000140 elif enum == lldb.eStateConnected:
141 return "connected"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000142 elif enum == lldb.eStateAttaching:
Johnny Chen59b84772010-10-18 15:46:54 +0000143 return "attaching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000144 elif enum == lldb.eStateLaunching:
Johnny Chen59b84772010-10-18 15:46:54 +0000145 return "launching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000146 elif enum == lldb.eStateStopped:
Johnny Chen59b84772010-10-18 15:46:54 +0000147 return "stopped"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000148 elif enum == lldb.eStateRunning:
Johnny Chen59b84772010-10-18 15:46:54 +0000149 return "running"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000150 elif enum == lldb.eStateStepping:
Johnny Chen59b84772010-10-18 15:46:54 +0000151 return "stepping"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000152 elif enum == lldb.eStateCrashed:
Johnny Chen59b84772010-10-18 15:46:54 +0000153 return "crashed"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000154 elif enum == lldb.eStateDetached:
Johnny Chen59b84772010-10-18 15:46:54 +0000155 return "detached"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000156 elif enum == lldb.eStateExited:
Johnny Chen59b84772010-10-18 15:46:54 +0000157 return "exited"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000158 elif enum == lldb.eStateSuspended:
Johnny Chen59b84772010-10-18 15:46:54 +0000159 return "suspended"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000160 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000161 raise Exception("Unknown StateType enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000162
Johnny Chen47342d52011-04-27 17:43:07 +0000163def stop_reason_to_str(enum):
Johnny Chenbe683bc2010-10-07 22:15:58 +0000164 """Returns the stopReason string given an enum."""
165 if enum == lldb.eStopReasonInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000166 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000167 elif enum == lldb.eStopReasonNone:
Johnny Chen59b84772010-10-18 15:46:54 +0000168 return "none"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000169 elif enum == lldb.eStopReasonTrace:
Johnny Chen59b84772010-10-18 15:46:54 +0000170 return "trace"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000171 elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000172 return "breakpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000173 elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000174 return "watchpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000175 elif enum == lldb.eStopReasonSignal:
Johnny Chen59b84772010-10-18 15:46:54 +0000176 return "signal"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000177 elif enum == lldb.eStopReasonException:
Johnny Chen59b84772010-10-18 15:46:54 +0000178 return "exception"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000179 elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen59b84772010-10-18 15:46:54 +0000180 return "plancomplete"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000181 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000182 raise Exception("Unknown StopReason enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000183
Johnny Chen47342d52011-04-27 17:43:07 +0000184def value_type_to_str(enum):
Johnny Chen2c8d1592010-11-03 21:37:58 +0000185 """Returns the valueType string given an enum."""
186 if enum == lldb.eValueTypeInvalid:
187 return "invalid"
188 elif enum == lldb.eValueTypeVariableGlobal:
189 return "global_variable"
190 elif enum == lldb.eValueTypeVariableStatic:
191 return "static_variable"
192 elif enum == lldb.eValueTypeVariableArgument:
193 return "argument_variable"
194 elif enum == lldb.eValueTypeVariableLocal:
195 return "local_variable"
196 elif enum == lldb.eValueTypeRegister:
197 return "register"
198 elif enum == lldb.eValueTypeRegisterSet:
199 return "register_set"
200 elif enum == lldb.eValueTypeConstResult:
201 return "constant_result"
202 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000203 raise Exception("Unknown ValueType enum")
Johnny Chen2c8d1592010-11-03 21:37:58 +0000204
Johnny Chenbe683bc2010-10-07 22:15:58 +0000205
Johnny Chen168a61a2010-10-22 21:31:03 +0000206# ==================================================
207# Utility functions related to Threads and Processes
208# ==================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000209
Johnny Chene428d332011-04-25 22:04:05 +0000210def get_stopped_threads(process, reason):
211 """Returns the thread(s) with the specified stop reason in a list."""
212 threads = []
Johnny Chend643c082011-04-28 22:57:01 +0000213 for t in process:
Johnny Chene428d332011-04-25 22:04:05 +0000214 if t.GetStopReason() == reason:
215 threads.append(t)
216 return threads
217
218def get_stopped_thread(process, reason):
219 """A convenience function which returns the first thread with the given stop
220 reason or None.
221
222 Example usages:
223
224 1. Get the stopped thread due to a breakpoint condition
225
226 ...
227 from lldbutil import get_stopped_thread
228 thread = get_stopped_thread(self.process, lldb.eStopReasonPlanComplete)
229 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition")
230 ...
231
232 2. Get the thread stopped due to a breakpoint
233
234 ...
235 from lldbutil import get_stopped_thread
236 thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
237 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint")
238 ...
239
240 """
241 threads = get_stopped_threads(process, reason)
242 if len(threads) == 0:
243 return None
244 return threads[0]
245
Johnny Chen318aaa02011-04-25 23:38:13 +0000246def get_threads_stopped_at_breakpoint (process, bkpt):
247 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
248 stopped_threads = []
249 threads = []
250
251 stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
252
253 if len(stopped_threads) == 0:
254 return threads
255
256 for thread in stopped_threads:
257 # Make sure we've hit our breakpoint...
258 break_id = thread.GetStopReasonDataAtIndex (0)
259 if break_id == bkpt.GetID():
260 threads.append(thread)
261
262 return threads
263
264def continue_to_breakpoint (process, bkpt):
265 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
266 process.Continue()
267 if process.GetState() != lldb.eStateStopped:
268 return None
269 else:
270 return get_threads_stopped_at_breakpoint (process, bkpt)
271
Johnny Chen69af39d2011-03-09 23:45:56 +0000272def get_caller_symbol(thread):
273 """
274 Returns the symbol name for the call site of the leaf function.
275 """
276 depth = thread.GetNumFrames()
277 if depth <= 1:
278 return None
279 caller = thread.GetFrameAtIndex(1).GetSymbol()
280 if caller:
281 return caller.GetName()
282 else:
283 return None
284
285
Johnny Chen318aaa02011-04-25 23:38:13 +0000286def get_function_names(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000287 """
288 Returns a sequence of function names from the stack frames of this thread.
289 """
290 def GetFuncName(i):
291 return thread.GetFrameAtIndex(i).GetFunction().GetName()
292
293 return map(GetFuncName, range(thread.GetNumFrames()))
294
295
Johnny Chen318aaa02011-04-25 23:38:13 +0000296def get_symbol_names(thread):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000297 """
298 Returns a sequence of symbols for this thread.
299 """
300 def GetSymbol(i):
301 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
302
303 return map(GetSymbol, range(thread.GetNumFrames()))
304
305
Johnny Chen318aaa02011-04-25 23:38:13 +0000306def get_pc_addresses(thread):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000307 """
308 Returns a sequence of pc addresses for this thread.
309 """
310 def GetPCAddress(i):
311 return thread.GetFrameAtIndex(i).GetPCAddress()
312
313 return map(GetPCAddress, range(thread.GetNumFrames()))
314
315
Johnny Chen318aaa02011-04-25 23:38:13 +0000316def get_filenames(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000317 """
318 Returns a sequence of file names from the stack frames of this thread.
319 """
320 def GetFilename(i):
321 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
322
323 return map(GetFilename, range(thread.GetNumFrames()))
324
325
Johnny Chen318aaa02011-04-25 23:38:13 +0000326def get_line_numbers(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000327 """
328 Returns a sequence of line numbers from the stack frames of this thread.
329 """
330 def GetLineNumber(i):
331 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
332
333 return map(GetLineNumber, range(thread.GetNumFrames()))
334
335
Johnny Chen318aaa02011-04-25 23:38:13 +0000336def get_module_names(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000337 """
338 Returns a sequence of module names from the stack frames of this thread.
339 """
340 def GetModuleName(i):
341 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
342
343 return map(GetModuleName, range(thread.GetNumFrames()))
344
345
Johnny Chen318aaa02011-04-25 23:38:13 +0000346def get_stack_frames(thread):
Johnny Chen88866ac2010-09-09 00:55:07 +0000347 """
348 Returns a sequence of stack frames for this thread.
349 """
350 def GetStackFrame(i):
351 return thread.GetFrameAtIndex(i)
352
353 return map(GetStackFrame, range(thread.GetNumFrames()))
354
355
Johnny Chen318aaa02011-04-25 23:38:13 +0000356def print_stacktrace(thread, string_buffer = False):
Johnny Chen1605cf62010-09-08 22:54:46 +0000357 """Prints a simple stack trace of this thread."""
Johnny Chen30425e92010-10-07 18:52:48 +0000358
Johnny Chened5f04e2010-10-15 23:33:18 +0000359 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000360 target = thread.GetProcess().GetTarget()
361
Johnny Chen1605cf62010-09-08 22:54:46 +0000362 depth = thread.GetNumFrames()
363
Johnny Chen318aaa02011-04-25 23:38:13 +0000364 mods = get_module_names(thread)
365 funcs = get_function_names(thread)
366 symbols = get_symbol_names(thread)
367 files = get_filenames(thread)
368 lines = get_line_numbers(thread)
369 addrs = get_pc_addresses(thread)
Johnny Chen30425e92010-10-07 18:52:48 +0000370
Johnny Chenad5fd402010-10-25 19:13:52 +0000371 if thread.GetStopReason() != lldb.eStopReasonInvalid:
Johnny Chen47342d52011-04-27 17:43:07 +0000372 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
Johnny Chenad5fd402010-10-25 19:13:52 +0000373 else:
374 desc = ""
375 print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
376 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen1605cf62010-09-08 22:54:46 +0000377
Johnny Chenb51d87d2010-10-07 21:38:28 +0000378 for i in range(depth):
379 frame = thread.GetFrameAtIndex(i)
380 function = frame.GetFunction()
Johnny Chen1605cf62010-09-08 22:54:46 +0000381
Johnny Chenb51d87d2010-10-07 21:38:28 +0000382 load_addr = addrs[i].GetLoadAddress(target)
383 if not function.IsValid():
384 file_addr = addrs[i].GetFileAddress()
385 print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
386 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
387 else:
388 print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
389 num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
390
391 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000392 return output.getvalue()
Johnny Chenb51d87d2010-10-07 21:38:28 +0000393
394
Johnny Chen318aaa02011-04-25 23:38:13 +0000395def print_stacktraces(process, string_buffer = False):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000396 """Prints the stack traces of all the threads."""
397
Johnny Chened5f04e2010-10-15 23:33:18 +0000398 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000399
400 print >> output, "Stack traces for " + repr(process)
401
Johnny Chen311b1d62011-05-05 18:50:56 +0000402 for thread in process:
403 print >> output, print_stacktrace(thread, string_buffer=True)
Johnny Chen30425e92010-10-07 18:52:48 +0000404
405 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000406 return output.getvalue()
Johnny Chen185e2c12011-05-08 17:25:27 +0000407
408# ===================================
409# Utility functions related to Frames
410# ===================================
411
412def print_registers(frame, string_buffer = False):
Johnny Chenb2998772011-05-08 18:55:37 +0000413 """Prints all the register sets of the frame."""
Johnny Chen185e2c12011-05-08 17:25:27 +0000414
415 output = StringIO.StringIO() if string_buffer else sys.stdout
416
417 print >> output, "Register sets for " + repr(frame)
418
Johnny Chen728255b2011-05-10 19:21:13 +0000419 registerSet = frame.GetRegisters() # Return type of SBValueList.
420 print >> output, "Frame registers (size of register set = %d):" % registerSet.GetSize()
421 for value in registerSet:
Johnny Chen185e2c12011-05-08 17:25:27 +0000422 #print >> output, value
423 print >> output, "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
424 for child in value:
425 print >> output, "Name: %s, Value: %s" % (child.GetName(), child.GetValue(frame))
426
427 if string_buffer:
428 return output.getvalue()
Johnny Chen728255b2011-05-10 19:21:13 +0000429
430def get_registers(frame, kind):
431 """Returns the registers given the frame and the kind of registers desired.
432
433 Returns None if there's no such kind.
434 """
435 registerSet = frame.GetRegisters() # Return type of SBValueList.
436 for value in registerSet:
437 if kind.lower() in value.GetName().lower():
438 return value
439
440 return None
441
442def get_GPRs(frame):
443 """Returns the general purpose registers of the frame as an SBValue.
444
445 The returned SBValue object is iterable.
446 """
447 return get_registers(frame, "general purpose")
448
449def get_FPRs(frame):
450 """Returns the floating point registers of the frame as an SBValue.
451
452 The returned SBValue object is iterable.
453 """
454 return get_registers(frame, "floating point")
455
456def get_ESRs(frame):
457 """Returns the exception state registers of the frame as an SBValue.
458
459 The returned SBValue object is iterable.
460 """
461 return get_registers(frame, "exception state")