22#define DEBUG_TYPE "jitlink"
32 std::shared_ptr<orc::SymbolStringPool> SSP,
44 MachOPointer64Authenticated,
66 CPUSubType &= ~MachO::CPU_SUBTYPE_MASK;
68 return Triple(
"arm64e-apple-darwin");
69 return Triple(
"arm64-apple-darwin");
78 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
80 return MachOPointer32;
104 return MachOPageOffset12;
108 return MachOGOTPage21;
112 return MachOGOTPageOffset12;
116 return MachOPointerToGOT;
120 return MachOPairedAddend;
124 return MachOPointer64Authenticated;
128 return MachOTLVPage21;
132 return MachOTLVPageOffset12;
136 return make_error<JITLinkError>(
137 "Unsupported arm64 relocation: address=" +
141 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
142 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
146 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
156 using namespace support;
158 assert(((SubtractorKind == MachODelta32 && SubRI.
r_length == 2) ||
159 (SubtractorKind == MachODelta64 && SubRI.
r_length == 3)) &&
160 "Subtractor kind should match length");
161 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
162 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
164 if (UnsignedRelItr == RelEnd)
165 return make_error<JITLinkError>(
"arm64 SUBTRACTOR without paired "
166 "UNSIGNED relocation");
170 if (SubRI.
r_address != UnsignedRI.r_address)
171 return make_error<JITLinkError>(
"arm64 SUBTRACTOR and paired UNSIGNED "
172 "point to different addresses");
174 if (SubRI.
r_length != UnsignedRI.r_length)
175 return make_error<JITLinkError>(
"length of arm64 SUBTRACTOR and paired "
176 "UNSIGNED reloc must match");
180 FromSymbol = FromSymbolOrErr->GraphSymbol;
182 return FromSymbolOrErr.takeError();
187 FixupValue = *(
const little64_t *)FixupContent;
189 FixupValue = *(
const little32_t *)FixupContent;
193 Symbol *ToSymbol =
nullptr;
194 if (UnsignedRI.r_extern) {
197 ToSymbol = ToSymbolOrErr->GraphSymbol;
199 return ToSymbolOrErr.takeError();
203 return ToSymbolSec.takeError();
205 assert(ToSymbol &&
"No symbol for section");
213 bool FixingFromSymbol =
true;
219 FixingFromSymbol =
true;
220 else if (FromSymbol->
getAddress() > FixupAddress)
221 FixingFromSymbol =
false;
225 FixingFromSymbol =
true;
228 FixingFromSymbol =
false;
231 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
232 "either 'A' or 'B' (or a symbol in one "
233 "of their alt-entry groups)");
237 if (FixingFromSymbol) {
238 TargetSymbol = ToSymbol;
240 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
243 TargetSymbol = &*FromSymbol;
246 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
249 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
253 using namespace support;
264 if (S.relocation_begin() != S.relocation_end())
265 return make_error<JITLinkError>(
"Virtual section contains "
273 return NSec.takeError();
278 if (!NSec->GraphSection) {
280 dbgs() <<
" Skipping relocations for MachO section "
281 << NSec->SegName <<
"/" << NSec->SectName
282 <<
" which has no associated graph section\n";
288 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
289 RelItr != RelEnd; ++RelItr) {
294 auto MachORelocKind = getRelocationKind(RI);
296 return MachORelocKind.takeError();
302 dbgs() <<
" " << NSec->SectName <<
" + "
307 Block *BlockToFix =
nullptr;
310 if (!SymbolToFixOrErr)
311 return SymbolToFixOrErr.takeError();
312 BlockToFix = &SymbolToFixOrErr->getBlock();
317 return make_error<JITLinkError>(
318 "Relocation content extends past end of fixup block");
327 Symbol *TargetSymbol =
nullptr;
330 if (*MachORelocKind == MachOPairedAddend) {
337 if (RelItr == RelEnd)
338 return make_error<JITLinkError>(
"Unpaired Addend reloc at " +
339 formatv(
"{0:x16}", FixupAddress));
342 MachORelocKind = getRelocationKind(RI);
344 return MachORelocKind.takeError();
346 if (*MachORelocKind != MachOBranch26 &&
347 *MachORelocKind != MachOPage21 &&
348 *MachORelocKind != MachOPageOffset12)
349 return make_error<JITLinkError>(
350 "Invalid relocation pair: Addend + " +
351 StringRef(getMachOARM64RelocationKindName(*MachORelocKind)));
354 dbgs() <<
" Addend: value = " <<
formatv(
"{0:x6}", Addend)
356 << getMachOARM64RelocationKindName(*MachORelocKind) <<
"\n";
362 if (PairedFixupAddress != FixupAddress)
363 return make_error<JITLinkError>(
"Paired relocation points at "
367 switch (*MachORelocKind) {
368 case MachOBranch26: {
370 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
372 return TargetSymbolOrErr.takeError();
373 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
374 if ((Instr & 0x7fffffff) != 0x14000000)
375 return make_error<JITLinkError>(
"BRANCH26 target is not a B or BL "
376 "instruction with a zero addend");
382 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
384 return TargetSymbolOrErr.takeError();
385 Addend = *(
const ulittle32_t *)FixupContent;
389 case MachOPointer64Authenticated:
391 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
393 return TargetSymbolOrErr.takeError();
394 Addend = *(
const ulittle64_t *)FixupContent;
395 Kind = *MachORelocKind == MachOPointer64
399 case MachOPointer64Anon: {
403 return TargetNSec.takeError();
404 if (
auto TargetSymbolOrErr =
406 TargetSymbol = &*TargetSymbolOrErr;
408 return TargetSymbolOrErr.takeError();
409 Addend = TargetAddress - TargetSymbol->
getAddress();
415 case MachOTLVPage21: {
417 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
419 return TargetSymbolOrErr.takeError();
420 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
421 if ((Instr & 0xffffffe0) != 0x90000000)
422 return make_error<JITLinkError>(
"PAGE21/GOTPAGE21 target is not an "
423 "ADRP instruction with a zero "
426 if (*MachORelocKind == MachOPage21) {
428 }
else if (*MachORelocKind == MachOGOTPage21) {
430 }
else if (*MachORelocKind == MachOTLVPage21) {
435 case MachOPageOffset12: {
437 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
439 return TargetSymbolOrErr.takeError();
440 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
441 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
442 if (EncodedAddend != 0)
443 return make_error<JITLinkError>(
"GOTPAGEOFF12 target has non-zero "
448 case MachOGOTPageOffset12:
449 case MachOTLVPageOffset12: {
451 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
453 return TargetSymbolOrErr.takeError();
454 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
455 if ((Instr & 0xfffffc00) != 0xf9400000)
456 return make_error<JITLinkError>(
"GOTPAGEOFF12 target is not an LDR "
457 "immediate instruction with a zero "
460 if (*MachORelocKind == MachOGOTPageOffset12) {
462 }
else if (*MachORelocKind == MachOTLVPageOffset12) {
467 case MachOPointerToGOT:
469 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
471 return TargetSymbolOrErr.takeError();
483 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
484 FixupAddress, FixupContent, ++RelItr, RelEnd);
486 return PairInfo.takeError();
487 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
488 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
498 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
504 *TargetSymbol, Addend);
511 const char *getMachOARM64RelocationKindName(
Edge::Kind R) {
514 return "MachOBranch26";
516 return "MachOPointer64";
517 case MachOPointer64Anon:
518 return "MachOPointer64Anon";
519 case MachOPointer64Authenticated:
520 return "MachOPointer64Authenticated";
522 return "MachOPage21";
523 case MachOPageOffset12:
524 return "MachOPageOffset12";
526 return "MachOGOTPage21";
527 case MachOGOTPageOffset12:
528 return "MachOGOTPageOffset12";
530 return "MachOTLVPage21";
531 case MachOTLVPageOffset12:
532 return "MachOTLVPageOffset12";
533 case MachOPointerToGOT:
534 return "MachOPointerToGOT";
535 case MachOPairedAddend:
536 return "MachOPairedAddend";
537 case MachOLDRLiteral19:
538 return "MachOLDRLiteral19";
540 return "MachODelta32";
542 return "MachODelta64";
543 case MachONegDelta32:
544 return "MachONegDelta32";
545 case MachONegDelta64:
546 return "MachONegDelta64";
552 unsigned NumSymbols = 0;
574 std::unique_ptr<LinkGraph>
G,
587 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
590 return MachOObj.takeError();
592 auto Features = (*MachOObj)->getFeatures();
594 return Features.takeError();
596 return MachOLinkGraphBuilder_arm64(**MachOObj, std::move(SSP),
597 std::move(*Features))
603 "PAC signing only valid for arm64e");
605 if (
auto *ModInitSec =
G.findSectionByName(
"__DATA,__mod_init_func")) {
606 for (
auto *
B : ModInitSec->blocks()) {
607 for (
auto &
E :
B->edges()) {
611 if (
E.getAddend() >> 32)
612 return make_error<JITLinkError>(
613 "In " +
G.getName() +
", __mod_init_func pointer at " +
614 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
615 " has data in high bits of addend (addend >= 2^32)");
621 E.setAddend(
E.getAddend() | SigningBits);
645 constexpr uint32_t DWARFMode = 0x03000000;
653 std::unique_ptr<JITLinkContext> Ctx) {
657 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
659 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
660 Config.PrePrunePasses.push_back(std::move(MarkLive));
669 auto CompactUnwindMgr =
670 std::make_shared<CompactUnwindManager<CompactUnwindTraits_MachO_arm64>>(
676 return CompactUnwindMgr->prepareForPrune(
G);
680 Config.PostAllocationPasses.push_back(
688 if (
G->getTargetTriple().isArm64e()) {
690 Config.PostPrunePasses.push_back(
692 Config.PreFixupPasses.push_back(
698 return CompactUnwindMgr->processAndReserveUnwindInfo(
G);
703 return CompactUnwindMgr->writeUnwindInfo(
G);
707 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
708 return Ctx->notifyFailed(std::move(Err));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
size_t size() const
size - Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef - Represent a constant reference to a string, i.e.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
orc::ExecutorAddr getAddress() const
An Addressable with content and edges.
ArrayRef< char > getContent() const
Get the content for this block. Block must not be a zero-fill block.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...
A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.
Represents fixups and constraints in the LinkGraph.
static void link(ArgTs &&... Args)
Link constructs a LinkerImpl instance and calls linkPhase1.
MachOJITLinker_arm64(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)
const object::MachOObjectFile & getObject() const
virtual Error addRelocations()=0
Expected< Symbol & > findSymbolByAddress(NormalizedSection &NSec, orc::ExecutorAddr Address)
Returns the symbol with the highest address not greater than the search address, or an error if no su...
Expected< NormalizedSymbol & > findSymbolByIndex(uint64_t Index)
Try to get the symbol at the given index.
Symbol * getSymbolByAddress(NormalizedSection &NSec, orc::ExecutorAddr Address)
Returns the symbol with the highest address not greater than the search address, or null if no such s...
MachO::relocation_info getRelocationInfo(const object::relocation_iterator RelItr)
Expected< NormalizedSection & > findSectionByIndex(unsigned Index)
Try to get the section at the given index.
Addressable & getAddressable()
Return the addressable that this symbol points to.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
Global Offset Table Builder.
Procedure Linkage Table Builder.
StringRef getData() const
MachO::symtab_command getSymtabLoadCommand() const
uint64_t getSectionIndex(DataRefImpl Sec) const override
static Expected< std::unique_ptr< MachOObjectFile > > createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0, size_t MachOFilesetEntryOffset=0)
Create a MachOObjectFile instance from a given buffer.
section_iterator_range sections() const
Represents an address in the executor process.
uint64_t getValue() const
unique_function is a type-erasing functor similar to std::function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ARM64_RELOC_POINTER_TO_GOT
@ ARM64_RELOC_AUTHENTICATED_POINTER
@ ARM64_RELOC_GOT_LOAD_PAGE21
@ ARM64_RELOC_TLVP_LOAD_PAGEOFF12
@ ARM64_RELOC_GOT_LOAD_PAGEOFF12
@ ARM64_RELOC_TLVP_LOAD_PAGE21
constexpr uint64_t PointerSize
aarch64 pointer size.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)
Apply fixup expression for edge to block content.
Error createEmptyPointerSigningFunction(LinkGraph &G)
Creates a pointer signing function section, block, and symbol to reserve space for a signing function...
Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G)
Given a LinkGraph containing Pointer64Authenticated edges, transform those edges to Pointer64 and add...
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
@ Pointer64Authenticated
An arm64e authenticated pointer relocation.
@ RequestTLVPAndTransformToPageOffset12
A TLVP entry getter/constructor, transformed to PageOffset12.
@ Page21
The signed 21-bit delta from the fixup page to the page containing the target.
@ Branch26PCRel
A 26-bit PC-relative branch.
@ Pointer64
A plain 64-bit pointer value relocation.
@ Pointer32
A plain 32-bit pointer value relocation.
@ RequestTLVPAndTransformToPage21
A TLVP entry getter/constructor, transformed to Page21.
@ RequestGOTAndTransformToPage21
A GOT entry getter/constructor, transformed to Page21 pointing at the GOT entry for the original targ...
@ RequestGOTAndTransformToPageOffset12
A GOT entry getter/constructor, transformed to Pageoffset12 pointing at the GOT entry for the origina...
@ NegDelta32
A 32-bit negative delta.
@ NegDelta64
A 64-bit negative delta.
@ RequestGOTAndTransformToDelta32
A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...
@ PageOffset12
The 12-bit (potentially shifted) offset of the target within its page.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
void link_MachO_arm64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a MachO arm64 object file.
LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_arm64()
Returns a pass suitable for fixing missing edges in an __eh_frame section in a MachO/x86-64 object.
LinkGraphPassFunction createEHFrameSplitterPass_MachO_arm64()
Returns a pass suitable for splitting __eh_frame sections in MachO/x86-64 objects.
void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)
For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
Error buildTables_MachO_arm64(LinkGraph &G)
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from a MachO/arm64 relocatable object.
DefineExternalSectionStartAndEndSymbols< SymbolIdentifierFunction > createDefineExternalSectionStartAndEndSymbolsPass(SymbolIdentifierFunction &&F)
Returns a JITLink pass (as a function class) that uses the given symbol identification function to id...
SectionRangeSymbolDesc identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym)
MachO section start/end symbol detection.
static Error applyPACSigningToModInitPointers(LinkGraph &G)
StringRef MachOEHFrameSectionName
StringRef MachOCompactUnwindSectionName
StringRef MachOUnwindInfoSectionName
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Implement std::hash so that hash_code can be used in STL containers.
static bool encodingSpecifiesDWARF(uint32_t Encoding)
static bool encodingCannotBeMerged(uint32_t Encoding)
static constexpr uint32_t EncodingModeMask
static constexpr uint32_t DWARFSectionOffsetMask
static constexpr endianness Endianness
CRTP base for compact unwind traits classes.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...