| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| from lldbsuite.test_event.build_exception import BuildError | |
| class TestStepUntilAPI(TestBase): | |
| NO_DEBUG_INFO_TESTCASE = True | |
| SHARED_BUILD_TESTCASE = False | |
| def setUp(self): | |
| super().setUp() | |
| self.main_source = "main.c" | |
| self.main_spec = lldb.SBFileSpec(self.main_source) | |
| self.less_than_two = line_number("main.c", "Less than 2") | |
| self.greater_than_two = line_number("main.c", "Greater than or equal to 2.") | |
| self.back_out_in_main = line_number("main.c", "Back out in main") | |
| self.in_foo = line_number("main.c", "In foo") | |
| def _build_dict_for_discontinuity(self): | |
| return dict( | |
| CFLAGS_EXTRAS="-funique-basic-block-section-names " | |
| + "-ffunction-sections -fbasic-block-sections=list=" | |
| + self.getSourcePath("function.list"), | |
| LD_EXTRAS="-Wl,--script=" + self.getSourcePath("symbol.order"), | |
| ) | |
| def _do_until(self, build_dict, args, until_line, expected_line): | |
| self.build(dictionary=build_dict) | |
| launch_info = lldb.SBLaunchInfo(args) | |
| _, _, thread, _ = lldbutil.run_to_source_breakpoint( | |
| self, "At the start", self.main_spec, launch_info | |
| ) | |
| self.assertSuccess( | |
| thread.StepOverUntil(self.frame(), self.main_spec, until_line) | |
| ) | |
| self.runCmd("process status") | |
| line = self.frame().GetLineEntry().GetLine() | |
| self.assertEqual( | |
| line, expected_line, "Did not get the expected stop line number" | |
| ) | |
| def _assertDiscontinuity(self): | |
| target = self.target() | |
| foo = target.FindFunctions("foo") | |
| self.assertEqual(len(foo), 1) | |
| foo = foo[0] | |
| call_me = self.target().FindFunctions("call_me") | |
| self.assertEqual(len(call_me), 1) | |
| call_me = call_me[0] | |
| foo_addr = foo.function.GetStartAddress().GetLoadAddress(target) | |
| found_before = False | |
| found_after = False | |
| for range in call_me.function.GetRanges(): | |
| addr = range.GetBaseAddress().GetLoadAddress(target) | |
| if addr < foo_addr: | |
| found_before = True | |
| if addr > foo_addr: | |
| found_after = True | |
| self.assertTrue( | |
| found_before and found_after, | |
| "'foo' is not between 'call_me'" + str(foo) + str(call_me), | |
| ) | |
| def test_hitting(self): | |
| """Test SBThread.StepOverUntil - targeting a line and hitting it.""" | |
| self._do_until(None, None, self.less_than_two, self.less_than_two) | |
| @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) | |
| @skipIf(archs=no_match(["x86_64", "aarch64"])) | |
| @skipIf(compiler=no_match(["clang"])) | |
| def test_hitting_discontinuous(self): | |
| """Test SBThread.StepOverUntil - targeting a line and hitting it -- with | |
| discontinuous functions""" | |
| try: | |
| self._do_until( | |
| self._build_dict_for_discontinuity(), | |
| None, | |
| self.less_than_two, | |
| self.less_than_two, | |
| ) | |
| except BuildError as ex: | |
| self.skipTest(f"failed to build with linker script.") | |
| self._assertDiscontinuity() | |
| def test_missing(self): | |
| """Test SBThread.StepOverUntil - targeting a line and missing it by stepping out to call site""" | |
| self._do_until( | |
| None, ["foo", "bar", "baz"], self.less_than_two, self.back_out_in_main | |
| ) | |
| @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) | |
| @skipIf(archs=no_match(["x86_64", "aarch64"])) | |
| @skipIf(compiler=no_match(["clang"])) | |
| def test_missing_discontinuous(self): | |
| """Test SBThread.StepOverUntil - targeting a line and missing it by | |
| stepping out to call site -- with discontinuous functions""" | |
| try: | |
| self._do_until( | |
| self._build_dict_for_discontinuity(), | |
| ["foo", "bar", "baz"], | |
| self.less_than_two, | |
| self.back_out_in_main, | |
| ) | |
| except BuildError as ex: | |
| self.skipTest(f"failed to build with linker script.") | |
| self._assertDiscontinuity() | |
| def test_bad_line(self): | |
| """Test that we get an error if attempting to step outside the current | |
| function""" | |
| self.build() | |
| _, _, thread, _ = lldbutil.run_to_source_breakpoint( | |
| self, "At the start", self.main_spec | |
| ) | |
| self.assertIn( | |
| "step until target not in current function", | |
| thread.StepOverUntil( | |
| self.frame(), self.main_spec, self.in_foo | |
| ).GetCString(), | |
| ) | |
| @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) | |
| @skipIf(archs=no_match(["x86_64", "aarch64"])) | |
| @skipIf(compiler=no_match(["clang"])) | |
| def test_bad_line_discontinuous(self): | |
| """Test that we get an error if attempting to step outside the current | |
| function -- and the function is discontinuous""" | |
| try: | |
| self.build(dictionary=self._build_dict_for_discontinuity()) | |
| _, _, thread, _ = lldbutil.run_to_source_breakpoint( | |
| self, "At the start", self.main_spec | |
| ) | |
| except BuildError as ex: | |
| self.skipTest(f"failed to build with linker script.") | |
| self.assertIn( | |
| "step until target not in current function", | |
| thread.StepOverUntil( | |
| self.frame(), self.main_spec, self.in_foo | |
| ).GetCString(), | |
| ) | |
| self._assertDiscontinuity() |