19 #define DEBUG_TYPE "jitlink"
95 return make_error<JITLinkError>(
96 "Unsupported arm64 relocation: address=" +
100 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
101 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
105 using PairRelocInfo =
106 std::tuple<MachOARM64RelocationKind, Symbol *, uint64_t>;
120 "Subtractor kind should match length");
121 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
122 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
124 if (UnsignedRelItr == RelEnd)
125 return make_error<JITLinkError>(
"arm64 SUBTRACTOR without paired "
126 "UNSIGNED relocation");
128 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
130 if (SubRI.
r_address != UnsignedRI.r_address)
131 return make_error<JITLinkError>(
"arm64 SUBTRACTOR and paired UNSIGNED "
132 "point to different addresses");
134 if (SubRI.
r_length != UnsignedRI.r_length)
135 return make_error<JITLinkError>(
"length of arm64 SUBTRACTOR and paired "
136 "UNSIGNED reloc must match");
139 if (
auto FromSymbolOrErr = findSymbolByIndex(SubRI.
r_symbolnum))
140 FromSymbol = FromSymbolOrErr->GraphSymbol;
142 return FromSymbolOrErr.takeError();
147 FixupValue = *(
const little64_t *)FixupContent;
149 FixupValue = *(
const little32_t *)FixupContent;
153 Symbol *ToSymbol =
nullptr;
154 if (UnsignedRI.r_extern) {
156 if (
auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
157 ToSymbol = ToSymbolOrErr->GraphSymbol;
159 return ToSymbolOrErr.takeError();
161 auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
163 return ToSymbolSec.takeError();
164 ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);
165 assert(ToSymbol &&
"No symbol for section");
173 TargetSymbol = ToSymbol;
175 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
178 TargetSymbol = &*FromSymbol;
180 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
183 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
184 "either 'A' or 'B' (or a symbol in one "
185 "of their alt-entry groups)");
188 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
191 Error addRelocations()
override {
203 if (
S.relocation_begin() !=
S.relocation_end())
204 return make_error<JITLinkError>(
"Virtual section contains "
212 return NSec.takeError();
217 if (!NSec->GraphSection) {
219 dbgs() <<
" Skipping relocations for MachO section "
220 << NSec->SegName <<
"/" << NSec->SectName
221 <<
" which has no associated graph section\n";
227 for (
auto RelItr =
S.relocation_begin(), RelEnd =
S.relocation_end();
228 RelItr != RelEnd; ++RelItr) {
233 auto Kind = getRelocationKind(RI);
235 return Kind.takeError();
241 dbgs() <<
" " << NSec->SectName <<
" + "
246 Block *BlockToFix =
nullptr;
248 auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);
249 if (!SymbolToFixOrErr)
250 return SymbolToFixOrErr.takeError();
251 BlockToFix = &SymbolToFixOrErr->getBlock();
256 return make_error<JITLinkError>(
257 "Relocation content extends past end of fixup block");
264 Symbol *TargetSymbol =
nullptr;
273 if (RelItr == RelEnd)
274 return make_error<JITLinkError>(
"Unpaired Addend reloc at " +
275 formatv(
"{0:x16}", FixupAddress));
277 RI = getRelocationInfo(RelItr);
279 Kind = getRelocationKind(RI);
281 return Kind.takeError();
284 return make_error<JITLinkError>(
285 "Invalid relocation pair: Addend + " +
289 dbgs() <<
" Addend: value = " <<
formatv(
"{0:x6}", Addend)
297 if (PairedFixupAddress != FixupAddress)
298 return make_error<JITLinkError>(
"Paired relocation points at "
304 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
305 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
307 return TargetSymbolOrErr.takeError();
309 if ((Instr & 0x7fffffff) != 0x14000000)
310 return make_error<JITLinkError>(
"BRANCH26 target is not a B or BL "
311 "instruction with a zero addend");
315 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
316 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
318 return TargetSymbolOrErr.takeError();
322 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
323 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
325 return TargetSymbolOrErr.takeError();
330 auto TargetNSec = findSectionByIndex(RI.
r_symbolnum - 1);
332 return TargetNSec.takeError();
333 if (
auto TargetSymbolOrErr =
334 findSymbolByAddress(*TargetNSec, TargetAddress))
335 TargetSymbol = &*TargetSymbolOrErr;
337 return TargetSymbolOrErr.takeError();
338 Addend = TargetAddress - TargetSymbol->
getAddress();
344 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
345 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
347 return TargetSymbolOrErr.takeError();
349 if ((Instr & 0xffffffe0) != 0x90000000)
350 return make_error<JITLinkError>(
"PAGE21/GOTPAGE21 target is not an "
351 "ADRP instruction with a zero "
356 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
357 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
359 return TargetSymbolOrErr.takeError();
361 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
362 if (EncodedAddend != 0)
363 return make_error<JITLinkError>(
"GOTPAGEOFF12 target has non-zero "
369 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
370 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
372 return TargetSymbolOrErr.takeError();
374 if ((Instr & 0xfffffc00) != 0xf9400000)
375 return make_error<JITLinkError>(
"GOTPAGEOFF12 target is not an LDR "
376 "immediate instruction with a zero "
381 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
382 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
384 return TargetSymbolOrErr.takeError();
394 parsePairRelocation(*BlockToFix, *
Kind, RI, FixupAddress,
395 FixupContent, ++RelItr, RelEnd);
397 return PairInfo.takeError();
398 std::tie(*
Kind, TargetSymbol, Addend) = *PairInfo;
399 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
416 *TargetSymbol, Addend);
422 unsigned NumSymbols = 0;
425 class PerGraphGOTAndPLTStubsBuilder_MachO_arm64
427 PerGraphGOTAndPLTStubsBuilder_MachO_arm64> {
432 bool isGOTEdgeToFix(
Edge &
E)
const {
439 auto &GOTEntryBlock =
G.createContentBlock(
442 return G.addAnonymousSymbol(GOTEntryBlock, 0, 8,
false,
false);
449 E.setTarget(GOTEntry);
451 E.setTarget(GOTEntry);
457 bool isExternalBranchEdge(
Edge &
E) {
458 return E.getKind() ==
Branch26 && !
E.getTarget().isDefined();
462 auto &StubContentBlock =
G.createContentBlock(
465 auto &GOTEntrySymbol = getGOTEntry(
Target);
466 StubContentBlock.addEdge(
LDRLiteral19, 0, GOTEntrySymbol, 0);
467 return G.addAnonymousSymbol(StubContentBlock, 0, 8,
true,
false);
472 assert(
E.getAddend() == 0 &&
"Branch32 edge has non-zero addend?");
487 return *StubsSection;
491 return {
reinterpret_cast<const char *
>(NullGOTEntryContent),
492 sizeof(NullGOTEntryContent)};
496 return {
reinterpret_cast<const char *
>(StubContent),
sizeof(StubContent)};
499 static const uint8_t NullGOTEntryContent[8];
500 static const uint8_t StubContent[8];
502 Section *StubsSection =
nullptr;
506 PerGraphGOTAndPLTStubsBuilder_MachO_arm64::NullGOTEntryContent[8] = {
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
508 const uint8_t PerGraphGOTAndPLTStubsBuilder_MachO_arm64::StubContent[8] = {
509 0x10, 0x00, 0x00, 0x58,
510 0x00, 0x02, 0x1f, 0xd6
523 std::unique_ptr<LinkGraph>
G,
529 static unsigned getPageOffset12Shift(
uint32_t Instr) {
530 constexpr
uint32_t LoadStoreImm12Mask = 0x3b000000;
531 constexpr
uint32_t Vec128Mask = 0x04800000;
533 if ((Instr & LoadStoreImm12Mask) == 0x39000000) {
534 uint32_t ImplicitShift = Instr >> 30;
535 if (ImplicitShift == 0)
536 if ((Instr & Vec128Mask) == Vec128Mask)
539 return ImplicitShift;
548 char *BlockWorkingMem =
B.getAlreadyMutableContent().data();
549 char *FixupPtr = BlockWorkingMem +
E.getOffset();
552 switch (
E.getKind()) {
555 "Branch-inst is not 32-bit aligned");
557 int64_t
Value =
E.getTarget().getAddress() - FixupAddress +
E.getAddend();
560 return make_error<JITLinkError>(
"Branch26 target is not 32-bit "
563 if (
Value < -(1 << 27) ||
Value > ((1 << 27) - 1))
567 assert((RawInstr & 0x7fffffff) == 0x14000000 &&
568 "RawInstr isn't a B or BR immediate instruction");
575 uint64_t Value =
E.getTarget().getAddress().getValue() +
E.getAddend();
583 uint64_t Value =
E.getTarget().getAddress().getValue() +
E.getAddend();
591 "GOTPAGE21 with non-zero addend");
593 (
E.getTarget().getAddress().getValue() +
E.getAddend()) &
596 FixupAddress.
getValue() & ~static_cast<uint64_t>(4096 - 1);
598 int64_t PageDelta = TargetPage - PCPage;
599 if (PageDelta < -(1 << 30) || PageDelta > ((1 << 30) - 1))
603 assert((RawInstr & 0xffffffe0) == 0x90000000 &&
604 "RawInstr isn't an ADRP instruction");
607 uint32_t FixedInstr = RawInstr | (ImmLo << 29) | (ImmHi << 5);
613 (
E.getTarget().getAddress() +
E.getAddend()).getValue() & 0xfff;
616 unsigned ImmShift = getPageOffset12Shift(RawInstr);
618 if (TargetOffset & ((1 <<
ImmShift) - 1))
619 return make_error<JITLinkError>(
"PAGEOFF12 target is not aligned");
622 uint32_t FixedInstr = RawInstr | EncodedImm;
628 assert(
E.getAddend() == 0 &&
"GOTPAGEOF12 with non-zero addend");
631 assert((RawInstr & 0xfffffc00) == 0xf9400000 &&
632 "RawInstr isn't a 64-bit LDR immediate");
634 uint32_t TargetOffset =
E.getTarget().getAddress().getValue() & 0xfff;
635 assert((TargetOffset & 0x7) == 0 &&
"GOT entry is not 8-byte aligned");
636 uint32_t EncodedImm = (TargetOffset >> 3) << 10;
637 uint32_t FixedInstr = RawInstr | EncodedImm;
643 "LDR is not 32-bit aligned");
644 assert(
E.getAddend() == 0 &&
"LDRLiteral19 with non-zero addend");
646 assert(RawInstr == 0x58000010 &&
"RawInstr isn't a 64-bit LDR literal");
647 int64_t Delta =
E.getTarget().getAddress() - FixupAddress;
649 return make_error<JITLinkError>(
"LDR literal target is not 32-bit "
651 if (Delta < -(1 << 20) || Delta > ((1 << 20) - 1))
655 ((
static_cast<uint32_t>(Delta) >> 2) & 0x7ffff) << 5;
656 uint32_t FixedInstr = RawInstr | EncodedImm;
666 Value =
E.getTarget().getAddress() - FixupAddress +
E.getAddend();
668 Value = FixupAddress -
E.getTarget().getAddress() +
E.getAddend();
680 return make_error<JITLinkError>(
681 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
682 "unsupported edge kind" +
696 return MachOObj.takeError();
697 return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
701 std::unique_ptr<JITLinkContext> Ctx) {
705 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
707 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
727 PerGraphGOTAndPLTStubsBuilder_MachO_arm64::asPass);
730 if (
auto Err = Ctx->modifyPassConfig(*
G, Config))
731 return Ctx->notifyFailed(
std::move(Err));
744 return "Pointer64Anon";
748 return "PageOffset12";
752 return "GOTPageOffset12";
756 return "TLVPageOffset12";
758 return "PointerToGOT";
760 return "PairedAddend";
762 return "LDRLiteral19";