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
17 from six import StringIO as SixStringIO
22 from . import lldbtest_config
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)
51 if e.errno != errno.EEXIST:
53 if not os.path.isdir(path):
54 raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
55 # ===================================================
56 # Disassembly for an SBFunction or an SBSymbol object
57 # ===================================================
60 def disassemble(target, function_or_symbol):
61 """Disassemble the function or symbol given a target.
63 It returns the disassembly content in a string object.
66 insts = function_or_symbol.GetInstructions(target)
71 # ==========================================================
72 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
73 # ==========================================================
76 def int_to_bytearray(val, bytesize):
77 """Utility function to convert an integer into a bytearray.
79 It returns the bytearray in the little endian format. It is easy to get the
80 big endian format, just do ba.reverse() on the returned object.
85 return bytearray([val])
87 # Little endian followed by a format character.
98 packed = struct.pack(fmt, val)
99 return bytearray(packed)
102 def bytearray_to_int(bytes, bytesize):
103 """Utility function to convert a bytearray into an integer.
105 It interprets the bytearray in the little endian format. For a big endian
106 bytearray, just do ba.reverse() on the object before passing it in.
113 # Little endian followed by a format character.
124 unpacked = struct.unpack_from(fmt, bytes)
128 # ==============================================================
129 # Get the description of an lldb object or None if not available
130 # ==============================================================
131 def get_description(obj, option=None):
132 """Calls lldb_obj.GetDescription() and returns a string, or None.
134 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
135 option can be passed in to describe the detailed level of description
137 o lldb.eDescriptionLevelBrief
138 o lldb.eDescriptionLevelFull
139 o lldb.eDescriptionLevelVerbose
141 method = getattr(obj, 'GetDescription')
144 tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
145 if isinstance(obj, tuple):
147 option = lldb.eDescriptionLevelBrief
149 stream = lldb.SBStream()
151 success = method(stream)
153 success = method(stream, option)
156 return stream.GetData()
159 # =================================================
160 # Convert some enum value to its string counterpart
161 # =================================================
163 def state_type_to_str(enum):
164 """Returns the stateType string given an enum."""
165 if enum == lldb.eStateInvalid:
167 elif enum == lldb.eStateUnloaded:
169 elif enum == lldb.eStateConnected:
171 elif enum == lldb.eStateAttaching:
173 elif enum == lldb.eStateLaunching:
175 elif enum == lldb.eStateStopped:
177 elif enum == lldb.eStateRunning:
179 elif enum == lldb.eStateStepping:
181 elif enum == lldb.eStateCrashed:
183 elif enum == lldb.eStateDetached:
185 elif enum == lldb.eStateExited:
187 elif enum == lldb.eStateSuspended:
190 raise Exception("Unknown StateType enum")
193 def stop_reason_to_str(enum):
194 """Returns the stopReason string given an enum."""
195 if enum == lldb.eStopReasonInvalid:
197 elif enum == lldb.eStopReasonNone:
199 elif enum == lldb.eStopReasonTrace:
201 elif enum == lldb.eStopReasonBreakpoint:
203 elif enum == lldb.eStopReasonWatchpoint:
205 elif enum == lldb.eStopReasonExec:
207 elif enum == lldb.eStopReasonSignal:
209 elif enum == lldb.eStopReasonException:
211 elif enum == lldb.eStopReasonPlanComplete:
212 return "plancomplete"
213 elif enum == lldb.eStopReasonThreadExiting:
214 return "threadexiting"
216 raise Exception("Unknown StopReason enum")
219 def symbol_type_to_str(enum):
220 """Returns the symbolType string given an enum."""
221 if enum == lldb.eSymbolTypeInvalid:
223 elif enum == lldb.eSymbolTypeAbsolute:
225 elif enum == lldb.eSymbolTypeCode:
227 elif enum == lldb.eSymbolTypeData:
229 elif enum == lldb.eSymbolTypeTrampoline:
231 elif enum == lldb.eSymbolTypeRuntime:
233 elif enum == lldb.eSymbolTypeException:
235 elif enum == lldb.eSymbolTypeSourceFile:
237 elif enum == lldb.eSymbolTypeHeaderFile:
239 elif enum == lldb.eSymbolTypeObjectFile:
241 elif enum == lldb.eSymbolTypeCommonBlock:
243 elif enum == lldb.eSymbolTypeBlock:
245 elif enum == lldb.eSymbolTypeLocal:
247 elif enum == lldb.eSymbolTypeParam:
249 elif enum == lldb.eSymbolTypeVariable:
251 elif enum == lldb.eSymbolTypeVariableType:
252 return "variabletype"
253 elif enum == lldb.eSymbolTypeLineEntry:
255 elif enum == lldb.eSymbolTypeLineHeader:
257 elif enum == lldb.eSymbolTypeScopeBegin:
259 elif enum == lldb.eSymbolTypeScopeEnd:
261 elif enum == lldb.eSymbolTypeAdditional:
263 elif enum == lldb.eSymbolTypeCompiler:
265 elif enum == lldb.eSymbolTypeInstrumentation:
266 return "instrumentation"
267 elif enum == lldb.eSymbolTypeUndefined:
271 def value_type_to_str(enum):
272 """Returns the valueType string given an enum."""
273 if enum == lldb.eValueTypeInvalid:
275 elif enum == lldb.eValueTypeVariableGlobal:
276 return "global_variable"
277 elif enum == lldb.eValueTypeVariableStatic:
278 return "static_variable"
279 elif enum == lldb.eValueTypeVariableArgument:
280 return "argument_variable"
281 elif enum == lldb.eValueTypeVariableLocal:
282 return "local_variable"
283 elif enum == lldb.eValueTypeRegister:
285 elif enum == lldb.eValueTypeRegisterSet:
286 return "register_set"
287 elif enum == lldb.eValueTypeConstResult:
288 return "constant_result"
290 raise Exception("Unknown ValueType enum")
293 # ==================================================
294 # Get stopped threads due to each stop reason.
295 # ==================================================
297 def sort_stopped_threads(process,
298 breakpoint_threads=None,
299 crashed_threads=None,
300 watchpoint_threads=None,
302 exiting_threads=None,
304 """ Fills array *_threads with threads stopped for the corresponding stop
307 for lst in [breakpoint_threads,
315 for thread in process:
317 for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
318 (lldb.eStopReasonException, crashed_threads),
319 (lldb.eStopReasonWatchpoint, watchpoint_threads),
320 (lldb.eStopReasonSignal, signal_threads),
321 (lldb.eStopReasonThreadExiting, exiting_threads),
322 (None, other_threads)]:
323 if not dispatched and list is not None:
324 if thread.GetStopReason() == reason or reason is None:
328 # ==================================================
329 # Utility functions for setting breakpoints
330 # ==================================================
332 def run_break_set_by_script(
336 num_expected_locations=1):
337 """Set a scripted breakpoint. Check that it got the right number of locations."""
338 test.assertTrue(class_name is not None, "Must pass in a class name.")
339 command = "breakpoint set -P " + class_name
340 if extra_options is not None:
341 command += " " + extra_options
343 break_results = run_break_set_command(test, command)
344 check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
345 return get_bpno_from_match(break_results)
347 def run_break_set_by_file_and_line(
352 num_expected_locations=1,
355 """Set a breakpoint by file and line, returning the breakpoint number.
357 If extra_options is not None, then we append it to the breakpoint set command.
359 If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
360 check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
362 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
364 if file_name is None:
365 command = 'breakpoint set -l %d' % (line_number)
367 command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
370 command += " --shlib '%s'" % (module_name)
373 command += " " + extra_options
375 break_results = run_break_set_command(test, command)
377 if num_expected_locations == 1 and loc_exact:
378 check_breakpoint_result(
381 num_locations=num_expected_locations,
383 line_number=line_number,
384 module_name=module_name)
386 check_breakpoint_result(
389 num_locations=num_expected_locations)
391 return get_bpno_from_match(break_results)
394 def run_break_set_by_symbol(
398 num_expected_locations=-1,
401 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
403 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
404 command = 'breakpoint set -n "%s"' % (symbol)
407 command += " --shlib '%s'" % (module_name)
410 command += " " + extra_options
412 break_results = run_break_set_command(test, command)
414 if num_expected_locations == 1 and sym_exact:
415 check_breakpoint_result(
418 num_locations=num_expected_locations,
420 module_name=module_name)
422 check_breakpoint_result(
425 num_locations=num_expected_locations)
427 return get_bpno_from_match(break_results)
430 def run_break_set_by_selector(
434 num_expected_locations=-1,
436 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
438 command = 'breakpoint set -S "%s"' % (selector)
441 command += ' --shlib "%s"' % (module_name)
444 command += " " + extra_options
446 break_results = run_break_set_command(test, command)
448 if num_expected_locations == 1:
449 check_breakpoint_result(
452 num_locations=num_expected_locations,
453 symbol_name=selector,
454 symbol_match_exact=False,
455 module_name=module_name)
457 check_breakpoint_result(
460 num_locations=num_expected_locations)
462 return get_bpno_from_match(break_results)
465 def run_break_set_by_regexp(
469 num_expected_locations=-1):
470 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
472 command = 'breakpoint set -r "%s"' % (regexp)
474 command += " " + extra_options
476 break_results = run_break_set_command(test, command)
478 check_breakpoint_result(
481 num_locations=num_expected_locations)
483 return get_bpno_from_match(break_results)
486 def run_break_set_by_source_regexp(
490 num_expected_locations=-1):
491 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
492 command = 'breakpoint set -p "%s"' % (regexp)
494 command += " " + extra_options
496 break_results = run_break_set_command(test, command)
498 check_breakpoint_result(
501 num_locations=num_expected_locations)
503 return get_bpno_from_match(break_results)
506 def run_break_set_command(test, command):
507 """Run the command passed in - it must be some break set variant - and analyze the result.
508 Returns a dictionary of information gleaned from the command-line results.
509 Will assert if the breakpoint setting fails altogether.
511 Dictionary will contain:
512 bpno - breakpoint of the newly created breakpoint, -1 on error.
513 num_locations - number of locations set for the breakpoint.
515 If there is only one location, the dictionary MAY contain:
516 file - source file name
517 line_no - source line number
519 inline_symbol - inlined symbol name
520 offset - offset from the original symbol
522 address - address at which the breakpoint was set."""
525 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
526 r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
527 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]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$",
528 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]+)$"]
529 match_object = test.match(command, patterns)
530 break_results = match_object.groupdict()
532 # We always insert the breakpoint number, setting it to -1 if we couldn't find it
533 # Also, make sure it gets stored as an integer.
534 if not 'bpno' in break_results:
535 break_results['bpno'] = -1
537 break_results['bpno'] = int(break_results['bpno'])
539 # We always insert the number of locations
540 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
541 # We also make sure it is an integer.
543 if not 'num_locations' in break_results:
546 num_locations = break_results['num_locations']
547 if num_locations == 'no':
550 num_locations = int(break_results['num_locations'])
552 break_results['num_locations'] = num_locations
554 if 'line_no' in break_results:
555 break_results['line_no'] = int(break_results['line_no'])
560 def get_bpno_from_match(break_results):
561 return int(break_results['bpno'])
564 def check_breakpoint_result(
570 symbol_match_exact=True,
575 out_num_locations = break_results['num_locations']
577 if num_locations == -1:
578 test.assertTrue(out_num_locations > 0,
579 "Expecting one or more locations, got none.")
580 elif num_locations != -2:
582 num_locations == out_num_locations,
583 "Expecting %d locations, got %d." %
589 if 'file' in break_results:
590 out_file_name = break_results['file']
592 file_name.endswith(out_file_name),
593 "Breakpoint file name '%s' doesn't match resultant name '%s'." %
597 if line_number != -1:
599 if 'line_no' in break_results:
600 out_line_number = break_results['line_no']
603 line_number == out_line_number,
604 "Breakpoint line number %s doesn't match resultant line %s." %
610 # Look first for the inlined symbol name, otherwise use the symbol
612 if 'inline_symbol' in break_results and break_results['inline_symbol']:
613 out_symbol_name = break_results['inline_symbol']
614 elif 'symbol' in break_results:
615 out_symbol_name = break_results['symbol']
617 if symbol_match_exact:
619 symbol_name == out_symbol_name,
620 "Symbol name '%s' doesn't match resultant symbol '%s'." %
625 out_symbol_name.find(symbol_name) != -
627 "Symbol name '%s' isn't in resultant symbol '%s'." %
632 out_module_name = None
633 if 'module' in break_results:
634 out_module_name = break_results['module']
637 module_name.find(out_module_name) != -
639 "Symbol module name '%s' isn't in expected module name '%s'." %
643 # ==================================================
644 # Utility functions related to Threads and Processes
645 # ==================================================
648 def get_stopped_threads(process, reason):
649 """Returns the thread(s) with the specified stop reason in a list.
651 The list can be empty if no such thread exists.
655 if t.GetStopReason() == reason:
660 def get_stopped_thread(process, reason):
661 """A convenience function which returns the first thread with the given stop
666 1. Get the stopped thread due to a breakpoint condition
669 from lldbutil import get_stopped_thread
670 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
671 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
674 2. Get the thread stopped due to a breakpoint
677 from lldbutil import get_stopped_thread
678 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
679 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
683 threads = get_stopped_threads(process, reason)
684 if len(threads) == 0:
689 def get_threads_stopped_at_breakpoint_id(process, bpid):
690 """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
694 stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
696 if len(stopped_threads) == 0:
699 for thread in stopped_threads:
700 # Make sure we've hit our breakpoint...
701 break_id = thread.GetStopReasonDataAtIndex(0)
703 threads.append(thread)
708 def get_threads_stopped_at_breakpoint(process, bkpt):
709 return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
712 def get_one_thread_stopped_at_breakpoint_id(
713 process, bpid, require_exactly_one=True):
714 threads = get_threads_stopped_at_breakpoint_id(process, bpid)
715 if len(threads) == 0:
717 if require_exactly_one and len(threads) != 1:
723 def get_one_thread_stopped_at_breakpoint(
724 process, bkpt, require_exactly_one=True):
725 return get_one_thread_stopped_at_breakpoint_id(
726 process, bkpt.GetID(), require_exactly_one)
729 def is_thread_crashed(test, thread):
730 """In the test suite we dereference a null pointer to simulate a crash. The way this is
731 reported depends on the platform."""
732 if test.platformIsDarwin():
733 return thread.GetStopReason(
734 ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
735 elif test.getPlatform() == "linux":
736 return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
737 0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
738 elif test.getPlatform() == "windows":
739 return "Exception 0xc0000005" in thread.GetStopDescription(200)
741 return "invalid address" in thread.GetStopDescription(100)
744 def get_crashed_threads(test, process):
746 if process.GetState() != lldb.eStateStopped:
748 for thread in process:
749 if is_thread_crashed(test, thread):
750 threads.append(thread)
753 # Helper functions for run_to_{source,name}_breakpoint:
755 def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
757 exe = test.getBuildArtifact(exe_name)
760 target = test.dbg.CreateTarget(exe)
761 test.assertTrue(target, "Target: %s is not valid."%(exe_name))
763 # Set environment variables for the inferior.
764 if lldbtest_config.inferior_env:
765 test.runCmd('settings set target.env-vars {}'.format(
766 lldbtest_config.inferior_env))
770 def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None,
771 only_one_thread = True, extra_images = None):
773 # Launch the process, and do not stop at the entry point.
775 launch_info = target.GetLaunchInfo()
776 launch_info.SetWorkingDirectory(test.get_process_working_directory())
779 environ = test.registerSharedLibrariesWithTarget(target, extra_images)
780 launch_info.SetEnvironmentEntries(environ, True)
782 error = lldb.SBError()
783 process = target.Launch(launch_info, error)
785 test.assertTrue(process,
786 "Could not create a valid process for %s: %s"%(target.GetExecutable().GetFilename(),
788 test.assertFalse(error.Fail(),
789 "Process launch failed: %s" % (error.GetCString()))
791 test.assertEqual(process.GetState(), lldb.eStateStopped)
793 # Frame #0 should be at our breakpoint.
794 threads = get_threads_stopped_at_breakpoint(
797 num_threads = len(threads)
799 test.assertEqual(num_threads, 1, "Expected 1 thread to stop at breakpoint, %d did."%(num_threads))
801 test.assertGreater(num_threads, 0, "No threads stopped at breakpoint")
804 return (target, process, thread, bkpt)
806 def run_to_name_breakpoint (test, bkpt_name, launch_info = None,
810 only_one_thread = True,
811 extra_images = None):
812 """Start up a target, using exe_name as the executable, and run it to
813 a breakpoint set by name on bkpt_name restricted to bkpt_module.
815 If you want to pass in launch arguments or environment
816 variables, you can optionally pass in an SBLaunchInfo. If you
817 do that, remember to set the working directory as well.
819 If your executable isn't called a.out, you can pass that in.
820 And if your executable isn't in the CWD, pass in the absolute
821 path to the executable in exe_name, and set in_cwd to False.
823 If you need to restrict the breakpoint to a particular module,
824 pass the module name (a string not a FileSpec) in bkpt_module. If
825 nothing is passed in setting will be unrestricted.
827 If the target isn't valid, the breakpoint isn't found, or hit, the
828 function will cause a testsuite failure.
830 If successful it returns a tuple with the target process and
831 thread that hit the breakpoint, and the breakpoint that we set
834 If only_one_thread is true, we require that there be only one
835 thread stopped at the breakpoint. Otherwise we only require one
836 or more threads stop there. If there are more than one, we return
837 the first thread that stopped.
840 target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
842 breakpoint = target.BreakpointCreateByName(bkpt_name, bkpt_module)
845 test.assertTrue(breakpoint.GetNumLocations() > 0,
846 "No locations found for name breakpoint: '%s'."%(bkpt_name))
847 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
848 only_one_thread, extra_images)
850 def run_to_source_breakpoint(test, bkpt_pattern, source_spec,
851 launch_info = None, exe_name = "a.out",
854 only_one_thread = True,
855 extra_images = None):
856 """Start up a target, using exe_name as the executable, and run it to
857 a breakpoint set by source regex bkpt_pattern.
859 The rest of the behavior is the same as run_to_name_breakpoint.
862 target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
863 # Set the breakpoints
864 breakpoint = target.BreakpointCreateBySourceRegex(
865 bkpt_pattern, source_spec, bkpt_module)
866 test.assertTrue(breakpoint.GetNumLocations() > 0,
867 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
868 %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
869 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
870 only_one_thread, extra_images)
872 def run_to_line_breakpoint(test, source_spec, line_number, column = 0,
873 launch_info = None, exe_name = "a.out",
876 only_one_thread = True,
877 extra_images = None):
878 """Start up a target, using exe_name as the executable, and run it to
879 a breakpoint set by (source_spec, line_number(, column)).
881 The rest of the behavior is the same as run_to_name_breakpoint.
884 target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
885 # Set the breakpoints
886 breakpoint = target.BreakpointCreateByLocation(
887 source_spec, line_number, column, 0, lldb.SBFileSpecList())
888 test.assertTrue(breakpoint.GetNumLocations() > 0,
889 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
890 %(source_spec.GetFilename(), line_number, column,
891 source_spec.GetDirectory()))
892 return run_to_breakpoint_do_run(test, target, breakpoint, launch_info,
893 only_one_thread, extra_images)
896 def continue_to_breakpoint(process, bkpt):
897 """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
899 if process.GetState() != lldb.eStateStopped:
902 return get_threads_stopped_at_breakpoint(process, bkpt)
905 def get_caller_symbol(thread):
907 Returns the symbol name for the call site of the leaf function.
909 depth = thread.GetNumFrames()
912 caller = thread.GetFrameAtIndex(1).GetSymbol()
914 return caller.GetName()
919 def get_function_names(thread):
921 Returns a sequence of function names from the stack frames of this thread.
924 return thread.GetFrameAtIndex(i).GetFunctionName()
926 return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
929 def get_symbol_names(thread):
931 Returns a sequence of symbols for this thread.
934 return thread.GetFrameAtIndex(i).GetSymbol().GetName()
936 return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
939 def get_pc_addresses(thread):
941 Returns a sequence of pc addresses for this thread.
944 return thread.GetFrameAtIndex(i).GetPCAddress()
946 return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
949 def get_filenames(thread):
951 Returns a sequence of file names from the stack frames of this thread.
954 return thread.GetFrameAtIndex(
955 i).GetLineEntry().GetFileSpec().GetFilename()
957 return list(map(GetFilename, list(range(thread.GetNumFrames()))))
960 def get_line_numbers(thread):
962 Returns a sequence of line numbers from the stack frames of this thread.
964 def GetLineNumber(i):
965 return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
967 return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
970 def get_module_names(thread):
972 Returns a sequence of module names from the stack frames of this thread.
974 def GetModuleName(i):
975 return thread.GetFrameAtIndex(
976 i).GetModule().GetFileSpec().GetFilename()
978 return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
981 def get_stack_frames(thread):
983 Returns a sequence of stack frames for this thread.
985 def GetStackFrame(i):
986 return thread.GetFrameAtIndex(i)
988 return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
991 def print_stacktrace(thread, string_buffer=False):
992 """Prints a simple stack trace of this thread."""
994 output = SixStringIO() if string_buffer else sys.stdout
995 target = thread.GetProcess().GetTarget()
997 depth = thread.GetNumFrames()
999 mods = get_module_names(thread)
1000 funcs = get_function_names(thread)
1001 symbols = get_symbol_names(thread)
1002 files = get_filenames(thread)
1003 lines = get_line_numbers(thread)
1004 addrs = get_pc_addresses(thread)
1006 if thread.GetStopReason() != lldb.eStopReasonInvalid:
1007 desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
1011 "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
1012 thread.GetThreadID(),
1014 thread.GetQueueName()) + desc,
1017 for i in range(depth):
1018 frame = thread.GetFrameAtIndex(i)
1019 function = frame.GetFunction()
1021 load_addr = addrs[i].GetLoadAddress(target)
1023 file_addr = addrs[i].GetFileAddress()
1024 start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
1025 symbol_offset = file_addr - start_addr
1027 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
1032 offset=symbol_offset),
1036 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
1040 func='%s [inlined]' %
1041 funcs[i] if frame.IsInlined() else funcs[i],
1044 args=get_args_as_string(
1046 showFuncName=False) if not frame.IsInlined() else '()'),
1050 return output.getvalue()
1053 def print_stacktraces(process, string_buffer=False):
1054 """Prints the stack traces of all the threads."""
1056 output = SixStringIO() if string_buffer else sys.stdout
1058 print("Stack traces for " + str(process), file=output)
1060 for thread in process:
1061 print(print_stacktrace(thread, string_buffer=True), file=output)
1064 return output.getvalue()
1067 def expect_state_changes(test, listener, process, states, timeout=30):
1068 """Listens for state changed events on the listener and makes sure they match what we
1069 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
1071 for expected_state in states:
1072 def get_next_event():
1073 event = lldb.SBEvent()
1074 if not listener.WaitForEventForBroadcasterWithType(
1076 process.GetBroadcaster(),
1077 lldb.SBProcess.eBroadcastBitStateChanged,
1080 "Timed out while waiting for a transition to state %s" %
1081 lldb.SBDebugger.StateAsCString(expected_state))
1084 event = get_next_event()
1085 while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
1086 lldb.SBProcess.GetRestartedFromEvent(event)):
1087 # Ignore restarted event and the subsequent running event.
1088 event = get_next_event()
1090 lldb.SBProcess.GetStateFromEvent(event),
1092 "Restarted event followed by a running event")
1093 event = get_next_event()
1096 lldb.SBProcess.GetStateFromEvent(event),
1099 # ===================================
1100 # Utility functions related to Frames
1101 # ===================================
1104 def get_parent_frame(frame):
1106 Returns the parent frame of the input frame object; None if not available.
1108 thread = frame.GetThread()
1109 parent_found = False
1113 if f.GetFrameID() == frame.GetFrameID():
1116 # If we reach here, no parent has been found, return None.
1120 def get_args_as_string(frame, showFuncName=True):
1122 Returns the args of the input frame object as a string.
1127 # in_scope_only => True
1128 vars = frame.GetVariables(True, False, False, True) # type of SBValueList
1129 args = [] # list of strings
1131 args.append("(%s)%s=%s" % (var.GetTypeName(),
1134 if frame.GetFunction():
1135 name = frame.GetFunction().GetName()
1136 elif frame.GetSymbol():
1137 name = frame.GetSymbol().GetName()
1141 return "%s(%s)" % (name, ", ".join(args))
1143 return "(%s)" % (", ".join(args))
1146 def print_registers(frame, string_buffer=False):
1147 """Prints all the register sets of the frame."""
1149 output = SixStringIO() if string_buffer else sys.stdout
1151 print("Register sets for " + str(frame), file=output)
1153 registerSet = frame.GetRegisters() # Return type of SBValueList.
1154 print("Frame registers (size of register set = %d):" %
1155 registerSet.GetSize(), file=output)
1156 for value in registerSet:
1157 #print(value, file=output)
1158 print("%s (number of children = %d):" %
1159 (value.GetName(), value.GetNumChildren()), file=output)
1162 "Name: %s, Value: %s" %
1168 return output.getvalue()
1171 def get_registers(frame, kind):
1172 """Returns the registers given the frame and the kind of registers desired.
1174 Returns None if there's no such kind.
1176 registerSet = frame.GetRegisters() # Return type of SBValueList.
1177 for value in registerSet:
1178 if kind.lower() in value.GetName().lower():
1184 def get_GPRs(frame):
1185 """Returns the general purpose registers of the frame as an SBValue.
1187 The returned SBValue object is iterable. An example:
1189 from lldbutil import get_GPRs
1190 regs = get_GPRs(frame)
1192 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1195 return get_registers(frame, "general purpose")
1198 def get_FPRs(frame):
1199 """Returns the floating point registers of the frame as an SBValue.
1201 The returned SBValue object is iterable. An example:
1203 from lldbutil import get_FPRs
1204 regs = get_FPRs(frame)
1206 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1209 return get_registers(frame, "floating point")
1212 def get_ESRs(frame):
1213 """Returns the exception state registers of the frame as an SBValue.
1215 The returned SBValue object is iterable. An example:
1217 from lldbutil import get_ESRs
1218 regs = get_ESRs(frame)
1220 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1223 return get_registers(frame, "exception state")
1225 # ======================================
1226 # Utility classes/functions for SBValues
1227 # ======================================
1230 class BasicFormatter(object):
1231 """The basic formatter inspects the value object and prints the value."""
1233 def format(self, value, buffer=None, indent=0):
1235 output = SixStringIO()
1238 # If there is a summary, it suffices.
1239 val = value.GetSummary()
1240 # Otherwise, get the value.
1242 val = value.GetValue()
1243 if val is None and value.GetNumChildren() > 0:
1244 val = "%s (location)" % value.GetLocation()
1245 print("{indentation}({type}) {name} = {value}".format(
1246 indentation=' ' * indent,
1247 type=value.GetTypeName(),
1248 name=value.GetName(),
1249 value=val), file=output)
1250 return output.getvalue()
1253 class ChildVisitingFormatter(BasicFormatter):
1254 """The child visiting formatter prints the value and its immediate children.
1256 The constructor takes a keyword arg: indent_child, which defaults to 2.
1259 def __init__(self, indent_child=2):
1260 """Default indentation of 2 SPC's for the children."""
1261 self.cindent = indent_child
1263 def format(self, value, buffer=None):
1265 output = SixStringIO()
1269 BasicFormatter.format(self, value, buffer=output)
1271 BasicFormatter.format(
1272 self, child, buffer=output, indent=self.cindent)
1274 return output.getvalue()
1277 class RecursiveDecentFormatter(BasicFormatter):
1278 """The recursive decent formatter prints the value and the decendents.
1280 The constructor takes two keyword args: indent_level, which defaults to 0,
1281 and indent_child, which defaults to 2. The current indentation level is
1282 determined by indent_level, while the immediate children has an additional
1283 indentation by inden_child.
1286 def __init__(self, indent_level=0, indent_child=2):
1287 self.lindent = indent_level
1288 self.cindent = indent_child
1290 def format(self, value, buffer=None):
1292 output = SixStringIO()
1296 BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1297 new_indent = self.lindent + self.cindent
1299 if child.GetSummary() is not None:
1300 BasicFormatter.format(
1301 self, child, buffer=output, indent=new_indent)
1303 if child.GetNumChildren() > 0:
1304 rdf = RecursiveDecentFormatter(indent_level=new_indent)
1305 rdf.format(child, buffer=output)
1307 BasicFormatter.format(
1308 self, child, buffer=output, indent=new_indent)
1310 return output.getvalue()
1312 # ===========================================================
1313 # Utility functions for path manipulation on remote platforms
1314 # ===========================================================
1317 def join_remote_paths(*paths):
1318 # TODO: update with actual platform name for remote windows once it exists
1319 if lldb.remote_platform.GetName() == 'remote-windows':
1320 return os.path.join(*paths).replace(os.path.sep, '\\')
1321 return os.path.join(*paths).replace(os.path.sep, '/')
1324 def append_to_process_working_directory(test, *paths):
1325 remote = lldb.remote_platform
1327 return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1328 return os.path.join(test.getBuildDir(), *paths)
1330 # ==================================================
1331 # Utility functions to get the correct signal number
1332 # ==================================================
1337 def get_signal_number(signal_name):
1338 platform = lldb.remote_platform
1339 if platform and platform.IsValid():
1340 signals = platform.GetUnixSignals()
1341 if signals.IsValid():
1342 signal_number = signals.GetSignalNumberFromName(signal_name)
1343 if signal_number > 0:
1344 return signal_number
1345 # No remote platform; fall back to using local python signals.
1346 return getattr(signal, signal_name)
1349 class PrintableRegex(object):
1351 def __init__(self, text):
1352 self.regex = re.compile(text)
1355 def match(self, str):
1356 return self.regex.match(str)
1359 return "%s" % (self.text)
1362 return "re.compile(%s) -> %s" % (self.text, self.regex)
1365 def skip_if_callable(test, mycallable, reason):
1366 if six.callable(mycallable):
1367 if mycallable(test):
1368 test.skipTest(reason)
1373 def skip_if_library_missing(test, target, library):
1374 def find_library(target, library):
1375 for module in target.modules:
1376 filename = module.file.GetFilename()
1377 if isinstance(library, str):
1378 if library == filename:
1380 elif hasattr(library, 'match'):
1381 if library.match(filename):
1385 def find_library_callable(test):
1386 return find_library(target, library)
1387 return skip_if_callable(
1389 find_library_callable,
1390 "could not find library matching '%s' in target %s" %
1395 def read_file_on_target(test, remote):
1396 if lldb.remote_platform:
1397 local = test.getBuildArtifact("file_from_target")
1398 error = lldb.remote_platform.Get(lldb.SBFileSpec(remote, False),
1399 lldb.SBFileSpec(local, True))
1400 test.assertTrue(error.Success(), "Reading file {0} failed: {1}".format(remote, error))
1403 with open(local, 'r') as f:
1406 def read_file_from_process_wd(test, name):
1407 path = append_to_process_working_directory(test, name)
1408 return read_file_on_target(test, path)
1410 def wait_for_file_on_target(testcase, file_path, max_attempts=6):
1411 for i in range(max_attempts):
1412 err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1413 if err.Success() and retcode == 0:
1415 if i < max_attempts:
1416 # Exponential backoff!
1418 time.sleep(pow(2, i) * 0.25)
1421 "File %s not found even after %d attempts." %
1422 (file_path, max_attempts))
1424 return read_file_on_target(testcase, file_path)