blob: 8341f2cd9b772e309f26f609016aa73ec4fe76b3 [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 Chen30e48502011-05-13 21:55:30 +00003Some of the test suite takes advantage of the utility functions defined here.
4They can also be useful for general purpose lldb scripting.
Johnny Chen1605cf62010-09-08 22:54:46 +00005"""
6
7import lldb
Johnny Chen0bfa8592011-03-23 20:28:59 +00008import os, sys
Johnny Chened5f04e2010-10-15 23:33:18 +00009import StringIO
Johnny Chen1605cf62010-09-08 22:54:46 +000010
Johnny Chen8a3b54e2011-04-26 23:07:40 +000011# ===================================================
12# Utilities for locating/checking executable programs
13# ===================================================
Johnny Chen979cb5d2011-04-26 22:53:38 +000014
Johnny Chen0bfa8592011-03-23 20:28:59 +000015def is_exe(fpath):
Johnny Chenefdc26a2011-04-26 23:10:15 +000016 """Returns True if fpath is an executable."""
Johnny Chen0bfa8592011-03-23 20:28:59 +000017 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
18
Johnny Chen0bfa8592011-03-23 20:28:59 +000019def which(program):
Johnny Chenefdc26a2011-04-26 23:10:15 +000020 """Returns the full path to a program; None otherwise."""
Johnny Chen0bfa8592011-03-23 20:28:59 +000021 fpath, fname = os.path.split(program)
22 if fpath:
23 if is_exe(program):
24 return program
25 else:
26 for path in os.environ["PATH"].split(os.pathsep):
27 exe_file = os.path.join(path, program)
28 if is_exe(exe_file):
29 return exe_file
30 return None
31
Johnny Chen51ed1b62011-03-03 19:14:00 +000032# ===================================================
33# Disassembly for an SBFunction or an SBSymbol object
34# ===================================================
35
36def disassemble(target, function_or_symbol):
37 """Disassemble the function or symbol given a target.
38
39 It returns the disassembly content in a string object.
40 """
41 buf = StringIO.StringIO()
42 insts = function_or_symbol.GetInstructions(target)
Johnny Chend643c082011-04-28 22:57:01 +000043 for i in insts:
Johnny Chen51ed1b62011-03-03 19:14:00 +000044 print >> buf, i
45 return buf.getvalue()
46
Johnny Chen4c70f282011-03-02 01:36:45 +000047# ==========================================================
48# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
49# ==========================================================
50
51def int_to_bytearray(val, bytesize):
52 """Utility function to convert an integer into a bytearray.
53
Johnny Chend2765fc2011-03-02 20:54:22 +000054 It returns the bytearray in the little endian format. It is easy to get the
55 big endian format, just do ba.reverse() on the returned object.
Johnny Chen4c70f282011-03-02 01:36:45 +000056 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000057 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +000058
59 if bytesize == 1:
60 return bytearray([val])
61
62 # Little endian followed by a format character.
63 template = "<%c"
64 if bytesize == 2:
65 fmt = template % 'h'
66 elif bytesize == 4:
67 fmt = template % 'i'
68 elif bytesize == 4:
69 fmt = template % 'q'
70 else:
71 return None
72
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000073 packed = struct.pack(fmt, val)
Johnny Chen4c70f282011-03-02 01:36:45 +000074 return bytearray(map(ord, packed))
75
76def bytearray_to_int(bytes, bytesize):
77 """Utility function to convert a bytearray into an integer.
78
Johnny Chend2765fc2011-03-02 20:54:22 +000079 It interprets the bytearray in the little endian format. For a big endian
80 bytearray, just do ba.reverse() on the object before passing it in.
Johnny Chen4c70f282011-03-02 01:36:45 +000081 """
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000082 import struct
Johnny Chen4c70f282011-03-02 01:36:45 +000083
84 if bytesize == 1:
85 return ba[0]
86
87 # Little endian followed by a format character.
88 template = "<%c"
89 if bytesize == 2:
90 fmt = template % 'h'
91 elif bytesize == 4:
92 fmt = template % 'i'
93 elif bytesize == 4:
94 fmt = template % 'q'
95 else:
96 return None
97
Johnny Chenf4c0d1d2011-03-30 17:54:35 +000098 unpacked = struct.unpack(fmt, str(bytes))
Johnny Chen4c70f282011-03-02 01:36:45 +000099 return unpacked[0]
100
101
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000102# ==============================================================
103# Get the description of an lldb object or None if not available
104# ==============================================================
Johnny Chenbdc36bd2011-04-25 20:23:05 +0000105def get_description(obj, option=None):
106 """Calls lldb_obj.GetDescription() and returns a string, or None.
107
Johnny Chenecd4feb2011-10-14 00:42:25 +0000108 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
109 option can be passed in to describe the detailed level of description
110 desired:
Johnny Chenbdc36bd2011-04-25 20:23:05 +0000111 o lldb.eDescriptionLevelBrief
112 o lldb.eDescriptionLevelFull
113 o lldb.eDescriptionLevelVerbose
114 """
115 method = getattr(obj, 'GetDescription')
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000116 if not method:
117 return None
Johnny Chenecd4feb2011-10-14 00:42:25 +0000118 tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
Johnny Chen8a0d8972011-09-27 21:27:19 +0000119 if isinstance(obj, tuple):
Johnny Chenbdc36bd2011-04-25 20:23:05 +0000120 if option is None:
121 option = lldb.eDescriptionLevelBrief
122
Johnny Chenbc1a93e2011-04-23 00:13:34 +0000123 stream = lldb.SBStream()
124 if option is None:
125 success = method(stream)
126 else:
127 success = method(stream, option)
128 if not success:
129 return None
130 return stream.GetData()
131
132
Johnny Chen168a61a2010-10-22 21:31:03 +0000133# =================================================
134# Convert some enum value to its string counterpart
135# =================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000136
Johnny Chen47342d52011-04-27 17:43:07 +0000137def state_type_to_str(enum):
Johnny Chenbe683bc2010-10-07 22:15:58 +0000138 """Returns the stateType string given an enum."""
139 if enum == lldb.eStateInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000140 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000141 elif enum == lldb.eStateUnloaded:
Johnny Chen59b84772010-10-18 15:46:54 +0000142 return "unloaded"
Johnny Chen42da4da2011-03-05 01:20:11 +0000143 elif enum == lldb.eStateConnected:
144 return "connected"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000145 elif enum == lldb.eStateAttaching:
Johnny Chen59b84772010-10-18 15:46:54 +0000146 return "attaching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000147 elif enum == lldb.eStateLaunching:
Johnny Chen59b84772010-10-18 15:46:54 +0000148 return "launching"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000149 elif enum == lldb.eStateStopped:
Johnny Chen59b84772010-10-18 15:46:54 +0000150 return "stopped"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000151 elif enum == lldb.eStateRunning:
Johnny Chen59b84772010-10-18 15:46:54 +0000152 return "running"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000153 elif enum == lldb.eStateStepping:
Johnny Chen59b84772010-10-18 15:46:54 +0000154 return "stepping"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000155 elif enum == lldb.eStateCrashed:
Johnny Chen59b84772010-10-18 15:46:54 +0000156 return "crashed"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000157 elif enum == lldb.eStateDetached:
Johnny Chen59b84772010-10-18 15:46:54 +0000158 return "detached"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000159 elif enum == lldb.eStateExited:
Johnny Chen59b84772010-10-18 15:46:54 +0000160 return "exited"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000161 elif enum == lldb.eStateSuspended:
Johnny Chen59b84772010-10-18 15:46:54 +0000162 return "suspended"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000163 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000164 raise Exception("Unknown StateType enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000165
Johnny Chen47342d52011-04-27 17:43:07 +0000166def stop_reason_to_str(enum):
Johnny Chenbe683bc2010-10-07 22:15:58 +0000167 """Returns the stopReason string given an enum."""
168 if enum == lldb.eStopReasonInvalid:
Johnny Chen59b84772010-10-18 15:46:54 +0000169 return "invalid"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000170 elif enum == lldb.eStopReasonNone:
Johnny Chen59b84772010-10-18 15:46:54 +0000171 return "none"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000172 elif enum == lldb.eStopReasonTrace:
Johnny Chen59b84772010-10-18 15:46:54 +0000173 return "trace"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000174 elif enum == lldb.eStopReasonBreakpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000175 return "breakpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000176 elif enum == lldb.eStopReasonWatchpoint:
Johnny Chen59b84772010-10-18 15:46:54 +0000177 return "watchpoint"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000178 elif enum == lldb.eStopReasonSignal:
Johnny Chen59b84772010-10-18 15:46:54 +0000179 return "signal"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000180 elif enum == lldb.eStopReasonException:
Johnny Chen59b84772010-10-18 15:46:54 +0000181 return "exception"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000182 elif enum == lldb.eStopReasonPlanComplete:
Johnny Chen59b84772010-10-18 15:46:54 +0000183 return "plancomplete"
Johnny Chenbe683bc2010-10-07 22:15:58 +0000184 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000185 raise Exception("Unknown StopReason enum")
Johnny Chenbe683bc2010-10-07 22:15:58 +0000186
Johnny Chene7082612011-09-28 00:51:00 +0000187def symbol_type_to_str(enum):
188 """Returns the symbolType string given an enum."""
189 if enum == lldb.eSymbolTypeInvalid:
190 return "invalid"
191 elif enum == lldb.eSymbolTypeAbsolute:
192 return "absolute"
Johnny Chene7082612011-09-28 00:51:00 +0000193 elif enum == lldb.eSymbolTypeCode:
194 return "code"
195 elif enum == lldb.eSymbolTypeData:
196 return "data"
197 elif enum == lldb.eSymbolTypeTrampoline:
198 return "trampoline"
199 elif enum == lldb.eSymbolTypeRuntime:
200 return "runtime"
201 elif enum == lldb.eSymbolTypeException:
202 return "exception"
203 elif enum == lldb.eSymbolTypeSourceFile:
204 return "sourcefile"
205 elif enum == lldb.eSymbolTypeHeaderFile:
206 return "headerfile"
207 elif enum == lldb.eSymbolTypeObjectFile:
208 return "objectfile"
209 elif enum == lldb.eSymbolTypeCommonBlock:
210 return "commonblock"
211 elif enum == lldb.eSymbolTypeBlock:
212 return "block"
213 elif enum == lldb.eSymbolTypeLocal:
214 return "local"
215 elif enum == lldb.eSymbolTypeParam:
216 return "param"
217 elif enum == lldb.eSymbolTypeVariable:
218 return "variable"
219 elif enum == lldb.eSymbolTypeVariableType:
220 return "variabletype"
221 elif enum == lldb.eSymbolTypeLineEntry:
222 return "lineentry"
223 elif enum == lldb.eSymbolTypeLineHeader:
224 return "lineheader"
225 elif enum == lldb.eSymbolTypeScopeBegin:
226 return "scopebegin"
227 elif enum == lldb.eSymbolTypeScopeEnd:
228 return "scopeend"
229 elif enum == lldb.eSymbolTypeAdditional:
230 return "additional"
231 elif enum == lldb.eSymbolTypeCompiler:
232 return "compiler"
233 elif enum == lldb.eSymbolTypeInstrumentation:
234 return "instrumentation"
235 elif enum == lldb.eSymbolTypeUndefined:
236 return "undefined"
237
Johnny Chen47342d52011-04-27 17:43:07 +0000238def value_type_to_str(enum):
Johnny Chen2c8d1592010-11-03 21:37:58 +0000239 """Returns the valueType string given an enum."""
240 if enum == lldb.eValueTypeInvalid:
241 return "invalid"
242 elif enum == lldb.eValueTypeVariableGlobal:
243 return "global_variable"
244 elif enum == lldb.eValueTypeVariableStatic:
245 return "static_variable"
246 elif enum == lldb.eValueTypeVariableArgument:
247 return "argument_variable"
248 elif enum == lldb.eValueTypeVariableLocal:
249 return "local_variable"
250 elif enum == lldb.eValueTypeRegister:
251 return "register"
252 elif enum == lldb.eValueTypeRegisterSet:
253 return "register_set"
254 elif enum == lldb.eValueTypeConstResult:
255 return "constant_result"
256 else:
Johnny Chen42da4da2011-03-05 01:20:11 +0000257 raise Exception("Unknown ValueType enum")
Johnny Chen2c8d1592010-11-03 21:37:58 +0000258
Johnny Chenbe683bc2010-10-07 22:15:58 +0000259
Johnny Chen168a61a2010-10-22 21:31:03 +0000260# ==================================================
261# Utility functions related to Threads and Processes
262# ==================================================
Johnny Chenbe683bc2010-10-07 22:15:58 +0000263
Johnny Chene428d332011-04-25 22:04:05 +0000264def get_stopped_threads(process, reason):
Johnny Chen5aba3f52011-05-26 21:53:05 +0000265 """Returns the thread(s) with the specified stop reason in a list.
266
267 The list can be empty if no such thread exists.
268 """
Johnny Chene428d332011-04-25 22:04:05 +0000269 threads = []
Johnny Chend643c082011-04-28 22:57:01 +0000270 for t in process:
Johnny Chene428d332011-04-25 22:04:05 +0000271 if t.GetStopReason() == reason:
272 threads.append(t)
273 return threads
274
275def get_stopped_thread(process, reason):
276 """A convenience function which returns the first thread with the given stop
277 reason or None.
278
279 Example usages:
280
281 1. Get the stopped thread due to a breakpoint condition
282
283 ...
284 from lldbutil import get_stopped_thread
Johnny Chen3d8ae462011-06-15 22:14:12 +0000285 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
Johnny Chene428d332011-04-25 22:04:05 +0000286 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition")
287 ...
288
289 2. Get the thread stopped due to a breakpoint
290
291 ...
292 from lldbutil import get_stopped_thread
Johnny Chen3d8ae462011-06-15 22:14:12 +0000293 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
Johnny Chene428d332011-04-25 22:04:05 +0000294 self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint")
295 ...
296
297 """
298 threads = get_stopped_threads(process, reason)
299 if len(threads) == 0:
300 return None
301 return threads[0]
302
Johnny Chen318aaa02011-04-25 23:38:13 +0000303def get_threads_stopped_at_breakpoint (process, bkpt):
304 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
305 stopped_threads = []
306 threads = []
307
308 stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
309
310 if len(stopped_threads) == 0:
311 return threads
312
313 for thread in stopped_threads:
Johnny Chenec954922011-12-22 20:21:46 +0000314 # Make sure we've hit our breakpoint...
Johnny Chen318aaa02011-04-25 23:38:13 +0000315 break_id = thread.GetStopReasonDataAtIndex (0)
316 if break_id == bkpt.GetID():
317 threads.append(thread)
318
319 return threads
320
321def continue_to_breakpoint (process, bkpt):
322 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
323 process.Continue()
324 if process.GetState() != lldb.eStateStopped:
325 return None
326 else:
327 return get_threads_stopped_at_breakpoint (process, bkpt)
328
Johnny Chen69af39d2011-03-09 23:45:56 +0000329def get_caller_symbol(thread):
330 """
331 Returns the symbol name for the call site of the leaf function.
332 """
333 depth = thread.GetNumFrames()
334 if depth <= 1:
335 return None
336 caller = thread.GetFrameAtIndex(1).GetSymbol()
337 if caller:
338 return caller.GetName()
339 else:
340 return None
341
342
Johnny Chen318aaa02011-04-25 23:38:13 +0000343def get_function_names(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000344 """
345 Returns a sequence of function names from the stack frames of this thread.
346 """
347 def GetFuncName(i):
Johnny Chen64abe462011-06-20 00:26:39 +0000348 return thread.GetFrameAtIndex(i).GetFunctionName()
Johnny Chen1605cf62010-09-08 22:54:46 +0000349
350 return map(GetFuncName, range(thread.GetNumFrames()))
351
352
Johnny Chen318aaa02011-04-25 23:38:13 +0000353def get_symbol_names(thread):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000354 """
355 Returns a sequence of symbols for this thread.
356 """
357 def GetSymbol(i):
358 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
359
360 return map(GetSymbol, range(thread.GetNumFrames()))
361
362
Johnny Chen318aaa02011-04-25 23:38:13 +0000363def get_pc_addresses(thread):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000364 """
365 Returns a sequence of pc addresses for this thread.
366 """
367 def GetPCAddress(i):
368 return thread.GetFrameAtIndex(i).GetPCAddress()
369
370 return map(GetPCAddress, range(thread.GetNumFrames()))
371
372
Johnny Chen318aaa02011-04-25 23:38:13 +0000373def get_filenames(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000374 """
375 Returns a sequence of file names from the stack frames of this thread.
376 """
377 def GetFilename(i):
378 return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
379
380 return map(GetFilename, range(thread.GetNumFrames()))
381
382
Johnny Chen318aaa02011-04-25 23:38:13 +0000383def get_line_numbers(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000384 """
385 Returns a sequence of line numbers from the stack frames of this thread.
386 """
387 def GetLineNumber(i):
388 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
389
390 return map(GetLineNumber, range(thread.GetNumFrames()))
391
392
Johnny Chen318aaa02011-04-25 23:38:13 +0000393def get_module_names(thread):
Johnny Chen1605cf62010-09-08 22:54:46 +0000394 """
395 Returns a sequence of module names from the stack frames of this thread.
396 """
397 def GetModuleName(i):
398 return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
399
400 return map(GetModuleName, range(thread.GetNumFrames()))
401
402
Johnny Chen318aaa02011-04-25 23:38:13 +0000403def get_stack_frames(thread):
Johnny Chen88866ac2010-09-09 00:55:07 +0000404 """
405 Returns a sequence of stack frames for this thread.
406 """
407 def GetStackFrame(i):
408 return thread.GetFrameAtIndex(i)
409
410 return map(GetStackFrame, range(thread.GetNumFrames()))
411
412
Johnny Chen318aaa02011-04-25 23:38:13 +0000413def print_stacktrace(thread, string_buffer = False):
Johnny Chen1605cf62010-09-08 22:54:46 +0000414 """Prints a simple stack trace of this thread."""
Johnny Chen30425e92010-10-07 18:52:48 +0000415
Johnny Chened5f04e2010-10-15 23:33:18 +0000416 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000417 target = thread.GetProcess().GetTarget()
418
Johnny Chen1605cf62010-09-08 22:54:46 +0000419 depth = thread.GetNumFrames()
420
Johnny Chen318aaa02011-04-25 23:38:13 +0000421 mods = get_module_names(thread)
422 funcs = get_function_names(thread)
423 symbols = get_symbol_names(thread)
424 files = get_filenames(thread)
425 lines = get_line_numbers(thread)
426 addrs = get_pc_addresses(thread)
Johnny Chen30425e92010-10-07 18:52:48 +0000427
Johnny Chenad5fd402010-10-25 19:13:52 +0000428 if thread.GetStopReason() != lldb.eStopReasonInvalid:
Johnny Chen47342d52011-04-27 17:43:07 +0000429 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
Johnny Chenad5fd402010-10-25 19:13:52 +0000430 else:
431 desc = ""
432 print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
433 thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
Johnny Chen1605cf62010-09-08 22:54:46 +0000434
Johnny Chenb51d87d2010-10-07 21:38:28 +0000435 for i in range(depth):
436 frame = thread.GetFrameAtIndex(i)
437 function = frame.GetFunction()
Johnny Chen1605cf62010-09-08 22:54:46 +0000438
Johnny Chenb51d87d2010-10-07 21:38:28 +0000439 load_addr = addrs[i].GetLoadAddress(target)
Johnny Chen960ce122011-05-25 19:06:18 +0000440 if not function:
Johnny Chenb51d87d2010-10-07 21:38:28 +0000441 file_addr = addrs[i].GetFileAddress()
Johnny Chen49f3d812011-06-16 22:07:48 +0000442 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
443 symbol_offset = file_addr - start_addr
444 print >> output, " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
445 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset)
Johnny Chenb51d87d2010-10-07 21:38:28 +0000446 else:
Johnny Chen49f3d812011-06-16 22:07:48 +0000447 print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
Johnny Chen64abe462011-06-20 00:26:39 +0000448 num=i, addr=load_addr, mod=mods[i],
449 func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i],
Johnny Chen7d4c7fe2011-07-13 22:34:29 +0000450 file=files[i], line=lines[i],
451 args=get_args_as_string(frame, showFuncName=False) if not frame.IsInlined() else '()')
Johnny Chenb51d87d2010-10-07 21:38:28 +0000452
453 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000454 return output.getvalue()
Johnny Chenb51d87d2010-10-07 21:38:28 +0000455
456
Johnny Chen318aaa02011-04-25 23:38:13 +0000457def print_stacktraces(process, string_buffer = False):
Johnny Chenb51d87d2010-10-07 21:38:28 +0000458 """Prints the stack traces of all the threads."""
459
Johnny Chened5f04e2010-10-15 23:33:18 +0000460 output = StringIO.StringIO() if string_buffer else sys.stdout
Johnny Chenb51d87d2010-10-07 21:38:28 +0000461
462 print >> output, "Stack traces for " + repr(process)
463
Johnny Chen311b1d62011-05-05 18:50:56 +0000464 for thread in process:
465 print >> output, print_stacktrace(thread, string_buffer=True)
Johnny Chen30425e92010-10-07 18:52:48 +0000466
467 if string_buffer:
Johnny Chened5f04e2010-10-15 23:33:18 +0000468 return output.getvalue()
Johnny Chen185e2c12011-05-08 17:25:27 +0000469
470# ===================================
471# Utility functions related to Frames
472# ===================================
473
Johnny Chenabb3b2d2011-05-12 00:32:41 +0000474def get_parent_frame(frame):
475 """
476 Returns the parent frame of the input frame object; None if not available.
477 """
478 thread = frame.GetThread()
479 parent_found = False
480 for f in thread:
481 if parent_found:
482 return f
483 if f.GetFrameID() == frame.GetFrameID():
484 parent_found = True
485
486 # If we reach here, no parent has been found, return None.
487 return None
488
Johnny Chen49f3d812011-06-16 22:07:48 +0000489def get_args_as_string(frame, showFuncName=True):
Johnny Chenabb3b2d2011-05-12 00:32:41 +0000490 """
491 Returns the args of the input frame object as a string.
492 """
493 # arguments => True
494 # locals => False
495 # statics => False
496 # in_scope_only => True
497 vars = frame.GetVariables(True, False, False, True) # type of SBValueList
498 args = [] # list of strings
499 for var in vars:
500 args.append("(%s)%s=%s" % (var.GetTypeName(),
501 var.GetName(),
Greg Clayton0fb0bcc2011-08-03 22:57:10 +0000502 var.GetValue()))
Johnny Chen960ce122011-05-25 19:06:18 +0000503 if frame.GetFunction():
Johnny Chenbbc18b62011-05-13 00:44:49 +0000504 name = frame.GetFunction().GetName()
Johnny Chen960ce122011-05-25 19:06:18 +0000505 elif frame.GetSymbol():
Johnny Chenbbc18b62011-05-13 00:44:49 +0000506 name = frame.GetSymbol().GetName()
507 else:
508 name = ""
Johnny Chen49f3d812011-06-16 22:07:48 +0000509 if showFuncName:
510 return "%s(%s)" % (name, ", ".join(args))
511 else:
512 return "(%s)" % (", ".join(args))
513
Johnny Chen185e2c12011-05-08 17:25:27 +0000514def print_registers(frame, string_buffer = False):
Johnny Chenb2998772011-05-08 18:55:37 +0000515 """Prints all the register sets of the frame."""
Johnny Chen185e2c12011-05-08 17:25:27 +0000516
517 output = StringIO.StringIO() if string_buffer else sys.stdout
518
519 print >> output, "Register sets for " + repr(frame)
520
Johnny Chen728255b2011-05-10 19:21:13 +0000521 registerSet = frame.GetRegisters() # Return type of SBValueList.
522 print >> output, "Frame registers (size of register set = %d):" % registerSet.GetSize()
523 for value in registerSet:
Johnny Chen185e2c12011-05-08 17:25:27 +0000524 #print >> output, value
525 print >> output, "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
526 for child in value:
Greg Clayton0fb0bcc2011-08-03 22:57:10 +0000527 print >> output, "Name: %s, Value: %s" % (child.GetName(), child.GetValue())
Johnny Chen185e2c12011-05-08 17:25:27 +0000528
529 if string_buffer:
530 return output.getvalue()
Johnny Chen728255b2011-05-10 19:21:13 +0000531
532def get_registers(frame, kind):
533 """Returns the registers given the frame and the kind of registers desired.
534
535 Returns None if there's no such kind.
536 """
537 registerSet = frame.GetRegisters() # Return type of SBValueList.
538 for value in registerSet:
539 if kind.lower() in value.GetName().lower():
540 return value
541
542 return None
543
544def get_GPRs(frame):
545 """Returns the general purpose registers of the frame as an SBValue.
546
Johnny Chenfd1175c2011-05-10 23:01:44 +0000547 The returned SBValue object is iterable. An example:
548 ...
549 from lldbutil import get_GPRs
550 regs = get_GPRs(frame)
551 for reg in regs:
552 print "%s => %s" % (reg.GetName(), reg.GetValue())
553 ...
Johnny Chen728255b2011-05-10 19:21:13 +0000554 """
555 return get_registers(frame, "general purpose")
556
557def get_FPRs(frame):
558 """Returns the floating point registers of the frame as an SBValue.
559
Johnny Chenfd1175c2011-05-10 23:01:44 +0000560 The returned SBValue object is iterable. An example:
561 ...
562 from lldbutil import get_FPRs
563 regs = get_FPRs(frame)
564 for reg in regs:
565 print "%s => %s" % (reg.GetName(), reg.GetValue())
566 ...
Johnny Chen728255b2011-05-10 19:21:13 +0000567 """
568 return get_registers(frame, "floating point")
569
570def get_ESRs(frame):
571 """Returns the exception state registers of the frame as an SBValue.
572
Johnny Chenfd1175c2011-05-10 23:01:44 +0000573 The returned SBValue object is iterable. An example:
574 ...
575 from lldbutil import get_ESRs
576 regs = get_ESRs(frame)
577 for reg in regs:
578 print "%s => %s" % (reg.GetName(), reg.GetValue())
579 ...
Johnny Chen728255b2011-05-10 19:21:13 +0000580 """
581 return get_registers(frame, "exception state")
Johnny Chen084fd892011-07-22 00:47:58 +0000582
Johnny Chen8c062762011-07-22 00:51:54 +0000583# ======================================
584# Utility classes/functions for SBValues
585# ======================================
Johnny Chen084fd892011-07-22 00:47:58 +0000586
587class BasicFormatter(object):
Johnny Chen638ebcf2011-07-22 22:01:35 +0000588 """The basic formatter inspects the value object and prints the value."""
Johnny Chen084fd892011-07-22 00:47:58 +0000589 def format(self, value, buffer=None, indent=0):
590 if not buffer:
591 output = StringIO.StringIO()
592 else:
593 output = buffer
Johnny Chen638ebcf2011-07-22 22:01:35 +0000594 # If there is a summary, it suffices.
595 val = value.GetSummary()
596 # Otherwise, get the value.
597 if val == None:
598 val = value.GetValue()
599 if val == None and value.GetNumChildren() > 0:
600 val = "%s (location)" % value.GetLocation()
601 print >> output, "{indentation}({type}) {name} = {value}".format(
Johnny Chen084fd892011-07-22 00:47:58 +0000602 indentation = ' ' * indent,
603 type = value.GetTypeName(),
604 name = value.GetName(),
Johnny Chen638ebcf2011-07-22 22:01:35 +0000605 value = val)
Johnny Chen084fd892011-07-22 00:47:58 +0000606 return output.getvalue()
607
608class ChildVisitingFormatter(BasicFormatter):
Johnny Chen638ebcf2011-07-22 22:01:35 +0000609 """The child visiting formatter prints the value and its immediate children.
610
611 The constructor takes a keyword arg: indent_child, which defaults to 2.
612 """
613 def __init__(self, indent_child=2):
614 """Default indentation of 2 SPC's for the children."""
615 self.cindent = indent_child
Johnny Chen084fd892011-07-22 00:47:58 +0000616 def format(self, value, buffer=None):
617 if not buffer:
618 output = StringIO.StringIO()
619 else:
620 output = buffer
621
622 BasicFormatter.format(self, value, buffer=output)
623 for child in value:
Johnny Chen638ebcf2011-07-22 22:01:35 +0000624 BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
625
626 return output.getvalue()
627
628class RecursiveDecentFormatter(BasicFormatter):
629 """The recursive decent formatter prints the value and the decendents.
630
631 The constructor takes two keyword args: indent_level, which defaults to 0,
632 and indent_child, which defaults to 2. The current indentation level is
633 determined by indent_level, while the immediate children has an additional
634 indentation by inden_child.
635 """
636 def __init__(self, indent_level=0, indent_child=2):
637 self.lindent = indent_level
638 self.cindent = indent_child
639 def format(self, value, buffer=None):
640 if not buffer:
641 output = StringIO.StringIO()
642 else:
643 output = buffer
644
645 BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
646 new_indent = self.lindent + self.cindent
647 for child in value:
648 if child.GetSummary() != None:
649 BasicFormatter.format(self, child, buffer=output, indent=new_indent)
650 else:
651 if child.GetNumChildren() > 0:
652 rdf = RecursiveDecentFormatter(indent_level=new_indent)
653 rdf.format(child, buffer=output)
654 else:
655 BasicFormatter.format(self, child, buffer=output, indent=new_indent)
Johnny Chen084fd892011-07-22 00:47:58 +0000656
657 return output.getvalue()