Skip to content

Commit 74d4363

Browse files
committed
[lldb] Fix SBThread::StepOverUntil for discontinuous functions
I think the only issue here was that we would erroneously consider functions which are "in the middle" of the function were stepping to as a part of the function, and would try to step into them (likely stepping out of the function instead) instead of giving up early.
1 parent 7201cae commit 74d4363

File tree

5 files changed

+150
-2
lines changed

5 files changed

+150
-2
lines changed

lldb/source/API/SBThread.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
842842
// appropriate error message.
843843

844844
bool all_in_function = true;
845-
AddressRange fun_range = frame_sc.function->GetAddressRange();
845+
AddressRanges fun_ranges = frame_sc.function->GetAddressRanges();
846846

847847
std::vector<addr_t> step_over_until_addrs;
848848
const bool abort_other_plans = false;
@@ -859,7 +859,9 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
859859
addr_t step_addr =
860860
sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
861861
if (step_addr != LLDB_INVALID_ADDRESS) {
862-
if (fun_range.ContainsLoadAddress(step_addr, target))
862+
if (llvm::any_of(fun_ranges, [&](const AddressRange &r) {
863+
return r.ContainsLoadAddress(step_addr, target);
864+
}))
863865
step_over_until_addrs.push_back(step_addr);
864866
else
865867
all_in_function = false;
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
7+
class StepUntilTestCase(TestBase):
8+
9+
NO_DEBUG_INFO_TESTCASE = True
10+
11+
def setUp(self):
12+
super().setUp()
13+
14+
self.main_source = "main.c"
15+
self.main_spec = lldb.SBFileSpec(self.main_source)
16+
self.less_than_two = line_number("main.c", "Less than 2")
17+
self.greater_than_two = line_number("main.c", "Greater than or equal to 2.")
18+
self.back_out_in_main = line_number("main.c", "Back out in main")
19+
self.in_foo = line_number("main.c", "In foo")
20+
21+
def _build_dict_for_discontinuity(self):
22+
return dict(
23+
CFLAGS_EXTRAS="-funique-basic-block-section-names "
24+
+ "-ffunction-sections -fbasic-block-sections=list="
25+
+ self.getSourcePath("function.list"),
26+
LD_EXTRAS="-Wl,--section-ordering-file="
27+
+ self.getSourcePath("symbol.order"),
28+
)
29+
30+
def _do_until(self, build_dict, args, until_line, expected_line):
31+
self.build(dictionary=build_dict)
32+
launch_info = lldb.SBLaunchInfo(args)
33+
_, _, thread, _ = lldbutil.run_to_source_breakpoint(
34+
self, "At the start", self.main_spec, launch_info
35+
)
36+
37+
self.assertSuccess(
38+
thread.StepOverUntil(self.frame(), self.main_spec, until_line)
39+
)
40+
41+
self.runCmd("process status")
42+
43+
line = self.frame().GetLineEntry().GetLine()
44+
self.assertEqual(
45+
line, expected_line, "Did not get the expected stop line number"
46+
)
47+
48+
def _assertDiscontinuity(self):
49+
target = self.target()
50+
foo = target.FindFunctions("foo")
51+
self.assertEqual(len(foo), 1)
52+
foo = foo[0]
53+
54+
call_me = self.target().FindFunctions("call_me")
55+
self.assertEqual(len(call_me), 1)
56+
call_me = call_me[0]
57+
58+
foo_addr = foo.function.GetStartAddress().GetLoadAddress(target)
59+
found_before = False
60+
found_after = False
61+
for range in call_me.function.GetRanges():
62+
addr = range.GetBaseAddress().GetLoadAddress(target)
63+
if addr < foo_addr:
64+
found_before = True
65+
if addr > foo_addr:
66+
found_after = True
67+
68+
self.assertTrue(
69+
found_before and found_after,
70+
"'foo' is not between 'call_me'" + str(foo) + str(call_me),
71+
)
72+
73+
def test_hitting(self):
74+
"""Test SBThread.StepOverUntil - targeting a line and hitting it."""
75+
self._do_until(None, None, self.less_than_two, self.less_than_two)
76+
77+
@skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"])
78+
def test_hitting_discontinuous(self):
79+
"""Test SBThread.StepOverUntil - targeting a line and hitting it -- with
80+
discontinuous functions"""
81+
self._do_until(
82+
self._build_dict_for_discontinuity(),
83+
None,
84+
self.less_than_two,
85+
self.less_than_two,
86+
)
87+
self._assertDiscontinuity()
88+
89+
def test_missing(self):
90+
"""Test SBThread.StepOverUntil - targeting a line and missing it by stepping out to call site"""
91+
self._do_until(
92+
None, ["foo", "bar", "baz"], self.less_than_two, self.back_out_in_main
93+
)
94+
95+
@skipIf(oslist=lldbplatformutil.getDarwinOSTriples() + ["windows"])
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+
def test_bad_line_discontinuous(self):
123+
"""Test that we get an error if attempting to step outside the current
124+
function -- and the function is discontinuous"""
125+
self.build(dictionary=self._build_dict_for_discontinuity())
126+
_, _, thread, _ = lldbutil.run_to_source_breakpoint(
127+
self, "At the start", self.main_spec
128+
)
129+
self.assertIn(
130+
"step until target not in current function",
131+
thread.StepOverUntil(
132+
self.frame(), self.main_spec, self.in_foo
133+
).GetCString(),
134+
)
135+
self._assertDiscontinuity()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!call_me

lldb/test/API/functionalities/thread/step_until/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* unrelated to the program, just to achieve consistent
55
* debug line tables, across platforms, that are not
66
* dependent on compiler optimzations. */
7+
8+
int foo(int x) { return x; /* In foo */ }
9+
710
int call_me(int argc) {
811
printf ("At the start, argc: %d.\n", argc);
912

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.text : {
2+
*(.text.call_me)
3+
*(.text.foo)
4+
*(.text.call_me.call_me.__part.1)
5+
*(.text.call_me.call_me.__part.2)
6+
*(.text.call_me.call_me.__part.3)
7+
}

0 commit comments

Comments
 (0)