Skip to content

Commit 6957c00

Browse files
authored
[RuntimeDyld][ELF][AArch64] Fix resolveAArch64ShortBranch. (#92245)
We don't know the load addresses when this function is called, so it shouldn't be trying to use them to determine whether or not the branch is short. Notably, this will fail in the case where the code is being loaded into a target in such a way that the section offsets differ between the process generating the code and the target process. rdar://127673408
1 parent 326f58d commit 6957c00

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,8 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType,
11291129
bool RuntimeDyldELF::resolveAArch64ShortBranch(
11301130
unsigned SectionID, relocation_iterator RelI,
11311131
const RelocationValueRef &Value) {
1132-
uint64_t Address;
1132+
uint64_t TargetOffset;
1133+
unsigned TargetSectionID;
11331134
if (Value.SymbolName) {
11341135
auto Loc = GlobalSymbolTable.find(Value.SymbolName);
11351136

@@ -1138,23 +1139,32 @@ bool RuntimeDyldELF::resolveAArch64ShortBranch(
11381139
return false;
11391140

11401141
const auto &SymInfo = Loc->second;
1141-
Address =
1142-
uint64_t(Sections[SymInfo.getSectionID()].getLoadAddressWithOffset(
1143-
SymInfo.getOffset()));
1142+
1143+
TargetSectionID = SymInfo.getSectionID();
1144+
TargetOffset = SymInfo.getOffset();
11441145
} else {
1145-
Address = uint64_t(Sections[Value.SectionID].getLoadAddress());
1146+
TargetSectionID = Value.SectionID;
1147+
TargetOffset = 0;
11461148
}
1147-
uint64_t Offset = RelI->getOffset();
1148-
uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset);
1149+
1150+
// We don't actually know the load addresses at this point, so if the
1151+
// branch is cross-section, we don't know exactly how far away it is.
1152+
if (TargetSectionID != SectionID)
1153+
return false;
1154+
1155+
uint64_t SourceOffset = RelI->getOffset();
11491156

11501157
// R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27
11511158
// If distance between source and target is out of range then we should
11521159
// create thunk.
1153-
if (!isInt<28>(Address + Value.Addend - SourceAddress))
1160+
if (!isInt<28>(TargetOffset + Value.Addend - SourceOffset))
11541161
return false;
11551162

1156-
resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(),
1157-
Value.Addend);
1163+
RelocationEntry RE(SectionID, SourceOffset, RelI->getType(), Value.Addend);
1164+
if (Value.SymbolName)
1165+
addRelocationForSymbol(RE, Value.SymbolName);
1166+
else
1167+
addRelocationForSection(RE, Value.SectionID);
11581168

11591169
return true;
11601170
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %t %s
2+
# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -check=%s %t
3+
4+
.globl _main
5+
.weak _label1
6+
7+
.section .text.label1,"ax"
8+
_label1:
9+
nop
10+
11+
.section .text.main,"ax"
12+
_main:
13+
b _label1
14+
15+
# Branch must be to stub in .text.main, *not* back to _label1, because
16+
# in general sections could be loaded at arbitrary addresses in target memory,
17+
# and when initially processing locations and generating stubs we don't know
18+
# the final layout yet, so we can't tell if the branch offset is within range.
19+
20+
# rtdyld-check: *{4}(_main) = 0x14000001

0 commit comments

Comments
 (0)