Go to the documentation of this file.
22 #define DEBUG_TYPE "jitlink"
26 enum JITLinkErrorCode { GenericJITLinkError = 1 };
31 class 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";
51 void JITLinkError::log(
raw_ostream &OS)
const { OS << ErrMsg; }
53 std::error_code JITLinkError::convertToErrorCode()
const {
54 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
55 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
61 return "INVALID RELOCATION";
65 return "<Unrecognized edge kind>";
92 return OS <<
B.getAddress() <<
" -- " << (
B.getAddress() +
B.getSize())
94 <<
"size = " <<
formatv(
"{0:x8}",
B.getSize()) <<
", "
95 << (
B.isZeroFill() ?
"zero-fill" :
"content")
96 <<
", align = " <<
B.getAlignment()
97 <<
", align-ofs = " <<
B.getAlignmentOffset()
98 <<
", section = " <<
B.getSection().getName();
107 << (Sym.
isLive() ?
"live" :
"dead") <<
" - "
114 OS <<
"edge@" <<
B.getAddress() +
E.getOffset() <<
": " <<
B.getAddress()
115 <<
" + " <<
formatv(
"{0:x}",
E.getOffset()) <<
" -- " << EdgeKindName
118 auto &TargetSym =
E.getTarget();
119 if (TargetSym.hasName())
120 OS << TargetSym.getName();
122 auto &TargetBlock = TargetSym.getBlock();
123 auto &TargetSec = TargetBlock.getSection();
125 for (
auto *
B : TargetSec.blocks())
126 if (
B->getAddress() < SecAddress)
127 SecAddress =
B->getAddress();
130 OS << TargetSym.getAddress() <<
" (section " << TargetSec.getName();
132 OS <<
" + " <<
formatv(
"{0:x}", SecDelta);
133 OS <<
" / block " << TargetBlock.getAddress();
134 if (TargetSym.getOffset())
135 OS <<
" + " <<
formatv(
"{0:x}", TargetSym.getOffset());
139 if (
E.getAddend() != 0)
140 OS <<
" + " <<
E.getAddend();
143 Section::~Section() {
144 for (
auto *Sym : Symbols)
146 for (
auto *
B : Blocks)
153 assert(SplitIndex > 0 &&
"splitBlock can not be called with SplitIndex == 0");
156 if (SplitIndex ==
B.getSize())
159 assert(SplitIndex <
B.getSize() &&
"SplitIndex out of range");
164 ? createZeroFillBlock(
B.getSection(), SplitIndex,
B.getAddress(),
165 B.getAlignment(),
B.getAlignmentOffset())
166 : createContentBlock(
167 B.getSection(),
B.getContent().slice(0, SplitIndex),
168 B.getAddress(),
B.getAlignment(),
B.getAlignmentOffset());
171 B.setAddress(
B.getAddress() + SplitIndex);
172 B.setContent(
B.getContent().slice(SplitIndex));
173 B.setAlignmentOffset((
B.getAlignmentOffset() + SplitIndex) %
180 std::vector<Block::edge_iterator> EdgesToRemove;
181 for (
auto I =
B.edges().begin();
I !=
B.edges().end();) {
182 if (
I->getOffset() < SplitIndex) {
183 NewBlock.addEdge(*
I);
186 I->setOffset(
I->getOffset() - SplitIndex);
197 Cache = &LocalBlockSymbolsCache;
198 if (*Cache == std::nullopt) {
199 *Cache = SplitBlockCache::value_type();
200 for (
auto *Sym :
B.getSection().symbols())
201 if (&Sym->getBlock() == &
B)
202 (*Cache)->push_back(Sym);
205 return LHS->getOffset() >
RHS->getOffset();
208 auto &BlockSymbols = **Cache;
211 while (!BlockSymbols.empty() &&
212 BlockSymbols.back()->getOffset() < SplitIndex) {
213 auto *Sym = BlockSymbols.back();
216 if (Sym->getOffset() + Sym->getSize() > SplitIndex)
217 Sym->setSize(SplitIndex - Sym->getOffset());
218 Sym->setBlock(NewBlock);
219 BlockSymbols.pop_back();
223 for (
auto *Sym : BlockSymbols)
224 Sym->setOffset(Sym->getOffset() - SplitIndex);
234 for (
auto *Sym : defined_symbols())
235 BlockSymbols[&Sym->getBlock()].push_back(Sym);
239 for (
auto &KV : BlockSymbols)
241 if (LHS->getOffset() != RHS->getOffset())
242 return LHS->getOffset() < RHS->getOffset();
243 if (LHS->getLinkage() != RHS->getLinkage())
244 return LHS->getLinkage() < RHS->getLinkage();
245 if (LHS->getScope() != RHS->getScope())
246 return LHS->getScope() < RHS->getScope();
247 if (LHS->hasName()) {
250 return LHS->getName() < RHS->getName();
255 for (
auto &Sec : sections()) {
256 OS <<
"section " << Sec.getName() <<
":\n\n";
258 std::vector<Block *> SortedBlocks;
259 llvm::copy(Sec.blocks(), std::back_inserter(SortedBlocks));
261 return LHS->getAddress() <
RHS->getAddress();
264 for (
auto *
B : SortedBlocks) {
265 OS <<
" block " <<
B->getAddress()
266 <<
" size = " <<
formatv(
"{0:x8}",
B->getSize())
267 <<
", align = " <<
B->getAlignment()
268 <<
", alignment-offset = " <<
B->getAlignmentOffset();
273 auto BlockSymsI = BlockSymbols.find(
B);
274 if (BlockSymsI != BlockSymbols.end()) {
276 auto &Syms = BlockSymsI->second;
277 for (
auto *Sym : Syms)
278 OS <<
" " << *Sym <<
"\n";
280 OS <<
" no symbols\n";
282 if (!
B->edges_empty()) {
284 std::vector<Edge> SortedEdges;
285 llvm::copy(
B->edges(), std::back_inserter(SortedEdges));
287 return LHS.getOffset() <
RHS.getOffset();
289 for (
auto &
E : SortedEdges) {
290 OS <<
" " <<
B->getFixupAddress(
E) <<
" (block + "
291 <<
formatv(
"{0:x8}",
E.getOffset()) <<
"), addend = ";
292 if (
E.getAddend() >= 0)
293 OS <<
formatv(
"+{0:x8}",
E.getAddend());
295 OS <<
formatv(
"-{0:x8}", -
E.getAddend());
297 if (
E.getTarget().hasName())
298 OS <<
E.getTarget().getName();
301 <<
formatv(
"{0:x16}",
E.getTarget().getAddress()) <<
"+"
302 <<
formatv(
"{0:x8}",
E.getTarget().getOffset());
311 OS <<
"Absolute symbols:\n";
312 if (!absolute_symbols().empty()) {
313 for (
auto *Sym : absolute_symbols())
314 OS <<
" " << Sym->getAddress() <<
": " << *Sym <<
"\n";
318 OS <<
"\nExternal symbols:\n";
319 if (!external_symbols().empty()) {
320 for (
auto *Sym : external_symbols())
321 OS <<
" " << Sym->getAddress() <<
": " << *Sym <<
"\n";
328 case SymbolLookupFlags::RequiredSymbol:
329 return OS <<
"RequiredSymbol";
330 case SymbolLookupFlags::WeaklyReferencedSymbol:
331 return OS <<
"WeaklyReferencedSymbol";
336 void JITLinkAsyncLookupContinuation::anchor() {}
338 JITLinkContext::~JITLinkContext() =
default;
340 bool JITLinkContext::shouldAddDefaultTargetPasses(
const Triple &TT)
const {
354 for (
auto *Sym :
G.defined_symbols())
365 ErrStream <<
"In graph " <<
G.getName() <<
", section " << Sec.
getName()
366 <<
": relocation target ";
367 if (
E.getTarget().hasName()) {
368 ErrStream <<
"\"" <<
E.getTarget().getName() <<
"\"";
370 ErrStream <<
E.getTarget().getBlock().getSection().getName() <<
" + "
372 ErrStream <<
" at address " <<
formatv(
"{0:x}",
E.getTarget().getAddress())
373 <<
" is out of range of " <<
G.getEdgeKindName(
E.getKind())
374 <<
" fixup at " <<
formatv(
"{0:x}",
B.getFixupAddress(
E)) <<
" (";
376 Symbol *BestSymbolForBlock =
nullptr;
377 for (
auto *Sym : Sec.
symbols())
378 if (&Sym->getBlock() == &
B && Sym->hasName() && Sym->getOffset() == 0 &&
379 (!BestSymbolForBlock ||
381 Sym->getLinkage() < BestSymbolForBlock->
getLinkage()))
382 BestSymbolForBlock = Sym;
384 if (BestSymbolForBlock)
385 ErrStream << BestSymbolForBlock->
getName() <<
", ";
387 ErrStream <<
"<anonymous block> @ ";
389 ErrStream <<
formatv(
"{0:x}",
B.getAddress()) <<
" + "
390 <<
formatv(
"{0:x}",
E.getOffset()) <<
")";
392 return make_error<JITLinkError>(
std::move(ErrMsg));
397 return make_error<JITLinkError>(
"0x" + llvm::utohexstr(Loc.
getValue()) +
398 " improper alignment for relocation " +
399 formatv(
"{0:d}",
E.getKind()) +
": 0x" +
400 llvm::utohexstr(
Value) +
401 " is not aligned to " +
Twine(
N) +
" bytes");
415 return make_error<JITLinkError>(
"Unsupported file format");
419 void link(std::unique_ptr<LinkGraph>
G, std::unique_ptr<JITLinkContext> Ctx) {
420 switch (
G->getTargetTriple().getObjectFormat()) {
428 Ctx->notifyFailed(make_error<JITLinkError>(
"Unsupported object format"));
Represents an address in the executor process.
StringRef getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
This is an optimization pass for GlobalISel generic memory operations.
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.
SymbolLookupFlags
Flags for symbol lookup.
A raw_ostream that writes to an std::string.
bool isDefined() const
Returns true if this Symbol has content (potentially) defined within this object file (i....
void link_COFF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from the given object buffer.
static ErrorSuccess success()
Create a success value.
Triple - Helper class for working with autoconf configuration names.
uint64_t getValue() const
An Addressable with content and edges.
OutputIt copy(R &&Range, OutputIt Out)
void link_ELF(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
static void splitBlock(MachineBasicBlock &MBB, MachineInstr &MI, MachineDominatorTree *MDT)
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Tagged union holding either a T or a Error.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
orc::ExecutorAddrDiff getSize() const
Returns the size of this symbol.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This class implements an extremely fast bulk output stream that can only output to a stream.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
bool isLive() const
Returns true if this symbol is live (i.e.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an COFF relocatable object.
const char * getScopeName(Scope S)
For debugging output.
@ elf_relocatable
ELF Relocatable object file.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF relocatable object.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & operator<<(raw_ostream &OS, const SectionedAddress &Addr)
static std::string getLinkageName(GlobalValue::LinkageTypes LT)
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
@ coff_object
COFF object file.
message(STATUS "Targeting ${t}") add_subdirectory($
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool hasName() const
Returns true if this symbol has a name.
StringRef getBuffer() const
iterator_range< symbol_iterator > symbols()
Returns an iterator over the symbols defined in this section.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from a MachO relocatable object.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
StringRef - Represent a constant reference to a string, i.e.
static const char Magic[]
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Represents fixups and constraints in the LinkGraph.
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
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.
Linkage
Describes symbol linkage.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Represents an object file section.
Lightweight error class with error context and mandatory checking.
StringRef getName() const
Returns the name of this section.
orc::ExecutorAddrDiff getOffset() const
Returns the offset for this symbol within the underlying addressable.
std::function< Error(LinkGraph &)> LinkGraphPassFunction
A function for mutating LinkGraphs.
Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, const Edge &E)
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Scope getScope() const
Get the visibility for this Symbol.
LLVM Value Representation.
std::optional< SmallVector< Symbol *, 8 > > SplitBlockCache
Cache type for the splitBlock function.
@ macho_object
Mach-O Object file.
Linkage getLinkage() const
Get the linkage for this Symbol.