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.
14 from typing
import Dict
18 from . import lldbtest_config
19 from . import configuration
21 # How often failed simulator process launches are retried.
24 # ===================================================
25 # Utilities for locating/checking executable programs
26 # ===================================================
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
)
52 if e
.errno
!= errno
.EEXIST
:
54 if not os
.path
.isdir(path
):
55 raise OSError(errno
.ENOTDIR
, "%s is not a directory" % path
)
58 # ============================
59 # Dealing with SDK and triples
60 # ============================
63 def get_xcode_sdk(os
, env
):
64 # Respect --apple-sdk <path> if it's specified. If the SDK is simply
65 # mounted from some disk image, and not actually installed, this is the
67 if configuration
.apple_sdk
:
68 return configuration
.apple_sdk
70 if env
== "simulator":
71 return "iphonesimulator"
76 if env
== "simulator":
77 return "appletvsimulator"
80 if env
== "simulator":
81 return "watchsimulator"
86 def get_xcode_sdk_version(sdk
):
88 subprocess
.check_output(["xcrun", "--sdk", sdk
, "--show-sdk-version"])
94 def get_xcode_sdk_root(sdk
):
96 subprocess
.check_output(["xcrun", "--sdk", sdk
, "--show-sdk-path"])
102 def get_xcode_clang(sdk
):
104 subprocess
.check_output(["xcrun", "-sdk", sdk
, "-f", "clang"])
110 # ===================================================
111 # Disassembly for an SBFunction or an SBSymbol object
112 # ===================================================
115 def disassemble(target
, function_or_symbol
):
116 """Disassemble the function or symbol given a target.
118 It returns the disassembly content in a string object.
121 insts
= function_or_symbol
.GetInstructions(target
)
124 return buf
.getvalue()
127 # ==========================================================
128 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
129 # ==========================================================
132 def int_to_bytearray(val
, bytesize
):
133 """Utility function to convert an integer into a bytearray.
135 It returns the bytearray in the little endian format. It is easy to get the
136 big endian format, just do ba.reverse() on the returned object.
141 return bytearray([val
])
143 # Little endian followed by a format character.
154 packed
= struct
.pack(fmt
, val
)
155 return bytearray(packed
)
158 def bytearray_to_int(bytes
, bytesize
):
159 """Utility function to convert a bytearray into an integer.
161 It interprets the bytearray in the little endian format. For a big endian
162 bytearray, just do ba.reverse() on the object before passing it in.
169 # Little endian followed by a format character.
180 unpacked
= struct
.unpack_from(fmt
, bytes
)
184 # ==============================================================
185 # Get the description of an lldb object or None if not available
186 # ==============================================================
187 def get_description(obj
, option
=None):
188 """Calls lldb_obj.GetDescription() and returns a string, or None.
190 For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
191 option can be passed in to describe the detailed level of description
193 o lldb.eDescriptionLevelBrief
194 o lldb.eDescriptionLevelFull
195 o lldb.eDescriptionLevelVerbose
197 method
= getattr(obj
, "GetDescription")
200 tuple = (lldb
.SBTarget
, lldb
.SBBreakpointLocation
, lldb
.SBWatchpoint
)
201 if isinstance(obj
, tuple):
203 option
= lldb
.eDescriptionLevelBrief
205 stream
= lldb
.SBStream()
207 success
= method(stream
)
209 success
= method(stream
, option
)
212 return stream
.GetData()
215 # =================================================
216 # Convert some enum value to its string counterpart
217 # =================================================
220 def _enum_names(prefix
: str) -> Dict
[int, str]:
221 """Generate a mapping of enum value to name, for the enum prefix."""
222 suffix_start
= len(prefix
)
224 getattr(lldb
, attr
): attr
[suffix_start
:].lower()
225 for attr
in dir(lldb
)
226 if attr
.startswith(prefix
)
230 _STATE_NAMES
= _enum_names(prefix
="eState")
233 def state_type_to_str(enum
: int) -> str:
234 """Returns the stateType string given an enum."""
235 name
= _STATE_NAMES
.get(enum
)
238 raise Exception(f
"Unknown StateType enum: {enum}")
241 _STOP_REASON_NAMES
= _enum_names(prefix
="eStopReason")
244 def stop_reason_to_str(enum
: int) -> str:
245 """Returns the stopReason string given an enum."""
246 name
= _STOP_REASON_NAMES
.get(enum
)
249 raise Exception(f
"Unknown StopReason enum: {enum}")
252 _SYMBOL_TYPE_NAMES
= _enum_names(prefix
="eSymbolType")
255 def symbol_type_to_str(enum
: int) -> str:
256 """Returns the symbolType string given an enum."""
257 name
= _SYMBOL_TYPE_NAMES
.get(enum
)
260 raise Exception(f
"Unknown SymbolType enum: {enum}")
263 _VALUE_TYPE_NAMES
= _enum_names(prefix
="eValueType")
266 def value_type_to_str(enum
: int) -> str:
267 """Returns the valueType string given an enum."""
268 name
= _VALUE_TYPE_NAMES
.get(enum
)
271 raise Exception(f
"Unknown ValueType enum: {enum}")
274 # ==================================================
275 # Get stopped threads due to each stop reason.
276 # ==================================================
279 def sort_stopped_threads(
281 breakpoint_threads
=None,
282 crashed_threads
=None,
283 watchpoint_threads
=None,
285 exiting_threads
=None,
288 """Fills array *_threads with threads stopped for the corresponding stop
301 for thread
in process
:
303 for reason
, list in [
304 (lldb
.eStopReasonBreakpoint
, breakpoint_threads
),
305 (lldb
.eStopReasonException
, crashed_threads
),
306 (lldb
.eStopReasonWatchpoint
, watchpoint_threads
),
307 (lldb
.eStopReasonSignal
, signal_threads
),
308 (lldb
.eStopReasonThreadExiting
, exiting_threads
),
309 (None, other_threads
),
311 if not dispatched
and list is not None:
312 if thread
.GetStopReason() == reason
or reason
is None:
317 # ==================================================
318 # Utility functions for setting breakpoints
319 # ==================================================
322 def run_break_set_by_script(
323 test
, class_name
, extra_options
=None, num_expected_locations
=1
325 """Set a scripted breakpoint. Check that it got the right number of locations."""
326 test
.assertTrue(class_name
is not None, "Must pass in a class name.")
327 command
= "breakpoint set -P " + class_name
328 if extra_options
is not None:
329 command
+= " " + extra_options
331 break_results
= run_break_set_command(test
, command
)
332 check_breakpoint_result(test
, break_results
, num_locations
=num_expected_locations
)
333 return get_bpno_from_match(break_results
)
336 def run_break_set_by_file_and_line(
341 num_expected_locations
=1,
345 """Set a breakpoint by file and line, returning the breakpoint number.
347 If extra_options is not None, then we append it to the breakpoint set command.
349 If num_expected_locations is -1, we check that we got AT LEAST one location. If num_expected_locations is -2, we don't
350 check the actual number at all. Otherwise, we check that num_expected_locations equals the number of locations.
352 If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.
355 if file_name
is None:
356 command
= "breakpoint set -l %d" % (line_number
)
358 command
= 'breakpoint set -f "%s" -l %d' % (file_name
, line_number
)
361 command
+= " --shlib '%s'" % (module_name
)
364 command
+= " " + extra_options
366 break_results
= run_break_set_command(test
, command
)
368 if num_expected_locations
== 1 and loc_exact
:
369 check_breakpoint_result(
372 num_locations
=num_expected_locations
,
374 line_number
=line_number
,
375 module_name
=module_name
,
378 check_breakpoint_result(
379 test
, break_results
, num_locations
=num_expected_locations
382 return get_bpno_from_match(break_results
)
385 def run_break_set_by_symbol(
389 num_expected_locations
=-1,
393 """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
395 If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.
397 command
= 'breakpoint set -n "%s"' % (symbol
)
400 command
+= " --shlib '%s'" % (module_name
)
403 command
+= " " + extra_options
405 break_results
= run_break_set_command(test
, command
)
407 if num_expected_locations
== 1 and sym_exact
:
408 check_breakpoint_result(
411 num_locations
=num_expected_locations
,
413 module_name
=module_name
,
416 check_breakpoint_result(
417 test
, break_results
, num_locations
=num_expected_locations
420 return get_bpno_from_match(break_results
)
423 def run_break_set_by_selector(
424 test
, selector
, extra_options
=None, num_expected_locations
=-1, module_name
=None
426 """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
428 command
= 'breakpoint set -S "%s"' % (selector
)
431 command
+= ' --shlib "%s"' % (module_name
)
434 command
+= " " + extra_options
436 break_results
= run_break_set_command(test
, command
)
438 if num_expected_locations
== 1:
439 check_breakpoint_result(
442 num_locations
=num_expected_locations
,
443 symbol_name
=selector
,
444 symbol_match_exact
=False,
445 module_name
=module_name
,
448 check_breakpoint_result(
449 test
, break_results
, num_locations
=num_expected_locations
452 return get_bpno_from_match(break_results
)
455 def run_break_set_by_regexp(
456 test
, regexp
, extra_options
=None, num_expected_locations
=-1
458 """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
460 command
= 'breakpoint set -r "%s"' % (regexp
)
462 command
+= " " + extra_options
464 break_results
= run_break_set_command(test
, command
)
466 check_breakpoint_result(test
, break_results
, num_locations
=num_expected_locations
)
468 return get_bpno_from_match(break_results
)
471 def run_break_set_by_source_regexp(
472 test
, regexp
, extra_options
=None, num_expected_locations
=-1
474 """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
475 command
= 'breakpoint set -p "%s"' % (regexp
)
477 command
+= " " + extra_options
479 break_results
= run_break_set_command(test
, command
)
481 check_breakpoint_result(test
, break_results
, num_locations
=num_expected_locations
)
483 return get_bpno_from_match(break_results
)
486 def run_break_set_by_file_colon_line(
493 num_expected_locations
=-1,
495 command
= 'breakpoint set -y "%s"' % (specifier
)
497 command
+= " " + extra_options
499 print("About to run: '%s'", command
)
500 break_results
= run_break_set_command(test
, command
)
501 check_breakpoint_result(
504 num_locations
=num_expected_locations
,
506 line_number
=line_number
,
507 column_number
=column_number
,
510 return get_bpno_from_match(break_results
)
513 def run_break_set_command(test
, command
):
514 """Run the command passed in - it must be some break set variant - and analyze the result.
515 Returns a dictionary of information gleaned from the command-line results.
516 Will assert if the breakpoint setting fails altogether.
518 Dictionary will contain:
519 bpno - breakpoint of the newly created breakpoint, -1 on error.
520 num_locations - number of locations set for the breakpoint.
522 If there is only one location, the dictionary MAY contain:
523 file - source file name
524 line_no - source line number
525 column - source column number
527 inline_symbol - inlined symbol name
528 offset - offset from the original symbol
530 address - address at which the breakpoint was set."""
533 r
"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
534 r
"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
535 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]+)$",
536 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]+)$",
538 match_object
= test
.match(command
, patterns
)
539 break_results
= match_object
.groupdict()
541 # We always insert the breakpoint number, setting it to -1 if we couldn't find it
542 # Also, make sure it gets stored as an integer.
543 if not "bpno" in break_results
:
544 break_results
["bpno"] = -1
546 break_results
["bpno"] = int(break_results
["bpno"])
548 # We always insert the number of locations
549 # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
550 # We also make sure it is an integer.
552 if not "num_locations" in break_results
:
555 num_locations
= break_results
["num_locations"]
556 if num_locations
== "no":
559 num_locations
= int(break_results
["num_locations"])
561 break_results
["num_locations"] = num_locations
563 if "line_no" in break_results
:
564 break_results
["line_no"] = int(break_results
["line_no"])
569 def get_bpno_from_match(break_results
):
570 return int(break_results
["bpno"])
573 def check_breakpoint_result(
580 symbol_match_exact
=True,
585 out_num_locations
= break_results
["num_locations"]
587 if num_locations
== -1:
589 out_num_locations
> 0, "Expecting one or more locations, got none."
591 elif num_locations
!= -2:
593 num_locations
== out_num_locations
,
594 "Expecting %d locations, got %d." % (num_locations
, out_num_locations
),
599 if "file" in break_results
:
600 out_file_name
= break_results
["file"]
602 file_name
.endswith(out_file_name
),
603 "Breakpoint file name '%s' doesn't match resultant name '%s'."
604 % (file_name
, out_file_name
),
607 if line_number
!= -1:
609 if "line_no" in break_results
:
610 out_line_number
= break_results
["line_no"]
613 line_number
== out_line_number
,
614 "Breakpoint line number %s doesn't match resultant line %s."
615 % (line_number
, out_line_number
),
618 if column_number
!= 0:
619 out_column_number
= 0
620 if "column" in break_results
:
621 out_column_number
= break_results
["column"]
624 column_number
== out_column_number
,
625 "Breakpoint column number %s doesn't match resultant column %s."
626 % (column_number
, out_column_number
),
631 # Look first for the inlined symbol name, otherwise use the symbol
633 if "inline_symbol" in break_results
and break_results
["inline_symbol"]:
634 out_symbol_name
= break_results
["inline_symbol"]
635 elif "symbol" in break_results
:
636 out_symbol_name
= break_results
["symbol"]
638 if symbol_match_exact
:
640 symbol_name
== out_symbol_name
,
641 "Symbol name '%s' doesn't match resultant symbol '%s'."
642 % (symbol_name
, out_symbol_name
),
646 out_symbol_name
.find(symbol_name
) != -1,
647 "Symbol name '%s' isn't in resultant symbol '%s'."
648 % (symbol_name
, out_symbol_name
),
652 out_module_name
= None
653 if "module" in break_results
:
654 out_module_name
= break_results
["module"]
657 module_name
.find(out_module_name
) != -1,
658 "Symbol module name '%s' isn't in expected module name '%s'."
659 % (out_module_name
, module_name
),
663 def check_breakpoint(
666 expected_locations
=None,
667 expected_resolved_count
=None,
668 expected_hit_count
=None,
670 expected_location_resolved
=True,
671 expected_location_hit_count
=None,
674 Test breakpoint or breakpoint location.
675 Breakpoint resolved count is always checked. If not specified the assumption is that all locations
677 To test a breakpoint location, breakpoint number (bpno) and location_id must be set. In this case
678 the resolved count for a breakpoint is not tested by default. The location is expected to be resolved,
679 unless expected_location_resolved is set to False.
681 bpno - breakpoint number to test
682 expected_locations - expected number of locations for this breakpoint. If 'None' this parameter is not tested.
683 expected_resolved_count - expected resolved locations number for the breakpoint. If 'None' - all locations should be resolved.
684 expected_hit_count - expected hit count for this breakpoint. If 'None' this parameter is not tested.
685 location_id - If not 'None' sets the location ID for the breakpoint to test.
686 expected_location_resolved - Extected resolved status for the location_id (True/False). Default - True.
687 expected_location_hit_count - Expected hit count for the breakpoint at location_id. Must be set if the location_id parameter is set.
690 if isinstance(test
.target
, lldb
.SBTarget
):
693 target
= test
.target()
694 bkpt
= target
.FindBreakpointByID(bpno
)
696 test
.assertTrue(bkpt
.IsValid(), "Breakpoint is not valid.")
698 if expected_locations
is not None:
699 test
.assertEqual(expected_locations
, bkpt
.GetNumLocations())
701 if expected_resolved_count
is not None:
702 test
.assertEqual(expected_resolved_count
, bkpt
.GetNumResolvedLocations())
704 expected_resolved_count
= bkpt
.GetNumLocations()
705 if location_id
is None:
706 test
.assertEqual(expected_resolved_count
, bkpt
.GetNumResolvedLocations())
708 if expected_hit_count
is not None:
709 test
.assertEqual(expected_hit_count
, bkpt
.GetHitCount())
711 if location_id
is not None:
712 loc_bkpt
= bkpt
.FindLocationByID(location_id
)
713 test
.assertTrue(loc_bkpt
.IsValid(), "Breakpoint location is not valid.")
714 test
.assertEqual(loc_bkpt
.IsResolved(), expected_location_resolved
)
715 if expected_location_hit_count
is not None:
716 test
.assertEqual(expected_location_hit_count
, loc_bkpt
.GetHitCount())
719 # ==================================================
720 # Utility functions related to Threads and Processes
721 # ==================================================
724 def get_stopped_threads(process
, reason
):
725 """Returns the thread(s) with the specified stop reason in a list.
727 The list can be empty if no such thread exists.
731 if t
.GetStopReason() == reason
:
736 def get_stopped_thread(process
, reason
):
737 """A convenience function which returns the first thread with the given stop
742 1. Get the stopped thread due to a breakpoint condition
745 from lldbutil import get_stopped_thread
746 thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
747 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
750 2. Get the thread stopped due to a breakpoint
753 from lldbutil import get_stopped_thread
754 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
755 self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
759 threads
= get_stopped_threads(process
, reason
)
760 if len(threads
) == 0:
765 def get_threads_stopped_at_breakpoint_id(process
, bpid
):
766 """For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
770 stopped_threads
= get_stopped_threads(process
, lldb
.eStopReasonBreakpoint
)
772 if len(stopped_threads
) == 0:
775 for thread
in stopped_threads
:
776 # Make sure we've hit our breakpoint...
777 break_id
= thread
.GetStopReasonDataAtIndex(0)
779 threads
.append(thread
)
784 def get_threads_stopped_at_breakpoint(process
, bkpt
):
785 return get_threads_stopped_at_breakpoint_id(process
, bkpt
.GetID())
788 def get_one_thread_stopped_at_breakpoint_id(process
, bpid
, require_exactly_one
=True):
789 threads
= get_threads_stopped_at_breakpoint_id(process
, bpid
)
790 if len(threads
) == 0:
792 if require_exactly_one
and len(threads
) != 1:
798 def get_one_thread_stopped_at_breakpoint(process
, bkpt
, require_exactly_one
=True):
799 return get_one_thread_stopped_at_breakpoint_id(
800 process
, bkpt
.GetID(), require_exactly_one
804 def is_thread_crashed(test
, thread
):
805 """In the test suite we dereference a null pointer to simulate a crash. The way this is
806 reported depends on the platform."""
807 if test
.platformIsDarwin():
809 thread
.GetStopReason() == lldb
.eStopReasonException
810 and "EXC_BAD_ACCESS" in thread
.GetStopDescription(100)
812 elif test
.getPlatform() == "linux":
814 thread
.GetStopReason() == lldb
.eStopReasonSignal
815 and thread
.GetStopReasonDataAtIndex(0)
816 == thread
.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
818 elif test
.getPlatform() == "windows":
819 return "Exception 0xc0000005" in thread
.GetStopDescription(200)
821 return "invalid address" in thread
.GetStopDescription(100)
824 def get_crashed_threads(test
, process
):
826 if process
.GetState() != lldb
.eStateStopped
:
828 for thread
in process
:
829 if is_thread_crashed(test
, thread
):
830 threads
.append(thread
)
834 # Helper functions for run_to_{source,name}_breakpoint:
837 def run_to_breakpoint_make_target(test
, exe_name
="a.out", in_cwd
=True):
838 exe
= test
.getBuildArtifact(exe_name
) if in_cwd
else exe_name
841 target
= test
.dbg
.CreateTarget(exe
)
842 test
.assertTrue(target
, "Target: %s is not valid." % (exe_name
))
844 # Set environment variables for the inferior.
845 if lldbtest_config
.inferior_env
:
847 "settings set target.env-vars {}".format(lldbtest_config
.inferior_env
)
853 def run_to_breakpoint_do_run(
854 test
, target
, bkpt
, launch_info
=None, only_one_thread
=True, extra_images
=None
856 # Launch the process, and do not stop at the entry point.
858 launch_info
= target
.GetLaunchInfo()
859 launch_info
.SetWorkingDirectory(test
.get_process_working_directory())
862 environ
= test
.registerSharedLibrariesWithTarget(target
, extra_images
)
863 launch_info
.SetEnvironmentEntries(environ
, True)
865 error
= lldb
.SBError()
866 process
= target
.Launch(launch_info
, error
)
868 # Unfortunate workaround for the iPhone simulator.
869 retry
= SIMULATOR_RETRY
873 and error
.GetCString()
874 and "Unable to boot the Simulator" in error
.GetCString()
877 print("** Simulator is unresponsive. Retrying %d more time(s)" % retry
)
881 error
= lldb
.SBError()
882 process
= target
.Launch(launch_info
, error
)
886 "Could not create a valid process for %s: %s"
887 % (target
.GetExecutable().GetFilename(), error
.GetCString()),
889 test
.assertFalse(error
.Fail(), "Process launch failed: %s" % (error
.GetCString()))
891 def processStateInfo(process
):
892 info
= "state: {}".format(state_type_to_str(process
.state
))
893 if process
.state
== lldb
.eStateExited
:
894 info
+= ", exit code: {}".format(process
.GetExitStatus())
895 if process
.exit_description
:
896 info
+= ", exit description: '{}'".format(process
.exit_description
)
897 stdout
= process
.GetSTDOUT(999)
899 info
+= ", stdout: '{}'".format(stdout
)
900 stderr
= process
.GetSTDERR(999)
902 info
+= ", stderr: '{}'".format(stderr
)
905 if process
.state
!= lldb
.eStateStopped
:
907 "Test process is not stopped at breakpoint: {}".format(
908 processStateInfo(process
)
912 # Frame #0 should be at our breakpoint.
913 threads
= get_threads_stopped_at_breakpoint(process
, bkpt
)
915 num_threads
= len(threads
)
920 "Expected 1 thread to stop at breakpoint, %d did." % (num_threads
),
923 test
.assertGreater(num_threads
, 0, "No threads stopped at breakpoint")
926 return (target
, process
, thread
, bkpt
)
929 def run_to_name_breakpoint(
936 only_one_thread
=True,
939 """Start up a target, using exe_name as the executable, and run it to
940 a breakpoint set by name on bkpt_name restricted to bkpt_module.
942 If you want to pass in launch arguments or environment
943 variables, you can optionally pass in an SBLaunchInfo. If you
944 do that, remember to set the working directory as well.
946 If your executable isn't called a.out, you can pass that in.
947 And if your executable isn't in the CWD, pass in the absolute
948 path to the executable in exe_name, and set in_cwd to False.
950 If you need to restrict the breakpoint to a particular module,
951 pass the module name (a string not a FileSpec) in bkpt_module. If
952 nothing is passed in setting will be unrestricted.
954 If the target isn't valid, the breakpoint isn't found, or hit, the
955 function will cause a testsuite failure.
957 If successful it returns a tuple with the target process and
958 thread that hit the breakpoint, and the breakpoint that we set
961 If only_one_thread is true, we require that there be only one
962 thread stopped at the breakpoint. Otherwise we only require one
963 or more threads stop there. If there are more than one, we return
964 the first thread that stopped.
967 target
= run_to_breakpoint_make_target(test
, exe_name
, in_cwd
)
969 breakpoint
= target
.BreakpointCreateByName(bkpt_name
, bkpt_module
)
972 breakpoint
.GetNumLocations() > 0,
973 "No locations found for name breakpoint: '%s'." % (bkpt_name
),
975 return run_to_breakpoint_do_run(
976 test
, target
, breakpoint
, launch_info
, only_one_thread
, extra_images
980 def run_to_source_breakpoint(
988 only_one_thread
=True,
990 has_locations_before_run
=True,
992 """Start up a target, using exe_name as the executable, and run it to
993 a breakpoint set by source regex bkpt_pattern.
995 The rest of the behavior is the same as run_to_name_breakpoint.
998 target
= run_to_breakpoint_make_target(test
, exe_name
, in_cwd
)
999 # Set the breakpoints
1000 breakpoint
= target
.BreakpointCreateBySourceRegex(
1001 bkpt_pattern
, source_spec
, bkpt_module
1003 if has_locations_before_run
:
1005 breakpoint
.GetNumLocations() > 0,
1006 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
1007 % (bkpt_pattern
, source_spec
.GetFilename(), source_spec
.GetDirectory()),
1009 return run_to_breakpoint_do_run(
1010 test
, target
, breakpoint
, launch_info
, only_one_thread
, extra_images
1014 def run_to_line_breakpoint(
1023 only_one_thread
=True,
1026 """Start up a target, using exe_name as the executable, and run it to
1027 a breakpoint set by (source_spec, line_number(, column)).
1029 The rest of the behavior is the same as run_to_name_breakpoint.
1032 target
= run_to_breakpoint_make_target(test
, exe_name
, in_cwd
)
1033 # Set the breakpoints
1034 breakpoint
= target
.BreakpointCreateByLocation(
1035 source_spec
, line_number
, column
, 0, lldb
.SBFileSpecList()
1038 breakpoint
.GetNumLocations() > 0,
1039 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
1040 % (source_spec
.GetFilename(), line_number
, column
, source_spec
.GetDirectory()),
1042 return run_to_breakpoint_do_run(
1043 test
, target
, breakpoint
, launch_info
, only_one_thread
, extra_images
1047 def continue_to_breakpoint(process
, bkpt
):
1048 """Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
1050 if process
.GetState() != lldb
.eStateStopped
:
1053 return get_threads_stopped_at_breakpoint(process
, bkpt
)
1056 def continue_to_source_breakpoint(test
, process
, bkpt_pattern
, source_spec
):
1058 Sets a breakpoint set by source regex bkpt_pattern, continues the process, and deletes the breakpoint again.
1059 Otherwise the same as `continue_to_breakpoint`
1061 breakpoint
= process
.target
.BreakpointCreateBySourceRegex(
1062 bkpt_pattern
, source_spec
, None
1065 breakpoint
.GetNumLocations() > 0,
1066 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
1067 % (bkpt_pattern
, source_spec
.GetFilename(), source_spec
.GetDirectory()),
1069 stopped_threads
= continue_to_breakpoint(process
, breakpoint
)
1070 process
.target
.BreakpointDelete(breakpoint
.GetID())
1071 return stopped_threads
1074 def get_caller_symbol(thread
):
1076 Returns the symbol name for the call site of the leaf function.
1078 depth
= thread
.GetNumFrames()
1081 caller
= thread
.GetFrameAtIndex(1).GetSymbol()
1083 return caller
.GetName()
1088 def get_function_names(thread
):
1090 Returns a sequence of function names from the stack frames of this thread.
1094 return thread
.GetFrameAtIndex(i
).GetFunctionName()
1096 return list(map(GetFuncName
, list(range(thread
.GetNumFrames()))))
1099 def get_symbol_names(thread
):
1101 Returns a sequence of symbols for this thread.
1105 return thread
.GetFrameAtIndex(i
).GetSymbol().GetName()
1107 return list(map(GetSymbol
, list(range(thread
.GetNumFrames()))))
1110 def get_pc_addresses(thread
):
1112 Returns a sequence of pc addresses for this thread.
1115 def GetPCAddress(i
):
1116 return thread
.GetFrameAtIndex(i
).GetPCAddress()
1118 return list(map(GetPCAddress
, list(range(thread
.GetNumFrames()))))
1121 def get_filenames(thread
):
1123 Returns a sequence of file names from the stack frames of this thread.
1127 return thread
.GetFrameAtIndex(i
).GetLineEntry().GetFileSpec().GetFilename()
1129 return list(map(GetFilename
, list(range(thread
.GetNumFrames()))))
1132 def get_line_numbers(thread
):
1134 Returns a sequence of line numbers from the stack frames of this thread.
1137 def GetLineNumber(i
):
1138 return thread
.GetFrameAtIndex(i
).GetLineEntry().GetLine()
1140 return list(map(GetLineNumber
, list(range(thread
.GetNumFrames()))))
1143 def get_module_names(thread
):
1145 Returns a sequence of module names from the stack frames of this thread.
1148 def GetModuleName(i
):
1149 return thread
.GetFrameAtIndex(i
).GetModule().GetFileSpec().GetFilename()
1151 return list(map(GetModuleName
, list(range(thread
.GetNumFrames()))))
1154 def get_stack_frames(thread
):
1156 Returns a sequence of stack frames for this thread.
1159 def GetStackFrame(i
):
1160 return thread
.GetFrameAtIndex(i
)
1162 return list(map(GetStackFrame
, list(range(thread
.GetNumFrames()))))
1165 def print_stacktrace(thread
, string_buffer
=False):
1166 """Prints a simple stack trace of this thread."""
1168 output
= io
.StringIO() if string_buffer
else sys
.stdout
1169 target
= thread
.GetProcess().GetTarget()
1171 depth
= thread
.GetNumFrames()
1173 mods
= get_module_names(thread
)
1174 funcs
= get_function_names(thread
)
1175 symbols
= get_symbol_names(thread
)
1176 files
= get_filenames(thread
)
1177 lines
= get_line_numbers(thread
)
1178 addrs
= get_pc_addresses(thread
)
1180 if thread
.GetStopReason() != lldb
.eStopReasonInvalid
:
1181 desc
= "stop reason=" + stop_reason_to_str(thread
.GetStopReason())
1185 "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
1186 thread
.GetThreadID(), thread
.GetName(), thread
.GetQueueName()
1192 for i
in range(depth
):
1193 frame
= thread
.GetFrameAtIndex(i
)
1194 function
= frame
.GetFunction()
1196 load_addr
= addrs
[i
].GetLoadAddress(target
)
1198 file_addr
= addrs
[i
].GetFileAddress()
1199 start_addr
= frame
.GetSymbol().GetStartAddress().GetFileAddress()
1200 symbol_offset
= file_addr
- start_addr
1202 " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
1207 offset
=symbol_offset
,
1213 " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
1217 func
="%s [inlined]" % funcs
[i
] if frame
.IsInlined() else funcs
[i
],
1220 args
=get_args_as_string(frame
, showFuncName
=False)
1221 if not frame
.IsInlined()
1228 return output
.getvalue()
1231 def print_stacktraces(process
, string_buffer
=False):
1232 """Prints the stack traces of all the threads."""
1234 output
= io
.StringIO() if string_buffer
else sys
.stdout
1236 print("Stack traces for " + str(process
), file=output
)
1238 for thread
in process
:
1239 print(print_stacktrace(thread
, string_buffer
=True), file=output
)
1242 return output
.getvalue()
1245 def expect_state_changes(test
, listener
, process
, states
, timeout
=30):
1246 """Listens for state changed events on the listener and makes sure they match what we
1247 expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.
1250 for expected_state
in states
:
1252 def get_next_event():
1253 event
= lldb
.SBEvent()
1254 if not listener
.WaitForEventForBroadcasterWithType(
1256 process
.GetBroadcaster(),
1257 lldb
.SBProcess
.eBroadcastBitStateChanged
,
1261 "Timed out while waiting for a transition to state %s"
1262 % lldb
.SBDebugger
.StateAsCString(expected_state
)
1266 event
= get_next_event()
1267 while lldb
.SBProcess
.GetStateFromEvent(
1269 ) == lldb
.eStateStopped
and lldb
.SBProcess
.GetRestartedFromEvent(event
):
1270 # Ignore restarted event and the subsequent running event.
1271 event
= get_next_event()
1273 lldb
.SBProcess
.GetStateFromEvent(event
),
1275 "Restarted event followed by a running event",
1277 event
= get_next_event()
1279 test
.assertEqual(lldb
.SBProcess
.GetStateFromEvent(event
), expected_state
)
1282 def start_listening_from(broadcaster
, event_mask
):
1283 """Creates a listener for a specific event mask and add it to the source broadcaster."""
1285 listener
= lldb
.SBListener("lldb.test.listener")
1286 broadcaster
.AddListener(listener
, event_mask
)
1290 def fetch_next_event(test
, listener
, broadcaster
, match_class
=False, timeout
=10):
1291 """Fetch one event from the listener and return it if it matches the provided broadcaster.
1292 If `match_class` is set to True, this will match an event with an entire broadcaster class.
1295 event
= lldb
.SBEvent()
1297 if listener
.WaitForEvent(timeout
, event
):
1299 if event
.GetBroadcasterClass() == broadcaster
:
1302 if event
.BroadcasterMatchesRef(broadcaster
):
1305 stream
= lldb
.SBStream()
1306 event
.GetDescription(stream
)
1308 "received event '%s' from unexpected broadcaster '%s'."
1309 % (stream
.GetData(), event
.GetBroadcaster().GetName())
1312 test
.fail("couldn't fetch an event before reaching the timeout.")
1315 # ===================================
1316 # Utility functions related to Frames
1317 # ===================================
1320 def get_parent_frame(frame
):
1322 Returns the parent frame of the input frame object; None if not available.
1324 thread
= frame
.GetThread()
1325 parent_found
= False
1329 if f
.GetFrameID() == frame
.GetFrameID():
1332 # If we reach here, no parent has been found, return None.
1336 def get_args_as_string(frame
, showFuncName
=True):
1338 Returns the args of the input frame object as a string.
1343 # in_scope_only => True
1344 vars = frame
.GetVariables(True, False, False, True) # type of SBValueList
1345 args
= [] # list of strings
1347 args
.append("(%s)%s=%s" % (var
.GetTypeName(), var
.GetName(), var
.GetValue()))
1348 if frame
.GetFunction():
1349 name
= frame
.GetFunction().GetName()
1350 elif frame
.GetSymbol():
1351 name
= frame
.GetSymbol().GetName()
1355 return "%s(%s)" % (name
, ", ".join(args
))
1357 return "(%s)" % (", ".join(args
))
1360 def print_registers(frame
, string_buffer
=False):
1361 """Prints all the register sets of the frame."""
1363 output
= io
.StringIO() if string_buffer
else sys
.stdout
1365 print("Register sets for " + str(frame
), file=output
)
1367 registerSet
= frame
.GetRegisters() # Return type of SBValueList.
1369 "Frame registers (size of register set = %d):" % registerSet
.GetSize(),
1372 for value
in registerSet
:
1373 # print(value, file=output)
1375 "%s (number of children = %d):" % (value
.GetName(), value
.GetNumChildren()),
1380 "Name: %s, Value: %s" % (child
.GetName(), child
.GetValue()), file=output
1384 return output
.getvalue()
1387 def get_registers(frame
, kind
):
1388 """Returns the registers given the frame and the kind of registers desired.
1390 Returns None if there's no such kind.
1392 registerSet
= frame
.GetRegisters() # Return type of SBValueList.
1393 for value
in registerSet
:
1394 if kind
.lower() in value
.GetName().lower():
1400 def get_GPRs(frame
):
1401 """Returns the general purpose registers of the frame as an SBValue.
1403 The returned SBValue object is iterable. An example:
1405 from lldbutil import get_GPRs
1406 regs = get_GPRs(frame)
1408 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1411 return get_registers(frame
, "general purpose")
1414 def get_FPRs(frame
):
1415 """Returns the floating point registers of the frame as an SBValue.
1417 The returned SBValue object is iterable. An example:
1419 from lldbutil import get_FPRs
1420 regs = get_FPRs(frame)
1422 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1425 return get_registers(frame
, "floating point")
1428 def get_ESRs(frame
):
1429 """Returns the exception state registers of the frame as an SBValue.
1431 The returned SBValue object is iterable. An example:
1433 from lldbutil import get_ESRs
1434 regs = get_ESRs(frame)
1436 print("%s => %s" % (reg.GetName(), reg.GetValue()))
1439 return get_registers(frame
, "exception state")
1442 # ======================================
1443 # Utility classes/functions for SBValues
1444 # ======================================
1447 class BasicFormatter(object):
1448 """The basic formatter inspects the value object and prints the value."""
1450 def format(self
, value
, buffer=None, indent
=0):
1452 output
= io
.StringIO()
1455 # If there is a summary, it suffices.
1456 val
= value
.GetSummary()
1457 # Otherwise, get the value.
1459 val
= value
.GetValue()
1460 if val
is None and value
.GetNumChildren() > 0:
1461 val
= "%s (location)" % value
.GetLocation()
1463 "{indentation}({type}) {name} = {value}".format(
1464 indentation
=" " * indent
,
1465 type=value
.GetTypeName(),
1466 name
=value
.GetName(),
1471 return output
.getvalue()
1474 class ChildVisitingFormatter(BasicFormatter
):
1475 """The child visiting formatter prints the value and its immediate children.
1477 The constructor takes a keyword arg: indent_child, which defaults to 2.
1480 def __init__(self
, indent_child
=2):
1481 """Default indentation of 2 SPC's for the children."""
1482 self
.cindent
= indent_child
1484 def format(self
, value
, buffer=None):
1486 output
= io
.StringIO()
1490 BasicFormatter
.format(self
, value
, buffer=output
)
1492 BasicFormatter
.format(self
, child
, buffer=output
, indent
=self
.cindent
)
1494 return output
.getvalue()
1497 class RecursiveDecentFormatter(BasicFormatter
):
1498 """The recursive decent formatter prints the value and the decendents.
1500 The constructor takes two keyword args: indent_level, which defaults to 0,
1501 and indent_child, which defaults to 2. The current indentation level is
1502 determined by indent_level, while the immediate children has an additional
1503 indentation by inden_child.
1506 def __init__(self
, indent_level
=0, indent_child
=2):
1507 self
.lindent
= indent_level
1508 self
.cindent
= indent_child
1510 def format(self
, value
, buffer=None):
1512 output
= io
.StringIO()
1516 BasicFormatter
.format(self
, value
, buffer=output
, indent
=self
.lindent
)
1517 new_indent
= self
.lindent
+ self
.cindent
1519 if child
.GetSummary() is not None:
1520 BasicFormatter
.format(self
, child
, buffer=output
, indent
=new_indent
)
1522 if child
.GetNumChildren() > 0:
1523 rdf
= RecursiveDecentFormatter(indent_level
=new_indent
)
1524 rdf
.format(child
, buffer=output
)
1526 BasicFormatter
.format(self
, child
, buffer=output
, indent
=new_indent
)
1528 return output
.getvalue()
1531 # ===========================================================
1532 # Utility functions for path manipulation on remote platforms
1533 # ===========================================================
1536 def join_remote_paths(*paths
):
1537 # TODO: update with actual platform name for remote windows once it exists
1538 if lldb
.remote_platform
.GetName() == "remote-windows":
1539 return os
.path
.join(*paths
).replace(os
.path
.sep
, "\\")
1540 return os
.path
.join(*paths
).replace(os
.path
.sep
, "/")
1543 def append_to_process_working_directory(test
, *paths
):
1544 remote
= lldb
.remote_platform
1546 return join_remote_paths(remote
.GetWorkingDirectory(), *paths
)
1547 return os
.path
.join(test
.getBuildDir(), *paths
)
1550 # ==================================================
1551 # Utility functions to get the correct signal number
1552 # ==================================================
1557 def get_signal_number(signal_name
):
1558 platform
= lldb
.remote_platform
1559 if platform
and platform
.IsValid():
1560 signals
= platform
.GetUnixSignals()
1561 if signals
.IsValid():
1562 signal_number
= signals
.GetSignalNumberFromName(signal_name
)
1563 if signal_number
> 0:
1564 return signal_number
1565 # No remote platform; fall back to using local python signals.
1566 return getattr(signal
, signal_name
)
1569 def get_actions_for_signal(
1570 testcase
, signal_name
, from_target
=False, expected_absent
=False
1572 """Returns a triple of (pass, stop, notify)"""
1573 return_obj
= lldb
.SBCommandReturnObject()
1574 command
= "process handle {0}".format(signal_name
)
1577 testcase
.dbg
.GetCommandInterpreter().HandleCommand(command
, return_obj
)
1579 "NAME *PASS *STOP *NOTIFY.*(false|true|not set) *(false|true|not set) *(false|true|not set)",
1580 return_obj
.GetOutput(),
1581 re
.IGNORECASE | re
.DOTALL
,
1583 if match
and expected_absent
:
1584 testcase
.fail('Signal "{0}" was supposed to be absent'.format(signal_name
))
1587 return (None, None, None)
1588 testcase
.fail("Unable to retrieve default signal disposition.")
1589 return (match
.group(1), match
.group(2), match
.group(3))
1592 def set_actions_for_signal(
1593 testcase
, signal_name
, pass_action
, stop_action
, notify_action
, expect_success
=True
1595 return_obj
= lldb
.SBCommandReturnObject()
1596 command
= "process handle {0}".format(signal_name
)
1597 if pass_action
!= None:
1598 command
+= " -p {0}".format(pass_action
)
1599 if stop_action
!= None:
1600 command
+= " -s {0}".format(stop_action
)
1601 if notify_action
!= None:
1602 command
+= " -n {0}".format(notify_action
)
1604 testcase
.dbg
.GetCommandInterpreter().HandleCommand(command
, return_obj
)
1605 testcase
.assertEqual(
1607 return_obj
.Succeeded(),
1608 "Setting signal handling for {0} worked as expected".format(signal_name
),
1612 class PrintableRegex(object):
1613 def __init__(self
, text
):
1614 self
.regex
= re
.compile(text
)
1617 def match(self
, str):
1618 return self
.regex
.match(str)
1621 return "%s" % (self
.text
)
1624 return "re.compile(%s) -> %s" % (self
.text
, self
.regex
)
1627 def skip_if_callable(test
, mycallable
, reason
):
1628 if callable(mycallable
):
1629 if mycallable(test
):
1630 test
.skipTest(reason
)
1635 def skip_if_library_missing(test
, target
, library
):
1636 def find_library(target
, library
):
1637 for module
in target
.modules
:
1638 filename
= module
.file.GetFilename()
1639 if isinstance(library
, str):
1640 if library
== filename
:
1642 elif hasattr(library
, "match"):
1643 if library
.match(filename
):
1647 def find_library_callable(test
):
1648 return find_library(target
, library
)
1650 return skip_if_callable(
1652 find_library_callable
,
1653 "could not find library matching '%s' in target %s" % (library
, target
),
1657 def read_file_on_target(test
, remote
):
1658 if lldb
.remote_platform
:
1659 local
= test
.getBuildArtifact("file_from_target")
1660 error
= lldb
.remote_platform
.Get(
1661 lldb
.SBFileSpec(remote
, False), lldb
.SBFileSpec(local
, True)
1664 error
.Success(), "Reading file {0} failed: {1}".format(remote
, error
)
1668 with
open(local
, "r") as f
:
1672 def read_file_from_process_wd(test
, name
):
1673 path
= append_to_process_working_directory(test
, name
)
1674 return read_file_on_target(test
, path
)
1677 def wait_for_file_on_target(testcase
, file_path
, max_attempts
=6):
1678 for i
in range(max_attempts
):
1679 err
, retcode
, msg
= testcase
.run_platform_command("ls %s" % file_path
)
1680 if err
.Success() and retcode
== 0:
1682 if i
< max_attempts
:
1683 # Exponential backoff!
1686 time
.sleep(pow(2, i
) * 0.25)
1689 "File %s not found even after %d attempts." % (file_path
, max_attempts
)
1692 return read_file_on_target(testcase
, file_path
)
1695 def packetlog_get_process_info(log
):
1696 """parse a gdb-remote packet log file and extract the response to qProcessInfo"""
1697 process_info
= dict()
1698 with
open(log
, "r") as logfile
:
1699 process_info_ostype
= None
1700 expect_process_info_response
= False
1701 for line
in logfile
:
1702 if expect_process_info_response
:
1703 for pair
in line
.split(";"):
1704 keyval
= pair
.split(":")
1705 if len(keyval
) == 2:
1706 process_info
[keyval
[0]] = keyval
[1]
1708 if "send packet: $qProcessInfo#" in line
:
1709 expect_process_info_response
= True
1713 def packetlog_get_dylib_info(log
):
1714 """parse a gdb-remote packet log file and extract the *last* complete
1715 (=> fetch_all_solibs=true) response to jGetLoadedDynamicLibrariesInfos"""
1719 with
open(log
, "r") as logfile
:
1721 expect_dylib_info_response
= False
1722 for line
in logfile
:
1723 if expect_dylib_info_response
:
1724 while line
[0] != "$":
1728 dylib_info
= json
.loads(line
.replace("}]", "}")[:-4])
1729 expect_dylib_info_response
= False
1731 'send packet: $jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}'
1734 expect_dylib_info_response
= True