20#define DEBUG_TYPE "jitlink"
30 std::shared_ptr<orc::SymbolStringPool> SSP,
42 MachOPointer64Authenticated,
64 CPUSubType &= ~MachO::CPU_SUBTYPE_MASK;
66 return Triple(
"arm64e-apple-darwin");
67 return Triple(
"arm64-apple-darwin");
76 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
78 return MachOPointer32;
102 return MachOPageOffset12;
106 return MachOGOTPage21;
110 return MachOGOTPageOffset12;
114 return MachOPointerToGOT;
118 return MachOPairedAddend;
122 return MachOPointer64Authenticated;
126 return MachOTLVPage21;
130 return MachOTLVPageOffset12;
134 return make_error<JITLinkError>(
135 "Unsupported arm64 relocation: address=" +
139 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
140 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
144 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
154 using namespace support;
156 assert(((SubtractorKind == MachODelta32 && SubRI.
r_length == 2) ||
157 (SubtractorKind == MachODelta64 && SubRI.
r_length == 3)) &&
158 "Subtractor kind should match length");
159 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
160 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
162 if (UnsignedRelItr == RelEnd)
163 return make_error<JITLinkError>(
"arm64 SUBTRACTOR without paired "
164 "UNSIGNED relocation");
168 if (SubRI.
r_address != UnsignedRI.r_address)
169 return make_error<JITLinkError>(
"arm64 SUBTRACTOR and paired UNSIGNED "
170 "point to different addresses");
172 if (SubRI.
r_length != UnsignedRI.r_length)
173 return make_error<JITLinkError>(
"length of arm64 SUBTRACTOR and paired "
174 "UNSIGNED reloc must match");
178 FromSymbol = FromSymbolOrErr->GraphSymbol;
180 return FromSymbolOrErr.takeError();
185 FixupValue = *(
const little64_t *)FixupContent;
187 FixupValue = *(
const little32_t *)FixupContent;
191 Symbol *ToSymbol =
nullptr;
192 if (UnsignedRI.r_extern) {
195 ToSymbol = ToSymbolOrErr->GraphSymbol;
197 return ToSymbolOrErr.takeError();
201 return ToSymbolSec.takeError();
203 assert(ToSymbol &&
"No symbol for section");
211 bool FixingFromSymbol =
true;
217 FixingFromSymbol =
true;
218 else if (FromSymbol->
getAddress() > FixupAddress)
219 FixingFromSymbol =
false;
223 FixingFromSymbol =
true;
226 FixingFromSymbol =
false;
229 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
230 "either 'A' or 'B' (or a symbol in one "
231 "of their alt-entry groups)");
235 if (FixingFromSymbol) {
236 TargetSymbol = ToSymbol;
238 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
241 TargetSymbol = &*FromSymbol;
244 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
247 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
251 using namespace support;
262 if (S.relocation_begin() != S.relocation_end())
263 return make_error<JITLinkError>(
"Virtual section contains "
271 return NSec.takeError();
276 if (!NSec->GraphSection) {
278 dbgs() <<
" Skipping relocations for MachO section "
279 << NSec->SegName <<
"/" << NSec->SectName
280 <<
" which has no associated graph section\n";
286 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
287 RelItr != RelEnd; ++RelItr) {
292 auto MachORelocKind = getRelocationKind(RI);
294 return MachORelocKind.takeError();
300 dbgs() <<
" " << NSec->SectName <<
" + "
305 Block *BlockToFix =
nullptr;
308 if (!SymbolToFixOrErr)
309 return SymbolToFixOrErr.takeError();
310 BlockToFix = &SymbolToFixOrErr->getBlock();
315 return make_error<JITLinkError>(
316 "Relocation content extends past end of fixup block");
325 Symbol *TargetSymbol =
nullptr;
328 if (*MachORelocKind == MachOPairedAddend) {
335 if (RelItr == RelEnd)
336 return make_error<JITLinkError>(
"Unpaired Addend reloc at " +
337 formatv(
"{0:x16}", FixupAddress));
340 MachORelocKind = getRelocationKind(RI);
342 return MachORelocKind.takeError();
344 if (*MachORelocKind != MachOBranch26 &&
345 *MachORelocKind != MachOPage21 &&
346 *MachORelocKind != MachOPageOffset12)
347 return make_error<JITLinkError>(
348 "Invalid relocation pair: Addend + " +
349 StringRef(getMachOARM64RelocationKindName(*MachORelocKind)));
352 dbgs() <<
" Addend: value = " <<
formatv(
"{0:x6}", Addend)
354 << getMachOARM64RelocationKindName(*MachORelocKind) <<
"\n";
360 if (PairedFixupAddress != FixupAddress)
361 return make_error<JITLinkError>(
"Paired relocation points at "
365 switch (*MachORelocKind) {
366 case MachOBranch26: {
368 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
370 return TargetSymbolOrErr.takeError();
371 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
372 if ((Instr & 0x7fffffff) != 0x14000000)
373 return make_error<JITLinkError>(
"BRANCH26 target is not a B or BL "
374 "instruction with a zero addend");
380 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
382 return TargetSymbolOrErr.takeError();
383 Addend = *(
const ulittle32_t *)FixupContent;
387 case MachOPointer64Authenticated:
389 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
391 return TargetSymbolOrErr.takeError();
392 Addend = *(
const ulittle64_t *)FixupContent;
393 Kind = *MachORelocKind == MachOPointer64
397 case MachOPointer64Anon: {
401 return TargetNSec.takeError();
402 if (
auto TargetSymbolOrErr =
404 TargetSymbol = &*TargetSymbolOrErr;
406 return TargetSymbolOrErr.takeError();
407 Addend = TargetAddress - TargetSymbol->
getAddress();
413 case MachOTLVPage21: {
415 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
417 return TargetSymbolOrErr.takeError();
418 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
419 if ((Instr & 0xffffffe0) != 0x90000000)
420 return make_error<JITLinkError>(
"PAGE21/GOTPAGE21 target is not an "
421 "ADRP instruction with a zero "
424 if (*MachORelocKind == MachOPage21) {
426 }
else if (*MachORelocKind == MachOGOTPage21) {
428 }
else if (*MachORelocKind == MachOTLVPage21) {
433 case MachOPageOffset12: {
435 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
437 return TargetSymbolOrErr.takeError();
438 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
439 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
440 if (EncodedAddend != 0)
441 return make_error<JITLinkError>(
"GOTPAGEOFF12 target has non-zero "
446 case MachOGOTPageOffset12:
447 case MachOTLVPageOffset12: {
449 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
451 return TargetSymbolOrErr.takeError();
452 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
453 if ((Instr & 0xfffffc00) != 0xf9400000)
454 return make_error<JITLinkError>(
"GOTPAGEOFF12 target is not an LDR "
455 "immediate instruction with a zero "
458 if (*MachORelocKind == MachOGOTPageOffset12) {
460 }
else if (*MachORelocKind == MachOTLVPageOffset12) {
465 case MachOPointerToGOT:
467 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
469 return TargetSymbolOrErr.takeError();
481 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
482 FixupAddress, FixupContent, ++RelItr, RelEnd);
484 return PairInfo.takeError();
485 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
486 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
496 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
502 *TargetSymbol, Addend);
509 const char *getMachOARM64RelocationKindName(
Edge::Kind R) {
512 return "MachOBranch26";
514 return "MachOPointer64";
515 case MachOPointer64Anon:
516 return "MachOPointer64Anon";
517 case MachOPointer64Authenticated:
518 return "MachOPointer64Authenticated";
520 return "MachOPage21";
521 case MachOPageOffset12:
522 return "MachOPageOffset12";
524 return "MachOGOTPage21";
525 case MachOGOTPageOffset12:
526 return "MachOGOTPageOffset12";
528 return "MachOTLVPage21";
529 case MachOTLVPageOffset12:
530 return "MachOTLVPageOffset12";
531 case MachOPointerToGOT:
532 return "MachOPointerToGOT";
533 case MachOPairedAddend:
534 return "MachOPairedAddend";
535 case MachOLDRLiteral19:
536 return "MachOLDRLiteral19";
538 return "MachODelta32";
540 return "MachODelta64";
541 case MachONegDelta32:
542 return "MachONegDelta32";
543 case MachONegDelta64:
544 return "MachONegDelta64";
550 unsigned NumSymbols = 0;
572 std::unique_ptr<LinkGraph>
G,
585 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
588 return MachOObj.takeError();
590 auto Features = (*MachOObj)->getFeatures();
592 return Features.takeError();
594 return MachOLinkGraphBuilder_arm64(**MachOObj, std::move(SSP),
595 std::move(*Features))
601 "PAC signing only valid for arm64e");
603 if (
auto *ModInitSec =
G.findSectionByName(
"__DATA,__mod_init_func")) {
604 for (
auto *
B : ModInitSec->blocks()) {
605 for (
auto &
E :
B->edges()) {
609 if (
E.getAddend() >> 32)
610 return make_error<JITLinkError>(
611 "In " +
G.getName() +
", __mod_init_func pointer at " +
612 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
613 " has data in high bits of addend (addend >= 2^32)");
619 E.setAddend(
E.getAddend() | SigningBits);
629 std::unique_ptr<JITLinkContext> Ctx) {
633 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
635 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
636 Config.PrePrunePasses.push_back(std::move(MarkLive));
641 Config.PrePrunePasses.push_back(
651 Config.PostAllocationPasses.push_back(
659 if (
G->getTargetTriple().isArm64e()) {
661 Config.PostPrunePasses.push_back(
663 Config.PreFixupPasses.push_back(
668 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
669 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 pass to split up __LD,__compact_unwind sections.
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)
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.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...