]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - utils/lui/lldbutil.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / utils / lui / lldbutil.py
1 ##===-- lldbutil.py ------------------------------------------*- Python -*-===##
2 ##
3 ##                     The LLVM Compiler Infrastructure
4 ##
5 ## This file is distributed under the University of Illinois Open Source
6 ## License. See LICENSE.TXT for details.
7 ##
8 ##===----------------------------------------------------------------------===##
9
10 """
11 This LLDB module contains miscellaneous utilities.
12 Some of the test suite takes advantage of the utility functions defined here.
13 They can also be useful for general purpose lldb scripting.
14 """
15
16 import lldb
17 import os, sys
18 import StringIO
19
20 # ===================================================
21 # Utilities for locating/checking executable programs
22 # ===================================================
23
24 def is_exe(fpath):
25     """Returns True if fpath is an executable."""
26     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
27
28 def which(program):
29     """Returns the full path to a program; None otherwise."""
30     fpath, fname = os.path.split(program)
31     if fpath:
32         if is_exe(program):
33             return program
34     else:
35         for path in os.environ["PATH"].split(os.pathsep):
36             exe_file = os.path.join(path, program)
37             if is_exe(exe_file):
38                 return exe_file
39     return None
40
41 # ===================================================
42 # Disassembly for an SBFunction or an SBSymbol object
43 # ===================================================
44
45 def disassemble(target, function_or_symbol):
46     """Disassemble the function or symbol given a target.
47
48     It returns the disassembly content in a string object.
49     """
50     buf = StringIO.StringIO()
51     insts = function_or_symbol.GetInstructions(target)
52     for i in insts:
53         print >> buf, i
54     return buf.getvalue()
55
56 # ==========================================================
57 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
58 # ==========================================================
59
60 def int_to_bytearray(val, bytesize):
61     """Utility function to convert an integer into a bytearray.
62
63     It returns the bytearray in the little endian format.  It is easy to get the
64     big endian format, just do ba.reverse() on the returned object.
65     """
66     import struct
67
68     if bytesize == 1:
69         return bytearray([val])
70
71     # Little endian followed by a format character.
72     template = "<%c"
73     if bytesize == 2:
74         fmt = template % 'h'
75     elif bytesize == 4:
76         fmt = template % 'i'
77     elif bytesize == 4:
78         fmt = template % 'q'
79     else:
80         return None
81
82     packed = struct.pack(fmt, val)
83     return bytearray(map(ord, packed))
84
85 def bytearray_to_int(bytes, bytesize):
86     """Utility function to convert a bytearray into an integer.
87
88     It interprets the bytearray in the little endian format. For a big endian
89     bytearray, just do ba.reverse() on the object before passing it in.
90     """
91     import struct
92
93     if bytesize == 1:
94         return bytes[0]
95
96     # Little endian followed by a format character.
97     template = "<%c"
98     if bytesize == 2:
99         fmt = template % 'h'
100     elif bytesize == 4:
101         fmt = template % 'i'
102     elif bytesize == 4:
103         fmt = template % 'q'
104     else:
105         return None
106
107     unpacked = struct.unpack(fmt, str(bytes))
108     return unpacked[0]
109
110
111 # ==============================================================
112 # Get the description of an lldb object or None if not available
113 # ==============================================================
114 def get_description(obj, option=None):
115     """Calls lldb_obj.GetDescription() and returns a string, or None.
116
117     For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
118     option can be passed in to describe the detailed level of description
119     desired:
120         o lldb.eDescriptionLevelBrief
121         o lldb.eDescriptionLevelFull
122         o lldb.eDescriptionLevelVerbose
123     """
124     method = getattr(obj, 'GetDescription')
125     if not method:
126         return None
127     tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
128     if isinstance(obj, tuple):
129         if option is None:
130             option = lldb.eDescriptionLevelBrief
131
132     stream = lldb.SBStream()
133     if option is None:
134         success = method(stream)
135     else:
136         success = method(stream, option)
137     if not success:
138         return None
139     return stream.GetData()
140         
141
142 # =================================================
143 # Convert some enum value to its string counterpart
144 # =================================================
145
146 def state_type_to_str(enum):
147     """Returns the stateType string given an enum."""
148     if enum == lldb.eStateInvalid:
149         return "invalid"
150     elif enum == lldb.eStateUnloaded:
151         return "unloaded"
152     elif enum == lldb.eStateConnected:
153         return "connected"
154     elif enum == lldb.eStateAttaching:
155         return "attaching"
156     elif enum == lldb.eStateLaunching:
157         return "launching"
158     elif enum == lldb.eStateStopped:
159         return "stopped"
160     elif enum == lldb.eStateRunning:
161         return "running"
162     elif enum == lldb.eStateStepping:
163         return "stepping"
164     elif enum == lldb.eStateCrashed:
165         return "crashed"
166     elif enum == lldb.eStateDetached:
167         return "detached"
168     elif enum == lldb.eStateExited:
169         return "exited"
170     elif enum == lldb.eStateSuspended:
171         return "suspended"
172     else:
173         raise Exception("Unknown StateType enum")
174
175 def stop_reason_to_str(enum):
176     """Returns the stopReason string given an enum."""
177     if enum == lldb.eStopReasonInvalid:
178         return "invalid"
179     elif enum == lldb.eStopReasonNone:
180         return "none"
181     elif enum == lldb.eStopReasonTrace:
182         return "trace"
183     elif enum == lldb.eStopReasonBreakpoint:
184         return "breakpoint"
185     elif enum == lldb.eStopReasonWatchpoint:
186         return "watchpoint"
187     elif enum == lldb.eStopReasonSignal:
188         return "signal"
189     elif enum == lldb.eStopReasonException:
190         return "exception"
191     elif enum == lldb.eStopReasonPlanComplete:
192         return "plancomplete"
193     elif enum == lldb.eStopReasonThreadExiting:
194         return "threadexiting"
195     else:
196         raise Exception("Unknown StopReason enum")
197
198 def symbol_type_to_str(enum):
199     """Returns the symbolType string given an enum."""
200     if enum == lldb.eSymbolTypeInvalid:
201         return "invalid"
202     elif enum == lldb.eSymbolTypeAbsolute:
203         return "absolute"
204     elif enum == lldb.eSymbolTypeCode:
205         return "code"
206     elif enum == lldb.eSymbolTypeData:
207         return "data"
208     elif enum == lldb.eSymbolTypeTrampoline:
209         return "trampoline"
210     elif enum == lldb.eSymbolTypeRuntime:
211         return "runtime"
212     elif enum == lldb.eSymbolTypeException:
213         return "exception"
214     elif enum == lldb.eSymbolTypeSourceFile:
215         return "sourcefile"
216     elif enum == lldb.eSymbolTypeHeaderFile:
217         return "headerfile"
218     elif enum == lldb.eSymbolTypeObjectFile:
219         return "objectfile"
220     elif enum == lldb.eSymbolTypeCommonBlock:
221         return "commonblock"
222     elif enum == lldb.eSymbolTypeBlock:
223         return "block"
224     elif enum == lldb.eSymbolTypeLocal:
225         return "local"
226     elif enum == lldb.eSymbolTypeParam:
227         return "param"
228     elif enum == lldb.eSymbolTypeVariable:
229         return "variable"
230     elif enum == lldb.eSymbolTypeVariableType:
231         return "variabletype"
232     elif enum == lldb.eSymbolTypeLineEntry:
233         return "lineentry"
234     elif enum == lldb.eSymbolTypeLineHeader:
235         return "lineheader"
236     elif enum == lldb.eSymbolTypeScopeBegin:
237         return "scopebegin"
238     elif enum == lldb.eSymbolTypeScopeEnd:
239         return "scopeend"
240     elif enum == lldb.eSymbolTypeAdditional:
241         return "additional"
242     elif enum == lldb.eSymbolTypeCompiler:
243         return "compiler"
244     elif enum == lldb.eSymbolTypeInstrumentation:
245         return "instrumentation"
246     elif enum == lldb.eSymbolTypeUndefined:
247         return "undefined"
248
249 def value_type_to_str(enum):
250     """Returns the valueType string given an enum."""
251     if enum == lldb.eValueTypeInvalid:
252         return "invalid"
253     elif enum == lldb.eValueTypeVariableGlobal:
254         return "global_variable"
255     elif enum == lldb.eValueTypeVariableStatic:
256         return "static_variable"
257     elif enum == lldb.eValueTypeVariableArgument:
258         return "argument_variable"
259     elif enum == lldb.eValueTypeVariableLocal:
260         return "local_variable"
261     elif enum == lldb.eValueTypeRegister:
262         return "register"
263     elif enum == lldb.eValueTypeRegisterSet:
264         return "register_set"
265     elif enum == lldb.eValueTypeConstResult:
266         return "constant_result"
267     else:
268         raise Exception("Unknown ValueType enum")
269
270
271 # ==================================================
272 # Get stopped threads due to each stop reason.
273 # ==================================================
274
275 def sort_stopped_threads(process,
276                          breakpoint_threads = None,
277                          crashed_threads = None,
278                          watchpoint_threads = None,
279                          signal_threads = None,
280                          exiting_threads = None,
281                          other_threads = None):
282     """ Fills array *_threads with threads stopped for the corresponding stop
283         reason.
284     """
285     for lst in [breakpoint_threads,
286                 watchpoint_threads,
287                 signal_threads,
288                 exiting_threads,
289                 other_threads]:
290         if lst is not None:
291             lst[:] = []
292
293     for thread in process:
294         dispatched = False
295         for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
296                                (lldb.eStopReasonException, crashed_threads),
297                                (lldb.eStopReasonWatchpoint, watchpoint_threads),
298                                (lldb.eStopReasonSignal, signal_threads),
299                                (lldb.eStopReasonThreadExiting, exiting_threads),
300                                (None, other_threads)]:
301             if not dispatched and list is not None:
302                 if thread.GetStopReason() == reason or reason is None:
303                     list.append(thread)
304                     dispatched = True
305
306 # ==================================================
307 # Utility functions for setting breakpoints
308 # ==================================================
309
310 def run_break_set_by_file_and_line (test, file_name, line_number, extra_options = None, num_expected_locations = 1, loc_exact=False, module_name=None):
311     """Set a breakpoint by file and line, returning the breakpoint number. 
312
313     If extra_options is not None, then we append it to the breakpoint set command.
314
315     If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations.
316
317     If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
318
319     if file_name == None:
320         command = 'breakpoint set -l %d'%(line_number)
321     else:
322         command = 'breakpoint set -f "%s" -l %d'%(file_name, line_number)
323
324     if module_name:
325         command += " --shlib '%s'" % (module_name)
326
327     if extra_options:
328         command += " " + extra_options
329
330     break_results = run_break_set_command (test, command)
331
332     if num_expected_locations == 1 and loc_exact:
333         check_breakpoint_result (test, break_results, num_locations=num_expected_locations, file_name = file_name, line_number = line_number, module_name=module_name)
334     else:
335         check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
336
337     return get_bpno_from_match (break_results)
338
339 def run_break_set_by_symbol (test, symbol, extra_options = None, num_expected_locations = -1, sym_exact = False, module_name=None):
340     """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
341
342     If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
343     command = 'breakpoint set -n "%s"'%(symbol)
344
345     if module_name:
346         command += " --shlib '%s'" % (module_name)
347
348     if extra_options:
349         command += " " + extra_options
350
351     break_results = run_break_set_command (test, command)
352
353     if num_expected_locations == 1 and sym_exact:
354         check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = symbol, module_name=module_name)
355     else:
356         check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
357
358     return get_bpno_from_match (break_results)
359
360 def run_break_set_by_selector (test, selector, extra_options = None, num_expected_locations = -1, module_name=None):
361     """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
362
363     command = 'breakpoint set -S "%s"' % (selector)
364
365     if module_name:
366         command += ' --shlib "%s"' % (module_name)
367
368     if extra_options:
369         command += " " + extra_options
370
371     break_results = run_break_set_command (test, command)
372
373     if num_expected_locations == 1:
374         check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = selector, symbol_match_exact=False, module_name=module_name)
375     else:
376         check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
377
378     return get_bpno_from_match (break_results)
379
380 def run_break_set_by_regexp (test, regexp, extra_options=None, num_expected_locations=-1):
381     """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
382
383     command = 'breakpoint set -r "%s"'%(regexp)
384     if extra_options:
385         command += " " + extra_options
386     
387     break_results = run_break_set_command (test, command)
388     
389     check_breakpoint_result (test, break_results, num_locations=num_expected_locations)
390
391     return get_bpno_from_match (break_results)
392
393 def run_break_set_by_source_regexp (test, regexp, extra_options=None, num_expected_locations=-1):
394     """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
395     command = 'breakpoint set -p "%s"'%(regexp)
396     if extra_options:
397         command += " " + extra_options
398     
399     break_results = run_break_set_command (test, command)
400     
401     check_breakpoint_result (test, break_results, num_locations=num_expected_locations)
402
403     return get_bpno_from_match (break_results)
404
405 def run_break_set_command (test, command):
406     """Run the command passed in - it must be some break set variant - and analyze the result.  
407     Returns a dictionary of information gleaned from the command-line results.
408     Will assert if the breakpoint setting fails altogether.
409
410     Dictionary will contain:
411         bpno          - breakpoint of the newly created breakpoint, -1 on error.
412         num_locations - number of locations set for the breakpoint.
413
414     If there is only one location, the dictionary MAY contain:
415         file          - source file name
416         line_no       - source line number
417         symbol        - symbol name
418         inline_symbol - inlined symbol name
419         offset        - offset from the original symbol
420         module        - module
421         address       - address at which the breakpoint was set."""
422
423     patterns = [r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
424                 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
425                 r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
426                 r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
427     match_object = test.match (command, patterns)
428     break_results = match_object.groupdict()
429
430     # We always insert the breakpoint number, setting it to -1 if we couldn't find it
431     # Also, make sure it gets stored as an integer.
432     if not 'bpno' in break_results:
433         break_results['bpno'] = -1
434     else:
435         break_results['bpno'] = int(break_results['bpno'])
436         
437     # We always insert the number of locations
438     # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
439     # We also make sure it is an integer.
440
441     if not 'num_locations' in break_results:
442         num_locations = 1
443     else:
444         num_locations = break_results['num_locations']
445         if num_locations == 'no':
446             num_locations = 0
447         else:
448             num_locations = int(break_results['num_locations'])
449
450     break_results['num_locations'] = num_locations
451     
452     if 'line_no' in break_results:
453         break_results['line_no'] = int(break_results['line_no'])
454
455     return break_results
456
457 def get_bpno_from_match (break_results):
458     return int (break_results['bpno'])
459
460 def check_breakpoint_result (test, break_results, file_name=None, line_number=-1, symbol_name=None, symbol_match_exact=True, module_name=None, offset=-1, num_locations=-1):
461
462     out_num_locations = break_results['num_locations']
463
464     if num_locations == -1:
465         test.assertTrue (out_num_locations > 0, "Expecting one or more locations, got none.")
466     else:
467         test.assertTrue (num_locations == out_num_locations, "Expecting %d locations, got %d."%(num_locations, out_num_locations))
468
469     if file_name:
470         out_file_name = ""
471         if 'file' in break_results:
472             out_file_name = break_results['file']
473         test.assertTrue (file_name == out_file_name, "Breakpoint file name '%s' doesn't match resultant name '%s'."%(file_name, out_file_name))
474
475     if line_number != -1:
476         out_file_line = -1
477         if 'line_no' in break_results:
478             out_line_number = break_results['line_no']
479
480         test.assertTrue (line_number == out_line_number, "Breakpoint line number %s doesn't match resultant line %s."%(line_number, out_line_number))
481
482     if symbol_name:
483         out_symbol_name = ""
484         # Look first for the inlined symbol name, otherwise use the symbol name:
485         if 'inline_symbol' in break_results and break_results['inline_symbol']:
486             out_symbol_name = break_results['inline_symbol']
487         elif 'symbol' in break_results:
488             out_symbol_name = break_results['symbol']
489
490         if symbol_match_exact:
491             test.assertTrue(symbol_name == out_symbol_name, "Symbol name '%s' doesn't match resultant symbol '%s'."%(symbol_name, out_symbol_name))
492         else:
493             test.assertTrue(out_symbol_name.find(symbol_name) != -1, "Symbol name '%s' isn't in resultant symbol '%s'."%(symbol_name, out_symbol_name))
494
495     if module_name:
496         out_nodule_name = None
497         if 'module' in break_results:
498             out_module_name = break_results['module']
499         
500         test.assertTrue (module_name.find(out_module_name) != -1, "Symbol module name '%s' isn't in expected module name '%s'."%(out_module_name, module_name))
501
502 # ==================================================
503 # Utility functions related to Threads and Processes
504 # ==================================================
505
506 def get_stopped_threads(process, reason):
507     """Returns the thread(s) with the specified stop reason in a list.
508
509     The list can be empty if no such thread exists.
510     """
511     threads = []
512     for t in process:
513         if t.GetStopReason() == reason:
514             threads.append(t)
515     return threads
516
517 def get_stopped_thread(process, reason):
518     """A convenience function which returns the first thread with the given stop
519     reason or None.
520
521     Example usages:
522
523     1. Get the stopped thread due to a breakpoint condition
524
525     ...
526         from lldbutil import get_stopped_thread
527         thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
528         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
529     ...
530
531     2. Get the thread stopped due to a breakpoint
532
533     ...
534         from lldbutil import get_stopped_thread
535         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
536         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
537     ...
538
539     """
540     threads = get_stopped_threads(process, reason)
541     if len(threads) == 0:
542         return None
543     return threads[0]
544
545 def get_threads_stopped_at_breakpoint (process, bkpt):
546     """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
547     stopped_threads = []
548     threads = []
549
550     stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
551
552     if len(stopped_threads) == 0:
553         return threads
554     
555     for thread in stopped_threads:
556         # Make sure we've hit our breakpoint...
557         break_id = thread.GetStopReasonDataAtIndex (0)
558         if break_id == bkpt.GetID():
559             threads.append(thread)
560
561     return threads
562
563 def continue_to_breakpoint (process, bkpt):
564     """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
565     process.Continue()
566     if process.GetState() != lldb.eStateStopped:
567         return None
568     else:
569         return get_threads_stopped_at_breakpoint (process, bkpt)
570
571 def get_caller_symbol(thread):
572     """
573     Returns the symbol name for the call site of the leaf function.
574     """
575     depth = thread.GetNumFrames()
576     if depth <= 1:
577         return None
578     caller = thread.GetFrameAtIndex(1).GetSymbol()
579     if caller:
580         return caller.GetName()
581     else:
582         return None
583
584
585 def get_function_names(thread):
586     """
587     Returns a sequence of function names from the stack frames of this thread.
588     """
589     def GetFuncName(i):
590         return thread.GetFrameAtIndex(i).GetFunctionName()
591
592     return map(GetFuncName, range(thread.GetNumFrames()))
593
594
595 def get_symbol_names(thread):
596     """
597     Returns a sequence of symbols for this thread.
598     """
599     def GetSymbol(i):
600         return thread.GetFrameAtIndex(i).GetSymbol().GetName()
601
602     return map(GetSymbol, range(thread.GetNumFrames()))
603
604
605 def get_pc_addresses(thread):
606     """
607     Returns a sequence of pc addresses for this thread.
608     """
609     def GetPCAddress(i):
610         return thread.GetFrameAtIndex(i).GetPCAddress()
611
612     return map(GetPCAddress, range(thread.GetNumFrames()))
613
614
615 def get_filenames(thread):
616     """
617     Returns a sequence of file names from the stack frames of this thread.
618     """
619     def GetFilename(i):
620         return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
621
622     return map(GetFilename, range(thread.GetNumFrames()))
623
624
625 def get_line_numbers(thread):
626     """
627     Returns a sequence of line numbers from the stack frames of this thread.
628     """
629     def GetLineNumber(i):
630         return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
631
632     return map(GetLineNumber, range(thread.GetNumFrames()))
633
634
635 def get_module_names(thread):
636     """
637     Returns a sequence of module names from the stack frames of this thread.
638     """
639     def GetModuleName(i):
640         return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
641
642     return map(GetModuleName, range(thread.GetNumFrames()))
643
644
645 def get_stack_frames(thread):
646     """
647     Returns a sequence of stack frames for this thread.
648     """
649     def GetStackFrame(i):
650         return thread.GetFrameAtIndex(i)
651
652     return map(GetStackFrame, range(thread.GetNumFrames()))
653
654
655 def print_stacktrace(thread, string_buffer = False):
656     """Prints a simple stack trace of this thread."""
657
658     output = StringIO.StringIO() if string_buffer else sys.stdout
659     target = thread.GetProcess().GetTarget()
660
661     depth = thread.GetNumFrames()
662
663     mods = get_module_names(thread)
664     funcs = get_function_names(thread)
665     symbols = get_symbol_names(thread)
666     files = get_filenames(thread)
667     lines = get_line_numbers(thread)
668     addrs = get_pc_addresses(thread)
669
670     if thread.GetStopReason() != lldb.eStopReasonInvalid:
671         desc =  "stop reason=" + stop_reason_to_str(thread.GetStopReason())
672     else:
673         desc = ""
674     print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
675         thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
676
677     for i in range(depth):
678         frame = thread.GetFrameAtIndex(i)
679         function = frame.GetFunction()
680
681         load_addr = addrs[i].GetLoadAddress(target)
682         if not function:
683             file_addr = addrs[i].GetFileAddress()
684             start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
685             symbol_offset = file_addr - start_addr
686             print >> output, "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
687                 num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset)
688         else:
689             print >> output, "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
690                 num=i, addr=load_addr, mod=mods[i],
691                 func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i],
692                 file=files[i], line=lines[i],
693                 args=get_args_as_string(frame, showFuncName=False) if not frame.IsInlined() else '()')
694
695     if string_buffer:
696         return output.getvalue()
697
698
699 def print_stacktraces(process, string_buffer = False):
700     """Prints the stack traces of all the threads."""
701
702     output = StringIO.StringIO() if string_buffer else sys.stdout
703
704     print >> output, "Stack traces for " + str(process)
705
706     for thread in process:
707         print >> output, print_stacktrace(thread, string_buffer=True)
708
709     if string_buffer:
710         return output.getvalue()
711
712 # ===================================
713 # Utility functions related to Frames
714 # ===================================
715
716 def get_parent_frame(frame):
717     """
718     Returns the parent frame of the input frame object; None if not available.
719     """
720     thread = frame.GetThread()
721     parent_found = False
722     for f in thread:
723         if parent_found:
724             return f
725         if f.GetFrameID() == frame.GetFrameID():
726             parent_found = True
727
728     # If we reach here, no parent has been found, return None.
729     return None
730
731 def get_args_as_string(frame, showFuncName=True):
732     """
733     Returns the args of the input frame object as a string.
734     """
735     # arguments     => True
736     # locals        => False
737     # statics       => False
738     # in_scope_only => True
739     vars = frame.GetVariables(True, False, False, True) # type of SBValueList
740     args = [] # list of strings
741     for var in vars:
742         args.append("(%s)%s=%s" % (var.GetTypeName(),
743                                    var.GetName(),
744                                    var.GetValue()))
745     if frame.GetFunction():
746         name = frame.GetFunction().GetName()
747     elif frame.GetSymbol():
748         name = frame.GetSymbol().GetName()
749     else:
750         name = ""
751     if showFuncName:
752         return "%s(%s)" % (name, ", ".join(args))
753     else:
754         return "(%s)" % (", ".join(args))
755         
756 def print_registers(frame, string_buffer = False):
757     """Prints all the register sets of the frame."""
758
759     output = StringIO.StringIO() if string_buffer else sys.stdout
760
761     print >> output, "Register sets for " + str(frame)
762
763     registerSet = frame.GetRegisters() # Return type of SBValueList.
764     print >> output, "Frame registers (size of register set = %d):" % registerSet.GetSize()
765     for value in registerSet:
766         #print >> output, value 
767         print >> output, "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
768         for child in value:
769             print >> output, "Name: %s, Value: %s" % (child.GetName(), child.GetValue())
770
771     if string_buffer:
772         return output.getvalue()
773
774 def get_registers(frame, kind):
775     """Returns the registers given the frame and the kind of registers desired.
776
777     Returns None if there's no such kind.
778     """
779     registerSet = frame.GetRegisters() # Return type of SBValueList.
780     for value in registerSet:
781         if kind.lower() in value.GetName().lower():
782             return value
783
784     return None
785
786 def get_GPRs(frame):
787     """Returns the general purpose registers of the frame as an SBValue.
788
789     The returned SBValue object is iterable.  An example:
790         ...
791         from lldbutil import get_GPRs
792         regs = get_GPRs(frame)
793         for reg in regs:
794             print "%s => %s" % (reg.GetName(), reg.GetValue())
795         ...
796     """
797     return get_registers(frame, "general purpose")
798
799 def get_FPRs(frame):
800     """Returns the floating point registers of the frame as an SBValue.
801
802     The returned SBValue object is iterable.  An example:
803         ...
804         from lldbutil import get_FPRs
805         regs = get_FPRs(frame)
806         for reg in regs:
807             print "%s => %s" % (reg.GetName(), reg.GetValue())
808         ...
809     """
810     return get_registers(frame, "floating point")
811
812 def get_ESRs(frame):
813     """Returns the exception state registers of the frame as an SBValue.
814
815     The returned SBValue object is iterable.  An example:
816         ...
817         from lldbutil import get_ESRs
818         regs = get_ESRs(frame)
819         for reg in regs:
820             print "%s => %s" % (reg.GetName(), reg.GetValue())
821         ...
822     """
823     return get_registers(frame, "exception state")
824
825 # ======================================
826 # Utility classes/functions for SBValues
827 # ======================================
828
829 class BasicFormatter(object):
830     """The basic formatter inspects the value object and prints the value."""
831     def format(self, value, buffer=None, indent=0):
832         if not buffer:
833             output = StringIO.StringIO()
834         else:
835             output = buffer
836         # If there is a summary, it suffices.
837         val = value.GetSummary()
838         # Otherwise, get the value.
839         if val == None:
840             val = value.GetValue()
841         if val == None and value.GetNumChildren() > 0:
842             val = "%s (location)" % value.GetLocation()
843         print >> output, "{indentation}({type}) {name} = {value}".format(
844             indentation = ' ' * indent,
845             type = value.GetTypeName(),
846             name = value.GetName(),
847             value = val)
848         return output.getvalue()
849
850 class ChildVisitingFormatter(BasicFormatter):
851     """The child visiting formatter prints the value and its immediate children.
852
853     The constructor takes a keyword arg: indent_child, which defaults to 2.
854     """
855     def __init__(self, indent_child=2):
856         """Default indentation of 2 SPC's for the children."""
857         self.cindent = indent_child
858     def format(self, value, buffer=None):
859         if not buffer:
860             output = StringIO.StringIO()
861         else:
862             output = buffer
863
864         BasicFormatter.format(self, value, buffer=output)
865         for child in value:
866             BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
867
868         return output.getvalue()
869
870 class RecursiveDecentFormatter(BasicFormatter):
871     """The recursive decent formatter prints the value and the decendents.
872
873     The constructor takes two keyword args: indent_level, which defaults to 0,
874     and indent_child, which defaults to 2.  The current indentation level is
875     determined by indent_level, while the immediate children has an additional
876     indentation by inden_child. 
877     """
878     def __init__(self, indent_level=0, indent_child=2):
879         self.lindent = indent_level
880         self.cindent = indent_child
881     def format(self, value, buffer=None):
882         if not buffer:
883             output = StringIO.StringIO()
884         else:
885             output = buffer
886
887         BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
888         new_indent = self.lindent + self.cindent
889         for child in value:
890             if child.GetSummary() != None:
891                 BasicFormatter.format(self, child, buffer=output, indent=new_indent)
892             else:
893                 if child.GetNumChildren() > 0:
894                     rdf = RecursiveDecentFormatter(indent_level=new_indent)
895                     rdf.format(child, buffer=output)
896                 else:
897                     BasicFormatter.format(self, child, buffer=output, indent=new_indent)
898
899         return output.getvalue()