20#define DEBUG_TYPE "jitlink"
35 enum MachONormalizedRelocationType :
unsigned {
45 MachOPCRel32Minus1Anon,
46 MachOPCRel32Minus2Anon,
47 MachOPCRel32Minus4Anon,
61 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
63 return MachOPointer32;
68 return RI.
r_extern ? MachOPCRel32 : MachOPCRel32Anon;
76 return MachOPCRel32GOTLoad;
80 return MachOPCRel32GOT;
85 return MachOSubtractor32;
87 return MachOSubtractor64;
92 return RI.
r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;
96 return RI.
r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;
100 return RI.
r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;
104 return MachOPCRel32TLV;
108 return make_error<JITLinkError>(
109 "Unsupported x86-64 relocation: address=" +
113 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
114 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
118 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
123 Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,
127 using namespace support;
129 assert(((SubtractorKind == MachOSubtractor32 && SubRI.
r_length == 2) ||
130 (SubtractorKind == MachOSubtractor64 && SubRI.
r_length == 3)) &&
131 "Subtractor kind should match length");
132 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
133 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
135 if (UnsignedRelItr == RelEnd)
136 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR without paired "
137 "UNSIGNED relocation");
141 if (SubRI.
r_address != UnsignedRI.r_address)
142 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR and paired UNSIGNED "
143 "point to different addresses");
145 if (SubRI.
r_length != UnsignedRI.r_length)
146 return make_error<JITLinkError>(
"length of x86_64 SUBTRACTOR and paired "
147 "UNSIGNED reloc must match");
151 FromSymbol = FromSymbolOrErr->GraphSymbol;
153 return FromSymbolOrErr.takeError();
158 FixupValue = *(
const little64_t *)FixupContent;
160 FixupValue = *(
const little32_t *)FixupContent;
164 Symbol *ToSymbol =
nullptr;
165 if (UnsignedRI.r_extern) {
168 ToSymbol = ToSymbolOrErr->GraphSymbol;
170 return ToSymbolOrErr.takeError();
174 return ToSymbolSec.takeError();
176 assert(ToSymbol &&
"No symbol for section");
184 bool FixingFromSymbol =
true;
190 FixingFromSymbol =
true;
191 else if (FromSymbol->
getAddress() > FixupAddress)
192 FixingFromSymbol =
false;
196 FixingFromSymbol =
true;
199 FixingFromSymbol =
false;
202 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
203 "either 'A' or 'B' (or a symbol in one "
204 "of their alt-entry groups)");
208 if (FixingFromSymbol) {
209 TargetSymbol = ToSymbol;
211 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
214 TargetSymbol = FromSymbol;
217 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
220 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
224 using namespace support;
229 for (
const auto &S : Obj.
sections()) {
235 if (S.relocation_begin() != S.relocation_end())
236 return make_error<JITLinkError>(
"Virtual section contains "
244 return NSec.takeError();
249 if (!NSec->GraphSection) {
251 dbgs() <<
" Skipping relocations for MachO section "
252 << NSec->SegName <<
"/" << NSec->SectName
253 <<
" which has no associated graph section\n";
260 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
261 RelItr != RelEnd; ++RelItr) {
269 dbgs() <<
" " << NSec->SectName <<
" + "
274 Block *BlockToFix =
nullptr;
277 if (!SymbolToFixOrErr)
278 return SymbolToFixOrErr.takeError();
279 BlockToFix = &SymbolToFixOrErr->getBlock();
284 return make_error<JITLinkError>(
285 "Relocation extends past end of fixup block");
291 size_t FixupOffset = FixupAddress - BlockToFix->
getAddress();
294 Symbol *TargetSymbol =
nullptr;
298 auto MachORelocKind = getRelocKind(RI);
300 return MachORelocKind.takeError();
304 switch (*MachORelocKind) {
307 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
309 return TargetSymbolOrErr.takeError();
310 Addend = *(
const little32_t *)FixupContent;
315 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
317 return TargetSymbolOrErr.takeError();
318 Addend = *(
const little32_t *)FixupContent - 4;
321 case MachOPCRel32GOTLoad:
323 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
325 return TargetSymbolOrErr.takeError();
326 Addend = *(
const little32_t *)FixupContent;
329 return make_error<JITLinkError>(
"GOTLD at invalid offset " +
332 case MachOPCRel32GOT:
334 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
336 return TargetSymbolOrErr.takeError();
337 Addend = *(
const little32_t *)FixupContent - 4;
340 case MachOPCRel32TLV:
342 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
344 return TargetSymbolOrErr.takeError();
345 Addend = *(
const little32_t *)FixupContent;
348 return make_error<JITLinkError>(
"TLV at invalid offset " +
353 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
355 return TargetSymbolOrErr.takeError();
356 Addend = *(
const ulittle32_t *)FixupContent;
361 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
363 return TargetSymbolOrErr.takeError();
364 Addend = *(
const ulittle64_t *)FixupContent;
367 case MachOPointer64Anon: {
371 return TargetNSec.takeError();
372 if (
auto TargetSymbolOrErr =
374 TargetSymbol = &*TargetSymbolOrErr;
376 return TargetSymbolOrErr.takeError();
377 Addend = TargetAddress - TargetSymbol->
getAddress();
381 case MachOPCRel32Minus1:
382 case MachOPCRel32Minus2:
383 case MachOPCRel32Minus4:
385 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
387 return TargetSymbolOrErr.takeError();
388 Addend = *(
const little32_t *)FixupContent - 4;
391 case MachOPCRel32Anon: {
393 *(
const little32_t *)FixupContent);
396 return TargetNSec.takeError();
397 if (
auto TargetSymbolOrErr =
399 TargetSymbol = &*TargetSymbolOrErr;
401 return TargetSymbolOrErr.takeError();
402 Addend = TargetAddress - TargetSymbol->
getAddress() - 4;
406 case MachOPCRel32Minus1Anon:
407 case MachOPCRel32Minus2Anon:
408 case MachOPCRel32Minus4Anon: {
411 1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
413 FixupAddress + Delta + *(
const little32_t *)FixupContent;
416 return TargetNSec.takeError();
417 if (
auto TargetSymbolOrErr =
419 TargetSymbol = &*TargetSymbolOrErr;
421 return TargetSymbolOrErr.takeError();
422 Addend = TargetAddress - TargetSymbol->
getAddress() - Delta;
426 case MachOSubtractor32:
427 case MachOSubtractor64: {
434 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
435 FixupAddress, FixupContent, ++RelItr, RelEnd);
437 return PairInfo.takeError();
438 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
439 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
446 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
452 *TargetSymbol, Addend);
476 std::unique_ptr<LinkGraph>
G,
490 return MachOObj.takeError();
492 auto Features = (*MachOObj)->getFeatures();
494 return Features.takeError();
496 return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(*Features))
501 std::unique_ptr<JITLinkContext> Ctx) {
505 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
511 Config.PrePrunePasses.push_back(
515 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
516 Config.PrePrunePasses.push_back(std::move(MarkLive));
521 Config.PostAllocationPasses.push_back(
526 Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);
532 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
533 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.
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_x86_64(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.
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.
@ X86_64_RELOC_SUBTRACTOR
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given x86-64 edge.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)
Apply fixup expression for edge to block content.
constexpr uint64_t PointerSize
x86_64 pointer size.
Error optimizeGOTAndStubAccesses(LinkGraph &G)
Optimize the GOT and Stub relocations if the edge target address is in range.
@ Pointer32
A plain 32-bit pointer value relocation.
@ RequestGOTAndTransformToDelta32
A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...
@ BranchPCRel32
A 32-bit PC-relative branch.
@ RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable
A TLVP entry getter/constructor, transformed to Delta32ToTLVPLoadREXRelaxable.
@ NegDelta64
A 64-bit negative delta.
@ Pointer64
A plain 64-bit pointer value relocation.
@ RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable
A GOT entry getter/constructor, transformed to PCRel32ToGOTLoadREXRelaxable pointing at the GOT entry...
@ NegDelta32
A 32-bit negative delta.
LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64()
Returns a pass suitable for fixing missing edges in an __eh_frame section in a MachO/x86-64 object.
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.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from a MachO/x86-64 relocatable object.
void link_MachO_x86_64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given LinkGraph.
LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64()
Returns a pass suitable for splitting __eh_frame sections in MachO/x86-64 objects.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
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.
uint64_t ExecutorAddrDiff
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.
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...