[Lldb-commits] [lldb] f66a5e2 - [lldb] Fix SBThread::StepOverUntil for discontinuous functions (#123046)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 17 03:13:34 PST 2025
Author: Pavel Labath
Date: 2025-01-17T12:13:30+01:00
New Revision: f66a5e220cbc2650a5843db854d0734d2aaa030f
URL: https://github.com/llvm/llvm-project/commit/f66a5e220cbc2650a5843db854d0734d2aaa030f
DIFF: https://github.com/llvm/llvm-project/commit/f66a5e220cbc2650a5843db854d0734d2aaa030f.diff
LOG: [lldb] Fix SBThread::StepOverUntil for discontinuous functions (#123046)
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.
Added:
lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
lldb/test/API/functionalities/thread/step_until/function.list
lldb/test/API/functionalities/thread/step_until/symbol.order
Modified:
lldb/include/lldb/Symbol/Function.h
lldb/source/API/SBThread.cpp
lldb/test/API/functionalities/thread/step_until/main.c
Removed:
################################################################################
diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h
index 157c007bdf0e84..d0b27269568b04 100644
--- a/lldb/include/lldb/Symbol/Function.h
+++ b/lldb/include/lldb/Symbol/Function.h
@@ -454,6 +454,11 @@ class Function : public UserID, public SymbolContextScope {
/// and variables).
const Address &GetAddress() const { return m_address; }
+ bool GetRangeContainingLoadAddress(lldb::addr_t load_addr, Target &target,
+ AddressRange &range) {
+ return m_block.GetRangeContainingLoadAddress(load_addr, target, range);
+ }
+
lldb::LanguageType GetLanguage() const;
/// Find the file and line number of the source location of the start of the
/// function. This will use the declaration if present and fall back on the
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 4e61c83889b0b0..cc848076dab5fa 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -842,7 +842,6 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
// appropriate error message.
bool all_in_function = true;
- AddressRange fun_range = frame_sc.function->GetAddressRange();
std::vector<addr_t> step_over_until_addrs;
const bool abort_other_plans = false;
@@ -859,7 +858,9 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
addr_t step_addr =
sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
if (step_addr != LLDB_INVALID_ADDRESS) {
- if (fun_range.ContainsLoadAddress(step_addr, target))
+ AddressRange unused_range;
+ if (frame_sc.function->GetRangeContainingLoadAddress(step_addr, *target,
+ unused_range))
step_over_until_addrs.push_back(step_addr);
else
all_in_function = false;
diff --git a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
new file mode 100644
index 00000000000000..de3892ed278f80
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -0,0 +1,133 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestStepUntilAPI(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ 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"])
+ def test_hitting_discontinuous(self):
+ """Test SBThread.StepOverUntil - targeting a line and hitting it -- with
+ discontinuous functions"""
+ self._do_until(
+ self._build_dict_for_discontinuity(),
+ None,
+ self.less_than_two,
+ self.less_than_two,
+ )
+ 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"])
+ def test_missing_discontinuous(self):
+ """Test SBThread.StepOverUntil - targeting a line and missing it by
+ stepping out to call site -- with discontinuous functions"""
+ self._do_until(
+ self._build_dict_for_discontinuity(),
+ ["foo", "bar", "baz"],
+ self.less_than_two,
+ self.back_out_in_main,
+ )
+ 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"])
+ 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"""
+ self.build(dictionary=self._build_dict_for_discontinuity())
+ _, _, 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(),
+ )
+ self._assertDiscontinuity()
diff --git a/lldb/test/API/functionalities/thread/step_until/function.list b/lldb/test/API/functionalities/thread/step_until/function.list
new file mode 100644
index 00000000000000..5900fe8c350695
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/step_until/function.list
@@ -0,0 +1 @@
+!call_me
diff --git a/lldb/test/API/functionalities/thread/step_until/main.c b/lldb/test/API/functionalities/thread/step_until/main.c
index bb866079cf5f54..4c52308f030e98 100644
--- a/lldb/test/API/functionalities/thread/step_until/main.c
+++ b/lldb/test/API/functionalities/thread/step_until/main.c
@@ -4,6 +4,9 @@
* unrelated to the program, just to achieve consistent
* debug line tables, across platforms, that are not
* dependent on compiler optimzations. */
+
+int foo(int x) { return x; /* In foo */ }
+
int call_me(int argc) {
printf ("At the start, argc: %d.\n", argc);
diff --git a/lldb/test/API/functionalities/thread/step_until/symbol.order b/lldb/test/API/functionalities/thread/step_until/symbol.order
new file mode 100644
index 00000000000000..dcc9607a4188fe
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/step_until/symbol.order
@@ -0,0 +1,9 @@
+SECTIONS {
+ .text.ordered : {
+ *(.text.call_me)
+ *(.text.foo)
+ *(.text.call_me.call_me.__part.1)
+ *(.text.call_me.call_me.__part.2)
+ *(.text.call_me.call_me.__part.3)
+ }
+} INSERT BEFORE .text;
More information about the lldb-commits
mailing list