18 #define DEBUG_TYPE "jitlink" 30 addCustomSectionParser(
31 "__eh_frame", [
this](NormalizedSection &EHFrameSection) {
32 if (!EHFrameSection.Data)
33 return make_error<JITLinkError>(
34 "__eh_frame section is marked zero-fill");
35 return MachOEHFrameBinaryParser(
36 *
this, EHFrameSection.Address,
37 StringRef(EHFrameSection.Data, EHFrameSection.Size),
100 return make_error<JITLinkError>(
101 "Unsupported x86-64 relocation: address=" +
105 ", pc_rel=" + (RI.
r_pcrel ?
"true" :
"false") +
106 ", extern=" + (RI.
r_extern ?
"true" :
"false") +
113 getObject().getRelocation(RelItr->getRawDataRefImpl());
119 using PairRelocInfo = std::tuple<MachOX86RelocationKind, Symbol *, uint64_t>;
129 using namespace support;
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");
141 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
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");
152 if (
auto FromSymbolOrErr = findSymbolByIndex(SubRI.
r_symbolnum))
153 FromSymbol = FromSymbolOrErr->GraphSymbol;
155 return FromSymbolOrErr.takeError();
158 uint64_t FixupValue = 0;
160 FixupValue = *(
const little64_t *)FixupContent;
162 FixupValue = *(
const little32_t *)FixupContent;
166 Symbol *ToSymbol =
nullptr;
167 if (UnsignedRI.r_extern) {
169 if (
auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
170 ToSymbol = ToSymbolOrErr->GraphSymbol;
172 return ToSymbolOrErr.takeError();
174 if (
auto ToSymbolOrErr = findSymbolByAddress(FixupValue))
175 ToSymbol = &*ToSymbolOrErr;
177 return ToSymbolOrErr.takeError();
184 if (&BlockToFix == &FromSymbol->getAddressable()) {
185 TargetSymbol = ToSymbol;
187 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
190 TargetSymbol = FromSymbol;
192 Addend = FixupValue - (FixupAddress - ToSymbol->
getAddress());
195 return make_error<JITLinkError>(
"SUBTRACTOR relocation must fix up " 196 "either 'A' or 'B' (or a symbol in one " 197 "of their alt-entry chains)");
200 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
203 Error addRelocations()
override {
204 using namespace support;
212 if (S.relocation_begin() != S.relocation_end())
213 return make_error<JITLinkError>(
"Virtual section contains " 218 for (
auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
219 RelItr != RelEnd; ++RelItr) {
224 auto Kind = getRelocationKind(RI);
226 return Kind.takeError();
232 dbgs() <<
"Processing relocation at " 233 <<
format(
"0x%016" PRIx64, FixupAddress) <<
"\n";
237 Block *BlockToFix =
nullptr;
239 auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
240 if (!SymbolToFixOrErr)
241 return SymbolToFixOrErr.takeError();
242 BlockToFix = &SymbolToFixOrErr->getBlock();
245 if (FixupAddress + static_cast<JITTargetAddress>(1ULL << RI.
r_length) >
247 return make_error<JITLinkError>(
248 "Relocation extends past end of fixup block");
255 Symbol *TargetSymbol =
nullptr;
263 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
264 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
266 return TargetSymbolOrErr.takeError();
270 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
271 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
273 return TargetSymbolOrErr.takeError();
277 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
278 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
280 return TargetSymbolOrErr.takeError();
285 if (
auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
286 TargetSymbol = &*TargetSymbolOrErr;
288 return TargetSymbolOrErr.takeError();
289 Addend = TargetAddress - TargetSymbol->
getAddress();
295 if (
auto TargetSymbolOrErr = findSymbolByIndex(RI.
r_symbolnum))
296 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
298 return TargetSymbolOrErr.takeError();
304 FixupAddress + 4 + *(
const ulittle32_t *)FixupContent;
305 if (
auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
306 TargetSymbol = &*TargetSymbolOrErr;
308 return TargetSymbolOrErr.takeError();
309 Addend = TargetAddress - TargetSymbol->
getAddress();
318 FixupAddress + 4 + Delta + *(
const ulittle32_t *)FixupContent;
319 if (
auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
320 TargetSymbol = &*TargetSymbolOrErr;
322 return TargetSymbolOrErr.takeError();
323 Addend = TargetAddress - TargetSymbol->
getAddress();
334 parsePairRelocation(*BlockToFix, *
Kind, RI, FixupAddress,
335 FixupContent, ++RelItr, RelEnd);
337 return PairInfo.takeError();
338 std::tie(*
Kind, TargetSymbol, Addend) = *PairInfo;
339 assert(TargetSymbol &&
"No target symbol from parsePairRelocation?");
355 *TargetSymbol, Addend);
362 class MachO_x86_64_GOTAndStubsBuilder
368 bool isGOTEdge(
Edge &
E)
const {
374 getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
387 bool isExternalBranchEdge(
Edge &E) {
392 auto &StubContentBlock =
395 auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
396 StubContentBlock.addEdge(
PCRel32, 2, GOTEntrySymbol, 0);
400 void fixExternalBranchEdge(
Edge &E,
Symbol &Stub) {
419 return *StubsSection;
423 return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
424 sizeof(NullGOTEntryContent));
428 return StringRef(reinterpret_cast<const char *>(StubContent),
429 sizeof(StubContent));
432 static const uint8_t NullGOTEntryContent[8];
433 static const uint8_t StubContent[6];
435 Section *StubsSection =
nullptr;
438 const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
440 const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
441 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
464 return MachOObj.takeError();
465 return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
472 ErrStream <<
"Relocation target out of range: ";
476 return make_error<JITLinkError>(std::move(ErrMsg));
479 Error applyFixup(
Block &B,
const Edge &E,
char *BlockWorkingMem)
const {
481 using namespace support;
483 char *FixupPtr = BlockWorkingMem + E.
getOffset();
492 if (Value < std::numeric_limits<int32_t>::min() ||
494 return targetOutOfRangeError(B, E);
510 if (Value < std::numeric_limits<int32_t>::min() ||
512 return targetOutOfRangeError(B, E);
522 if (Value < std::numeric_limits<int32_t>::min() ||
524 return targetOutOfRangeError(B, E);
539 if (Value < std::numeric_limits<int32_t>::min() ||
541 return targetOutOfRangeError(B, E);
550 return targetOutOfRangeError(B, E);
561 uint64_t NullValue = 0;
568 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
570 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
577 MachO_x86_64_GOTAndStubsBuilder(G).run();
582 if (
auto Err = Ctx->modifyPassConfig(TT, Config))
583 return Ctx->notifyFailed(std::move(Err));
598 return "Pointer64Anon";
602 return "PCRel32Minus1";
604 return "PCRel32Minus2";
606 return "PCRel32Minus4";
608 return "PCRel32Anon";
610 return "PCRel32Minus1Anon";
612 return "PCRel32Minus2Anon";
614 return "PCRel32Minus4Anon";
616 return "PCRel32GOTLoad";
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
detail::packed_endian_specific_integral< int64_t, little, unaligned > little64_t
This class represents lattice values for constants.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
static std::error_code getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
OffsetT getOffset() const
An Addressable with content and edges.
void jitLink_MachO_x86_64(std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a MachO x86-64 object file.
detail::packed_endian_specific_integral< uint64_t, little, unaligned > ulittle64_t
StringRef getContent() const
Get the content for this block. Block must not be a zero-fill block.
JITTargetAddress getAddress() const
Symbol & addAnonymousSymbol(Block &Content, JITTargetAddress Offset, JITTargetAddress Size, bool IsCallable, bool IsLive)
Add an anonymous symbol.
Tagged union holding either a T or a Error.
Symbol & getTarget() const
LLVM_NODISCARD size_t size() const
size - Get the string size.
section_iterator_range sections() const
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Addressable & getAddressable()
Return the addressable that this symbol points to.
static void link(ArgTs &&... Args)
Link constructs a LinkerImpl instance and calls linkPhase1.
StringRef getMachOX86RelocationKindName(Edge::Kind R)
Return the string name of the given MachO x86-64 edge kind.
Represents an object file section.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void setTarget(Symbol &Target)
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
MachOJITLinker_x86_64(std::unique_ptr< JITLinkContext > Ctx, PassConfiguration PassConfig)
LinkGraphPassList PostPrunePasses
Post-prune passes.
Section & createSection(StringRef Name, sys::Memory::ProtectionFlags Prot)
Create a section with the given name, protection flags, and alignment.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
LinkGraphPassList PrePrunePasses
Pre-prune passes.
static ErrorSuccess success()
Create a success value.
Align max(MaybeAlign Lhs, Align Rhs)
static Expected< std::unique_ptr< MachOObjectFile > > createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0)
AddendT getAddend() const
JITTargetAddress getAddress() const
Returns the address of this symbol.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Target - Wrapper for Target specific information.
Represents fixups and constraints in the LinkGraph.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
Block & createContentBlock(Section &Parent, StringRef Content, uint64_t Address, uint64_t Alignment, uint64_t AlignmentOffset)
Create a content block.
detail::packed_endian_specific_integral< int32_t, little, unaligned > little32_t
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
LLVM Value Representation.
Lightweight error class with error context and mandatory checking.
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i...
StringRef - Represent a constant reference to a string, i.e.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.