29#define DEBUG_TYPE "jitlink"
33enum JITLinkErrorCode { GenericJITLinkError = 1 };
38class JITLinkerErrorCategory :
public std::error_category {
40 const char *
name()
const noexcept override {
return "runtimedyld"; }
42 std::string message(
int Condition)
const override {
43 switch (
static_cast<JITLinkErrorCode
>(Condition)) {
44 case GenericJITLinkError:
45 return "Generic JITLink error";
61 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
62 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
68 return "INVALID RELOCATION";
72 return "<Unrecognized edge kind>";
93 return "side-effects-only";
101 if (
B.getSize() == 0)
106 return B.getSize() == 1;
108 for (
size_t I = 0;
I !=
B.getSize() - 1; ++
I)
109 if (
B.getContent()[
I] ==
'\0')
112 return B.getContent()[
B.getSize() - 1] ==
'\0';
116 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
118 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
119 << (
B.isZeroFill() ?
"zero-fill" :
"content")
120 <<
", align = " <<
B.getAlignment()
121 <<
", align-ofs = " <<
B.getAlignmentOffset()
122 <<
", section = " <<
B.getSection().getName();
131 << (Sym.
isLive() ?
"live" :
"dead") <<
" - "
138 OS <<
"edge@" <<
B.getAddress() + E.getOffset() <<
": " <<
B.getAddress()
139 <<
" + " <<
formatv(
"{0:x}", E.getOffset()) <<
" -- " << EdgeKindName
142 auto &TargetSym = E.getTarget();
143 if (TargetSym.hasName())
144 OS << TargetSym.getName();
146 auto &TargetBlock = TargetSym.getBlock();
147 auto &TargetSec = TargetBlock.getSection();
149 for (
auto *
B : TargetSec.blocks())
150 if (
B->getAddress() < SecAddress)
151 SecAddress =
B->getAddress();
154 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
156 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
157 OS <<
" / block " << TargetBlock.getAddress();
158 if (TargetSym.getOffset())
159 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
163 if (E.getAddend() != 0)
164 OS <<
" + " << E.getAddend();
168 for (
auto *Sym : Symbols)
170 for (
auto *
B : Blocks)
175 for (
auto *Sym : AbsoluteSymbols) {
181 ExternalSymbols.clear();
184std::vector<Block *> LinkGraph::splitBlockImpl(std::vector<Block *> Blocks,
185 SplitBlockCache *Cache) {
186 assert(!Blocks.empty() &&
"Blocks must at least contain the original block");
190 for (
size_t I = 0;
I != Blocks.size() - 1; ++
I) {
191 Blocks[
I]->setContent(
192 Content.
slice(Blocks[
I]->getAddress() - Blocks[0]->getAddress(),
193 Blocks[
I + 1]->getAddress() - Blocks[
I]->getAddress()));
195 Blocks.back()->setContent(
196 Content.
slice(Blocks.back()->getAddress() - Blocks[0]->getAddress()));
197 bool IsMutable = Blocks[0]->ContentMutable;
198 for (
auto *
B : Blocks)
199 B->ContentMutable = IsMutable;
205 Cache = &LocalBlockSymbolsCache;
208 if (*Cache == std::nullopt) {
209 *Cache = SplitBlockCache::value_type();
211 for (
auto *Sym : Blocks[0]->
getSection().symbols())
212 if (&Sym->getBlock() == Blocks[0])
213 (*Cache)->push_back(Sym);
214 llvm::sort(**Cache, [](
const Symbol *LHS,
const Symbol *RHS) {
215 return LHS->getAddress() > RHS->getAddress();
220 Sym.setOffset(Sym.getAddress() -
B.getAddress());
222 if (Sym.getSize() >
B.getSize())
223 Sym.setSize(
B.getSize() - Sym.getOffset());
227 for (
size_t I = 0;
I != Blocks.size() - 1; ++
I) {
228 if ((*Cache)->empty())
230 while (!(*Cache)->empty() &&
231 (*Cache)->back()->getAddress() < Blocks[
I + 1]->getAddress()) {
232 TransferSymbol(*(*Cache)->back(), *Blocks[
I]);
233 (*Cache)->pop_back();
237 while (!(*Cache)->empty()) {
238 auto &Sym = *(*Cache)->back();
239 (*Cache)->pop_back();
240 assert(Sym.getAddress() >= Blocks.back()->getAddress() &&
241 "Symbol address preceeds block");
242 assert(Sym.getAddress() <= Blocks.back()->getRange().End &&
243 "Symbol address starts past end of block");
244 TransferSymbol(Sym, *Blocks.back());
249 auto &Edges = Blocks[0]->Edges;
251 return LHS.getOffset() <
RHS.getOffset();
254 for (
size_t I = Blocks.size() - 1;
I != 0; --
I) {
260 Edge::OffsetT Delta = Blocks[
I]->getAddress() - Blocks[0]->getAddress();
263 if (Edges.back().getOffset() < Delta)
266 size_t EI = Edges.size() - 1;
267 while (EI != 0 && Edges[EI - 1].
getOffset() >= Delta)
270 for (
size_t J = EI; J != Edges.size(); ++J) {
271 Blocks[
I]->Edges.push_back(std::move(Edges[J]));
272 Blocks[
I]->Edges.back().setOffset(Blocks[
I]->Edges.back().getOffset() -
276 while (Edges.size() > EI)
286 OS <<
"LinkGraph \"" <<
getName()
291 BlockSymbols[&Sym->getBlock()].push_back(Sym);
295 for (
auto &KV : BlockSymbols)
297 if (LHS->getOffset() != RHS->getOffset())
298 return LHS->getOffset() < RHS->getOffset();
299 if (LHS->getLinkage() != RHS->getLinkage())
300 return LHS->getLinkage() < RHS->getLinkage();
301 if (LHS->getScope() != RHS->getScope())
302 return LHS->getScope() < RHS->getScope();
303 if (LHS->hasName()) {
306 return LHS->getName() < RHS->getName();
311 std::vector<Section *> SortedSections;
313 SortedSections.push_back(&Sec);
315 return LHS->getName() < RHS->getName();
318 for (
auto *Sec : SortedSections) {
319 OS <<
"section " << Sec->getName() <<
":\n\n";
321 std::vector<Block *> SortedBlocks;
324 return LHS->getAddress() < RHS->getAddress();
327 for (
auto *
B : SortedBlocks) {
328 OS <<
" block " <<
B->getAddress()
329 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
330 <<
", align = " <<
B->getAlignment()
331 <<
", alignment-offset = " <<
B->getAlignmentOffset();
336 auto BlockSymsI = BlockSymbols.find(
B);
337 if (BlockSymsI != BlockSymbols.end()) {
339 auto &Syms = BlockSymsI->second;
340 for (
auto *Sym : Syms)
341 OS <<
" " << *Sym <<
"\n";
343 OS <<
" no symbols\n";
345 if (!
B->edges_empty()) {
347 std::vector<Edge> SortedEdges;
350 return LHS.getOffset() <
RHS.getOffset();
352 for (
auto &
E : SortedEdges) {
353 OS <<
" " <<
B->getFixupAddress(
E) <<
" (block + "
354 <<
formatv(
"{0:x8}",
E.getOffset()) <<
"), addend = ";
355 if (
E.getAddend() >= 0)
356 OS <<
formatv(
"+{0:x8}",
E.getAddend());
358 OS <<
formatv(
"-{0:x8}", -
E.getAddend());
360 if (
E.getTarget().hasName())
361 OS <<
E.getTarget().getName();
364 <<
formatv(
"{0:x16}",
E.getTarget().getAddress()) <<
"+"
365 <<
formatv(
"{0:x8}",
E.getTarget().getOffset());
374 OS <<
"Absolute symbols:\n";
375 if (!absolute_symbols().
empty()) {
376 for (
auto *Sym : absolute_symbols())
377 OS <<
" " << Sym->getAddress() <<
": " << *Sym <<
"\n";
381 OS <<
"\nExternal symbols:\n";
382 if (!external_symbols().
empty()) {
383 for (
auto *Sym : external_symbols())
384 OS <<
" " << Sym->getAddress() <<
": " << *Sym
385 << (Sym->isWeaklyReferenced() ?
" (weakly referenced)" :
"") <<
"\n";
393 return OS <<
"RequiredSymbol";
395 return OS <<
"WeaklyReferencedSymbol";
400void JITLinkAsyncLookupContinuation::anchor() {}
402JITLinkContext::~JITLinkContext() =
default;
418 for (
auto *Sym :
G.defined_symbols())
429 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
430 <<
": relocation target "
431 <<
formatv(
"{0:x}", E.getTarget().getAddress() + E.getAddend())
433 if (E.getTarget().hasName())
434 ErrStream << E.getTarget().getName();
436 ErrStream <<
"<anonymous symbol>";
439 ErrStream <<
formatv(
":{0:x}", E.getTarget().getAddress()) <<
" + "
440 <<
formatv(
"{0:x}", E.getAddend());
442 ErrStream <<
") is out of range of " <<
G.getEdgeKindName(E.getKind())
443 <<
" fixup at address "
444 <<
formatv(
"{0:x}", E.getTarget().getAddress()) <<
" (";
446 Symbol *BestSymbolForBlock =
nullptr;
447 for (
auto *Sym : Sec.
symbols())
448 if (&Sym->getBlock() == &
B && Sym->hasName() && Sym->getOffset() == 0 &&
449 (!BestSymbolForBlock ||
450 Sym->getScope() < BestSymbolForBlock->
getScope() ||
451 Sym->getLinkage() < BestSymbolForBlock->
getLinkage()))
452 BestSymbolForBlock = Sym;
454 if (BestSymbolForBlock)
455 ErrStream << BestSymbolForBlock->
getName() <<
", ";
457 ErrStream <<
"<anonymous block> @ ";
459 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
460 <<
formatv(
"{0:x}", E.getOffset()) <<
")";
468 " improper alignment for relocation " +
469 formatv(
"{0:d}", E.getKind()) +
": 0x" +
471 " is not aligned to " +
Twine(
N) +
" bytes");
475 switch (TT.getArch()) {
501 switch (TT.getArch()) {
530 std::shared_ptr<orc::SymbolStringPool> SSP) {
546std::unique_ptr<LinkGraph>
549 static std::atomic<uint64_t> Counter = {0};
550 auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
551 unsigned PointerSize = TT.getArchPointerBitWidth() / 8;
552 auto G = std::make_unique<LinkGraph>(
553 "<Absolute Symbols " + std::to_string(Index) +
">", std::move(SSP),
555 for (
auto &[Name, Def] : Symbols) {
557 G->addAbsoluteSymbol(*Name, Def.getAddress(), 0,
559 Sym.setCallable(Def.getFlags().isCallable());
565void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
566 switch (
G->getTargetTriple().getObjectFormat()) {
570 return link_ELF(std::move(
G), std::move(Ctx));
572 return link_COFF(std::move(
G), std::move(Ctx));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bbsections Prepares for basic block sections
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::pair< BasicBlock *, BasicBlock * > Edge
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
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 getBuffer() const
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.
const std::string & str() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
An Addressable with content and edges.
Represents fixups and constraints in the LinkGraph.
virtual Error modifyPassConfig(LinkGraph &G, PassConfiguration &Config)
Called by JITLink to modify the pass pipeline prior to linking.
virtual bool shouldAddDefaultTargetPasses(const Triple &TT) const
Called by JITLink prior to linking to determine whether default passes for the target should be added...
virtual LinkGraphPassFunction getMarkLivePass(const Triple &TT) const
Returns the mark-live pass to be used for this link.
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(raw_ostream &OS) const override
Print an error message to an output stream.
const std::string & getName() const
Returns the name of this graph (usually the name of the original underlying MemoryBuffer).
LLVM_ABI void dump(raw_ostream &OS)
Dump the graph.
iterator_range< external_symbol_iterator > external_symbols()
const Triple & getTargetTriple() const
Returns the target triple for this Graph.
iterator_range< defined_symbol_iterator > defined_symbols()
std::optional< SmallVector< Symbol *, 8 > > SplitBlockCache
Cache type for the splitBlock function.
Represents an object file section.
iterator_range< symbol_iterator > symbols()
Returns an iterator over the symbols defined in this section.
StringRef getName() const
Returns the name of this section.
bool isLive() const
Returns true if this symbol is live (i.e.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
Scope getScope() const
Get the visibility for this Symbol.
Linkage getLinkage() const
Get the linkage for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
orc::ExecutorAddrDiff getSize() const
Returns the size of this symbol.
orc::ExecutorAddrDiff getOffset() const
Returns the offset for this symbol within the underlying addressable.
bool hasName() const
Returns true if this symbol has a name.
Represents an address in the executor process.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Get a human-readable name for the given AArch32 edge kind.
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Creates a new pointer block in the given section and returns an Anonymous symbol pointing to it.
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Creates a new pointer block in the given section and returns an Anonymous symbol pointing to it.
LLVM_ABI Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, Edge::AddendT InitialAddend=0)
Creates an anonymous pointer, optionally initialized to InitialTarget.
LLVM_ABI Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Creates a stub that materializes PointerSymbol, loads its value into $t9, and jumps to $t9.
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Symbol & createDefaultAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Creates a new pointer block in the given section and returns an Anonymous symbol pointing to it.
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Creates a new pointer block in the given section and returns an anonymous symbol pointing to it.
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Creates a new pointer block in the given section and returns an anonymous symbol pointing to it.
unique_function< Error(LinkGraph &)> LinkGraphPassFunction
A function for mutating LinkGraphs.
LLVM_ABI Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, const Edge &E)
Create an out of range error for the given edge in the given block.
LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
LLVM_ABI const char * getLinkageName(Linkage L)
For errors and debugging output.
SymbolLookupFlags
Flags for symbol lookup.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an COFF relocatable object.
LLVM_ABI std::unique_ptr< LinkGraph > absoluteSymbolsLinkGraph(Triple TT, std::shared_ptr< orc::SymbolStringPool > SSP, orc::SymbolMap Symbols)
Create a LinkGraph defining the given absolute symbols.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an ELF relocatable object.
LLVM_ABI Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, const Edge &E)
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const Block &B)
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromXCOFFObject(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an XCOFF relocatable object.
LLVM_ABI PointerJumpStubCreator getPointerJumpStubCreator(const Triple &TT)
Get target-specific PointerJumpStubCreator.
unique_function< Symbol &( LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)> PointerJumpStubCreator
Create a jump stub that jumps via the pointer at the given symbol and an anonymous symbol pointing to...
LLVM_ABI void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from a MachO relocatable object.
LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
LLVM_ABI void link_COFF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
LLVM_ABI void link_ELF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
LLVM_ABI const char * getScopeName(Scope S)
For debugging output.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromObject(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from the given object buffer.
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
unique_function< Symbol &(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget, uint64_t InitialAddend)> AnonymousPointerCreator
Creates a new pointer block in the given section and returns an Anonymous symbol pointing to it.
LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
LLVM_ABI void link_XCOFF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
LLVM_ABI bool isCStringBlock(Block &B)
LLVM_ABI void link_MachO(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given ObjBuffer, which must be a MachO object file.
LLVM_ABI AnonymousPointerCreator getAnonymousPointerCreator(const Triple &TT)
Get target-specific AnonymousPointerCreator.
Expected< const typename ELFT::Shdr * > getSection(typename ELFT::ShdrRange Sections, uint32_t Index)
uint64_t ExecutorAddrDiff
DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
@ elf_relocatable
ELF Relocatable object file.
@ xcoff_object_64
64-bit XCOFF object file
@ macho_object
Mach-O Object file.
@ coff_object
COFF object file.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...