19#define DEBUG_TYPE "jitlink"
34 enum MachONormalizedRelocationType :
unsigned {
44 MachOPCRel32Minus1Anon,
45 MachOPCRel32Minus2Anon,
46 MachOPCRel32Minus4Anon,
60 return RI.
r_extern ? MachOPointer64 : MachOPointer64Anon;
62 return MachOPointer32;
67 return RI.
r_extern ? MachOPCRel32 : MachOPCRel32Anon;
75 return MachOPCRel32GOTLoad;
79 return MachOPCRel32GOT;
84 return MachOSubtractor32;
86 return MachOSubtractor64;
91 return RI.
r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;
95 return RI.
r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;
99 return RI.
r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;
103 return MachOPCRel32TLV;
107 return make_error<JITLinkError>(
108 "Unsupported x86-64 relocation: address=" +
112 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
113 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
117 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
122 Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,
126 using namespace support;
128 assert(((SubtractorKind == MachOSubtractor32 && SubRI.
r_length == 2) ||
129 (SubtractorKind == MachOSubtractor64 && SubRI.
r_length == 3)) &&
130 "Subtractor kind should match length");
131 assert(SubRI.
r_extern &&
"SUBTRACTOR reloc symbol should be extern");
132 assert(!SubRI.
r_pcrel &&
"SUBTRACTOR reloc should not be PCRel");
134 if (UnsignedRelItr == RelEnd)
135 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR without paired "
136 "UNSIGNED relocation");
140 if (SubRI.
r_address != UnsignedRI.r_address)
141 return make_error<JITLinkError>(
"x86_64 SUBTRACTOR and paired UNSIGNED "
142 "point to different addresses");
144 if (SubRI.
r_length != UnsignedRI.r_length)
145 return make_error<JITLinkError>(
"length of x86_64 SUBTRACTOR and paired "
146 "UNSIGNED reloc must match");
150 FromSymbol = FromSymbolOrErr->GraphSymbol;
152 return FromSymbolOrErr.takeError();
157 FixupValue = *(
const little64_t *)FixupContent;
159 FixupValue = *(
const little32_t *)FixupContent;
163 Symbol *ToSymbol =
nullptr;
164 if (UnsignedRI.r_extern) {
167 ToSymbol = ToSymbolOrErr->GraphSymbol;
169 return ToSymbolOrErr.takeError();
173 return ToSymbolSec.takeError();
175 assert(ToSymbol &&
"No symbol for section");
183 TargetSymbol = ToSymbol;
185 Addend = FixupValue + (FixupAddress - FromSymbol->
getAddress());
188 TargetSymbol = FromSymbol;
191 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
194 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up "
195 "either 'A' or 'B' (or a symbol in one "
196 "of their alt-entry chains)");
199 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
203 using namespace support;
208 for (
const auto &S : Obj.
sections()) {
214 if (S.relocation_begin() != S.relocation_end())
215 return make_error<JITLinkError>(
"Virtual section contains "
223 return NSec.takeError();
228 if (!NSec->GraphSection) {
230 dbgs() <<
" Skipping relocations for MachO section "
231 << NSec->SegName <<
"/" << NSec->SectName
232 <<
" which has no associated graph section\n";
239 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
240 RelItr != RelEnd; ++RelItr) {
248 dbgs() <<
" " << NSec->SectName <<
" + "
253 Block *BlockToFix =
nullptr;
256 if (!SymbolToFixOrErr)
257 return SymbolToFixOrErr.takeError();
258 BlockToFix = &SymbolToFixOrErr->getBlock();
263 return make_error<JITLinkError>(
264 "Relocation extends past end of fixup block");
270 size_t FixupOffset = FixupAddress - BlockToFix->
getAddress();
273 Symbol *TargetSymbol =
nullptr;
277 auto MachORelocKind = getRelocKind(RI);
279 return MachORelocKind.takeError();
283 switch (*MachORelocKind) {
286 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
288 return TargetSymbolOrErr.takeError();
289 Addend = *(
const little32_t *)FixupContent;
294 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
296 return TargetSymbolOrErr.takeError();
297 Addend = *(
const little32_t *)FixupContent - 4;
300 case MachOPCRel32GOTLoad:
302 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
304 return TargetSymbolOrErr.takeError();
305 Addend = *(
const little32_t *)FixupContent;
308 return make_error<JITLinkError>(
"GOTLD at invalid offset " +
311 case MachOPCRel32GOT:
313 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
315 return TargetSymbolOrErr.takeError();
316 Addend = *(
const little32_t *)FixupContent - 4;
319 case MachOPCRel32TLV:
321 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
323 return TargetSymbolOrErr.takeError();
324 Addend = *(
const little32_t *)FixupContent;
327 return make_error<JITLinkError>(
"TLV at invalid offset " +
332 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
334 return TargetSymbolOrErr.takeError();
335 Addend = *(
const ulittle32_t *)FixupContent;
340 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
342 return TargetSymbolOrErr.takeError();
343 Addend = *(
const ulittle64_t *)FixupContent;
346 case MachOPointer64Anon: {
350 return TargetNSec.takeError();
351 if (
auto TargetSymbolOrErr =
353 TargetSymbol = &*TargetSymbolOrErr;
355 return TargetSymbolOrErr.takeError();
356 Addend = TargetAddress - TargetSymbol->
getAddress();
360 case MachOPCRel32Minus1:
361 case MachOPCRel32Minus2:
362 case MachOPCRel32Minus4:
364 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
366 return TargetSymbolOrErr.takeError();
367 Addend = *(
const little32_t *)FixupContent - 4;
370 case MachOPCRel32Anon: {
372 *(
const little32_t *)FixupContent);
375 return TargetNSec.takeError();
376 if (
auto TargetSymbolOrErr =
378 TargetSymbol = &*TargetSymbolOrErr;
380 return TargetSymbolOrErr.takeError();
381 Addend = TargetAddress - TargetSymbol->
getAddress() - 4;
385 case MachOPCRel32Minus1Anon:
386 case MachOPCRel32Minus2Anon:
387 case MachOPCRel32Minus4Anon: {
390 1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
392 FixupAddress + Delta + *(
const little32_t *)FixupContent;
395 return TargetNSec.takeError();
396 if (
auto TargetSymbolOrErr =
398 TargetSymbol = &*TargetSymbolOrErr;
400 return TargetSymbolOrErr.takeError();
401 Addend = TargetAddress - TargetSymbol->
getAddress() - Delta;
405 case MachOSubtractor32:
406 case MachOSubtractor64: {
413 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
414 FixupAddress, FixupContent, ++RelItr, RelEnd);
416 return PairInfo.takeError();
417 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
418 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
425 Edge GE(Kind, FixupAddress - BlockToFix->
getAddress(), *TargetSymbol,
431 *TargetSymbol, Addend);
455 std::unique_ptr<LinkGraph>
G,
469 return MachOObj.takeError();
471 auto Features = (*MachOObj)->getFeatures();
473 return Features.takeError();
475 return MachOLinkGraphBuilder_x86_64(**MachOObj, Features->getFeatures())
480 std::unique_ptr<JITLinkContext> Ctx) {
484 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
490 Config.PrePrunePasses.push_back(
494 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
495 Config.PrePrunePasses.push_back(std::move(MarkLive));
500 Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);
506 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
507 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")
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.
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.
std::vector< std::string > FeatureVector
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
section_iterator_range sections() const
static Expected< std::unique_ptr< MachOObjectFile > > createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0)
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)
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(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.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...