22#define DEBUG_TYPE "jitlink"
26enum JITLinkErrorCode { GenericJITLinkError = 1 };
31class JITLinkerErrorCategory :
public std::error_category {
33 const char *
name()
const noexcept override {
return "runtimedyld"; }
35 std::string message(
int Condition)
const override {
36 switch (
static_cast<JITLinkErrorCode
>(Condition)) {
37 case GenericJITLinkError:
38 return "Generic JITLink error";
54 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
55 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
61 return "INVALID RELOCATION";
65 return "<Unrecognized edge kind>";
97 return B.getSize() == 1;
99 for (
size_t I = 0;
I !=
B.getSize() - 1; ++
I)
100 if (
B.getContent()[
I] ==
'\0')
103 return B.getContent()[
B.getSize() - 1] ==
'\0';
107 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
109 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
110 << (
B.isZeroFill() ?
"zero-fill" :
"content")
111 <<
", align = " <<
B.getAlignment()
112 <<
", align-ofs = " <<
B.getAlignmentOffset()
113 <<
", section = " <<
B.getSection().getName();
122 << (
Sym.
isLive() ?
"live" :
"dead") <<
" - "
129 OS <<
"edge@" <<
B.getAddress() +
E.getOffset() <<
": " <<
B.getAddress()
130 <<
" + " <<
formatv(
"{0:x}",
E.getOffset()) <<
" -- " << EdgeKindName
133 auto &TargetSym =
E.getTarget();
134 if (TargetSym.hasName())
135 OS << TargetSym.getName();
137 auto &TargetBlock = TargetSym.getBlock();
138 auto &TargetSec = TargetBlock.getSection();
140 for (
auto *
B : TargetSec.blocks())
141 if (
B->getAddress() < SecAddress)
142 SecAddress =
B->getAddress();
145 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
147 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
148 OS <<
" / block " << TargetBlock.getAddress();
149 if (TargetSym.getOffset())
150 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
154 if (
E.getAddend() != 0)
155 OS <<
" + " <<
E.getAddend();
159 for (
auto *
Sym : Symbols)
161 for (
auto *
B : Blocks)
168 assert(SplitIndex > 0 &&
"splitBlock can not be called with SplitIndex == 0");
171 if (SplitIndex ==
B.getSize())
174 assert(SplitIndex <
B.getSize() &&
"SplitIndex out of range");
180 B.getAlignment(),
B.getAlignmentOffset())
182 B.getSection(),
B.getContent().slice(0, SplitIndex),
183 B.getAddress(),
B.getAlignment(),
B.getAlignmentOffset());
186 B.setAddress(
B.getAddress() + SplitIndex);
187 B.setContent(
B.getContent().slice(SplitIndex));
188 B.setAlignmentOffset((
B.getAlignmentOffset() + SplitIndex) %
195 std::vector<Block::edge_iterator> EdgesToRemove;
196 for (
auto I =
B.edges().begin();
I !=
B.edges().end();) {
197 if (
I->getOffset() < SplitIndex) {
198 NewBlock.addEdge(*
I);
201 I->setOffset(
I->getOffset() - SplitIndex);
212 Cache = &LocalBlockSymbolsCache;
213 if (*Cache == std::nullopt) {
214 *Cache = SplitBlockCache::value_type();
215 for (
auto *
Sym :
B.getSection().symbols())
216 if (&
Sym->getBlock() == &
B)
217 (*Cache)->push_back(
Sym);
220 return LHS->getOffset() >
RHS->getOffset();
223 auto &BlockSymbols = **Cache;
226 while (!BlockSymbols.empty() &&
227 BlockSymbols.back()->getOffset() < SplitIndex) {
228 auto *
Sym = BlockSymbols.back();
231 if (
Sym->getOffset() +
Sym->getSize() > SplitIndex)
232 Sym->setSize(SplitIndex -
Sym->getOffset());
233 Sym->setBlock(NewBlock);
234 BlockSymbols.pop_back();
238 for (
auto *
Sym : BlockSymbols)
239 Sym->setOffset(
Sym->getOffset() - SplitIndex);
250 BlockSymbols[&
Sym->getBlock()].push_back(
Sym);
254 for (
auto &KV : BlockSymbols)
256 if (LHS->getOffset() != RHS->getOffset())
257 return LHS->getOffset() < RHS->getOffset();
258 if (LHS->getLinkage() != RHS->getLinkage())
259 return LHS->getLinkage() < RHS->getLinkage();
260 if (LHS->getScope() != RHS->getScope())
261 return LHS->getScope() < RHS->getScope();
262 if (LHS->hasName()) {
265 return LHS->getName() < RHS->getName();
270 for (
auto &Sec : sections()) {
271 OS <<
"section " << Sec.getName() <<
":\n\n";
273 std::vector<Block *> SortedBlocks;
274 llvm::copy(Sec.blocks(), std::back_inserter(SortedBlocks));
276 return LHS->getAddress() <
RHS->getAddress();
279 for (
auto *
B : SortedBlocks) {
280 OS <<
" block " <<
B->getAddress()
281 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
282 <<
", align = " <<
B->getAlignment()
283 <<
", alignment-offset = " <<
B->getAlignmentOffset();
288 auto BlockSymsI = BlockSymbols.find(
B);
289 if (BlockSymsI != BlockSymbols.end()) {
291 auto &Syms = BlockSymsI->second;
292 for (
auto *
Sym : Syms)
293 OS <<
" " << *
Sym <<
"\n";
295 OS <<
" no symbols\n";
297 if (!
B->edges_empty()) {
299 std::vector<Edge> SortedEdges;
300 llvm::copy(
B->edges(), std::back_inserter(SortedEdges));
301 llvm::sort(SortedEdges, [](
const Edge &LHS,
const Edge &RHS) {
302 return LHS.getOffset() <
RHS.getOffset();
304 for (
auto &
E : SortedEdges) {
305 OS <<
" " <<
B->getFixupAddress(
E) <<
" (block + "
306 <<
formatv(
"{0:x8}",
E.getOffset()) <<
"), addend = ";
307 if (
E.getAddend() >= 0)
312 if (
E.getTarget().hasName())
313 OS <<
E.getTarget().getName();
316 <<
formatv(
"{0:x16}",
E.getTarget().getAddress()) <<
"+"
317 <<
formatv(
"{0:x8}",
E.getTarget().getOffset());
326 OS <<
"Absolute symbols:\n";
327 if (!absolute_symbols().empty()) {
328 for (
auto *
Sym : absolute_symbols())
333 OS <<
"\nExternal symbols:\n";
334 if (!external_symbols().empty()) {
335 for (
auto *
Sym : external_symbols())
343 case SymbolLookupFlags::RequiredSymbol:
344 return OS <<
"RequiredSymbol";
345 case SymbolLookupFlags::WeaklyReferencedSymbol:
346 return OS <<
"WeaklyReferencedSymbol";
351void JITLinkAsyncLookupContinuation::anchor() {}
353JITLinkContext::~JITLinkContext() =
default;
355bool JITLinkContext::shouldAddDefaultTargetPasses(
const Triple &TT)
const {
369 for (
auto *
Sym :
G.defined_symbols())
380 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
381 <<
": relocation target ";
382 if (
E.getTarget().hasName()) {
383 ErrStream <<
"\"" <<
E.getTarget().getName() <<
"\"";
385 ErrStream <<
E.getTarget().getBlock().getSection().getName() <<
" + "
387 ErrStream <<
" at address " <<
formatv(
"{0:x}",
E.getTarget().getAddress())
388 <<
" is out of range of " <<
G.getEdgeKindName(
E.getKind())
389 <<
" fixup at " <<
formatv(
"{0:x}",
B.getFixupAddress(
E)) <<
" (";
391 Symbol *BestSymbolForBlock =
nullptr;
393 if (&
Sym->getBlock() == &
B &&
Sym->hasName() &&
Sym->getOffset() == 0 &&
394 (!BestSymbolForBlock ||
395 Sym->getScope() < BestSymbolForBlock->
getScope() ||
397 BestSymbolForBlock =
Sym;
399 if (BestSymbolForBlock)
400 ErrStream << BestSymbolForBlock->
getName() <<
", ";
402 ErrStream <<
"<anonymous block> @ ";
404 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
405 <<
formatv(
"{0:x}",
E.getOffset()) <<
")";
407 return make_error<JITLinkError>(std::move(ErrMsg));
412 return make_error<JITLinkError>(
"0x" + llvm::utohexstr(Loc.
getValue()) +
413 " improper alignment for relocation " +
414 formatv(
"{0:d}",
E.getKind()) +
": 0x" +
415 llvm::utohexstr(
Value) +
416 " is not aligned to " +
Twine(
N) +
" bytes");
430 return make_error<JITLinkError>(
"Unsupported file format");
434void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
435 switch (
G->getTargetTriple().getObjectFormat()) {
439 return link_ELF(std::move(
G), std::move(Ctx));
441 return link_COFF(std::move(
G), std::move(Ctx));
443 Ctx->notifyFailed(make_error<JITLinkError>(
"Unsupported object format"));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-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.
Represents fixups and constraints in the LinkGraph.
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.
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.
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)
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.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from a MachO relocatable object.
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(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void sort(IteratorTy Start, IteratorTy End)
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...