[Lldb-commits] [lldb] [llvm] [Support] [lldb] Fix thread jump #45326 (PR #135778)

Ebuka Ezike via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 15 08:53:02 PDT 2025


https://github.com/da-viper updated https://github.com/llvm/llvm-project/pull/135778

>From 73fc9565d973fd7e1ce92b005696f17c9a9acd5f Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Tue, 15 Apr 2025 12:21:59 +0100
Subject: [PATCH 1/4] [Support] Recognise the '+' char for positive integers

Fixes https://github.com/llvm/llvm-project/issues/45326

Signed-off-by: Ebuka Ezike <yerimyah1 at gmail.com>
---
 llvm/lib/Support/StringRef.cpp       |  3 +++
 llvm/unittests/ADT/StringRefTest.cpp | 28 +++++++++++++++-------------
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp
index 4f5fcb4857e80..bdf7a9aa5c7e0 100644
--- a/llvm/lib/Support/StringRef.cpp
+++ b/llvm/lib/Support/StringRef.cpp
@@ -409,6 +409,9 @@ static unsigned GetAutoSenseRadix(StringRef &Str) {
 
 bool llvm::consumeUnsignedInteger(StringRef &Str, unsigned Radix,
                                   unsigned long long &Result) {
+  // Consume the + value
+  Str.consume_front("+");
+
   // Autosense radix if not specified.
   if (Radix == 0)
     Radix = GetAutoSenseRadix(Str);
diff --git a/llvm/unittests/ADT/StringRefTest.cpp b/llvm/unittests/ADT/StringRefTest.cpp
index ec9cdc197597d..55d222a915ab5 100644
--- a/llvm/unittests/ADT/StringRefTest.cpp
+++ b/llvm/unittests/ADT/StringRefTest.cpp
@@ -622,19 +622,21 @@ TEST(StringRefTest, Hashing) {
 struct UnsignedPair {
   const char *Str;
   uint64_t Expected;
-} Unsigned[] =
-  { {"0", 0}
-  , {"255", 255}
-  , {"256", 256}
-  , {"65535", 65535}
-  , {"65536", 65536}
-  , {"4294967295", 4294967295ULL}
-  , {"4294967296", 4294967296ULL}
-  , {"18446744073709551615", 18446744073709551615ULL}
-  , {"042", 34}
-  , {"0x42", 66}
-  , {"0b101010", 42}
-  };
+} Unsigned[] = {{"0", 0},
+                {"255", 255},
+                {"256", 256},
+                {"65535", 65535},
+                {"65536", 65536},
+                {"4294967295", 4294967295ULL},
+                {"4294967296", 4294967296ULL},
+                {"18446744073709551615", 18446744073709551615ULL},
+                {"042", 34},
+                {"0x42", 66},
+                {"0b101010", 42},
+                {"+42", 42},
+                {"+042", 34},
+                {"+0x42", 66},
+                {"+0b101010", 42}};
 
 struct SignedPair {
   const char *Str;

>From 6ab61ef8ca7de96d3cdb6deb60c30fc1c8b6e9d2 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Tue, 15 Apr 2025 12:25:41 +0100
Subject: [PATCH 2/4] [lldb] Add test for jumping by offset

Signed-off-by: Ebuka Ezike <yerimyah1 at gmail.com>
---
 .../thread/jump/TestThreadJump.py             | 70 ++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/lldb/test/API/functionalities/thread/jump/TestThreadJump.py b/lldb/test/API/functionalities/thread/jump/TestThreadJump.py
index 3c13a969bc3fd..d603580ac6f36 100644
--- a/lldb/test/API/functionalities/thread/jump/TestThreadJump.py
+++ b/lldb/test/API/functionalities/thread/jump/TestThreadJump.py
@@ -10,9 +10,12 @@
 
 
 class ThreadJumpTestCase(TestBase):
+    def setUp(self):
+        TestBase.setUp(self)
+        self.build()
+
     def test(self):
         """Test thread jump handling."""
-        self.build()
         exe = self.getBuildArtifact("a.out")
         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
 
@@ -62,6 +65,71 @@ def test(self):
             substrs=["error"],
         )
 
+    def test_jump_offset(self):
+        """Test Thread Jump by negative or positive offset"""
+        exe = self.getBuildArtifact("a.out")
+        file_name = "main.cpp"
+        self.runCmd(f"target create {exe}", CURRENT_EXECUTABLE_SET)
+
+        pos_jump = line_number(file_name, "// jump_offset 1")
+        neg_jump = line_number(file_name, "// jump_offset 2")
+        pos_breakpoint = line_number(file_name, "// breakpoint 1")
+        neg_breakpoint = line_number(file_name, "// breakpoint 2")
+        pos_jump_offset = pos_jump - pos_breakpoint
+        neg_jump_offset = neg_jump - neg_breakpoint
+
+        var_1, var_1_value = ("var_1", "10")
+        var_2, var_2_value = ("var_2", "40")
+        var_3, var_3_value = ("var_3", "10")
+
+        # create pos_breakpoint and neg_breakpoint
+        lldbutil.run_break_set_by_file_and_line(
+            self, file_name, pos_breakpoint, num_expected_locations=1
+        )
+        lldbutil.run_break_set_by_file_and_line(
+            self, file_name, neg_breakpoint, num_expected_locations=1
+        )
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # test positive jump
+        # The stop reason of the thread should be breakpoint 1.
+        self.expect(
+            "thread list",
+            STOPPED_DUE_TO_BREAKPOINT + " 1",
+            substrs=[
+                "stopped",
+                f"{file_name}:{pos_breakpoint}",
+                "stop reason = breakpoint 1",
+            ],
+        )
+
+        self.runCmd(f"thread jump --by +{pos_jump_offset}")
+        self.expect("process status", substrs=[f"at {file_name}:{pos_jump}"])
+        self.expect(f"print {var_1}", substrs=[var_1_value])
+
+        self.runCmd("thread step-over")
+        self.expect(f"print {var_2}", substrs=[var_2_value])
+
+        self.runCmd("continue")
+
+        # test negative jump
+        # The stop reason of the thread should be breakpoint 1.
+        self.expect(
+            "thread list",
+            STOPPED_DUE_TO_BREAKPOINT + " 2",
+            substrs=[
+                "stopped",
+                f"{file_name}:{neg_breakpoint}",
+                "stop reason = breakpoint 2",
+            ],
+        )
+
+        self.runCmd(f"thread jump --by {neg_jump_offset}")
+        self.expect("process status", substrs=[f"at {file_name}:{neg_jump}"])
+        self.runCmd("thread step-over")
+        self.expect(f"print {var_3}", substrs=[var_3_value])
+
     def do_min_test(self, start, jump, var, value):
         # jump to the start marker
         self.runCmd("j %i" % start)

>From 90ec3ff7ceb1ca631cf22086311ecfce5a8e21c6 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Tue, 15 Apr 2025 12:33:52 +0100
Subject: [PATCH 3/4] [lldb] Add test main.cpp file

Signed-off-by: Ebuka Ezike <yerimyah1 at gmail.com>
---
 .../API/functionalities/thread/jump/main.cpp    | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lldb/test/API/functionalities/thread/jump/main.cpp b/lldb/test/API/functionalities/thread/jump/main.cpp
index d3c0de2af4bf4..9c7f0bcb3b732 100644
--- a/lldb/test/API/functionalities/thread/jump/main.cpp
+++ b/lldb/test/API/functionalities/thread/jump/main.cpp
@@ -13,6 +13,21 @@ T min(T a, T b)
     }
 }
 
+int jump_positive_offset() {
+  int var_1 = 10;
+  var_1 = 20; // breakpoint 1
+
+  int var_2 = 40; // jump_offset 1
+  return var_2;
+}
+
+int jump_negative_offset() {
+  int var_3 = 10; // jump_offset 2
+  var_3 = 99;
+
+  return var_3; // breakpoint 2
+}
+
 int main ()
 {
     int i;
@@ -22,5 +37,7 @@ int main ()
     i = min(min_i_a, min_i_b); // 3rd marker
     j = min(min_j_a, min_j_b); // 4th marker
 
+    jump_positive_offset();
+    jump_negative_offset();
     return 0;
 }

>From f5c3ac98a05c5366036d9d07f6d2483df401f1b8 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Tue, 15 Apr 2025 16:52:24 +0100
Subject: [PATCH 4/4] [symbolizer] Address starting with a plus sign is valid.

this is also the same behaviour in gnu addr2line.

Signed-off-by: Ebuka Ezike <yerimyah1 at gmail.com>
---
 llvm/test/tools/llvm-symbolizer/symbol-search.test | 5 +++--
 llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp     | 9 ++++++---
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/llvm/test/tools/llvm-symbolizer/symbol-search.test b/llvm/test/tools/llvm-symbolizer/symbol-search.test
index 6729c4b01bfef..fe9a61bd8ef6c 100644
--- a/llvm/test/tools/llvm-symbolizer/symbol-search.test
+++ b/llvm/test/tools/llvm-symbolizer/symbol-search.test
@@ -65,8 +65,9 @@ RUN: llvm-symbolizer --obj=%p/Inputs/symbols.so func_01+0A | FileCheck --check-p
 RUN: llvm-addr2line --obj=%p/Inputs/symbols.so func_01+0A | FileCheck --check-prefix=NONEXISTENT %s
 
 # If '+' is not preceded by a symbol, it is part of a symbol name, not an offset separator.
-RUN: llvm-symbolizer --obj=%p/Inputs/symbols.so +0x1138 | FileCheck --check-prefix=NONEXISTENT %s
-RUN: llvm-addr2line --obj=%p/Inputs/symbols.so +0x1138 | FileCheck --check-prefix=NONEXISTENT %s
+# address starting with a `+` sign is a valid address
+RUN: llvm-symbolizer --obj=%p/Inputs/symbols.so +0x1138 | FileCheck --check-prefix=CODE-CMD %s
+RUN: llvm-addr2line --obj=%p/Inputs/symbols.so +0x1138 | FileCheck --check-prefix=CODE-CMD %s
 
 # Show that C++ mangled names may be specified.
 RUN: llvm-addr2line --obj=%p/Inputs/symbols.so _ZL14static_func_01i | FileCheck --check-prefix=MULTI-CXX %s
diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 3ba7f59d5b847..c8abddbbab5dd 100644
--- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -238,9 +238,12 @@ static Error parseCommand(StringRef BinaryName, bool IsAddr2Line,
   bool StartsWithDigit = std::isdigit(AddrSpec.front());
 
   // GNU addr2line assumes the address is hexadecimal and allows a redundant
-  // "0x" or "0X" prefix; do the same for compatibility.
-  if (IsAddr2Line)
-    AddrSpec.consume_front("0x") || AddrSpec.consume_front("0X");
+  // "0x" or "0X" prefix or with an optional `+` sign; do the same for
+  // compatibility.
+  if (IsAddr2Line) {
+    AddrSpec.consume_front_insensitive("0x") ||
+        AddrSpec.consume_front_insensitive("+0x");
+  }
 
   // If address specification is a number, treat it as a module offset.
   if (!AddrSpec.getAsInteger(IsAddr2Line ? 16 : 0, Offset)) {



More information about the lldb-commits mailing list