Skip to content

Branch island with numbers #138781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 6, 2025
Merged

Conversation

jimingham
Copy link
Collaborator

Reapply the support for stepping through branch islands, add support for a branch that takes multiple hops to get to the target.

jimingham added 2 commits May 5, 2025 15:02
forms: '.island2' and '.island.2'.  Also add more padding so that
we produce an island that takes several jumps.
@jimingham jimingham requested a review from JDevlieghere as a code owner May 6, 2025 23:34
@llvmbot llvmbot added the lldb label May 6, 2025
@jimingham jimingham requested a review from adrian-prantl May 6, 2025 23:35
@llvmbot
Copy link
Member

llvmbot commented May 6, 2025

@llvm/pr-subscribers-lldb

Author: None (jimingham)

Changes

Reapply the support for stepping through branch islands, add support for a branch that takes multiple hops to get to the target.


Full diff: https://github.com/llvm/llvm-project/pull/138781.diff

9 Files Affected:

  • (modified) lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp (+25-7)
  • (added) lldb/test/API/macosx/branch-islands/Makefile (+16)
  • (added) lldb/test/API/macosx/branch-islands/TestBranchIslands.py (+35)
  • (added) lldb/test/API/macosx/branch-islands/foo.c (+6)
  • (added) lldb/test/API/macosx/branch-islands/main.c (+6)
  • (added) lldb/test/API/macosx/branch-islands/padding1.s (+3)
  • (added) lldb/test/API/macosx/branch-islands/padding2.s (+3)
  • (added) lldb/test/API/macosx/branch-islands/padding3.s (+3)
  • (added) lldb/test/API/macosx/branch-islands/padding4.s (+3)
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index e25c4ff55e408..ad3b63cf59135 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -26,6 +26,7 @@
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadPlanCallFunction.h"
 #include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
 #include "lldb/Utility/DataBuffer.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/LLDBLog.h"
@@ -923,15 +924,15 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
   if (current_symbol != nullptr) {
     std::vector<Address> addresses;
 
+    ConstString current_name =
+        current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
     if (current_symbol->IsTrampoline()) {
-      ConstString trampoline_name =
-          current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
 
-      if (trampoline_name) {
+      if (current_name) {
         const ModuleList &images = target_sp->GetImages();
 
         SymbolContextList code_symbols;
-        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode,
+        images.FindSymbolsWithNameAndType(current_name, eSymbolTypeCode,
                                           code_symbols);
         for (const SymbolContext &context : code_symbols) {
           Address addr = context.GetFunctionOrSymbolAddress();
@@ -945,8 +946,8 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
         }
 
         SymbolContextList reexported_symbols;
-        images.FindSymbolsWithNameAndType(
-            trampoline_name, eSymbolTypeReExported, reexported_symbols);
+        images.FindSymbolsWithNameAndType(current_name, eSymbolTypeReExported,
+                                          reexported_symbols);
         for (const SymbolContext &context : reexported_symbols) {
           if (context.symbol) {
             Symbol *actual_symbol =
@@ -968,7 +969,7 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
         }
 
         SymbolContextList indirect_symbols;
-        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver,
+        images.FindSymbolsWithNameAndType(current_name, eSymbolTypeResolver,
                                           indirect_symbols);
 
         for (const SymbolContext &context : indirect_symbols) {
@@ -1028,6 +1029,23 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
       thread_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
           thread, load_addrs, stop_others);
     }
+    // One more case we have to consider is "branch islands".  These are regular
+    // TEXT symbols but their names end in .island plus maybe a .digit suffix.  
+    // They are to allow arm64 code to branch further than the size of the 
+    // address slot allows.  We just need to single-instruction step in that 
+    // case.
+    static const char *g_branch_island_pattern = "\\.island\\.?[0-9]*$";
+    static RegularExpression g_branch_island_regex(g_branch_island_pattern);
+
+    bool is_branch_island = g_branch_island_regex.Execute(current_name);
+    if (!thread_plan_sp && is_branch_island) {
+      thread_plan_sp = std::make_shared<ThreadPlanStepInstruction>(
+          thread,
+          /* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
+          eVoteNoOpinion);
+      LLDB_LOG(log, "Stepping one instruction over branch island: '{0}'.",
+               current_name);
+    }
   } else {
     LLDB_LOGF(log, "Could not find symbol for step through.");
   }
diff --git a/lldb/test/API/macosx/branch-islands/Makefile b/lldb/test/API/macosx/branch-islands/Makefile
new file mode 100644
index 0000000000000..062e947f6d6ee
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/Makefile
@@ -0,0 +1,16 @@
+C_SOURCES := main.c foo.c
+CFLAGS_EXTRAS := -std=c99
+
+include Makefile.rules
+
+a.out: main.o padding1.o padding2.o padding3.o padding4.o foo.o
+	${CC} ${LDFLAGS} foo.o padding1.o padding2.o padding3.o padding4.o main.o -o a.out
+
+%.o: $(SRCDIR)/%.s
+	${CC} -c $<
+
+#padding1.o: padding1.s
+#	${CC} -c $(SRCDIR)/padding1.s
+
+#padding2.o: padding2.s
+#	${CC} -c $(SRCDIR)/padding2.s
diff --git a/lldb/test/API/macosx/branch-islands/TestBranchIslands.py b/lldb/test/API/macosx/branch-islands/TestBranchIslands.py
new file mode 100644
index 0000000000000..b397e0c229b08
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/TestBranchIslands.py
@@ -0,0 +1,35 @@
+"""
+Make sure that we can step in across an arm64 branch island
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+
+class TestBranchIslandStepping(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessDarwin
+    def test_step_in_branch_island(self):
+        """Make sure we can step in across a branch island"""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("main.c")
+        self.do_test()
+
+    def do_test(self):
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", self.main_source_file
+        )
+
+        # Make sure that we did manage to generate a branch island for foo:
+        syms = target.FindSymbols("foo.island", lldb.eSymbolTypeCode)
+        self.assertEqual(len(syms), 1, "We did generate an island for foo")
+
+        thread.StepInto()
+        stop_frame = thread.frames[0]
+        self.assertIn("foo", stop_frame.name, "Stepped into foo")
+        var = stop_frame.FindVariable("a_variable_in_foo")
+        self.assertTrue(var.IsValid(), "Found the variable in foo")
diff --git a/lldb/test/API/macosx/branch-islands/foo.c b/lldb/test/API/macosx/branch-islands/foo.c
new file mode 100644
index 0000000000000..a5dd2e59e1d82
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/foo.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void foo() {
+  int a_variable_in_foo = 10;
+  printf("I am foo: %d.\n", a_variable_in_foo);
+}
diff --git a/lldb/test/API/macosx/branch-islands/main.c b/lldb/test/API/macosx/branch-islands/main.c
new file mode 100644
index 0000000000000..b5578bdd715df
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/main.c
@@ -0,0 +1,6 @@
+extern void foo();
+
+int main() {
+  foo(); // Set a breakpoint here
+  return 0;
+}
diff --git a/lldb/test/API/macosx/branch-islands/padding1.s b/lldb/test/API/macosx/branch-islands/padding1.s
new file mode 100644
index 0000000000000..4911e53b0240d
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/padding1.s
@@ -0,0 +1,3 @@
+.text
+_padding1:
+.space 120*1024*1024
diff --git a/lldb/test/API/macosx/branch-islands/padding2.s b/lldb/test/API/macosx/branch-islands/padding2.s
new file mode 100644
index 0000000000000..5ad1bad11263b
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/padding2.s
@@ -0,0 +1,3 @@
+.text
+_padding2:
+.space 120*1024*1024
diff --git a/lldb/test/API/macosx/branch-islands/padding3.s b/lldb/test/API/macosx/branch-islands/padding3.s
new file mode 100644
index 0000000000000..9f614eecf56d9
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/padding3.s
@@ -0,0 +1,3 @@
+.text
+_padding3:
+.space 120*1024*1024
diff --git a/lldb/test/API/macosx/branch-islands/padding4.s b/lldb/test/API/macosx/branch-islands/padding4.s
new file mode 100644
index 0000000000000..12896cf5e5b8e
--- /dev/null
+++ b/lldb/test/API/macosx/branch-islands/padding4.s
@@ -0,0 +1,3 @@
+.text
+_padding4:
+.space 120*1024*1024

Copy link

github-actions bot commented May 6, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship it

@jimingham jimingham merged commit 11f33ab into llvm:main May 6, 2025
6 of 9 checks passed
@jimingham jimingham deleted the branch-island-with-numbers branch May 6, 2025 23:58
// They are to allow arm64 code to branch further than the size of the
// address slot allows. We just need to single-instruction step in that
// case.
static const char *g_branch_island_pattern = "\\.island\\.?[0-9]*$";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pedantic, but maybe "\\.island\\(.[0-9]+)?$" would be more precise, since foo.island. with no number should probably not get matched?

if (!thread_plan_sp && is_branch_island) {
thread_plan_sp = std::make_shared<ThreadPlanStepInstruction>(
thread,
/* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
/*step_over=*/ false, /*stop_others=*/ false, eVoteNoOpinion,

%.o: $(SRCDIR)/%.s
${CC} -c $<

#padding1.o: padding1.s
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete this?

@@ -0,0 +1,3 @@
.text
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the first cross-architecture assembler source file I've seen :-)

@llvm-ci
Copy link
Collaborator

llvm-ci commented May 7, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/21769

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-shell :: SymbolFile/PDB/function-level-linking.test (2882 of 2891)
UNSUPPORTED: lldb-shell :: SymbolFile/DWARF/x86/dwarf5-macho.c (2883 of 2891)
UNSUPPORTED: lldb-api :: macosx/branch-islands/TestBranchIslands.py (2884 of 2891)
PASS: lldb-api :: tools/lldb-server/TestLldbGdbServer.py (2885 of 2891)
PASS: lldb-api :: api/multithreaded/TestMultithreaded.py (2886 of 2891)
PASS: lldb-api :: terminal/TestEditlineCompletions.py (2887 of 2891)
PASS: lldb-api :: commands/process/attach/TestProcessAttach.py (2888 of 2891)
PASS: lldb-api :: repl/clang/TestClangREPL.py (2889 of 2891)
PASS: lldb-api :: tools/lldb-dap/attach/TestDAP_attachByPortNum.py (2890 of 2891)
TIMEOUT: lldb-api :: tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py (2891 of 2891)
******************** TEST 'lldb-api :: tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/breakpoint -p TestDAP_setExceptionBreakpoints.py
--
Exit Code: -9
Timeout: Reached timeout of 600 seconds

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 11f33ab3850886510a831122078a155be7dc1167)
  clang revision 11f33ab3850886510a831122078a155be7dc1167
  llvm revision 11f33ab3850886510a831122078a155be7dc1167

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/breakpoint
runCmd: settings clear --all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 

runCmd: settings set target.auto-apply-fixits false

felipepiovezan added a commit that referenced this pull request May 7, 2025
This reverts commit 11f33ab.

This is failing on CI.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
Reapply the support for stepping through branch islands, add support for
a branch that takes multiple hops to get to the target.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
This reverts commit 11f33ab.

This is failing on CI.
jimingham added a commit to jimingham/from-apple-llvm-project that referenced this pull request May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants