1 ##===-- lldbutil.py ------------------------------------------*- Python -*-===##
3 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 # See https://llvm.org/LICENSE.txt for license information.
5 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 ##===----------------------------------------------------------------------===##
10 This LLDB module contains miscellaneous utilities.
11 Some of the test suite takes advantage of the utility functions defined here.
12 They can also be useful for general purpose lldb scripting.
20 # ===================================================
21 # Utilities for locating/checking executable programs
22 # ===================================================
26 """Returns True if fpath is an executable."""
27 return os
.path
.isfile(fpath
) and os
.access(fpath
, os
.X_OK
)
31 """Returns the full path to a program; None otherwise."""
32 fpath
, fname
= os
.path
.split(program
)
37 for path
in os
.environ
["PATH"].split(os
.pathsep
):
38 exe_file
= os
.path
.join(path
, program
)
44 # ===================================================
45 # Disassembly for an SBFunction or an SBSymbol object
46 # ===================================================
49 def disassemble(target
, function_or_symbol
):
50 """Disassemble the function or symbol given a target.
52 It returns the disassembly content in a string object.
55 insts
= function_or_symbol
.GetInstructions(target
)
61 # ==========================================================
62 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
63 # ==========================================================
66 def int_to_bytearray(val
, bytesize
):
67 """Utility function to convert an integer into a bytearray.
69 It returns the bytearray in the little endian format. It is easy to get the
70 big endian format, just do ba.reverse() on the returned object.
75 return bytearray([val
])
77 # Little endian followed by a format character.
88 packed
= struct
.pack(fmt
, val
)
89 return bytearray(ord(x
) for x
in packed
)
92 def bytearray_to_int(bytes
, bytesize
):
93 """Utility function to convert a bytearray into an integer.
95 It interprets the bytearray in the little endian format. For a big endian
96 bytearray, just do ba.reverse() on the object before passing it in.
103 # Little endian followed by a format character.
114 unpacked
= struct
.unpack(fmt
, str(bytes
))
118 # ==============================================================
119 # Get the description of an lldb object or None if not available
120 # ==============================================================
121 def get_description(obj
, option
=None):
122 """Calls lldb_obj.GetDescription() and returns a string, or None.
124 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
125 option can be passed in to describe the detailed level of description
127 o lldb.eDescriptionLevelBrief
128 o lldb.eDescriptionLevelFull
129 o lldb.eDescriptionLevelVerbose
131 method
= getattr(obj
, "GetDescription")
134 tuple = (lldb
.SBTarget
, lldb
.SBBreakpointLocation
, lldb
.SBWatchpoint
)
135 if isinstance(obj
, tuple):
137 option
= lldb
.eDescriptionLevelBrief
139 stream
= lldb
.SBStream()
141 success
= method(stream
)
143 success
= method(stream
, option
)
146 return stream
.GetData()
149 # =================================================
150 # Convert some enum value to its string counterpart
151 # =================================================
154 def state_type_to_str(enum
):
155 """Returns the stateType string given an enum."""
156 if enum
== lldb
.eStateInvalid
:
158 elif enum
== lldb
.eStateUnloaded
:
160 elif enum
== lldb
.eStateConnected
:
162 elif enum
== lldb
.eStateAttaching
:
164 elif enum
== lldb
.eStateLaunching
:
166 elif enum
== lldb
.eStateStopped
:
168 elif enum
== lldb
.eStateRunning
:
170 elif enum
== lldb
.eStateStepping
:
172 elif enum
== lldb
.eStateCrashed
:
174 elif enum
== lldb
.eStateDetached
:
176 elif enum
== lldb
.eStateExited
:
178 elif enum
== lldb
.eStateSuspended
:
181 raise Exception("Unknown StateType enum")
184 def stop_reason_to_str(enum
):
185 """Returns the stopReason string given an enum."""
186 if enum
== lldb
.eStopReasonInvalid
:
188 elif enum
== lldb
.eStopReasonNone
:
190 elif enum
== lldb
.eStopReasonTrace
:
192 elif enum
== lldb
.eStopReasonBreakpoint
:
194 elif enum
== lldb
.eStopReasonWatchpoint
:
196 elif enum
== lldb
.eStopReasonSignal
:
198 elif enum
== lldb
.eStopReasonException
:
200 elif enum
== lldb
.eStopReasonPlanComplete
:
201 return "plancomplete"
202 elif enum
== lldb
.eStopReasonThreadExiting
:
203 return "threadexiting"
205 raise Exception("Unknown StopReason enum")
208 def symbol_type_to_str(enum
):
209 """Returns the symbolType string given an enum."""
210 if enum
== lldb
.eSymbolTypeInvalid
:
212 elif enum
== lldb
.eSymbolTypeAbsolute
:
214 elif enum
== lldb
.eSymbolTypeCode
:
216 elif enum
== lldb
.eSymbolTypeData
:
218 elif enum
== lldb
.eSymbolTypeTrampoline
:
220 elif enum
== lldb
.eSymbolTypeRuntime
:
222 elif enum
== lldb
.eSymbolTypeException
:
224 elif enum
== lldb
.eSymbolTypeSourceFile
:
226 elif enum
== lldb
.eSymbolTypeHeaderFile
:
228 elif enum
== lldb
.eSymbolTypeObjectFile
:
230 elif enum
== lldb
.eSymbolTypeCommonBlock
:
232 elif enum
== lldb
.eSymbolTypeBlock
:
234 elif enum
== lldb
.eSymbolTypeLocal
:
236 elif enum
== lldb
.eSymbolTypeParam
:
238 elif enum
== lldb
.eSymbolTypeVariable
:
240 elif enum
== lldb
.eSymbolTypeVariableType
:
241 return "variabletype"
242 elif enum
== lldb
.eSymbolTypeLineEntry
:
244 elif enum
== lldb
.eSymbolTypeLineHeader
:
246 elif enum
== lldb
.eSymbolTypeScopeBegin
:
248 elif enum
== lldb
.eSymbolTypeScopeEnd
:
250 elif enum
== lldb
.eSymbolTypeAdditional
:
252 elif enum
== lldb
.eSymbolTypeCompiler
:
254 elif enum
== lldb
.eSymbolTypeInstrumentation
:
255 return "instrumentation"
256 elif enum
== lldb
.eSymbolTypeUndefined
:
260 def value_type_to_str(enum
):
261 """Returns the valueType string given an enum."""
262 if enum
== lldb
.eValueTypeInvalid
:
264 elif enum
== lldb
.eValueTypeVariableGlobal
:
265 return "global_variable"
266 elif enum
== lldb
.eValueTypeVariableStatic
:
267 return "static_variable"
268 elif enum
== lldb
.eValueTypeVariableArgument
:
269 return "argument_variable"
270 elif enum
== lldb
.eValueTypeVariableLocal
:
271 return "local_variable"
272 elif enum
== lldb
.eValueTypeRegister
:
274 elif enum
== lldb
.eValueTypeRegisterSet
:
275 return "register_set"
276 elif enum
== lldb
.eValueTypeConstResult
:
277 return "constant_result"
279 raise Exception("Unknown ValueType enum")
282 # ==================================================
283 # Get stopped threads due to each stop reason.
284 # ==================================================
287 def sort_stopped_threads(
289 breakpoint_threads
=None,
290 crashed_threads
=None,
291 watchpoint_threads
=None,
293 exiting_threads
=None,
296 """Fills array *_threads with threads stopped for the corresponding stop
309 for thread
in process
:
311 for reason
, list in [
312 (lldb
.eStopReasonBreakpoint
, breakpoint_threads
),
313 (lldb
.eStopReasonException
, crashed_threads
),
314 (lldb
.eStopReasonWatchpoint
, watchpoint_threads
),
315 (lldb
.eStopReasonSignal
, signal_threads
),
316 (lldb
.eStopReasonThreadExiting
, exiting_threads
),
317 (None, other_threads
),
319 if not dispatched
and list is not None:
320 if thread
.GetStopReason() == reason
or reason
is None:
325 # ==================================================
326 # Utility functions for setting breakpoints
327 # ==================================================
330 def run_break_set_by_file_and_line(
335 num_expected_locations
=1,
339 """Set a breakpoint by file and line, returning the breakpoint number.
341 If extra_options is not None, then we append it to the breakpoint set command.
343 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.
345 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.
348 if file_name
is None:
349 command
= "breakpoint set -l %d" % (line_number
)
351 command
= 'breakpoint set -f "%s" -l %d' % (file_name
, line_number
)
354 command
+= " --shlib '%s'" % (module_name
)
357 command
+= " " + extra_options
359 break_results
= run_break_set_command(test
, command
)
361 if num_expected_locations
== 1 and loc_exact
:
362 check_breakpoint_result(
365 num_locations
=num_expected_locations
,
367 line_number
=line_number
,
368 module_name
=module_name
,
371 check_breakpoint_result(
372 test
, break_results
, num_locations
=num_expected_locations
375 return get_bpno_from_match(break_results
)
378 def run_break_set_by_symbol(
382 num_expected_locations
=-1,
386 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
388 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.
390 command
= 'breakpoint set -n "%s"' % (symbol
)
393 command
+= " --shlib '%s'" % (module_name
)
396 command
+= " " + extra_options
398 break_results
= run_break_set_command(test
, command
)
400 if num_expected_locations
== 1 and sym_exact
:
401 check_breakpoint_result(
404 num_locations
=num_expected_locations
,
406 module_name
=module_name
,
409 check_breakpoint_result(
410 test
, break_results
, num_locations
=num_expected_locations
413 return get_bpno_from_match(break_results
)
416 def run_break_set_by_selector(
417 test
, selector
, extra_options
=None, num_expected_locations
=-1, module_name
=None
419 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
421 command
= 'breakpoint set -S "%s"' % (selector
)
424 command
+= ' --shlib "%s"' % (module_name
)
427 command
+= " " + extra_options
429 break_results
= run_break_set_command(test
, command
)
431 if num_expected_locations
== 1:
432 check_breakpoint_result(
435 num_locations
=num_expected_locations
,
436 symbol_name
=selector
,
437 symbol_match_exact
=False,
438 module_name
=module_name
,
441 check_breakpoint_result(
442 test
, break_results
, num_locations
=num_expected_locations
445 return get_bpno_from_match(break_results
)
448 def run_break_set_by_regexp(
449 test
, regexp
, extra_options
=None, num_expected_locations
=-1
451 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
453 command
= 'breakpoint set -r "%s"' % (regexp
)
455 command
+= " " + extra_options
457 break_results
= run_break_set_command(test
, command
)
459 check_breakpoint_result(test
, break_results
, num_locations
=num_expected_locations
)
461 return get_bpno_from_match(break_results
)
464 def run_break_set_by_source_regexp(
465 test
, regexp
, extra_options
=None, num_expected_locations
=-1
467 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
468 command
= 'breakpoint set -p "%s"' % (regexp
)
470 command
+= " " + extra_options
472 break_results
= run_break_set_command(test
, command
)
474 check_breakpoint_result(test
, break_results
, num_locations
=num_expected_locations
)
476 return get_bpno_from_match(break_results
)
479 def run_break_set_command(test
, command
):
480 """Run the command passed in - it must be some break set variant - and analyze the result.
481 Returns a dictionary of information gleaned from the command-line results.
482 Will assert if the breakpoint setting fails altogether.
484 Dictionary will contain:
485 bpno - breakpoint of the newly created breakpoint, -1 on error.
486 num_locations - number of locations set for the breakpoint.
488 If there is only one location, the dictionary MAY contain:
489 file - source file name
490 line_no - source line number
492 inline_symbol - inlined symbol name
493 offset - offset from the original symbol
495 address - address at which the breakpoint was set."""
498 r
"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
499 r
"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
500 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]+)$",
501 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]+)$",
503 match_object
= test
.match(command
, patterns
)
504 break_results
= match_object
.groupdict()
506 # We always insert the breakpoint number, setting it to -1 if we couldn't find it
507 # Also, make sure it gets stored as an integer.
508 if not "bpno" in break_results
:
509 break_results
["bpno"] = -1
511 break_results
["bpno"] = int(break_results
["bpno"])
513 # We always insert the number of locations
514 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
515 # We also make sure it is an integer.
517 if not "num_locations" in break_results
:
520 num_locations
= break_results
["num_locations"]
521 if num_locations
== "no":
524 num_locations
= int(break_results
["num_locations"])
526 break_results
["num_locations"] = num_locations
528 if "line_no" in break_results
:
529 break_results
["line_no"] = int(break_results
["line_no"])
534 def get_bpno_from_match(break_results
):
535 return int(break_results
["bpno"])
538 def check_breakpoint_result(
544 symbol_match_exact
=True,
549 out_num_locations
= break_results
["num_locations"]
551 if num_locations
== -1:
553 out_num_locations
> 0, "Expecting one or more locations, got none."
557 num_locations
== out_num_locations
,
558 "Expecting %d locations, got %d." % (num_locations
, out_num_locations
),
563 if "file" in break_results
:
564 out_file_name
= break_results
["file"]
566 file_name
== out_file_name
,
567 "Breakpoint file name '%s' doesn't match resultant name '%s'."
568 % (file_name
, out_file_name
),
571 if line_number
!= -1:
573 if "line_no" in break_results
:
574 out_line_number
= break_results
["line_no"]
577 line_number
== out_line_number
,
578 "Breakpoint line number %s doesn't match resultant line %s."
579 % (line_number
, out_line_number
),
584 # Look first for the inlined symbol name, otherwise use the symbol
586 if "inline_symbol" in break_results
and break_results
["inline_symbol"]:
587 out_symbol_name
= break_results
["inline_symbol"]
588 elif "symbol" in break_results
:
589 out_symbol_name
= break_results
["symbol"]
591 if symbol_match_exact
:
593 symbol_name
== out_symbol_name
,
594 "Symbol name '%s' doesn't match resultant symbol '%s'."
595 % (symbol_name
, out_symbol_name
),
599 out_symbol_name
.find(symbol_name
) != -1,
600 "Symbol name '%s' isn't in resultant symbol '%s'."
601 % (symbol_name
, out_symbol_name
),
605 out_nodule_name
= None
606 if "module" in break_results
:
607 out_module_name
= break_results
["module"]
610 module_name
.find(out_module_name
) != -1,
611 "Symbol module name '%s' isn't in expected module name '%s'."
612 % (out_module_name
, module_name
),
616 # ==================================================
617 # Utility functions related to Threads and Processes
618 # ==================================================
621 def get_stopped_threads(process
, reason
):
622 """Returns the thread(s) with the specified stop reason in a list.
624 The list can be empty if no such thread exists.
628 if t
.GetStopReason() == reason
:
633 def get_stopped_thread(process
, reason
):
634 """A convenience function which returns the first thread with the given stop
639 1. Get the stopped thread due to a breakpoint condition
642 from lldbutil import get_stopped_thread
643 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
644 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
647 2. Get the thread stopped due to a breakpoint
650 from lldbutil import get_stopped_thread
651 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
652 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
656 threads
= get_stopped_threads(process
, reason
)
657 if len(threads
) == 0:
662 def get_threads_stopped_at_breakpoint(process
, bkpt
):
663 """For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
667 stopped_threads
= get_stopped_threads(process
, lldb
.eStopReasonBreakpoint
)
669 if len(stopped_threads
) == 0:
672 for thread
in stopped_threads
:
673 # Make sure we've hit our breakpoint...
674 break_id
= thread
.GetStopReasonDataAtIndex(0)
675 if break_id
== bkpt
.GetID():
676 threads
.append(thread
)
681 def continue_to_breakpoint(process
, bkpt
):
682 """Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
684 if process
.GetState() != lldb
.eStateStopped
:
687 return get_threads_stopped_at_breakpoint(process
, bkpt
)
690 def get_caller_symbol(thread
):
692 Returns the symbol name for the call site of the leaf function.
694 depth
= thread
.GetNumFrames()
697 caller
= thread
.GetFrameAtIndex(1).GetSymbol()
699 return caller
.GetName()
704 def get_function_names(thread
):
706 Returns a sequence of function names from the stack frames of this thread.
710 return thread
.GetFrameAtIndex(i
).GetFunctionName()
712 return [GetFuncName(i
) for i
in range(thread
.GetNumFrames())]
715 def get_symbol_names(thread
):
717 Returns a sequence of symbols for this thread.
721 return thread
.GetFrameAtIndex(i
).GetSymbol().GetName()
723 return [GetSymbol(i
) for i
in range(thread
.GetNumFrames())]
726 def get_pc_addresses(thread
):
728 Returns a sequence of pc addresses for this thread.
732 return thread
.GetFrameAtIndex(i
).GetPCAddress()
734 return [GetPCAddress(i
) for i
in range(thread
.GetNumFrames())]
737 def get_filenames(thread
):
739 Returns a sequence of file names from the stack frames of this thread.
743 return thread
.GetFrameAtIndex(i
).GetLineEntry().GetFileSpec().GetFilename()
745 return [GetFilename(i
) for i
in range(thread
.GetNumFrames())]
748 def get_line_numbers(thread
):
750 Returns a sequence of line numbers from the stack frames of this thread.
753 def GetLineNumber(i
):
754 return thread
.GetFrameAtIndex(i
).GetLineEntry().GetLine()
756 return [GetLineNumber(i
) for i
in range(thread
.GetNumFrames())]
759 def get_module_names(thread
):
761 Returns a sequence of module names from the stack frames of this thread.
764 def GetModuleName(i
):
765 return thread
.GetFrameAtIndex(i
).GetModule().GetFileSpec().GetFilename()
767 return [GetModuleName(i
) for i
in range(thread
.GetNumFrames())]
770 def get_stack_frames(thread
):
772 Returns a sequence of stack frames for this thread.
775 def GetStackFrame(i
):
776 return thread
.GetFrameAtIndex(i
)
778 return [GetStackFrame(i
) for i
in range(thread
.GetNumFrames())]
781 def print_stacktrace(thread
, string_buffer
=False):
782 """Prints a simple stack trace of this thread."""
784 output
= io
.StringIO() if string_buffer
else sys
.stdout
785 target
= thread
.GetProcess().GetTarget()
787 depth
= thread
.GetNumFrames()
789 mods
= get_module_names(thread
)
790 funcs
= get_function_names(thread
)
791 symbols
= get_symbol_names(thread
)
792 files
= get_filenames(thread
)
793 lines
= get_line_numbers(thread
)
794 addrs
= get_pc_addresses(thread
)
796 if thread
.GetStopReason() != lldb
.eStopReasonInvalid
:
797 desc
= "stop reason=" + stop_reason_to_str(thread
.GetStopReason())
801 "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
802 thread
.GetThreadID(), thread
.GetName(), thread
.GetQueueName()
808 for i
in range(depth
):
809 frame
= thread
.GetFrameAtIndex(i
)
810 function
= frame
.GetFunction()
812 load_addr
= addrs
[i
].GetLoadAddress(target
)
814 file_addr
= addrs
[i
].GetFileAddress()
815 start_addr
= frame
.GetSymbol().GetStartAddress().GetFileAddress()
816 symbol_offset
= file_addr
- start_addr
818 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
823 offset
=symbol_offset
,
829 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
833 func
="%s [inlined]" % funcs
[i
] if frame
.IsInlined() else funcs
[i
],
836 args
=get_args_as_string(frame
, showFuncName
=False)
837 if not frame
.IsInlined()
844 return output
.getvalue()
847 def print_stacktraces(process
, string_buffer
=False):
848 """Prints the stack traces of all the threads."""
850 output
= io
.StringIO() if string_buffer
else sys
.stdout
852 print("Stack traces for " + str(process
), file=output
)
854 for thread
in process
:
855 print(print_stacktrace(thread
, string_buffer
=True), file=output
)
858 return output
.getvalue()
861 # ===================================
862 # Utility functions related to Frames
863 # ===================================
866 def get_parent_frame(frame
):
868 Returns the parent frame of the input frame object; None if not available.
870 thread
= frame
.GetThread()
875 if f
.GetFrameID() == frame
.GetFrameID():
878 # If we reach here, no parent has been found, return None.
882 def get_args_as_string(frame
, showFuncName
=True):
884 Returns the args of the input frame object as a string.
889 # in_scope_only => True
890 vars = frame
.GetVariables(True, False, False, True) # type of SBValueList
891 args
= [] # list of strings
893 args
.append("(%s)%s=%s" % (var
.GetTypeName(), var
.GetName(), var
.GetValue()))
894 if frame
.GetFunction():
895 name
= frame
.GetFunction().GetName()
896 elif frame
.GetSymbol():
897 name
= frame
.GetSymbol().GetName()
901 return "%s(%s)" % (name
, ", ".join(args
))
903 return "(%s)" % (", ".join(args
))
906 def print_registers(frame
, string_buffer
=False):
907 """Prints all the register sets of the frame."""
909 output
= io
.StringIO() if string_buffer
else sys
.stdout
911 print("Register sets for " + str(frame
), file=output
)
913 registerSet
= frame
.GetRegisters() # Return type of SBValueList.
915 "Frame registers (size of register set = %d):" % registerSet
.GetSize(),
918 for value
in registerSet
:
919 # print >> output, value
921 "%s (number of children = %d):" % (value
.GetName(), value
.GetNumChildren()),
926 "Name: %s, Value: %s" % (child
.GetName(), child
.GetValue()), file=output
930 return output
.getvalue()
933 def get_registers(frame
, kind
):
934 """Returns the registers given the frame and the kind of registers desired.
936 Returns None if there's no such kind.
938 registerSet
= frame
.GetRegisters() # Return type of SBValueList.
939 for value
in registerSet
:
940 if kind
.lower() in value
.GetName().lower():
947 """Returns the general purpose registers of the frame as an SBValue.
949 The returned SBValue object is iterable. An example:
951 from lldbutil import get_GPRs
952 regs = get_GPRs(frame)
954 print "%s => %s" % (reg.GetName(), reg.GetValue())
957 return get_registers(frame
, "general purpose")
961 """Returns the floating point registers of the frame as an SBValue.
963 The returned SBValue object is iterable. An example:
965 from lldbutil import get_FPRs
966 regs = get_FPRs(frame)
968 print "%s => %s" % (reg.GetName(), reg.GetValue())
971 return get_registers(frame
, "floating point")
975 """Returns the exception state registers of the frame as an SBValue.
977 The returned SBValue object is iterable. An example:
979 from lldbutil import get_ESRs
980 regs = get_ESRs(frame)
982 print "%s => %s" % (reg.GetName(), reg.GetValue())
985 return get_registers(frame
, "exception state")
988 # ======================================
989 # Utility classes/functions for SBValues
990 # ======================================
993 class BasicFormatter(object):
994 """The basic formatter inspects the value object and prints the value."""
996 def format(self
, value
, buffer=None, indent
=0):
998 output
= io
.StringIO()
1001 # If there is a summary, it suffices.
1002 val
= value
.GetSummary()
1003 # Otherwise, get the value.
1005 val
= value
.GetValue()
1006 if val
is None and value
.GetNumChildren() > 0:
1007 val
= "%s (location)" % value
.GetLocation()
1009 "{indentation}({type}) {name} = {value}".format(
1010 indentation
=" " * indent
,
1011 type=value
.GetTypeName(),
1012 name
=value
.GetName(),
1017 return output
.getvalue()
1020 class ChildVisitingFormatter(BasicFormatter
):
1021 """The child visiting formatter prints the value and its immediate children.
1023 The constructor takes a keyword arg: indent_child, which defaults to 2.
1026 def __init__(self
, indent_child
=2):
1027 """Default indentation of 2 SPC's for the children."""
1028 self
.cindent
= indent_child
1030 def format(self
, value
, buffer=None):
1032 output
= io
.StringIO()
1036 BasicFormatter
.format(self
, value
, buffer=output
)
1038 BasicFormatter
.format(self
, child
, buffer=output
, indent
=self
.cindent
)
1040 return output
.getvalue()
1043 class RecursiveDecentFormatter(BasicFormatter
):
1044 """The recursive decent formatter prints the value and the decendents.
1046 The constructor takes two keyword args: indent_level, which defaults to 0,
1047 and indent_child, which defaults to 2. The current indentation level is
1048 determined by indent_level, while the immediate children has an additional
1049 indentation by inden_child.
1052 def __init__(self
, indent_level
=0, indent_child
=2):
1053 self
.lindent
= indent_level
1054 self
.cindent
= indent_child
1056 def format(self
, value
, buffer=None):
1058 output
= io
.StringIO()
1062 BasicFormatter
.format(self
, value
, buffer=output
, indent
=self
.lindent
)
1063 new_indent
= self
.lindent
+ self
.cindent
1065 if child
.GetSummary() is not None:
1066 BasicFormatter
.format(self
, child
, buffer=output
, indent
=new_indent
)
1068 if child
.GetNumChildren() > 0:
1069 rdf
= RecursiveDecentFormatter(indent_level
=new_indent
)
1070 rdf
.format(child
, buffer=output
)
1072 BasicFormatter
.format(self
, child
, buffer=output
, indent
=new_indent
)
1074 return output
.getvalue()