LLVM 17.0.0git
JITLink.cpp
Go to the documentation of this file.
1//===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
15#include "llvm/Support/Format.h"
18
19using namespace llvm;
20using namespace llvm::object;
21
22#define DEBUG_TYPE "jitlink"
23
24namespace {
25
26enum JITLinkErrorCode { GenericJITLinkError = 1 };
27
28// FIXME: This class is only here to support the transition to llvm::Error. It
29// will be removed once this transition is complete. Clients should prefer to
30// deal with the Error value directly, rather than converting to error_code.
31class JITLinkerErrorCategory : public std::error_category {
32public:
33 const char *name() const noexcept override { return "runtimedyld"; }
34
35 std::string message(int Condition) const override {
36 switch (static_cast<JITLinkErrorCode>(Condition)) {
37 case GenericJITLinkError:
38 return "Generic JITLink error";
39 }
40 llvm_unreachable("Unrecognized JITLinkErrorCode");
41 }
42};
43
44} // namespace
45
46namespace llvm {
47namespace jitlink {
48
49char JITLinkError::ID = 0;
50
51void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg; }
52
53std::error_code JITLinkError::convertToErrorCode() const {
54 static JITLinkerErrorCategory TheJITLinkerErrorCategory;
55 return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
56}
57
59 switch (K) {
60 case Edge::Invalid:
61 return "INVALID RELOCATION";
62 case Edge::KeepAlive:
63 return "Keep-Alive";
64 default:
65 return "<Unrecognized edge kind>";
66 }
67}
68
69const char *getLinkageName(Linkage L) {
70 switch (L) {
71 case Linkage::Strong:
72 return "strong";
73 case Linkage::Weak:
74 return "weak";
75 }
76 llvm_unreachable("Unrecognized llvm.jitlink.Linkage enum");
77}
78
79const char *getScopeName(Scope S) {
80 switch (S) {
81 case Scope::Default:
82 return "default";
83 case Scope::Hidden:
84 return "hidden";
85 case Scope::Local:
86 return "local";
87 }
88 llvm_unreachable("Unrecognized llvm.jitlink.Scope enum");
89}
90
92 if (B.getSize() == 0) // Empty blocks are not valid C-strings.
93 return false;
94
95 // Zero-fill blocks of size one are valid empty strings.
96 if (B.isZeroFill())
97 return B.getSize() == 1;
98
99 for (size_t I = 0; I != B.getSize() - 1; ++I)
100 if (B.getContent()[I] == '\0')
101 return false;
102
103 return B.getContent()[B.getSize() - 1] == '\0';
104}
105
107 return OS << B.getAddress() << " -- " << (B.getAddress() + B.getSize())
108 << ": "
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();
114}
115
117 OS << Sym.getAddress() << " (" << (Sym.isDefined() ? "block" : "addressable")
118 << " + " << formatv("{0:x8}", Sym.getOffset())
119 << "): size: " << formatv("{0:x8}", Sym.getSize())
120 << ", linkage: " << formatv("{0:6}", getLinkageName(Sym.getLinkage()))
121 << ", scope: " << formatv("{0:8}", getScopeName(Sym.getScope())) << ", "
122 << (Sym.isLive() ? "live" : "dead") << " - "
123 << (Sym.hasName() ? Sym.getName() : "<anonymous symbol>");
124 return OS;
125}
126
127void printEdge(raw_ostream &OS, const Block &B, const Edge &E,
128 StringRef EdgeKindName) {
129 OS << "edge@" << B.getAddress() + E.getOffset() << ": " << B.getAddress()
130 << " + " << formatv("{0:x}", E.getOffset()) << " -- " << EdgeKindName
131 << " -> ";
132
133 auto &TargetSym = E.getTarget();
134 if (TargetSym.hasName())
135 OS << TargetSym.getName();
136 else {
137 auto &TargetBlock = TargetSym.getBlock();
138 auto &TargetSec = TargetBlock.getSection();
139 orc::ExecutorAddr SecAddress(~uint64_t(0));
140 for (auto *B : TargetSec.blocks())
141 if (B->getAddress() < SecAddress)
142 SecAddress = B->getAddress();
143
144 orc::ExecutorAddrDiff SecDelta = TargetSym.getAddress() - SecAddress;
145 OS << TargetSym.getAddress() << " (section " << TargetSec.getName();
146 if (SecDelta)
147 OS << " + " << formatv("{0:x}", SecDelta);
148 OS << " / block " << TargetBlock.getAddress();
149 if (TargetSym.getOffset())
150 OS << " + " << formatv("{0:x}", TargetSym.getOffset());
151 OS << ")";
152 }
153
154 if (E.getAddend() != 0)
155 OS << " + " << E.getAddend();
156}
157
159 for (auto *Sym : Symbols)
160 Sym->~Symbol();
161 for (auto *B : Blocks)
162 B->~Block();
163}
164
165Block &LinkGraph::splitBlock(Block &B, size_t SplitIndex,
166 SplitBlockCache *Cache) {
167
168 assert(SplitIndex > 0 && "splitBlock can not be called with SplitIndex == 0");
169
170 // If the split point covers all of B then just return B.
171 if (SplitIndex == B.getSize())
172 return B;
173
174 assert(SplitIndex < B.getSize() && "SplitIndex out of range");
175
176 // Create the new block covering [ 0, SplitIndex ).
177 auto &NewBlock =
178 B.isZeroFill()
179 ? createZeroFillBlock(B.getSection(), SplitIndex, B.getAddress(),
180 B.getAlignment(), B.getAlignmentOffset())
182 B.getSection(), B.getContent().slice(0, SplitIndex),
183 B.getAddress(), B.getAlignment(), B.getAlignmentOffset());
184
185 // Modify B to cover [ SplitIndex, B.size() ).
186 B.setAddress(B.getAddress() + SplitIndex);
187 B.setContent(B.getContent().slice(SplitIndex));
188 B.setAlignmentOffset((B.getAlignmentOffset() + SplitIndex) %
189 B.getAlignment());
190
191 // Handle edge transfer/update.
192 {
193 // Copy edges to NewBlock (recording their iterators so that we can remove
194 // them from B), and update of Edges remaining on B.
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);
199 I = B.removeEdge(I);
200 } else {
201 I->setOffset(I->getOffset() - SplitIndex);
202 ++I;
203 }
204 }
205 }
206
207 // Handle symbol transfer/update.
208 {
209 // Initialize the symbols cache if necessary.
210 SplitBlockCache LocalBlockSymbolsCache;
211 if (!Cache)
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);
218
219 llvm::sort(**Cache, [](const Symbol *LHS, const Symbol *RHS) {
220 return LHS->getOffset() > RHS->getOffset();
221 });
222 }
223 auto &BlockSymbols = **Cache;
224
225 // Transfer all symbols with offset less than SplitIndex to NewBlock.
226 while (!BlockSymbols.empty() &&
227 BlockSymbols.back()->getOffset() < SplitIndex) {
228 auto *Sym = BlockSymbols.back();
229 // If the symbol extends beyond the split, update the size to be within
230 // the new block.
231 if (Sym->getOffset() + Sym->getSize() > SplitIndex)
232 Sym->setSize(SplitIndex - Sym->getOffset());
233 Sym->setBlock(NewBlock);
234 BlockSymbols.pop_back();
235 }
236
237 // Update offsets for all remaining symbols in B.
238 for (auto *Sym : BlockSymbols)
239 Sym->setOffset(Sym->getOffset() - SplitIndex);
240 }
241
242 return NewBlock;
243}
244
247
248 // Map from blocks to the symbols pointing at them.
249 for (auto *Sym : defined_symbols())
250 BlockSymbols[&Sym->getBlock()].push_back(Sym);
251
252 // For each block, sort its symbols by something approximating
253 // relevance.
254 for (auto &KV : BlockSymbols)
255 llvm::sort(KV.second, [](const Symbol *LHS, const Symbol *RHS) {
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()) {
263 if (!RHS->hasName())
264 return true;
265 return LHS->getName() < RHS->getName();
266 }
267 return false;
268 });
269
270 for (auto &Sec : sections()) {
271 OS << "section " << Sec.getName() << ":\n\n";
272
273 std::vector<Block *> SortedBlocks;
274 llvm::copy(Sec.blocks(), std::back_inserter(SortedBlocks));
275 llvm::sort(SortedBlocks, [](const Block *LHS, const Block *RHS) {
276 return LHS->getAddress() < RHS->getAddress();
277 });
278
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();
284 if (B->isZeroFill())
285 OS << ", zero-fill";
286 OS << "\n";
287
288 auto BlockSymsI = BlockSymbols.find(B);
289 if (BlockSymsI != BlockSymbols.end()) {
290 OS << " symbols:\n";
291 auto &Syms = BlockSymsI->second;
292 for (auto *Sym : Syms)
293 OS << " " << *Sym << "\n";
294 } else
295 OS << " no symbols\n";
296
297 if (!B->edges_empty()) {
298 OS << " edges:\n";
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();
303 });
304 for (auto &E : SortedEdges) {
305 OS << " " << B->getFixupAddress(E) << " (block + "
306 << formatv("{0:x8}", E.getOffset()) << "), addend = ";
307 if (E.getAddend() >= 0)
308 OS << formatv("+{0:x8}", E.getAddend());
309 else
310 OS << formatv("-{0:x8}", -E.getAddend());
311 OS << ", kind = " << getEdgeKindName(E.getKind()) << ", target = ";
312 if (E.getTarget().hasName())
313 OS << E.getTarget().getName();
314 else
315 OS << "addressable@"
316 << formatv("{0:x16}", E.getTarget().getAddress()) << "+"
317 << formatv("{0:x8}", E.getTarget().getOffset());
318 OS << "\n";
319 }
320 } else
321 OS << " no edges\n";
322 OS << "\n";
323 }
324 }
325
326 OS << "Absolute symbols:\n";
327 if (!absolute_symbols().empty()) {
328 for (auto *Sym : absolute_symbols())
329 OS << " " << Sym->getAddress() << ": " << *Sym << "\n";
330 } else
331 OS << " none\n";
332
333 OS << "\nExternal symbols:\n";
334 if (!external_symbols().empty()) {
335 for (auto *Sym : external_symbols())
336 OS << " " << Sym->getAddress() << ": " << *Sym << "\n";
337 } else
338 OS << " none\n";
339}
340
342 switch (LF) {
343 case SymbolLookupFlags::RequiredSymbol:
344 return OS << "RequiredSymbol";
345 case SymbolLookupFlags::WeaklyReferencedSymbol:
346 return OS << "WeaklyReferencedSymbol";
347 }
348 llvm_unreachable("Unrecognized lookup flags");
349}
350
351void JITLinkAsyncLookupContinuation::anchor() {}
352
353JITLinkContext::~JITLinkContext() = default;
354
355bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const {
356 return true;
357}
358
359LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const {
360 return LinkGraphPassFunction();
361}
362
363Error JITLinkContext::modifyPassConfig(LinkGraph &G,
365 return Error::success();
366}
367
369 for (auto *Sym : G.defined_symbols())
370 Sym->setLive(true);
371 return Error::success();
372}
373
375 const Edge &E) {
376 std::string ErrMsg;
377 {
378 raw_string_ostream ErrStream(ErrMsg);
379 Section &Sec = B.getSection();
380 ErrStream << "In graph " << G.getName() << ", section " << Sec.getName()
381 << ": relocation target ";
382 if (E.getTarget().hasName()) {
383 ErrStream << "\"" << E.getTarget().getName() << "\"";
384 } else
385 ErrStream << E.getTarget().getBlock().getSection().getName() << " + "
386 << formatv("{0:x}", E.getOffset());
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)) << " (";
390
391 Symbol *BestSymbolForBlock = nullptr;
392 for (auto *Sym : Sec.symbols())
393 if (&Sym->getBlock() == &B && Sym->hasName() && Sym->getOffset() == 0 &&
394 (!BestSymbolForBlock ||
395 Sym->getScope() < BestSymbolForBlock->getScope() ||
396 Sym->getLinkage() < BestSymbolForBlock->getLinkage()))
397 BestSymbolForBlock = Sym;
398
399 if (BestSymbolForBlock)
400 ErrStream << BestSymbolForBlock->getName() << ", ";
401 else
402 ErrStream << "<anonymous block> @ ";
403
404 ErrStream << formatv("{0:x}", B.getAddress()) << " + "
405 << formatv("{0:x}", E.getOffset()) << ")";
406 }
407 return make_error<JITLinkError>(std::move(ErrMsg));
408}
409
411 const Edge &E) {
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");
417}
418
421 auto Magic = identify_magic(ObjectBuffer.getBuffer());
422 switch (Magic) {
424 return createLinkGraphFromMachOObject(ObjectBuffer);
426 return createLinkGraphFromELFObject(ObjectBuffer);
428 return createLinkGraphFromCOFFObject(ObjectBuffer);
429 default:
430 return make_error<JITLinkError>("Unsupported file format");
431 };
432}
433
434void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
435 switch (G->getTargetTriple().getObjectFormat()) {
436 case Triple::MachO:
437 return link_MachO(std::move(G), std::move(Ctx));
438 case Triple::ELF:
439 return link_ELF(std::move(G), std::move(Ctx));
440 case Triple::COFF:
441 return link_COFF(std::move(G), std::move(Ctx));
442 default:
443 Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
444 };
445}
446
447} // end namespace jitlink
448} // end namespace llvm
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
RelaxConfig Config
Definition: ELF_riscv.cpp:490
Symbol * Sym
Definition: ELF_riscv.cpp:463
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
Definition: SMEABIPass.cpp:49
raw_pwrite_stream & OS
Value * RHS
Value * LHS
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
StringRef getBuffer() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM Value Representation.
Definition: Value.h:74
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.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:642
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.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:33
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)
Definition: STLExtras.h:1744
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:292
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1921
#define N
@ elf_relocatable
ELF Relocatable object file.
Definition: Magic.h:26
@ macho_object
Mach-O Object file.
Definition: Magic.h:31
@ coff_object
COFF object file.
Definition: Magic.h:46