2 This LLDB module contains miscellaneous utilities.
3 Some of the test suite takes advantage of the utility functions defined here.
4 They can also be useful for general purpose lldb scripting.
7 from __future__ import print_function
8 from __future__ import absolute_import
18 from six import StringIO as SixStringIO
25 # ===================================================
26 # Utilities for locating/checking executable programs
27 # ===================================================
30 """Returns True if fpath is an executable."""
31 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
35 """Returns the full path to a program; None otherwise."""
36 fpath, fname = os.path.split(program)
41 for path in os.environ["PATH"].split(os.pathsep):
42 exe_file = os.path.join(path, program)
47 # ===================================================
48 # Disassembly for an SBFunction or an SBSymbol object
49 # ===================================================
52 def disassemble(target, function_or_symbol):
53 """Disassemble the function or symbol given a target.
55 It returns the disassembly content in a string object.
58 insts = function_or_symbol.GetInstructions(target)
63 # ==========================================================
64 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
65 # ==========================================================
68 def int_to_bytearray(val, bytesize):
69 """Utility function to convert an integer into a bytearray.
71 It returns the bytearray in the little endian format. It is easy to get the
72 big endian format, just do ba.reverse() on the returned object.
77 return bytearray([val])
79 # Little endian followed by a format character.
90 packed = struct.pack(fmt, val)
91 return bytearray(packed)
94 def bytearray_to_int(bytes, bytesize):
95 """Utility function to convert a bytearray into an integer.
97 It interprets the bytearray in the little endian format. For a big endian
98 bytearray, just do ba.reverse() on the object before passing it in.
105 # Little endian followed by a format character.
116 unpacked = struct.unpack_from(fmt, bytes)
120 # ==============================================================
121 # Get the description of an lldb object or None if not available
122 # ==============================================================
123 def get_description(obj, option=None):
124 """Calls lldb_obj.GetDescription() and returns a string, or None.
126 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
127 option can be passed in to describe the detailed level of description
129 o lldb.eDescriptionLevelBrief
130 o lldb.eDescriptionLevelFull
131 o lldb.eDescriptionLevelVerbose
133 method = getattr(obj, 'GetDescription')
136 tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
137 if isinstance(obj, tuple):
139 option = lldb.eDescriptionLevelBrief
141 stream = lldb.SBStream()
143 success = method(stream)
145 success = method(stream, option)
148 return stream.GetData()
151 # =================================================
152 # Convert some enum value to its string counterpart
153 # =================================================
155 def state_type_to_str(enum):
156 """Returns the stateType string given an enum."""
157 if enum == lldb.eStateInvalid:
159 elif enum == lldb.eStateUnloaded:
161 elif enum == lldb.eStateConnected:
163 elif enum == lldb.eStateAttaching:
165 elif enum == lldb.eStateLaunching:
167 elif enum == lldb.eStateStopped:
169 elif enum == lldb.eStateRunning:
171 elif enum == lldb.eStateStepping:
173 elif enum == lldb.eStateCrashed:
175 elif enum == lldb.eStateDetached:
177 elif enum == lldb.eStateExited:
179 elif enum == lldb.eStateSuspended:
182 raise Exception("Unknown StateType enum")
185 def stop_reason_to_str(enum):
186 """Returns the stopReason string given an enum."""
187 if enum == lldb.eStopReasonInvalid:
189 elif enum == lldb.eStopReasonNone:
191 elif enum == lldb.eStopReasonTrace:
193 elif enum == lldb.eStopReasonBreakpoint:
195 elif enum == lldb.eStopReasonWatchpoint:
197 elif enum == lldb.eStopReasonExec:
199 elif enum == lldb.eStopReasonSignal:
201 elif enum == lldb.eStopReasonException:
203 elif enum == lldb.eStopReasonPlanComplete:
204 return "plancomplete"
205 elif enum == lldb.eStopReasonThreadExiting:
206 return "threadexiting"
208 raise Exception("Unknown StopReason enum")
211 def symbol_type_to_str(enum):
212 """Returns the symbolType string given an enum."""
213 if enum == lldb.eSymbolTypeInvalid:
215 elif enum == lldb.eSymbolTypeAbsolute:
217 elif enum == lldb.eSymbolTypeCode:
219 elif enum == lldb.eSymbolTypeData:
221 elif enum == lldb.eSymbolTypeTrampoline:
223 elif enum == lldb.eSymbolTypeRuntime:
225 elif enum == lldb.eSymbolTypeException:
227 elif enum == lldb.eSymbolTypeSourceFile:
229 elif enum == lldb.eSymbolTypeHeaderFile:
231 elif enum == lldb.eSymbolTypeObjectFile:
233 elif enum == lldb.eSymbolTypeCommonBlock:
235 elif enum == lldb.eSymbolTypeBlock:
237 elif enum == lldb.eSymbolTypeLocal:
239 elif enum == lldb.eSymbolTypeParam:
241 elif enum == lldb.eSymbolTypeVariable:
243 elif enum == lldb.eSymbolTypeVariableType:
244 return "variabletype"
245 elif enum == lldb.eSymbolTypeLineEntry:
247 elif enum == lldb.eSymbolTypeLineHeader:
249 elif enum == lldb.eSymbolTypeScopeBegin:
251 elif enum == lldb.eSymbolTypeScopeEnd:
253 elif enum == lldb.eSymbolTypeAdditional:
255 elif enum == lldb.eSymbolTypeCompiler:
257 elif enum == lldb.eSymbolTypeInstrumentation:
258 return "instrumentation"
259 elif enum == lldb.eSymbolTypeUndefined:
263 def value_type_to_str(enum):
264 """Returns the valueType string given an enum."""
265 if enum == lldb.eValueTypeInvalid:
267 elif enum == lldb.eValueTypeVariableGlobal:
268 return "global_variable"
269 elif enum == lldb.eValueTypeVariableStatic:
270 return "static_variable"
271 elif enum == lldb.eValueTypeVariableArgument:
272 return "argument_variable"
273 elif enum == lldb.eValueTypeVariableLocal:
274 return "local_variable"
275 elif enum == lldb.eValueTypeRegister:
277 elif enum == lldb.eValueTypeRegisterSet:
278 return "register_set"
279 elif enum == lldb.eValueTypeConstResult:
280 return "constant_result"
282 raise Exception("Unknown ValueType enum")
285 # ==================================================
286 # Get stopped threads due to each stop reason.
287 # ==================================================
289 def sort_stopped_threads(process,
290 breakpoint_threads=None,
291 crashed_threads=None,
292 watchpoint_threads=None,
294 exiting_threads=None,
296 """ Fills array *_threads with threads stopped for the corresponding stop
299 for lst in [breakpoint_threads,
307 for thread in process:
309 for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
310 (lldb.eStopReasonException, crashed_threads),
311 (lldb.eStopReasonWatchpoint, watchpoint_threads),
312 (lldb.eStopReasonSignal, signal_threads),
313 (lldb.eStopReasonThreadExiting, exiting_threads),
314 (None, other_threads)]:
315 if not dispatched and list is not None:
316 if thread.GetStopReason() == reason or reason is None:
320 # ==================================================
321 # Utility functions for setting breakpoints
322 # ==================================================
325 def run_break_set_by_file_and_line(
330 num_expected_locations=1,
333 """Set a breakpoint by file and line, returning the breakpoint number.
335 If extra_options is not None, then we append it to the breakpoint set command.
337 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.
339 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
341 if file_name is None:
342 command = 'breakpoint set -l %d' % (line_number)
344 command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
347 command += " --shlib '%s'" % (module_name)
350 command += " " + extra_options
352 break_results = run_break_set_command(test, command)
354 if num_expected_locations == 1 and loc_exact:
355 check_breakpoint_result(
358 num_locations=num_expected_locations,
360 line_number=line_number,
361 module_name=module_name)
363 check_breakpoint_result(
366 num_locations=num_expected_locations)
368 return get_bpno_from_match(break_results)
371 def run_break_set_by_symbol(
375 num_expected_locations=-1,
378 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
380 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
381 command = 'breakpoint set -n "%s"' % (symbol)
384 command += " --shlib '%s'" % (module_name)
387 command += " " + extra_options
389 break_results = run_break_set_command(test, command)
391 if num_expected_locations == 1 and sym_exact:
392 check_breakpoint_result(
395 num_locations=num_expected_locations,
397 module_name=module_name)
399 check_breakpoint_result(
402 num_locations=num_expected_locations)
404 return get_bpno_from_match(break_results)
407 def run_break_set_by_selector(
411 num_expected_locations=-1,
413 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
415 command = 'breakpoint set -S "%s"' % (selector)
418 command += ' --shlib "%s"' % (module_name)
421 command += " " + extra_options
423 break_results = run_break_set_command(test, command)
425 if num_expected_locations == 1:
426 check_breakpoint_result(
429 num_locations=num_expected_locations,
430 symbol_name=selector,
431 symbol_match_exact=False,
432 module_name=module_name)
434 check_breakpoint_result(
437 num_locations=num_expected_locations)
439 return get_bpno_from_match(break_results)
442 def run_break_set_by_regexp(
446 num_expected_locations=-1):
447 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
449 command = 'breakpoint set -r "%s"' % (regexp)
451 command += " " + extra_options
453 break_results = run_break_set_command(test, command)
455 check_breakpoint_result(
458 num_locations=num_expected_locations)
460 return get_bpno_from_match(break_results)
463 def run_break_set_by_source_regexp(
467 num_expected_locations=-1):
468 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
469 command = 'breakpoint set -p "%s"' % (regexp)
471 command += " " + extra_options
473 break_results = run_break_set_command(test, command)
475 check_breakpoint_result(
478 num_locations=num_expected_locations)
480 return get_bpno_from_match(break_results)
483 def run_break_set_command(test, command):
484 """Run the command passed in - it must be some break set variant - and analyze the result.
485 Returns a dictionary of information gleaned from the command-line results.
486 Will assert if the breakpoint setting fails altogether.
488 Dictionary will contain:
489 bpno - breakpoint of the newly created breakpoint, -1 on error.
490 num_locations - number of locations set for the breakpoint.
492 If there is only one location, the dictionary MAY contain:
493 file - source file name
494 line_no - source line number
496 inline_symbol - inlined symbol name
497 offset - offset from the original symbol
499 address - address at which the breakpoint was set."""
502 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
503 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
504 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]+)$",
505 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]+)$"]
506 match_object = test.match(command, patterns)
507 break_results = match_object.groupdict()
509 # We always insert the breakpoint number, setting it to -1 if we couldn't find it
510 # Also, make sure it gets stored as an integer.
511 if not 'bpno' in break_results:
512 break_results['bpno'] = -1
514 break_results['bpno'] = int(break_results['bpno'])
516 # We always insert the number of locations
517 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
518 # We also make sure it is an integer.
520 if not 'num_locations' in break_results:
523 num_locations = break_results['num_locations']
524 if num_locations == 'no':
527 num_locations = int(break_results['num_locations'])
529 break_results['num_locations'] = num_locations
531 if 'line_no' in break_results:
532 break_results['line_no'] = int(break_results['line_no'])
537 def get_bpno_from_match(break_results):
538 return int(break_results['bpno'])
541 def check_breakpoint_result(
547 symbol_match_exact=True,
552 out_num_locations = break_results['num_locations']
554 if num_locations == -1:
555 test.assertTrue(out_num_locations > 0,
556 "Expecting one or more locations, got none.")
559 num_locations == out_num_locations,
560 "Expecting %d locations, got %d." %
566 if 'file' in break_results:
567 out_file_name = break_results['file']
569 file_name == out_file_name,
570 "Breakpoint file name '%s' doesn't match resultant name '%s'." %
574 if line_number != -1:
576 if 'line_no' in break_results:
577 out_line_number = break_results['line_no']
580 line_number == out_line_number,
581 "Breakpoint line number %s doesn't match resultant line %s." %
587 # Look first for the inlined symbol name, otherwise use the symbol
589 if 'inline_symbol' in break_results and break_results['inline_symbol']:
590 out_symbol_name = break_results['inline_symbol']
591 elif 'symbol' in break_results:
592 out_symbol_name = break_results['symbol']
594 if symbol_match_exact:
596 symbol_name == out_symbol_name,
597 "Symbol name '%s' doesn't match resultant symbol '%s'." %
602 out_symbol_name.find(symbol_name) != -
604 "Symbol name '%s' isn't in resultant symbol '%s'." %
609 out_module_name = None
610 if 'module' in break_results:
611 out_module_name = break_results['module']
614 module_name.find(out_module_name) != -
616 "Symbol module name '%s' isn't in expected module name '%s'." %
620 # ==================================================
621 # Utility functions related to Threads and Processes
622 # ==================================================
625 def get_stopped_threads(process, reason):
626 """Returns the thread(s) with the specified stop reason in a list.
628 The list can be empty if no such thread exists.
632 if t.GetStopReason() == reason:
637 def get_stopped_thread(process, reason):
638 """A convenience function which returns the first thread with the given stop
643 1. Get the stopped thread due to a breakpoint condition
646 from lldbutil import get_stopped_thread
647 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
648 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
651 2. Get the thread stopped due to a breakpoint
654 from lldbutil import get_stopped_thread
655 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
656 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
660 threads = get_stopped_threads(process, reason)
661 if len(threads) == 0:
666 def get_threads_stopped_at_breakpoint_id(process, bpid):
667 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
671 stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
673 if len(stopped_threads) == 0:
676 for thread in stopped_threads:
677 # Make sure we've hit our breakpoint...
678 break_id = thread.GetStopReasonDataAtIndex(0)
680 threads.append(thread)
685 def get_threads_stopped_at_breakpoint(process, bkpt):
686 return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
689 def get_one_thread_stopped_at_breakpoint_id(
690 process, bpid, require_exactly_one=True):
691 threads = get_threads_stopped_at_breakpoint_id(process, bpid)
692 if len(threads) == 0:
694 if require_exactly_one and len(threads) != 1:
700 def get_one_thread_stopped_at_breakpoint(
701 process, bkpt, require_exactly_one=True):
702 return get_one_thread_stopped_at_breakpoint_id(
703 process, bkpt.GetID(), require_exactly_one)
706 def is_thread_crashed(test, thread):
707 """In the test suite we dereference a null pointer to simulate a crash. The way this is
708 reported depends on the platform."""
709 if test.platformIsDarwin():
710 return thread.GetStopReason(
711 ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
712 elif test.getPlatform() == "linux":
713 return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
714 0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
716 return "invalid address" in thread.GetStopDescription(100)
719 def get_crashed_threads(test, process):
721 if process.GetState() != lldb.eStateStopped:
723 for thread in process:
724 if is_thread_crashed(test, thread):
725 threads.append(thread)
729 def continue_to_breakpoint(process, bkpt):
730 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
732 if process.GetState() != lldb.eStateStopped:
735 return get_threads_stopped_at_breakpoint(process, bkpt)
738 def get_caller_symbol(thread):
740 Returns the symbol name for the call site of the leaf function.
742 depth = thread.GetNumFrames()
745 caller = thread.GetFrameAtIndex(1).GetSymbol()
747 return caller.GetName()
752 def get_function_names(thread):
754 Returns a sequence of function names from the stack frames of this thread.
757 return thread.GetFrameAtIndex(i).GetFunctionName()
759 return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
762 def get_symbol_names(thread):
764 Returns a sequence of symbols for this thread.
767 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
769 return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
772 def get_pc_addresses(thread):
774 Returns a sequence of pc addresses for this thread.
777 return thread.GetFrameAtIndex(i).GetPCAddress()
779 return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
782 def get_filenames(thread):
784 Returns a sequence of file names from the stack frames of this thread.
787 return thread.GetFrameAtIndex(
788 i).GetLineEntry().GetFileSpec().GetFilename()
790 return list(map(GetFilename, list(range(thread.GetNumFrames()))))
793 def get_line_numbers(thread):
795 Returns a sequence of line numbers from the stack frames of this thread.
797 def GetLineNumber(i):
798 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
800 return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
803 def get_module_names(thread):
805 Returns a sequence of module names from the stack frames of this thread.
807 def GetModuleName(i):
808 return thread.GetFrameAtIndex(
809 i).GetModule().GetFileSpec().GetFilename()
811 return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
814 def get_stack_frames(thread):
816 Returns a sequence of stack frames for this thread.
818 def GetStackFrame(i):
819 return thread.GetFrameAtIndex(i)
821 return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
824 def print_stacktrace(thread, string_buffer=False):
825 """Prints a simple stack trace of this thread."""
827 output = SixStringIO() if string_buffer else sys.stdout
828 target = thread.GetProcess().GetTarget()
830 depth = thread.GetNumFrames()
832 mods = get_module_names(thread)
833 funcs = get_function_names(thread)
834 symbols = get_symbol_names(thread)
835 files = get_filenames(thread)
836 lines = get_line_numbers(thread)
837 addrs = get_pc_addresses(thread)
839 if thread.GetStopReason() != lldb.eStopReasonInvalid:
840 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
844 "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
845 thread.GetThreadID(),
847 thread.GetQueueName()) + desc,
850 for i in range(depth):
851 frame = thread.GetFrameAtIndex(i)
852 function = frame.GetFunction()
854 load_addr = addrs[i].GetLoadAddress(target)
856 file_addr = addrs[i].GetFileAddress()
857 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
858 symbol_offset = file_addr - start_addr
860 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
865 offset=symbol_offset),
869 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
873 func='%s [inlined]' %
874 funcs[i] if frame.IsInlined() else funcs[i],
877 args=get_args_as_string(
879 showFuncName=False) if not frame.IsInlined() else '()'),
883 return output.getvalue()
886 def print_stacktraces(process, string_buffer=False):
887 """Prints the stack traces of all the threads."""
889 output = SixStringIO() if string_buffer else sys.stdout
891 print("Stack traces for " + str(process), file=output)
893 for thread in process:
894 print(print_stacktrace(thread, string_buffer=True), file=output)
897 return output.getvalue()
900 def expect_state_changes(test, listener, process, states, timeout=5):
901 """Listens for state changed events on the listener and makes sure they match what we
902 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
904 for expected_state in states:
905 def get_next_event():
906 event = lldb.SBEvent()
907 if not listener.WaitForEventForBroadcasterWithType(
909 process.GetBroadcaster(),
910 lldb.SBProcess.eBroadcastBitStateChanged,
913 "Timed out while waiting for a transition to state %s" %
914 lldb.SBDebugger.StateAsCString(expected_state))
917 event = get_next_event()
918 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
919 lldb.SBProcess.GetRestartedFromEvent(event)):
920 # Ignore restarted event and the subsequent running event.
921 event = get_next_event()
923 lldb.SBProcess.GetStateFromEvent(event),
925 "Restarted event followed by a running event")
926 event = get_next_event()
929 lldb.SBProcess.GetStateFromEvent(event),
932 # ===================================
933 # Utility functions related to Frames
934 # ===================================
937 def get_parent_frame(frame):
939 Returns the parent frame of the input frame object; None if not available.
941 thread = frame.GetThread()
946 if f.GetFrameID() == frame.GetFrameID():
949 # If we reach here, no parent has been found, return None.
953 def get_args_as_string(frame, showFuncName=True):
955 Returns the args of the input frame object as a string.
960 # in_scope_only => True
961 vars = frame.GetVariables(True, False, False, True) # type of SBValueList
962 args = [] # list of strings
964 args.append("(%s)%s=%s" % (var.GetTypeName(),
967 if frame.GetFunction():
968 name = frame.GetFunction().GetName()
969 elif frame.GetSymbol():
970 name = frame.GetSymbol().GetName()
974 return "%s(%s)" % (name, ", ".join(args))
976 return "(%s)" % (", ".join(args))
979 def print_registers(frame, string_buffer=False):
980 """Prints all the register sets of the frame."""
982 output = SixStringIO() if string_buffer else sys.stdout
984 print("Register sets for " + str(frame), file=output)
986 registerSet = frame.GetRegisters() # Return type of SBValueList.
987 print("Frame registers (size of register set = %d):" %
988 registerSet.GetSize(), file=output)
989 for value in registerSet:
990 #print(value, file=output)
991 print("%s (number of children = %d):" %
992 (value.GetName(), value.GetNumChildren()), file=output)
995 "Name: %s, Value: %s" %
1001 return output.getvalue()
1004 def get_registers(frame, kind):
1005 """Returns the registers given the frame and the kind of registers desired.
1007 Returns None if there's no such kind.
1009 registerSet = frame.GetRegisters() # Return type of SBValueList.
1010 for value in registerSet:
1011 if kind.lower() in value.GetName().lower():
1017 def get_GPRs(frame):
1018 """Returns the general purpose registers of the frame as an SBValue.
1020 The returned SBValue object is iterable. An example:
1022 from lldbutil import get_GPRs
1023 regs = get_GPRs(frame)
1025 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1028 return get_registers(frame, "general purpose")
1031 def get_FPRs(frame):
1032 """Returns the floating point registers of the frame as an SBValue.
1034 The returned SBValue object is iterable. An example:
1036 from lldbutil import get_FPRs
1037 regs = get_FPRs(frame)
1039 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1042 return get_registers(frame, "floating point")
1045 def get_ESRs(frame):
1046 """Returns the exception state registers of the frame as an SBValue.
1048 The returned SBValue object is iterable. An example:
1050 from lldbutil import get_ESRs
1051 regs = get_ESRs(frame)
1053 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1056 return get_registers(frame, "exception state")
1058 # ======================================
1059 # Utility classes/functions for SBValues
1060 # ======================================
1063 class BasicFormatter(object):
1064 """The basic formatter inspects the value object and prints the value."""
1066 def format(self, value, buffer=None, indent=0):
1068 output = SixStringIO()
1071 # If there is a summary, it suffices.
1072 val = value.GetSummary()
1073 # Otherwise, get the value.
1075 val = value.GetValue()
1076 if val is None and value.GetNumChildren() > 0:
1077 val = "%s (location)" % value.GetLocation()
1078 print("{indentation}({type}) {name} = {value}".format(
1079 indentation=' ' * indent,
1080 type=value.GetTypeName(),
1081 name=value.GetName(),
1082 value=val), file=output)
1083 return output.getvalue()
1086 class ChildVisitingFormatter(BasicFormatter):
1087 """The child visiting formatter prints the value and its immediate children.
1089 The constructor takes a keyword arg: indent_child, which defaults to 2.
1092 def __init__(self, indent_child=2):
1093 """Default indentation of 2 SPC's for the children."""
1094 self.cindent = indent_child
1096 def format(self, value, buffer=None):
1098 output = SixStringIO()
1102 BasicFormatter.format(self, value, buffer=output)
1104 BasicFormatter.format(
1105 self, child, buffer=output, indent=self.cindent)
1107 return output.getvalue()
1110 class RecursiveDecentFormatter(BasicFormatter):
1111 """The recursive decent formatter prints the value and the decendents.
1113 The constructor takes two keyword args: indent_level, which defaults to 0,
1114 and indent_child, which defaults to 2. The current indentation level is
1115 determined by indent_level, while the immediate children has an additional
1116 indentation by inden_child.
1119 def __init__(self, indent_level=0, indent_child=2):
1120 self.lindent = indent_level
1121 self.cindent = indent_child
1123 def format(self, value, buffer=None):
1125 output = SixStringIO()
1129 BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1130 new_indent = self.lindent + self.cindent
1132 if child.GetSummary() is not None:
1133 BasicFormatter.format(
1134 self, child, buffer=output, indent=new_indent)
1136 if child.GetNumChildren() > 0:
1137 rdf = RecursiveDecentFormatter(indent_level=new_indent)
1138 rdf.format(child, buffer=output)
1140 BasicFormatter.format(
1141 self, child, buffer=output, indent=new_indent)
1143 return output.getvalue()
1145 # ===========================================================
1146 # Utility functions for path manipulation on remote platforms
1147 # ===========================================================
1150 def join_remote_paths(*paths):
1151 # TODO: update with actual platform name for remote windows once it exists
1152 if lldb.remote_platform.GetName() == 'remote-windows':
1153 return os.path.join(*paths).replace(os.path.sep, '\\')
1154 return os.path.join(*paths).replace(os.path.sep, '/')
1157 def append_to_process_working_directory(*paths):
1158 remote = lldb.remote_platform
1160 return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1161 return os.path.join(os.getcwd(), *paths)
1163 # ==================================================
1164 # Utility functions to get the correct signal number
1165 # ==================================================
1170 def get_signal_number(signal_name):
1171 platform = lldb.remote_platform
1172 if platform and platform.IsValid():
1173 signals = platform.GetUnixSignals()
1174 if signals.IsValid():
1175 signal_number = signals.GetSignalNumberFromName(signal_name)
1176 if signal_number > 0:
1177 return signal_number
1178 # No remote platform; fall back to using local python signals.
1179 return getattr(signal, signal_name)
1182 class PrintableRegex(object):
1184 def __init__(self, text):
1185 self.regex = re.compile(text)
1188 def match(self, str):
1189 return self.regex.match(str)
1192 return "%s" % (self.text)
1195 return "re.compile(%s) -> %s" % (self.text, self.regex)
1198 def skip_if_callable(test, mycallable, reason):
1199 if six.callable(mycallable):
1200 if mycallable(test):
1201 test.skipTest(reason)
1206 def skip_if_library_missing(test, target, library):
1207 def find_library(target, library):
1208 for module in target.modules:
1209 filename = module.file.GetFilename()
1210 if isinstance(library, str):
1211 if library == filename:
1213 elif hasattr(library, 'match'):
1214 if library.match(filename):
1218 def find_library_callable(test):
1219 return find_library(target, library)
1220 return skip_if_callable(
1222 find_library_callable,
1223 "could not find library matching '%s' in target %s" %
1228 def wait_for_file_on_target(testcase, file_path, max_attempts=6):
1229 for i in range(max_attempts):
1230 err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1231 if err.Success() and retcode == 0:
1233 if i < max_attempts:
1234 # Exponential backoff!
1236 time.sleep(pow(2, i) * 0.25)
1239 "File %s not found even after %d attempts." %
1240 (file_path, max_attempts))
1242 err, retcode, data = testcase.run_platform_command("cat %s" % (file_path))
1244 testcase.assertTrue(
1245 err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" %
1246 (file_path, err.GetCString(), retcode))