27#define DEBUG_TYPE "jitlink"
31enum JITLinkErrorCode { GenericJITLinkError = 1 };
36class JITLinkerErrorCategory :
public std::error_category {
38 const char *
name()
const noexcept override {
return "runtimedyld"; }
40 std::string message(
int Condition)
const override {
41 switch (
static_cast<JITLinkErrorCode
>(Condition)) {
42 case GenericJITLinkError:
43 return "Generic JITLink error";
59 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
60 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
66 return "INVALID RELOCATION";
70 return "<Unrecognized edge kind>";
91 return "side-effects-only";
104 return B.getSize() == 1;
106 for (
size_t I = 0;
I !=
B.getSize() - 1; ++
I)
107 if (
B.getContent()[
I] ==
'\0')
110 return B.getContent()[
B.getSize() - 1] ==
'\0';
114 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
116 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
117 << (
B.isZeroFill() ?
"zero-fill" :
"content")
118 <<
", align = " <<
B.getAlignment()
119 <<
", align-ofs = " <<
B.getAlignmentOffset()
120 <<
", section = " <<
B.getSection().getName();
129 << (Sym.
isLive() ?
"live" :
"dead") <<
" - "
136 OS <<
"edge@" <<
B.getAddress() + E.getOffset() <<
": " <<
B.getAddress()
137 <<
" + " <<
formatv(
"{0:x}", E.getOffset()) <<
" -- " << EdgeKindName
140 auto &TargetSym = E.getTarget();
141 if (TargetSym.hasName())
142 OS << TargetSym.getName();
144 auto &TargetBlock = TargetSym.getBlock();
145 auto &TargetSec = TargetBlock.getSection();
147 for (
auto *
B : TargetSec.blocks())
148 if (
B->getAddress() < SecAddress)
149 SecAddress =
B->getAddress();
152 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
154 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
155 OS <<
" / block " << TargetBlock.getAddress();
156 if (TargetSym.getOffset())
157 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
161 if (E.getAddend() != 0)
162 OS <<
" + " << E.getAddend();
166 for (
auto *Sym : Symbols)
168 for (
auto *
B : Blocks)
173 for (
auto *Sym : AbsoluteSymbols) {
179 ExternalSymbols.clear();
182std::vector<Block *> LinkGraph::splitBlockImpl(std::vector<Block *> Blocks,
183 SplitBlockCache *Cache) {
184 assert(!Blocks.empty() &&
"Blocks must at least contain the original block");
188 for (
size_t I = 0;
I != Blocks.size() - 1; ++
I) {
189 Blocks[
I]->setContent(
190 Content.
slice(Blocks[
I]->getAddress() - Blocks[0]->getAddress(),
191 Blocks[
I + 1]->getAddress() - Blocks[
I]->getAddress()));
193 Blocks.back()->setContent(
194 Content.
slice(Blocks.back()->getAddress() - Blocks[0]->getAddress()));
195 bool IsMutable = Blocks[0]->ContentMutable;
196 for (
auto *
B : Blocks)
197 B->ContentMutable = IsMutable;
203 Cache = &LocalBlockSymbolsCache;
206 if (*Cache == std::nullopt) {
207 *Cache = SplitBlockCache::value_type();
209 for (
auto *Sym : Blocks[0]->
getSection().symbols())
210 if (&Sym->getBlock() == Blocks[0])
211 (*Cache)->push_back(Sym);
212 llvm::sort(**Cache, [](
const Symbol *LHS,
const Symbol *RHS) {
213 return LHS->getAddress() > RHS->getAddress();
218 Sym.setOffset(Sym.getAddress() -
B.getAddress());
220 if (Sym.getSize() >
B.getSize())
221 Sym.setSize(
B.getSize() - Sym.getOffset());
225 for (
size_t I = 0;
I != Blocks.size() - 1; ++
I) {
226 if ((*Cache)->empty())
228 while (!(*Cache)->empty() &&
229 (*Cache)->back()->getAddress() < Blocks[
I + 1]->getAddress()) {
230 TransferSymbol(*(*Cache)->back(), *Blocks[
I]);
231 (*Cache)->pop_back();
235 while (!(*Cache)->empty()) {
236 auto &Sym = *(*Cache)->back();
237 (*Cache)->pop_back();
238 assert(Sym.getAddress() >= Blocks.back()->getAddress() &&
239 "Symbol address preceeds block");
240 assert(Sym.getAddress() <= Blocks.back()->getRange().End &&
241 "Symbol address starts past end of block");
242 TransferSymbol(Sym, *Blocks.back());
247 auto &Edges = Blocks[0]->Edges;
249 return LHS.getOffset() <
RHS.getOffset();
252 for (
size_t I = Blocks.size() - 1;
I != 0; --
I) {
258 Edge::OffsetT Delta = Blocks[
I]->getAddress() - Blocks[0]->getAddress();
261 if (Edges.back().getOffset() < Delta)
264 size_t EI = Edges.size() - 1;
265 while (EI != 0 && Edges[EI - 1].
getOffset() >= Delta)
268 for (
size_t J = EI; J != Edges.size(); ++J) {
269 Blocks[
I]->Edges.push_back(std::move(Edges[J]));
270 Blocks[
I]->Edges.back().setOffset(Blocks[
I]->Edges.back().getOffset() -
274 while (Edges.size() > EI)
284 OS <<
"LinkGraph \"" <<
getName()
289 BlockSymbols[&Sym->getBlock()].push_back(Sym);
293 for (
auto &KV : BlockSymbols)
295 if (LHS->getOffset() != RHS->getOffset())
296 return LHS->getOffset() < RHS->getOffset();
297 if (LHS->getLinkage() != RHS->getLinkage())
298 return LHS->getLinkage() < RHS->getLinkage();
299 if (LHS->getScope() != RHS->getScope())
300 return LHS->getScope() < RHS->getScope();
301 if (LHS->hasName()) {
304 return LHS->getName() < RHS->getName();
309 std::vector<Section *> SortedSections;
311 SortedSections.push_back(&Sec);
313 return LHS->getName() < RHS->getName();
316 for (
auto *Sec : SortedSections) {
317 OS <<
"section " << Sec->getName() <<
":\n\n";
319 std::vector<Block *> SortedBlocks;
322 return LHS->getAddress() < RHS->getAddress();
325 for (
auto *
B : SortedBlocks) {
326 OS <<
" block " <<
B->getAddress()
327 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
328 <<
", align = " <<
B->getAlignment()
329 <<
", alignment-offset = " <<
B->getAlignmentOffset();
334 auto BlockSymsI = BlockSymbols.find(
B);
335 if (BlockSymsI != BlockSymbols.end()) {
337 auto &Syms = BlockSymsI->second;
338 for (
auto *Sym : Syms)
339 OS <<
" " << *Sym <<
"\n";
341 OS <<
" no symbols\n";
343 if (!
B->edges_empty()) {
345 std::vector<Edge> SortedEdges;
348 return LHS.getOffset() <
RHS.getOffset();
350 for (
auto &
E : SortedEdges) {
351 OS <<
" " <<
B->getFixupAddress(
E) <<
" (block + "
352 <<
formatv(
"{0:x8}",
E.getOffset()) <<
"), addend = ";
353 if (
E.getAddend() >= 0)
354 OS <<
formatv(
"+{0:x8}",
E.getAddend());
356 OS <<
formatv(
"-{0:x8}", -
E.getAddend());
358 if (
E.getTarget().hasName())
359 OS <<
E.getTarget().getName();
362 <<
formatv(
"{0:x16}",
E.getTarget().getAddress()) <<
"+"
363 <<
formatv(
"{0:x8}",
E.getTarget().getOffset());
372 OS <<
"Absolute symbols:\n";
373 if (!absolute_symbols().
empty()) {
374 for (
auto *Sym : absolute_symbols())
375 OS <<
" " << Sym->getAddress() <<
": " << *Sym <<
"\n";
379 OS <<
"\nExternal symbols:\n";
380 if (!external_symbols().
empty()) {
381 for (
auto *Sym : external_symbols())
382 OS <<
" " << Sym->getAddress() <<
": " << *Sym
383 << (Sym->isWeaklyReferenced() ?
" (weakly referenced)" :
"") <<
"\n";
391 return OS <<
"RequiredSymbol";
393 return OS <<
"WeaklyReferencedSymbol";
398void JITLinkAsyncLookupContinuation::anchor() {}
400JITLinkContext::~JITLinkContext() =
default;
416 for (
auto *Sym :
G.defined_symbols())
427 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
428 <<
": relocation target "
429 <<
formatv(
"{0:x}", E.getTarget().getAddress() + E.getAddend())
431 if (E.getTarget().hasName())
432 ErrStream << E.getTarget().getName();
434 ErrStream <<
"<anonymous symbol>";
437 ErrStream <<
formatv(
":{0:x}", E.getTarget().getAddress()) <<
" + "
438 <<
formatv(
"{0:x}", E.getAddend());
440 ErrStream <<
") is out of range of " <<
G.getEdgeKindName(E.getKind())
441 <<
" fixup at address "
442 <<
formatv(
"{0:x}", E.getTarget().getAddress()) <<
" (";
444 Symbol *BestSymbolForBlock =
nullptr;
445 for (
auto *Sym : Sec.
symbols())
446 if (&Sym->getBlock() == &
B && Sym->hasName() && Sym->getOffset() == 0 &&
447 (!BestSymbolForBlock ||
448 Sym->getScope() < BestSymbolForBlock->
getScope() ||
449 Sym->getLinkage() < BestSymbolForBlock->
getLinkage()))
450 BestSymbolForBlock = Sym;
452 if (BestSymbolForBlock)
453 ErrStream << BestSymbolForBlock->
getName() <<
", ";
455 ErrStream <<
"<anonymous block> @ ";
457 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
458 <<
formatv(
"{0:x}", E.getOffset()) <<
")";
466 " improper alignment for relocation " +
467 formatv(
"{0:d}", E.getKind()) +
": 0x" +
469 " is not aligned to " +
Twine(
N) +
" bytes");
473 switch (TT.getArch()) {
491 switch (TT.getArch()) {
510 std::shared_ptr<orc::SymbolStringPool> SSP) {
526std::unique_ptr<LinkGraph>
529 static std::atomic<uint64_t> Counter = {0};
530 auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
531 auto G = std::make_unique<LinkGraph>(
532 "<Absolute Symbols " + std::to_string(Index) +
">", std::move(SSP),
534 for (
auto &[Name, Def] : Symbols) {
536 G->addAbsoluteSymbol(*Name, Def.getAddress(), 0,
538 Sym.setCallable(Def.getFlags().isCallable());
544void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
545 switch (
G->getTargetTriple().getObjectFormat()) {
549 return link_ELF(std::move(
G), std::move(Ctx));
551 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
ArrayRef - 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
StringRef - 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.
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.
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.
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)
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.
void link_COFF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
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)
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...