1import lldb 2from lldbsuite.test.decorators import * 3from lldbsuite.test.lldbtest import * 4from lldbsuite.test import lldbutil 5 6 7class TestStepUntilAPI(TestBase): 8 NO_DEBUG_INFO_TESTCASE = True 9 10 def setUp(self): 11 super().setUp() 12 13 self.main_source = "main.c" 14 self.main_spec = lldb.SBFileSpec(self.main_source) 15 self.less_than_two = line_number("main.c", "Less than 2") 16 self.greater_than_two = line_number("main.c", "Greater than or equal to 2.") 17 self.back_out_in_main = line_number("main.c", "Back out in main") 18 self.in_foo = line_number("main.c", "In foo") 19 20 def _build_dict_for_discontinuity(self): 21 return dict( 22 CFLAGS_EXTRAS="-funique-basic-block-section-names " 23 + "-ffunction-sections -fbasic-block-sections=list=" 24 + self.getSourcePath("function.list"), 25 LD_EXTRAS="-Wl,--script=" + self.getSourcePath("symbol.order"), 26 ) 27 28 def _do_until(self, build_dict, args, until_line, expected_line): 29 self.build(dictionary=build_dict) 30 launch_info = lldb.SBLaunchInfo(args) 31 _, _, thread, _ = lldbutil.run_to_source_breakpoint( 32 self, "At the start", self.main_spec, launch_info 33 ) 34 35 self.assertSuccess( 36 thread.StepOverUntil(self.frame(), self.main_spec, until_line) 37 ) 38 39 self.runCmd("process status") 40 41 line = self.frame().GetLineEntry().GetLine() 42 self.assertEqual( 43 line, expected_line, "Did not get the expected stop line number" 44 ) 45 46 def _assertDiscontinuity(self): 47 target = self.target() 48 foo = target.FindFunctions("foo") 49 self.assertEqual(len(foo), 1) 50 foo = foo[0] 51 52 call_me = self.target().FindFunctions("call_me") 53 self.assertEqual(len(call_me), 1) 54 call_me = call_me[0] 55 56 foo_addr = foo.function.GetStartAddress().GetLoadAddress(target) 57 found_before = False 58 found_after = False 59 for range in call_me.function.GetRanges(): 60 addr = range.GetBaseAddress().GetLoadAddress(target) 61 if addr < foo_addr: 62 found_before = True 63 if addr > foo_addr: 64 found_after = True 65 66 self.assertTrue( 67 found_before and found_after, 68 "'foo' is not between 'call_me'" + str(foo) + str(call_me), 69 ) 70 71 def test_hitting(self): 72 """Test SBThread.StepOverUntil - targeting a line and hitting it.""" 73 self._do_until(None, None, self.less_than_two, self.less_than_two) 74 75 @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) 76 @skipIf(archs=no_match(["x86_64", "aarch64"])) 77 def test_hitting_discontinuous(self): 78 """Test SBThread.StepOverUntil - targeting a line and hitting it -- with 79 discontinuous functions""" 80 self._do_until( 81 self._build_dict_for_discontinuity(), 82 None, 83 self.less_than_two, 84 self.less_than_two, 85 ) 86 self._assertDiscontinuity() 87 88 def test_missing(self): 89 """Test SBThread.StepOverUntil - targeting a line and missing it by stepping out to call site""" 90 self._do_until( 91 None, ["foo", "bar", "baz"], self.less_than_two, self.back_out_in_main 92 ) 93 94 @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) 95 @skipIf(archs=no_match(["x86_64", "aarch64"])) 96 def test_missing_discontinuous(self): 97 """Test SBThread.StepOverUntil - targeting a line and missing it by 98 stepping out to call site -- with discontinuous functions""" 99 self._do_until( 100 self._build_dict_for_discontinuity(), 101 ["foo", "bar", "baz"], 102 self.less_than_two, 103 self.back_out_in_main, 104 ) 105 self._assertDiscontinuity() 106 107 def test_bad_line(self): 108 """Test that we get an error if attempting to step outside the current 109 function""" 110 self.build() 111 _, _, thread, _ = lldbutil.run_to_source_breakpoint( 112 self, "At the start", self.main_spec 113 ) 114 self.assertIn( 115 "step until target not in current function", 116 thread.StepOverUntil( 117 self.frame(), self.main_spec, self.in_foo 118 ).GetCString(), 119 ) 120 121 @skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"]) 122 @skipIf(archs=no_match(["x86_64", "aarch64"])) 123 def test_bad_line_discontinuous(self): 124 """Test that we get an error if attempting to step outside the current 125 function -- and the function is discontinuous""" 126 self.build(dictionary=self._build_dict_for_discontinuity()) 127 _, _, thread, _ = lldbutil.run_to_source_breakpoint( 128 self, "At the start", self.main_spec 129 ) 130 self.assertIn( 131 "step until target not in current function", 132 thread.StepOverUntil( 133 self.frame(), self.main_spec, self.in_foo 134 ).GetCString(), 135 ) 136 self._assertDiscontinuity() 137