20#define DEBUG_TYPE "jitlink"
30 std::shared_ptr<orc::SymbolStringPool> SSP,
33 Triple(
"x86_64-apple-darwin"),
37 enum MachONormalizedRelocationType :
unsigned {
47 MachOPCRel32Minus1Anon,
48 MachOPCRel32Minus2Anon,
49 MachOPCRel32Minus4Anon,
63 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
65 return MachOPointer32;
70 return RI.
r_extern ? MachOPCRel32 : MachOPCRel32Anon;
78 return MachOPCRel32GOTLoad;
82 return MachOPCRel32GOT;
87 return MachOSubtractor32;
89 return MachOSubtractor64;
94 return RI.
r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;
98 return RI.
r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;
102 return RI.
r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;
106 return MachOPCRel32TLV;
110 return make_error<JITLinkError>(
111 "Unsupported x86-64 relocation: address=" +
115 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
116 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
120 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
125 Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,
129 using namespace support;
131 assert(((SubtractorKind == MachOSubtractor32 && SubRI.
r_length == 2) ||
132 (SubtractorKind == MachOSubtractor64 && SubRI.
r_length == 3)) &&
133 "Subtractor kind should match length");
134 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
135 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
137 if (UnsignedRelItr == RelEnd)
138 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR without paired "
139 "UNSIGNED relocation");
143 if (SubRI.
r_address != UnsignedRI.r_address)
144 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR and paired UNSIGNED "
145 "point to different addresses");
147 if (SubRI.
r_length != UnsignedRI.r_length)
148 return make_error<JITLinkError>(
"length of x86_64 SUBTRACTOR and paired "
149 "UNSIGNED reloc must match");
153 FromSymbol = FromSymbolOrErr->GraphSymbol;
155 return FromSymbolOrErr.takeError();
160 FixupValue = *(
const little64_t *)FixupContent;
162 FixupValue = *(
const little32_t *)FixupContent;
166 Symbol *ToSymbol =
nullptr;
167 if (UnsignedRI.r_extern) {
170 ToSymbol = ToSymbolOrErr->GraphSymbol;
172 return ToSymbolOrErr.takeError();
176 return ToSymbolSec.takeError();
178 assert(ToSymbol &&
"No symbol for section");
186 bool FixingFromSymbol =
true;
192 FixingFromSymbol =
true;
193 else if (FromSymbol->
getAddress() > FixupAddress)
194 FixingFromSymbol =
false;
198 FixingFromSymbol =
true;
201 FixingFromSymbol =
false;
204 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
205 "either 'A' or 'B' (or a symbol in one "
206 "of their alt-entry groups)");
210 if (FixingFromSymbol) {
211 TargetSymbol = ToSymbol;
213 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
216 TargetSymbol = FromSymbol;
219 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
222 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
226 using namespace support;
231 for (
const auto &S : Obj.
sections()) {
237 if (S.relocation_begin() != S.relocation_end())
238 return make_error<JITLinkError>(
"Virtual section contains "
246 return NSec.takeError();
251 if (!NSec->GraphSection) {
253 dbgs() <<
" Skipping relocations for MachO section "
254 << NSec->SegName <<
"/" << NSec->SectName
255 <<
" which has no associated graph section\n";
262 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
263 RelItr != RelEnd; ++RelItr) {
271 dbgs() <<
" " << NSec->SectName <<
" + "
276 Block *BlockToFix =
nullptr;
279 if (!SymbolToFixOrErr)
280 return SymbolToFixOrErr.takeError();
281 BlockToFix = &SymbolToFixOrErr->getBlock();
286 return make_error<JITLinkError>(
287 "Relocation extends past end of fixup block");
293 size_t FixupOffset = FixupAddress - BlockToFix->
getAddress();
296 Symbol *TargetSymbol =
nullptr;
300 auto MachORelocKind = getRelocKind(RI);
302 return MachORelocKind.takeError();
306 switch (*MachORelocKind) {
309 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
311 return TargetSymbolOrErr.takeError();
312 Addend = *(
const little32_t *)FixupContent;
317 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
319 return TargetSymbolOrErr.takeError();
320 Addend = *(
const little32_t *)FixupContent - 4;
323 case MachOPCRel32GOTLoad:
325 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
327 return TargetSymbolOrErr.takeError();
328 Addend = *(
const little32_t *)FixupContent;
331 return make_error<JITLinkError>(
"GOTLD at invalid offset " +
334 case MachOPCRel32GOT:
336 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
338 return TargetSymbolOrErr.takeError();
339 Addend = *(
const little32_t *)FixupContent - 4;
342 case MachOPCRel32TLV:
344 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
346 return TargetSymbolOrErr.takeError();
347 Addend = *(
const little32_t *)FixupContent;
350 return make_error<JITLinkError>(
"TLV at invalid offset " +
355 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
357 return TargetSymbolOrErr.takeError();
358 Addend = *(
const ulittle32_t *)FixupContent;
363 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
365 return TargetSymbolOrErr.takeError();
366 Addend = *(
const ulittle64_t *)FixupContent;
369 case MachOPointer64Anon: {
373 return TargetNSec.takeError();
374 if (
auto TargetSymbolOrErr =
376 TargetSymbol = &*TargetSymbolOrErr;
378 return TargetSymbolOrErr.takeError();
379 Addend = TargetAddress - TargetSymbol->
getAddress();
383 case MachOPCRel32Minus1:
384 case MachOPCRel32Minus2:
385 case MachOPCRel32Minus4:
387 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
389 return TargetSymbolOrErr.takeError();
390 Addend = *(
const little32_t *)FixupContent - 4;
393 case MachOPCRel32Anon: {
395 *(
const little32_t *)FixupContent);
398 return TargetNSec.takeError();
399 if (
auto TargetSymbolOrErr =
401 TargetSymbol = &*TargetSymbolOrErr;
403 return TargetSymbolOrErr.takeError();
404 Addend = TargetAddress - TargetSymbol->
getAddress() - 4;
408 case MachOPCRel32Minus1Anon:
409 case MachOPCRel32Minus2Anon:
410 case MachOPCRel32Minus4Anon: {
413 1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
415 FixupAddress + Delta + *(
const little32_t *)FixupContent;
418 return TargetNSec.takeError();
419 if (
auto TargetSymbolOrErr =
421 TargetSymbol = &*TargetSymbolOrErr;
423 return TargetSymbolOrErr.takeError();
424 Addend = TargetAddress - TargetSymbol->
getAddress() - Delta;
428 case MachOSubtractor32:
429 case MachOSubtractor64: {
436 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
437 FixupAddress, FixupContent, ++RelItr, RelEnd);
439 return PairInfo.takeError();
440 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
441 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
448 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
454 *TargetSymbol, Addend);
478 std::unique_ptr<LinkGraph>
G,
489 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
492 return MachOObj.takeError();
494 auto Features = (*MachOObj)->getFeatures();
496 return Features.takeError();
498 return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(SSP),
499 std::move(*Features))
504 std::unique_ptr<JITLinkContext> Ctx) {
508 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
514 Config.PrePrunePasses.push_back(
518 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
519 Config.PrePrunePasses.push_back(std::move(MarkLive));
524 Config.PostAllocationPasses.push_back(
529 Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);
535 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
536 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.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from a MachO/x86-64 relocatable 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.
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(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.
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...