20#define DEBUG_TYPE "jitlink"
62 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
64 return MachOPointer32;
88 return MachOPageOffset12;
92 return MachOGOTPage21;
96 return MachOGOTPageOffset12;
100 return MachOPointerToGOT;
104 return MachOPairedAddend;
108 return MachOTLVPage21;
112 return MachOTLVPageOffset12;
116 return make_error<JITLinkError>(
117 "Unsupported arm64 relocation: address=" +
121 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
122 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
126 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
136 using namespace support;
138 assert(((SubtractorKind == MachODelta32 && SubRI.
r_length == 2) ||
139 (SubtractorKind == MachODelta64 && SubRI.
r_length == 3)) &&
140 "Subtractor kind should match length");
141 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
142 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
144 if (UnsignedRelItr == RelEnd)
145 return make_error<JITLinkError>(
"arm64 SUBTRACTOR without paired "
146 "UNSIGNED relocation");
150 if (SubRI.
r_address != UnsignedRI.r_address)
151 return make_error<JITLinkError>(
"arm64 SUBTRACTOR and paired UNSIGNED "
152 "point to different addresses");
154 if (SubRI.
r_length != UnsignedRI.r_length)
155 return make_error<JITLinkError>(
"length of arm64 SUBTRACTOR and paired "
156 "UNSIGNED reloc must match");
160 FromSymbol = FromSymbolOrErr->GraphSymbol;
162 return FromSymbolOrErr.takeError();
167 FixupValue = *(
const little64_t *)FixupContent;
169 FixupValue = *(
const little32_t *)FixupContent;
173 Symbol *ToSymbol =
nullptr;
174 if (UnsignedRI.r_extern) {
177 ToSymbol = ToSymbolOrErr->GraphSymbol;
179 return ToSymbolOrErr.takeError();
183 return ToSymbolSec.takeError();
185 assert(ToSymbol &&
"No symbol for section");
193 bool FixingFromSymbol =
true;
199 FixingFromSymbol =
true;
200 else if (FromSymbol->
getAddress() > FixupAddress)
201 FixingFromSymbol =
false;
205 FixingFromSymbol =
true;
208 FixingFromSymbol =
false;
211 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
212 "either 'A' or 'B' (or a symbol in one "
213 "of their alt-entry groups)");
217 if (FixingFromSymbol) {
218 TargetSymbol = ToSymbol;
220 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
223 TargetSymbol = &*FromSymbol;
226 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
229 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
233 using namespace support;
244 if (S.relocation_begin() != S.relocation_end())
245 return make_error<JITLinkError>(
"Virtual section contains "
253 return NSec.takeError();
258 if (!NSec->GraphSection) {
260 dbgs() <<
" Skipping relocations for MachO section "
261 << NSec->SegName <<
"/" << NSec->SectName
262 <<
" which has no associated graph section\n";
268 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
269 RelItr != RelEnd; ++RelItr) {
274 auto MachORelocKind = getRelocationKind(RI);
276 return MachORelocKind.takeError();
282 dbgs() <<
" " << NSec->SectName <<
" + "
287 Block *BlockToFix =
nullptr;
290 if (!SymbolToFixOrErr)
291 return SymbolToFixOrErr.takeError();
292 BlockToFix = &SymbolToFixOrErr->getBlock();
297 return make_error<JITLinkError>(
298 "Relocation content extends past end of fixup block");
307 Symbol *TargetSymbol =
nullptr;
310 if (*MachORelocKind == MachOPairedAddend) {
317 if (RelItr == RelEnd)
318 return make_error<JITLinkError>(
"Unpaired Addend reloc at " +
319 formatv(
"{0:x16}", FixupAddress));
322 MachORelocKind = getRelocationKind(RI);
324 return MachORelocKind.takeError();
326 if (*MachORelocKind != MachOBranch26 &&
327 *MachORelocKind != MachOPage21 &&
328 *MachORelocKind != MachOPageOffset12)
329 return make_error<JITLinkError>(
330 "Invalid relocation pair: Addend + " +
331 StringRef(getMachOARM64RelocationKindName(*MachORelocKind)));
334 dbgs() <<
" Addend: value = " <<
formatv(
"{0:x6}", Addend)
336 << getMachOARM64RelocationKindName(*MachORelocKind) <<
"\n";
342 if (PairedFixupAddress != FixupAddress)
343 return make_error<JITLinkError>(
"Paired relocation points at "
347 switch (*MachORelocKind) {
348 case MachOBranch26: {
350 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
352 return TargetSymbolOrErr.takeError();
353 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
354 if ((Instr & 0x7fffffff) != 0x14000000)
355 return make_error<JITLinkError>(
"BRANCH26 target is not a B or BL "
356 "instruction with a zero addend");
362 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
364 return TargetSymbolOrErr.takeError();
365 Addend = *(
const ulittle32_t *)FixupContent;
370 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
372 return TargetSymbolOrErr.takeError();
373 Addend = *(
const ulittle64_t *)FixupContent;
376 case MachOPointer64Anon: {
380 return TargetNSec.takeError();
381 if (
auto TargetSymbolOrErr =
383 TargetSymbol = &*TargetSymbolOrErr;
385 return TargetSymbolOrErr.takeError();
386 Addend = TargetAddress - TargetSymbol->
getAddress();
392 case MachOTLVPage21: {
394 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
396 return TargetSymbolOrErr.takeError();
397 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
398 if ((Instr & 0xffffffe0) != 0x90000000)
399 return make_error<JITLinkError>(
"PAGE21/GOTPAGE21 target is not an "
400 "ADRP instruction with a zero "
403 if (*MachORelocKind == MachOPage21) {
405 }
else if (*MachORelocKind == MachOGOTPage21) {
407 }
else if (*MachORelocKind == MachOTLVPage21) {
412 case MachOPageOffset12: {
414 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
416 return TargetSymbolOrErr.takeError();
417 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
418 uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
419 if (EncodedAddend != 0)
420 return make_error<JITLinkError>(
"GOTPAGEOFF12 target has non-zero "
425 case MachOGOTPageOffset12:
426 case MachOTLVPageOffset12: {
428 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
430 return TargetSymbolOrErr.takeError();
431 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
432 if ((Instr & 0xfffffc00) != 0xf9400000)
433 return make_error<JITLinkError>(
"GOTPAGEOFF12 target is not an LDR "
434 "immediate instruction with a zero "
437 if (*MachORelocKind == MachOGOTPageOffset12) {
439 }
else if (*MachORelocKind == MachOTLVPageOffset12) {
444 case MachOPointerToGOT:
446 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
448 return TargetSymbolOrErr.takeError();
460 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
461 FixupAddress, FixupContent, ++RelItr, RelEnd);
463 return PairInfo.takeError();
464 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
465 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
475 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
481 *TargetSymbol, Addend);
488 const char *getMachOARM64RelocationKindName(
Edge::Kind R) {
491 return "MachOBranch26";
493 return "MachOPointer64";
494 case MachOPointer64Anon:
495 return "MachOPointer64Anon";
497 return "MachOPage21";
498 case MachOPageOffset12:
499 return "MachOPageOffset12";
501 return "MachOGOTPage21";
502 case MachOGOTPageOffset12:
503 return "MachOGOTPageOffset12";
505 return "MachOTLVPage21";
506 case MachOTLVPageOffset12:
507 return "MachOTLVPageOffset12";
508 case MachOPointerToGOT:
509 return "MachOPointerToGOT";
510 case MachOPairedAddend:
511 return "MachOPairedAddend";
512 case MachOLDRLiteral19:
513 return "MachOLDRLiteral19";
515 return "MachODelta32";
517 return "MachODelta64";
518 case MachONegDelta32:
519 return "MachONegDelta32";
520 case MachONegDelta64:
521 return "MachONegDelta64";
527 unsigned NumSymbols = 0;
549 std::unique_ptr<LinkGraph>
G,
565 return MachOObj.takeError();
567 auto Features = (*MachOObj)->getFeatures();
569 return Features.takeError();
571 return MachOLinkGraphBuilder_arm64(**MachOObj, std::move(*Features))
576 std::unique_ptr<JITLinkContext> Ctx) {
580 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
582 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
583 Config.PrePrunePasses.push_back(std::move(MarkLive));
588 Config.PrePrunePasses.push_back(
598 Config.PostAllocationPasses.push_back(
606 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
607 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.
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.
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_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.
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
@ 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)
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.
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< 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...