Skip to content

Commit 1ba89ad

Browse files
authored
Handle step-in over a Darwin "branch island". (llvm#138330)
1 parent 13926e1 commit 1ba89ad

File tree

7 files changed

+86
-7
lines changed

7 files changed

+86
-7
lines changed

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "lldb/Target/Thread.h"
2727
#include "lldb/Target/ThreadPlanCallFunction.h"
2828
#include "lldb/Target/ThreadPlanRunToAddress.h"
29+
#include "lldb/Target/ThreadPlanStepInstruction.h"
2930
#include "lldb/Utility/DataBuffer.h"
3031
#include "lldb/Utility/DataBufferHeap.h"
3132
#include "lldb/Utility/LLDBLog.h"
@@ -923,15 +924,15 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
923924
if (current_symbol != nullptr) {
924925
std::vector<Address> addresses;
925926

927+
ConstString current_name =
928+
current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
926929
if (current_symbol->IsTrampoline()) {
927-
ConstString trampoline_name =
928-
current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
929930

930-
if (trampoline_name) {
931+
if (current_name) {
931932
const ModuleList &images = target_sp->GetImages();
932933

933934
SymbolContextList code_symbols;
934-
images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode,
935+
images.FindSymbolsWithNameAndType(current_name, eSymbolTypeCode,
935936
code_symbols);
936937
for (const SymbolContext &context : code_symbols) {
937938
Address addr = context.GetFunctionOrSymbolAddress();
@@ -945,8 +946,8 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
945946
}
946947

947948
SymbolContextList reexported_symbols;
948-
images.FindSymbolsWithNameAndType(
949-
trampoline_name, eSymbolTypeReExported, reexported_symbols);
949+
images.FindSymbolsWithNameAndType(current_name, eSymbolTypeReExported,
950+
reexported_symbols);
950951
for (const SymbolContext &context : reexported_symbols) {
951952
if (context.symbol) {
952953
Symbol *actual_symbol =
@@ -968,7 +969,7 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
968969
}
969970

970971
SymbolContextList indirect_symbols;
971-
images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver,
972+
images.FindSymbolsWithNameAndType(current_name, eSymbolTypeResolver,
972973
indirect_symbols);
973974

974975
for (const SymbolContext &context : indirect_symbols) {
@@ -1028,6 +1029,18 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
10281029
thread_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
10291030
thread, load_addrs, stop_others);
10301031
}
1032+
// One more case we have to consider is "branch islands". These are regular
1033+
// TEXT symbols but their names end in .island. They are to allow arm64
1034+
// code to branch further than the size of the address slot allows. We
1035+
// just need to single-instruction step in that case.
1036+
if (!thread_plan_sp && current_name.GetStringRef().ends_with(".island")) {
1037+
thread_plan_sp = std::make_shared<ThreadPlanStepInstruction>(
1038+
thread,
1039+
/* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
1040+
eVoteNoOpinion);
1041+
LLDB_LOG(log, "Stepping one instruction over branch island: '{0}'.",
1042+
current_name);
1043+
}
10311044
} else {
10321045
LLDB_LOGF(log, "Could not find symbol for step through.");
10331046
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
C_SOURCES := main.c foo.c
2+
CFLAGS_EXTRAS := -std=c99
3+
4+
include Makefile.rules
5+
6+
a.out: main.o padding1.o padding2.o foo.o
7+
${CC} ${LDFLAGS} foo.o padding1.o padding2.o main.o -o a.out
8+
9+
padding1.o: padding1.s
10+
${CC} -c $(SRCDIR)/padding1.s
11+
12+
padding2.o: padding2.s
13+
${CC} -c $(SRCDIR)/padding2.s
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Make sure that we can step in across an arm64 branch island
3+
"""
4+
5+
6+
import lldb
7+
import lldbsuite.test.lldbutil as lldbutil
8+
from lldbsuite.test.lldbtest import *
9+
from lldbsuite.test.decorators import *
10+
11+
12+
class TestBranchIslandStepping(TestBase):
13+
NO_DEBUG_INFO_TESTCASE = True
14+
15+
@skipUnlessDarwin
16+
def test_step_in_branch_island(self):
17+
"""Make sure we can step in across a branch island"""
18+
self.build()
19+
self.main_source_file = lldb.SBFileSpec("main.c")
20+
self.do_test()
21+
22+
def do_test(self):
23+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
24+
self, "Set a breakpoint here", self.main_source_file
25+
)
26+
27+
# Make sure that we did manage to generate a branch island for foo:
28+
syms = target.FindSymbols("foo.island", lldb.eSymbolTypeCode)
29+
self.assertEqual(len(syms), 1, "We did generate an island for foo")
30+
31+
thread.StepInto()
32+
stop_frame = thread.frames[0]
33+
self.assertIn("foo", stop_frame.name, "Stepped into foo")
34+
var = stop_frame.FindVariable("a_variable_in_foo")
35+
self.assertTrue(var.IsValid(), "Found the variable in foo")
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <stdio.h>
2+
3+
void foo() {
4+
int a_variable_in_foo = 10;
5+
printf("I am foo: %d.\n", a_variable_in_foo);
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern void foo();
2+
3+
int main() {
4+
foo(); // Set a breakpoint here
5+
return 0;
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.text
2+
_junk1:
3+
.space 120*1024*1024
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.text
2+
_junk2:
3+
.space 120*1024*1024

0 commit comments

Comments
 (0)