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>";
102 return B.getSize() == 1;
104 for (
size_t I = 0;
I !=
B.getSize() - 1; ++
I)
105 if (
B.getContent()[
I] ==
'\0')
108 return B.getContent()[
B.getSize() - 1] ==
'\0';
112 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
114 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
115 << (
B.isZeroFill() ?
"zero-fill" :
"content")
116 <<
", align = " <<
B.getAlignment()
117 <<
", align-ofs = " <<
B.getAlignmentOffset()
118 <<
", section = " <<
B.getSection().getName();
127 << (
Sym.
isLive() ?
"live" :
"dead") <<
" - "
134 OS <<
"edge@" <<
B.getAddress() + E.
getOffset() <<
": " <<
B.getAddress()
139 if (TargetSym.hasName())
140 OS << TargetSym.getName();
142 auto &TargetBlock = TargetSym.getBlock();
143 auto &TargetSec = TargetBlock.getSection();
145 for (
auto *
B : TargetSec.blocks())
146 if (
B->getAddress() < SecAddress)
147 SecAddress =
B->getAddress();
150 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
152 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
153 OS <<
" / block " << TargetBlock.getAddress();
154 if (TargetSym.getOffset())
155 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
164 for (
auto *
Sym : Symbols)
166 for (
auto *
B : Blocks)
173 assert(SplitIndex > 0 &&
"splitBlock can not be called with SplitIndex == 0");
176 if (SplitIndex ==
B.getSize())
179 assert(SplitIndex <
B.getSize() &&
"SplitIndex out of range");
185 B.getAlignment(),
B.getAlignmentOffset())
187 B.getSection(),
B.getContent().slice(0, SplitIndex),
188 B.getAddress(),
B.getAlignment(),
B.getAlignmentOffset());
191 B.setAddress(
B.getAddress() + SplitIndex);
192 B.setContent(
B.getContent().slice(SplitIndex));
193 B.setAlignmentOffset((
B.getAlignmentOffset() + SplitIndex) %
200 std::vector<Block::edge_iterator> EdgesToRemove;
201 for (
auto I =
B.edges().begin();
I !=
B.edges().end();) {
202 if (
I->getOffset() < SplitIndex) {
203 NewBlock.addEdge(*
I);
206 I->setOffset(
I->getOffset() - SplitIndex);
217 Cache = &LocalBlockSymbolsCache;
218 if (*Cache == std::nullopt) {
219 *Cache = SplitBlockCache::value_type();
220 for (
auto *
Sym :
B.getSection().symbols())
221 if (&
Sym->getBlock() == &
B)
222 (*Cache)->push_back(
Sym);
225 return LHS->getOffset() >
RHS->getOffset();
228 auto &BlockSymbols = **Cache;
231 while (!BlockSymbols.empty() &&
232 BlockSymbols.back()->getOffset() < SplitIndex) {
233 auto *
Sym = BlockSymbols.back();
236 if (
Sym->getOffset() +
Sym->getSize() > SplitIndex)
237 Sym->setSize(SplitIndex -
Sym->getOffset());
238 Sym->setBlock(NewBlock);
239 BlockSymbols.pop_back();
243 for (
auto *
Sym : BlockSymbols)
244 Sym->setOffset(
Sym->getOffset() - SplitIndex);
255 BlockSymbols[&
Sym->getBlock()].push_back(
Sym);
259 for (
auto &KV : BlockSymbols)
261 if (LHS->getOffset() != RHS->getOffset())
262 return LHS->getOffset() < RHS->getOffset();
263 if (LHS->getLinkage() != RHS->getLinkage())
264 return LHS->getLinkage() < RHS->getLinkage();
265 if (LHS->getScope() != RHS->getScope())
266 return LHS->getScope() < RHS->getScope();
267 if (LHS->hasName()) {
270 return LHS->getName() < RHS->getName();
276 OS <<
"section " << Sec.getName() <<
":\n\n";
278 std::vector<Block *> SortedBlocks;
279 llvm::copy(Sec.blocks(), std::back_inserter(SortedBlocks));
281 return LHS->getAddress() <
RHS->getAddress();
284 for (
auto *
B : SortedBlocks) {
285 OS <<
" block " <<
B->getAddress()
286 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
287 <<
", align = " <<
B->getAlignment()
288 <<
", alignment-offset = " <<
B->getAlignmentOffset();
293 auto BlockSymsI = BlockSymbols.find(
B);
294 if (BlockSymsI != BlockSymbols.end()) {
296 auto &Syms = BlockSymsI->second;
297 for (
auto *
Sym : Syms)
298 OS <<
" " << *
Sym <<
"\n";
300 OS <<
" no symbols\n";
302 if (!
B->edges_empty()) {
304 std::vector<Edge> SortedEdges;
305 llvm::copy(
B->edges(), std::back_inserter(SortedEdges));
306 llvm::sort(SortedEdges, [](
const Edge &LHS,
const Edge &RHS) {
307 return LHS.getOffset() <
RHS.getOffset();
309 for (
auto &E : SortedEdges) {
310 OS <<
" " <<
B->getFixupAddress(E) <<
" (block + "
311 <<
formatv(
"{0:x8}", E.getOffset()) <<
"), addend = ";
312 if (E.getAddend() >= 0)
315 OS <<
formatv(
"-{0:x8}", -E.getAddend());
317 if (E.getTarget().hasName())
318 OS << E.getTarget().getName();
321 <<
formatv(
"{0:x16}", E.getTarget().getAddress()) <<
"+"
322 <<
formatv(
"{0:x8}", E.getTarget().getOffset());
331 OS <<
"Absolute symbols:\n";
332 if (!absolute_symbols().empty()) {
333 for (
auto *
Sym : absolute_symbols())
338 OS <<
"\nExternal symbols:\n";
339 if (!external_symbols().empty()) {
340 for (
auto *
Sym : external_symbols())
349 case SymbolLookupFlags::RequiredSymbol:
350 return OS <<
"RequiredSymbol";
351 case SymbolLookupFlags::WeaklyReferencedSymbol:
352 return OS <<
"WeaklyReferencedSymbol";
357void JITLinkAsyncLookupContinuation::anchor() {}
359JITLinkContext::~JITLinkContext() =
default;
361bool JITLinkContext::shouldAddDefaultTargetPasses(
const Triple &TT)
const {
375 for (
auto *
Sym :
G.defined_symbols())
386 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
387 <<
": relocation target ";
394 <<
" is out of range of " <<
G.getEdgeKindName(E.
getKind())
395 <<
" fixup at " <<
formatv(
"{0:x}",
B.getFixupAddress(E)) <<
" (";
397 Symbol *BestSymbolForBlock =
nullptr;
399 if (&
Sym->getBlock() == &
B &&
Sym->hasName() &&
Sym->getOffset() == 0 &&
400 (!BestSymbolForBlock ||
401 Sym->getScope() < BestSymbolForBlock->
getScope() ||
403 BestSymbolForBlock =
Sym;
405 if (BestSymbolForBlock)
406 ErrStream << BestSymbolForBlock->
getName() <<
", ";
408 ErrStream <<
"<anonymous block> @ ";
410 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
413 return make_error<JITLinkError>(std::move(ErrMsg));
418 return make_error<JITLinkError>(
"0x" + llvm::utohexstr(Loc.
getValue()) +
419 " improper alignment for relocation " +
421 llvm::utohexstr(
Value) +
422 " is not aligned to " +
Twine(
N) +
" bytes");
426 switch (TT.getArch()) {
428 return aarch64::createAnonymousPointer;
430 return x86_64::createAnonymousPointer;
432 return i386::createAnonymousPointer;
435 return loongarch::createAnonymousPointer;
442 switch (TT.getArch()) {
444 return aarch64::createAnonymousPointerJumpStub;
446 return x86_64::createAnonymousPointerJumpStub;
448 return i386::createAnonymousPointerJumpStub;
451 return loongarch::createAnonymousPointerJumpStub;
468 return make_error<JITLinkError>(
"Unsupported file format");
474 unsigned PointerSize;
477 switch (TT.getArch()) {
492 static std::atomic<uint64_t> Counter = {0};
493 auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
494 auto G = std::make_unique<LinkGraph>(
495 "<Absolute Symbols " + std::to_string(
Index) +
">", TT, PointerSize,
496 Endianness,
nullptr);
497 for (
auto &[
Name, Def] : Symbols) {
499 G->addAbsoluteSymbol(*
Name, Def.getAddress(), 0,
500 Linkage::Strong, Scope::Default,
true);
501 Sym.setCallable(Def.getFlags().isCallable());
507void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
508 switch (
G->getTargetTriple().getObjectFormat()) {
512 return link_ELF(std::move(
G), std::move(Ctx));
514 return link_COFF(std::move(
G), std::move(Ctx));
516 Ctx->notifyFailed(make_error<JITLinkError>(
"Unsupported object format"));
bbsections Prepares for basic block sections
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
An Addressable with content and edges.
Section & getSection() const
Return the parent section for this block.
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.
Block & createContentBlock(Section &Parent, ArrayRef< char > Content, orc::ExecutorAddr Address, uint64_t Alignment, uint64_t AlignmentOffset)
Create a content block.
std::optional< SmallVector< Symbol *, 8 > > SplitBlockCache
Cache type for the splitBlock function.
Block & createZeroFillBlock(Section &Parent, orc::ExecutorAddrDiff Size, orc::ExecutorAddr Address, uint64_t Alignment, uint64_t AlignmentOffset)
Create a zero-fill block.
Block & splitBlock(Block &B, size_t SplitIndex, SplitBlockCache *Cache=nullptr)
Splits block B at the given index which must be greater than zero.
void dump(raw_ostream &OS)
Dump the graph.
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.
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
StringRef getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
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.
Block & getBlock()
Return the Block for this Symbol (Symbol must be defined).
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.
const char * getEdgeKindName(Edge::Kind K)
Get a human-readable name for the given AArch32 edge kind.
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.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
const char * getLinkageName(Linkage L)
For errors and debugging output.
SymbolLookupFlags
Flags for symbol lookup.
Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, const Edge &E)
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF relocatable object.
raw_ostream & operator<<(raw_ostream &OS, const Block &B)
PointerJumpStubCreator getPointerJumpStubCreator(const Triple &TT)
Get target-specific PointerJumpStubCreator.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from the given object buffer.
void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
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.
const char * getScopeName(Scope S)
For debugging output.
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an COFF relocatable object.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
bool isCStringBlock(Block &B)
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.
AnonymousPointerCreator getAnonymousPointerCreator(const Triple &TT)
Get target-specific AnonymousPointerCreator.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from a MachO relocatable object.
std::unique_ptr< LinkGraph > absoluteSymbolsLinkGraph(const Triple &TT, orc::SymbolMap Symbols)
Create a LinkGraph defining the given absolute symbols.
This is an optimization pass for GlobalISel generic memory operations.
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void sort(IteratorTy Start, IteratorTy End)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt copy(R &&Range, OutputIt Out)
@ elf_relocatable
ELF Relocatable 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...