26#define DEBUG_TYPE "jitlink"
30enum JITLinkErrorCode { GenericJITLinkError = 1 };
35class JITLinkerErrorCategory :
public std::error_category {
37 const char *
name()
const noexcept override {
return "runtimedyld"; }
39 std::string message(
int Condition)
const override {
40 switch (
static_cast<JITLinkErrorCode
>(Condition)) {
41 case GenericJITLinkError:
42 return "Generic JITLink error";
58 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
59 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
65 return "INVALID RELOCATION";
69 return "<Unrecognized edge kind>";
90 return "side-effects-only";
103 return B.getSize() == 1;
105 for (
size_t I = 0;
I !=
B.getSize() - 1; ++
I)
106 if (
B.getContent()[
I] ==
'\0')
109 return B.getContent()[
B.getSize() - 1] ==
'\0';
113 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
115 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
116 << (
B.isZeroFill() ?
"zero-fill" :
"content")
117 <<
", align = " <<
B.getAlignment()
118 <<
", align-ofs = " <<
B.getAlignmentOffset()
119 <<
", section = " <<
B.getSection().getName();
128 << (
Sym.
isLive() ?
"live" :
"dead") <<
" - "
135 OS <<
"edge@" <<
B.getAddress() + E.
getOffset() <<
": " <<
B.getAddress()
140 if (TargetSym.hasName())
141 OS << TargetSym.getName();
143 auto &TargetBlock = TargetSym.getBlock();
144 auto &TargetSec = TargetBlock.getSection();
146 for (
auto *
B : TargetSec.blocks())
147 if (
B->getAddress() < SecAddress)
148 SecAddress =
B->getAddress();
151 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
153 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
154 OS <<
" / block " << TargetBlock.getAddress();
155 if (TargetSym.getOffset())
156 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
165 for (
auto *
Sym : Symbols)
167 for (
auto *
B : Blocks)
172 for (
auto *
Sym : AbsoluteSymbols) {
178 ExternalSymbols.
clear();
181std::vector<Block *> LinkGraph::splitBlockImpl(std::vector<Block *>
Blocks,
182 SplitBlockCache *Cache) {
183 assert(!
Blocks.empty() &&
"Blocks must at least contain the original block");
187 for (
size_t I = 0;
I !=
Blocks.size() - 1; ++
I) {
192 Blocks.back()->setContent(
194 bool IsMutable =
Blocks[0]->ContentMutable;
196 B->ContentMutable = IsMutable;
202 Cache = &LocalBlockSymbolsCache;
205 if (*Cache == std::nullopt) {
206 *Cache = SplitBlockCache::value_type();
210 (*Cache)->push_back(
Sym);
211 llvm::sort(**Cache, [](
const Symbol *LHS,
const Symbol *RHS) {
212 return LHS->getAddress() >
RHS->getAddress();
217 Sym.setOffset(
Sym.getAddress() -
B.getAddress());
219 if (
Sym.getSize() >
B.getSize())
220 Sym.setSize(
B.getSize() -
Sym.getOffset());
224 for (
size_t I = 0;
I !=
Blocks.size() - 1; ++
I) {
225 if ((*Cache)->empty())
227 while (!(*Cache)->empty() &&
228 (*Cache)->back()->getAddress() <
Blocks[
I + 1]->getAddress()) {
229 TransferSymbol(*(*Cache)->back(), *
Blocks[
I]);
230 (*Cache)->pop_back();
234 while (!(*Cache)->empty()) {
235 auto &
Sym = *(*Cache)->back();
236 (*Cache)->pop_back();
238 "Symbol address preceeds block");
240 "Symbol address starts past end of block");
246 auto &Edges =
Blocks[0]->Edges;
247 llvm::sort(Edges, [](
const Edge &LHS,
const Edge &RHS) {
248 return LHS.getOffset() <
RHS.getOffset();
251 for (
size_t I =
Blocks.size() - 1;
I != 0; --
I) {
257 Edge::OffsetT Delta =
Blocks[
I]->getAddress() -
Blocks[0]->getAddress();
260 if (Edges.back().getOffset() < Delta)
263 size_t EI = Edges.size() - 1;
264 while (EI != 0 && Edges[EI - 1].
getOffset() >= Delta)
267 for (
size_t J = EI; J != Edges.size(); ++J) {
268 Blocks[
I]->Edges.push_back(std::move(Edges[J]));
269 Blocks[
I]->Edges.back().setOffset(
Blocks[
I]->Edges.back().getOffset() -
273 while (Edges.size() > EI)
285 BlockSymbols[&
Sym->getBlock()].push_back(
Sym);
289 for (
auto &KV : BlockSymbols)
291 if (LHS->getOffset() != RHS->getOffset())
292 return LHS->getOffset() < RHS->getOffset();
293 if (LHS->getLinkage() != RHS->getLinkage())
294 return LHS->getLinkage() < RHS->getLinkage();
295 if (LHS->getScope() != RHS->getScope())
296 return LHS->getScope() < RHS->getScope();
297 if (LHS->hasName()) {
300 return LHS->getName() < RHS->getName();
305 std::vector<Section *> SortedSections;
307 SortedSections.push_back(&Sec);
312 for (
auto *Sec : SortedSections) {
313 OS <<
"section " << Sec->getName() <<
":\n\n";
315 std::vector<Block *> SortedBlocks;
317 llvm::sort(SortedBlocks, [](
const Block *LHS,
const Block *RHS) {
318 return LHS->getAddress() <
RHS->getAddress();
321 for (
auto *
B : SortedBlocks) {
322 OS <<
" block " <<
B->getAddress()
323 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
324 <<
", align = " <<
B->getAlignment()
325 <<
", alignment-offset = " <<
B->getAlignmentOffset();
330 auto BlockSymsI = BlockSymbols.find(
B);
331 if (BlockSymsI != BlockSymbols.end()) {
333 auto &Syms = BlockSymsI->second;
334 for (
auto *
Sym : Syms)
335 OS <<
" " << *
Sym <<
"\n";
337 OS <<
" no symbols\n";
339 if (!
B->edges_empty()) {
341 std::vector<Edge> SortedEdges;
343 llvm::sort(SortedEdges, [](
const Edge &LHS,
const Edge &RHS) {
344 return LHS.getOffset() <
RHS.getOffset();
346 for (
auto &E : SortedEdges) {
347 OS <<
" " <<
B->getFixupAddress(E) <<
" (block + "
348 <<
formatv(
"{0:x8}", E.getOffset()) <<
"), addend = ";
349 if (E.getAddend() >= 0)
352 OS <<
formatv(
"-{0:x8}", -E.getAddend());
354 if (E.getTarget().hasName())
355 OS << E.getTarget().getName();
358 <<
formatv(
"{0:x16}", E.getTarget().getAddress()) <<
"+"
359 <<
formatv(
"{0:x8}", E.getTarget().getOffset());
368 OS <<
"Absolute symbols:\n";
369 if (!absolute_symbols().empty()) {
370 for (
auto *
Sym : absolute_symbols())
375 OS <<
"\nExternal symbols:\n";
376 if (!external_symbols().empty()) {
377 for (
auto *
Sym : external_symbols())
386 case SymbolLookupFlags::RequiredSymbol:
387 return OS <<
"RequiredSymbol";
388 case SymbolLookupFlags::WeaklyReferencedSymbol:
389 return OS <<
"WeaklyReferencedSymbol";
394void JITLinkAsyncLookupContinuation::anchor() {}
396JITLinkContext::~JITLinkContext() =
default;
398bool JITLinkContext::shouldAddDefaultTargetPasses(
const Triple &TT)
const {
412 for (
auto *
Sym :
G.defined_symbols())
423 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
424 <<
": relocation target "
430 ErrStream <<
"<anonymous symbol>";
436 ErrStream <<
") is out of range of " <<
G.getEdgeKindName(E.
getKind())
437 <<
" fixup at address "
440 Symbol *BestSymbolForBlock =
nullptr;
442 if (&
Sym->getBlock() == &
B &&
Sym->hasName() &&
Sym->getOffset() == 0 &&
443 (!BestSymbolForBlock ||
444 Sym->getScope() < BestSymbolForBlock->
getScope() ||
446 BestSymbolForBlock =
Sym;
448 if (BestSymbolForBlock)
449 ErrStream << BestSymbolForBlock->
getName() <<
", ";
451 ErrStream <<
"<anonymous block> @ ";
453 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
456 return make_error<JITLinkError>(std::move(ErrMsg));
461 return make_error<JITLinkError>(
"0x" + llvm::utohexstr(Loc.
getValue()) +
462 " improper alignment for relocation " +
464 llvm::utohexstr(
Value) +
465 " is not aligned to " +
Twine(
N) +
" bytes");
469 switch (TT.getArch()) {
471 return aarch64::createAnonymousPointer;
473 return x86_64::createAnonymousPointer;
475 return x86::createAnonymousPointer;
478 return loongarch::createAnonymousPointer;
485 switch (TT.getArch()) {
487 return aarch64::createAnonymousPointerJumpStub;
489 return x86_64::createAnonymousPointerJumpStub;
491 return x86::createAnonymousPointerJumpStub;
494 return loongarch::createAnonymousPointerJumpStub;
502 std::shared_ptr<orc::SymbolStringPool> SSP) {
514 return make_error<JITLinkError>(
"Unsupported file format");
518std::unique_ptr<LinkGraph>
521 static std::atomic<uint64_t> Counter = {0};
522 auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
523 auto G = std::make_unique<LinkGraph>(
524 "<Absolute Symbols " + std::to_string(Index) +
">", std::move(SSP),
526 for (
auto &[
Name, Def] : Symbols) {
528 G->addAbsoluteSymbol(*
Name, Def.getAddress(), 0,
529 Linkage::Strong, Scope::Default,
true);
530 Sym.setCallable(Def.getFlags().isCallable());
536void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
537 switch (
G->getTargetTriple().getObjectFormat()) {
541 return link_ELF(std::move(
G), std::move(Ctx));
543 return link_COFF(std::move(
G), std::move(Ctx));
547 Ctx->notifyFailed(make_error<JITLinkError>(
"Unsupported object format"));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bbsections Prepares for basic block sections
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DenseMap< Block *, BlockRelaxAux > Blocks
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An Addressable with content and edges.
Represents fixups and constraints in the LinkGraph.
Symbol & getTarget() const
AddendT getAddend() const
OffsetT getOffset() const
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.
std::optional< SmallVector< Symbol *, 8 > > SplitBlockCache
Cache type for the splitBlock function.
LLVM_ABI void dump(raw_ostream &OS)
Dump the graph.
iterator_range< external_symbol_iterator > external_symbols()
iterator_range< defined_symbol_iterator > defined_symbols()
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 isWeaklyReferenced() const
Returns true if this is a weakly referenced external symbol.
bool hasName() const
Returns true if this symbol has a name.
Represents an address in the executor process.
uint64_t getValue() const
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.
unique_function is a type-erasing functor similar to std::function.
#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.
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.
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.
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)
NodeAddr< BlockNode * > Block
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.
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)
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...