Author: jimingham Date: 2025-05-08T16:22:39-07:00 New Revision: 6bb30196912daeaa92babc39519b2ae0bfce9771
URL: https://github.com/llvm/llvm-project/commit/6bb30196912daeaa92babc39519b2ae0bfce9771 DIFF: https://github.com/llvm/llvm-project/commit/6bb30196912daeaa92babc39519b2ae0bfce9771.diff LOG: Branch island debug (#139166) This patch allows lldb to step in across "branch islands" which is the Darwin linker's way of dealing with immediate branches to targets that are too far away for the immediate slot to make the jump. I submitted this a couple days ago and it failed on the arm64 bot. I was able to match the bot OS and Tool versions (they are a bit old at this point) and ran the test there but sadly it succeeded. The x86_64 bot also failed but that was my bad, I did @skipUnlessDarwin when I should have done @skipUnlessAppleSilicon. So this resubmission is with the proper decoration for the test, and with a bunch of debug output printed in case of failure. With any luck, if this resubmission fails again I'll be able to see what's going on. Added: lldb/test/API/macosx/branch-islands/Makefile lldb/test/API/macosx/branch-islands/TestBranchIslands.py lldb/test/API/macosx/branch-islands/foo.c lldb/test/API/macosx/branch-islands/main.c lldb/test/API/macosx/branch-islands/padding1.s lldb/test/API/macosx/branch-islands/padding2.s lldb/test/API/macosx/branch-islands/padding3.s lldb/test/API/macosx/branch-islands/padding4.s Modified: lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index e25c4ff55e408..578ab12268ea3 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..c79840b400432 --- /dev/null +++ b/lldb/test/API/macosx/branch-islands/TestBranchIslands.py @@ -0,0 +1,65 @@ +""" +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 + + @skipUnlessAppleSilicon + 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") + + # Gathering some info to dump in case of failure: + trace_before = lldbutil.print_stacktrace(thread, True) + func_before = thread.frames[0].function + + thread.StepInto() + stop_frame = thread.frames[0] + # This is failing on the bot, but I can't reproduce the failure + # locally. Let's see if we can dump some more info here to help + # figure out what went wrong... + if stop_frame.name.find("foo") == -1: + stream = lldb.SBStream() + print("Branch island symbols: ") + syms[0].GetDescription(stream) + for i in range(0, 6): + for sep in ["", "."]: + syms = target.FindSymbols( + f"foo.island{sep}{i}", lldb.eSymbolTypeCode + ) + if len(syms) > 0: + stream.Print("\n") + syms[0].GetDescription(stream) + + print(stream.GetData()) + print(f"Start backtrace:") + print(trace_before) + print(f"\n'main' disassembly:\n{lldbutil.disassemble(target, func_before)}") + print("\nEnd backtrace:\n") + lldbutil.print_stacktrace(thread) + print( + f"\nStop disassembly:\n {lldbutil.disassemble(target, stop_frame.function)}" + ) + + 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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits