https://github.com/labath updated 
https://github.com/llvm/llvm-project/pull/123046

>From 74d436310319d17cb43ba598836b70a92c827111 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Wed, 15 Jan 2025 12:41:23 +0100
Subject: [PATCH 1/7] [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.
---
 lldb/source/API/SBThread.cpp                  |   6 +-
 .../thread/step_until/TestStepUntilAPI.py     | 135 ++++++++++++++++++
 .../thread/step_until/function.list           |   1 +
 .../functionalities/thread/step_until/main.c  |   3 +
 .../thread/step_until/symbol.order            |   7 +
 5 files changed, 150 insertions(+), 2 deletions(-)
 create mode 100644 
lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
 create mode 100644 
lldb/test/API/functionalities/thread/step_until/function.list
 create mode 100644 lldb/test/API/functionalities/thread/step_until/symbol.order

diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 4e61c83889b0b0..4481d1113d89e2 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -842,7 +842,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
     // appropriate error message.
 
     bool all_in_function = true;
-    AddressRange fun_range = frame_sc.function->GetAddressRange();
+    AddressRanges fun_ranges = frame_sc.function->GetAddressRanges();
 
     std::vector<addr_t> step_over_until_addrs;
     const bool abort_other_plans = false;
@@ -859,7 +859,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))
+        if (llvm::any_of(fun_ranges, [&](const AddressRange &r) {
+              return r.ContainsLoadAddress(step_addr, target);
+            }))
           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..95f3552d8968b7
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -0,0 +1,135 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class StepUntilTestCase(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,--section-ordering-file="
+            + 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..72519faefdc787
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/step_until/symbol.order
@@ -0,0 +1,7 @@
+.text : {
+  *(.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)
+}

>From 160a68dbdfc97a816173e4280e6a6ca80b320f5a Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Wed, 15 Jan 2025 12:55:06 +0100
Subject: [PATCH 2/7] reformat

---
 .../API/functionalities/thread/step_until/TestStepUntilAPI.py    | 1 -
 1 file changed, 1 deletion(-)

diff --git 
a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py 
b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
index 95f3552d8968b7..c15077d8a8f2bf 100644
--- a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -5,7 +5,6 @@
 
 
 class StepUntilTestCase(TestBase):
-
     NO_DEBUG_INFO_TESTCASE = True
 
     def setUp(self):

>From da52a02ea3cc45dbefc7026565e4bab5ff0a4be3 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Thu, 16 Jan 2025 10:07:11 +0100
Subject: [PATCH 3/7] feedback

---
 lldb/source/API/SBThread.cpp                           | 10 ++++++----
 .../thread/step_until/TestStepUntilAPI.py              |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 4481d1113d89e2..a1eb5c04e2030b 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -841,8 +841,10 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
     // function, and then if there are no addresses remaining, give an
     // appropriate error message.
 
+    // Function block range information is valid even without parsing the 
entire
+    // block.
+    Block &fun_block = frame_sc.function->GetBlock(/*can_create=*/false);
     bool all_in_function = true;
-    AddressRanges fun_ranges = frame_sc.function->GetAddressRanges();
 
     std::vector<addr_t> step_over_until_addrs;
     const bool abort_other_plans = false;
@@ -859,9 +861,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 (llvm::any_of(fun_ranges, [&](const AddressRange &r) {
-              return r.ContainsLoadAddress(step_addr, target);
-            }))
+        AddressRange unused_range;
+        if (fun_block.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
index c15077d8a8f2bf..f6307bd0cf0046 100644
--- a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -4,7 +4,7 @@
 from lldbsuite.test import lldbutil
 
 
-class StepUntilTestCase(TestBase):
+class TestStepUntilAPI(TestBase):
     NO_DEBUG_INFO_TESTCASE = True
 
     def setUp(self):

>From b9fb10867fdb7d82fc7ee9068191e749382957ad Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Thu, 16 Jan 2025 13:02:40 +0100
Subject: [PATCH 4/7] compatibility with older GNU ld

---
 .../thread/step_until/TestStepUntilAPI.py        |  2 +-
 .../thread/step_until/symbol.order               | 16 +++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git 
a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py 
b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
index f6307bd0cf0046..19a676be2c8f5f 100644
--- a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -22,7 +22,7 @@ def _build_dict_for_discontinuity(self):
             CFLAGS_EXTRAS="-funique-basic-block-section-names "
             + "-ffunction-sections -fbasic-block-sections=list="
             + self.getSourcePath("function.list"),
-            LD_EXTRAS="-Wl,--section-ordering-file="
+            LD_EXTRAS="-Wl,--script="
             + self.getSourcePath("symbol.order"),
         )
 
diff --git a/lldb/test/API/functionalities/thread/step_until/symbol.order 
b/lldb/test/API/functionalities/thread/step_until/symbol.order
index 72519faefdc787..c664a548a53c6e 100644
--- a/lldb/test/API/functionalities/thread/step_until/symbol.order
+++ b/lldb/test/API/functionalities/thread/step_until/symbol.order
@@ -1,7 +1,9 @@
-.text : {
-  *(.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)
-}
+SECTIONS {
+  .text : {
+    *(.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;

>From cd3d78761229df41acfe984ff699e5c683ac728c Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Thu, 16 Jan 2025 13:07:00 +0100
Subject: [PATCH 5/7] ..and with lld

---
 lldb/test/API/functionalities/thread/step_until/symbol.order | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/test/API/functionalities/thread/step_until/symbol.order 
b/lldb/test/API/functionalities/thread/step_until/symbol.order
index c664a548a53c6e..dcc9607a4188fe 100644
--- a/lldb/test/API/functionalities/thread/step_until/symbol.order
+++ b/lldb/test/API/functionalities/thread/step_until/symbol.order
@@ -1,5 +1,5 @@
 SECTIONS {
-  .text : {
+  .text.ordered : {
     *(.text.call_me)
     *(.text.foo)
     *(.text.call_me.call_me.__part.1)

>From a00392edfa4d33bda3711f0b9269de92bc970547 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Thu, 16 Jan 2025 13:08:13 +0100
Subject: [PATCH 6/7] and format

---
 .../API/functionalities/thread/step_until/TestStepUntilAPI.py  | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git 
a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py 
b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
index 19a676be2c8f5f..de3892ed278f80 100644
--- a/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
+++ b/lldb/test/API/functionalities/thread/step_until/TestStepUntilAPI.py
@@ -22,8 +22,7 @@ def _build_dict_for_discontinuity(self):
             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"),
+            LD_EXTRAS="-Wl,--script=" + self.getSourcePath("symbol.order"),
         )
 
     def _do_until(self, build_dict, args, until_line, expected_line):

>From b25701757258c9535a104f3d6f13f4517ceb970d Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Fri, 17 Jan 2025 11:17:50 +0100
Subject: [PATCH 7/7] Add GetRangeContainingLoadAddress

---
 lldb/include/lldb/Symbol/Function.h | 5 +++++
 lldb/source/API/SBThread.cpp        | 7 ++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

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 a1eb5c04e2030b..cc848076dab5fa 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -841,9 +841,6 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
     // function, and then if there are no addresses remaining, give an
     // appropriate error message.
 
-    // Function block range information is valid even without parsing the 
entire
-    // block.
-    Block &fun_block = frame_sc.function->GetBlock(/*can_create=*/false);
     bool all_in_function = true;
 
     std::vector<addr_t> step_over_until_addrs;
@@ -862,8 +859,8 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
           sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
       if (step_addr != LLDB_INVALID_ADDRESS) {
         AddressRange unused_range;
-        if (fun_block.GetRangeContainingLoadAddress(step_addr, *target,
-                                                    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;

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to