Skip to content

Commit 4c1bc8e

Browse files
committed
[JITLink][MachO] Handle intra-block subtractor relocations.
Previously the JITLink MachO backends (aarch64 and x86-64) only looked at the fixup block to determine which symbol was being fixed up. This assumption breaks if both symbols used in the subtractor are in the same block. The fix is to check for such cases and use the offsets of each symbol to decide which is being fixed up. The issue only resulted in incorrect behavior for negative-delta relocations, so the testcases use eh-frames with explicit edges for the CIE-pointer field in FDEs (since these are negative-deltas). rdar://119351329
1 parent d8ddcae commit 4c1bc8e

File tree

4 files changed

+517
-12
lines changed

4 files changed

+517
-12
lines changed

llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,21 +188,41 @@ class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
188188
Edge::Kind DeltaKind;
189189
Symbol *TargetSymbol;
190190
uint64_t Addend;
191+
192+
bool FixingFromSymbol = true;
191193
if (&BlockToFix == &FromSymbol->getAddressable()) {
194+
if (LLVM_UNLIKELY(&BlockToFix == &ToSymbol->getAddressable())) {
195+
// From and To are symbols in the same block. Decide direction by offset
196+
// instead.
197+
if (ToSymbol->getAddress() > FixupAddress)
198+
FixingFromSymbol = true;
199+
else if (FromSymbol->getAddress() > FixupAddress)
200+
FixingFromSymbol = false;
201+
else
202+
FixingFromSymbol = FromSymbol->getAddress() >= ToSymbol->getAddress();
203+
} else
204+
FixingFromSymbol = true;
205+
} else {
206+
if (&BlockToFix == &ToSymbol->getAddressable())
207+
FixingFromSymbol = false;
208+
else {
209+
// BlockToFix was neither FromSymbol nor ToSymbol.
210+
return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
211+
"either 'A' or 'B' (or a symbol in one "
212+
"of their alt-entry groups)");
213+
}
214+
}
215+
216+
if (FixingFromSymbol) {
192217
TargetSymbol = ToSymbol;
193218
DeltaKind = (SubRI.r_length == 3) ? aarch64::Delta64 : aarch64::Delta32;
194219
Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
195220
// FIXME: handle extern 'from'.
196-
} else if (&BlockToFix == &ToSymbol->getAddressable()) {
221+
} else {
197222
TargetSymbol = &*FromSymbol;
198223
DeltaKind =
199224
(SubRI.r_length == 3) ? aarch64::NegDelta64 : aarch64::NegDelta32;
200225
Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
201-
} else {
202-
// BlockToFix was neither FromSymbol nor ToSymbol.
203-
return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
204-
"either 'A' or 'B' (or a symbol in one "
205-
"of their alt-entry groups)");
206226
}
207227

208228
return PairRelocInfo(DeltaKind, TargetSymbol, Addend);

llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,41 @@ class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
179179
Edge::Kind DeltaKind;
180180
Symbol *TargetSymbol;
181181
uint64_t Addend;
182+
183+
bool FixingFromSymbol = true;
182184
if (&BlockToFix == &FromSymbol->getAddressable()) {
185+
if (LLVM_UNLIKELY(&BlockToFix == &ToSymbol->getAddressable())) {
186+
// From and To are symbols in the same block. Decide direction by offset
187+
// instead.
188+
if (ToSymbol->getAddress() > FixupAddress)
189+
FixingFromSymbol = true;
190+
else if (FromSymbol->getAddress() > FixupAddress)
191+
FixingFromSymbol = false;
192+
else
193+
FixingFromSymbol = FromSymbol->getAddress() >= ToSymbol->getAddress();
194+
} else
195+
FixingFromSymbol = true;
196+
} else {
197+
if (&BlockToFix == &ToSymbol->getAddressable())
198+
FixingFromSymbol = false;
199+
else {
200+
// BlockToFix was neither FromSymbol nor ToSymbol.
201+
return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
202+
"either 'A' or 'B' (or a symbol in one "
203+
"of their alt-entry groups)");
204+
}
205+
}
206+
207+
if (FixingFromSymbol) {
183208
TargetSymbol = ToSymbol;
184209
DeltaKind = (SubRI.r_length == 3) ? x86_64::Delta64 : x86_64::Delta32;
185210
Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
186211
// FIXME: handle extern 'from'.
187-
} else if (&BlockToFix == &ToSymbol->getAddressable()) {
212+
} else {
188213
TargetSymbol = FromSymbol;
189214
DeltaKind =
190215
(SubRI.r_length == 3) ? x86_64::NegDelta64 : x86_64::NegDelta32;
191216
Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
192-
} else {
193-
// BlockToFix was neither FromSymbol nor ToSymbol.
194-
return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
195-
"either 'A' or 'B' (or a symbol in one "
196-
"of their alt-entry chains)");
197217
}
198218

199219
return PairRelocInfo(DeltaKind, TargetSymbol, Addend);

0 commit comments

Comments
 (0)