1 //===--------- JITLinkGeneric.cpp - Generic JIT linker utilities ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // Generic JITLinker utility class.
11 //===----------------------------------------------------------------------===//
13 #include "JITLinkGeneric.h"
15 #include "llvm/Support/BinaryStreamReader.h"
16 #include "llvm/Support/MemoryBuffer.h"
18 #define DEBUG_TYPE "jitlink"
23 JITLinkerBase::~JITLinkerBase() {}
25 void JITLinkerBase::linkPhase1(std::unique_ptr
<JITLinkerBase
> Self
) {
28 dbgs() << "Starting link phase 1 for graph " << G
->getName() << "\n";
31 // Prune and optimize the graph.
32 if (auto Err
= runPasses(Passes
.PrePrunePasses
))
33 return Ctx
->notifyFailed(std::move(Err
));
36 dbgs() << "Link graph \"" << G
->getName() << "\" pre-pruning:\n";
43 dbgs() << "Link graph \"" << G
->getName() << "\" post-pruning:\n";
47 // Run post-pruning passes.
48 if (auto Err
= runPasses(Passes
.PostPrunePasses
))
49 return Ctx
->notifyFailed(std::move(Err
));
51 // Sort blocks into segments.
52 auto Layout
= layOutBlocks();
54 // Allocate memory for segments.
55 if (auto Err
= allocateSegments(Layout
))
56 return Ctx
->notifyFailed(std::move(Err
));
59 dbgs() << "Link graph \"" << G
->getName()
60 << "\" before post-allocation passes:\n";
64 // Run post-allocation passes.
65 if (auto Err
= runPasses(Passes
.PostAllocationPasses
))
66 return Ctx
->notifyFailed(std::move(Err
));
68 // Notify client that the defined symbols have been assigned addresses.
69 LLVM_DEBUG(dbgs() << "Resolving symbols defined in " << G
->getName() << "\n");
71 if (auto Err
= Ctx
->notifyResolved(*G
))
72 return Ctx
->notifyFailed(std::move(Err
));
74 auto ExternalSymbols
= getExternalSymbolNames();
76 // If there are no external symbols then proceed immediately with phase 2.
77 if (ExternalSymbols
.empty()) {
79 dbgs() << "No external symbols for " << G
->getName()
80 << ". Proceeding immediately with link phase 2.\n";
82 // FIXME: Once callee expressions are defined to be sequenced before
83 // argument expressions (c++17) we can simplify this. See below.
84 auto &TmpSelf
= *Self
;
85 TmpSelf
.linkPhase2(std::move(Self
), AsyncLookupResult(), std::move(Layout
));
89 // Otherwise look up the externals.
91 dbgs() << "Issuing lookup for external symbols for " << G
->getName()
92 << " (may trigger materialization/linking of other graphs)...\n";
95 // We're about to hand off ownership of ourself to the continuation. Grab a
96 // pointer to the context so that we can call it to initiate the lookup.
98 // FIXME: Once callee expressions are defined to be sequenced before argument
99 // expressions (c++17) we can simplify all this to:
101 // Ctx->lookup(std::move(UnresolvedExternals),
102 // [Self=std::move(Self)](Expected<AsyncLookupResult> Result) {
103 // Self->linkPhase2(std::move(Self), std::move(Result));
105 auto *TmpCtx
= Ctx
.get();
106 TmpCtx
->lookup(std::move(ExternalSymbols
),
107 createLookupContinuation(
108 [S
= std::move(Self
), L
= std::move(Layout
)](
109 Expected
<AsyncLookupResult
> LookupResult
) mutable {
111 TmpSelf
.linkPhase2(std::move(S
), std::move(LookupResult
),
116 void JITLinkerBase::linkPhase2(std::unique_ptr
<JITLinkerBase
> Self
,
117 Expected
<AsyncLookupResult
> LR
,
118 SegmentLayoutMap Layout
) {
121 dbgs() << "Starting link phase 2 for graph " << G
->getName() << "\n";
124 // If the lookup failed, bail out.
126 return deallocateAndBailOut(LR
.takeError());
128 // Assign addresses to external addressables.
129 applyLookupResult(*LR
);
131 // Copy block content to working memory.
132 copyBlockContentToWorkingMemory(Layout
, *Alloc
);
135 dbgs() << "Link graph \"" << G
->getName()
136 << "\" before pre-fixup passes:\n";
140 if (auto Err
= runPasses(Passes
.PreFixupPasses
))
141 return deallocateAndBailOut(std::move(Err
));
144 dbgs() << "Link graph \"" << G
->getName() << "\" before copy-and-fixup:\n";
148 // Fix up block content.
149 if (auto Err
= fixUpBlocks(*G
))
150 return deallocateAndBailOut(std::move(Err
));
153 dbgs() << "Link graph \"" << G
->getName() << "\" after copy-and-fixup:\n";
157 if (auto Err
= runPasses(Passes
.PostFixupPasses
))
158 return deallocateAndBailOut(std::move(Err
));
160 // FIXME: Use move capture once we have c++14.
161 auto *UnownedSelf
= Self
.release();
162 auto Phase3Continuation
= [UnownedSelf
](Error Err
) {
163 std::unique_ptr
<JITLinkerBase
> Self(UnownedSelf
);
164 UnownedSelf
->linkPhase3(std::move(Self
), std::move(Err
));
167 Alloc
->finalizeAsync(std::move(Phase3Continuation
));
170 void JITLinkerBase::linkPhase3(std::unique_ptr
<JITLinkerBase
> Self
, Error Err
) {
173 dbgs() << "Starting link phase 3 for graph " << G
->getName() << "\n";
177 return deallocateAndBailOut(std::move(Err
));
178 Ctx
->notifyFinalized(std::move(Alloc
));
180 LLVM_DEBUG({ dbgs() << "Link of graph " << G
->getName() << " complete\n"; });
183 Error
JITLinkerBase::runPasses(LinkGraphPassList
&Passes
) {
184 for (auto &P
: Passes
)
185 if (auto Err
= P(*G
))
187 return Error::success();
190 JITLinkerBase::SegmentLayoutMap
JITLinkerBase::layOutBlocks() {
192 SegmentLayoutMap Layout
;
194 /// Partition blocks based on permissions and content vs. zero-fill.
195 for (auto *B
: G
->blocks()) {
196 auto &SegLists
= Layout
[B
->getSection().getProtectionFlags()];
197 if (!B
->isZeroFill())
198 SegLists
.ContentBlocks
.push_back(B
);
200 SegLists
.ZeroFillBlocks
.push_back(B
);
203 /// Sort blocks within each list.
204 for (auto &KV
: Layout
) {
206 auto CompareBlocks
= [](const Block
*LHS
, const Block
*RHS
) {
207 // Sort by section, address and size
208 if (LHS
->getSection().getOrdinal() != RHS
->getSection().getOrdinal())
209 return LHS
->getSection().getOrdinal() < RHS
->getSection().getOrdinal();
210 if (LHS
->getAddress() != RHS
->getAddress())
211 return LHS
->getAddress() < RHS
->getAddress();
212 return LHS
->getSize() < RHS
->getSize();
215 auto &SegLists
= KV
.second
;
216 llvm::sort(SegLists
.ContentBlocks
, CompareBlocks
);
217 llvm::sort(SegLists
.ZeroFillBlocks
, CompareBlocks
);
221 dbgs() << "Computed segment ordering:\n";
222 for (auto &KV
: Layout
) {
223 dbgs() << " Segment "
224 << static_cast<sys::Memory::ProtectionFlags
>(KV
.first
) << ":\n";
225 auto &SL
= KV
.second
;
227 {std::make_pair(&SL
.ContentBlocks
, "content block"),
228 std::make_pair(&SL
.ZeroFillBlocks
, "zero-fill block")}) {
229 dbgs() << " " << SIEntry
.second
<< ":\n";
230 for (auto *B
: *SIEntry
.first
)
231 dbgs() << " " << *B
<< "\n";
239 Error
JITLinkerBase::allocateSegments(const SegmentLayoutMap
&Layout
) {
241 // Compute segment sizes and allocate memory.
242 LLVM_DEBUG(dbgs() << "JIT linker requesting: { ");
243 JITLinkMemoryManager::SegmentsRequestMap Segments
;
244 for (auto &KV
: Layout
) {
245 auto &Prot
= KV
.first
;
246 auto &SegLists
= KV
.second
;
248 uint64_t SegAlign
= 1;
250 // Calculate segment content size.
251 size_t SegContentSize
= 0;
252 for (auto *B
: SegLists
.ContentBlocks
) {
253 SegAlign
= std::max(SegAlign
, B
->getAlignment());
254 SegContentSize
= alignToBlock(SegContentSize
, *B
);
255 SegContentSize
+= B
->getSize();
258 uint64_t SegZeroFillStart
= SegContentSize
;
259 uint64_t SegZeroFillEnd
= SegZeroFillStart
;
261 for (auto *B
: SegLists
.ZeroFillBlocks
) {
262 SegAlign
= std::max(SegAlign
, B
->getAlignment());
263 SegZeroFillEnd
= alignToBlock(SegZeroFillEnd
, *B
);
264 SegZeroFillEnd
+= B
->getSize();
267 Segments
[Prot
] = {SegAlign
, SegContentSize
,
268 SegZeroFillEnd
- SegZeroFillStart
};
271 dbgs() << (&KV
== &*Layout
.begin() ? "" : "; ")
272 << static_cast<sys::Memory::ProtectionFlags
>(Prot
)
273 << ": alignment = " << SegAlign
274 << ", content size = " << SegContentSize
275 << ", zero-fill size = " << (SegZeroFillEnd
- SegZeroFillStart
);
278 LLVM_DEBUG(dbgs() << " }\n");
280 if (auto AllocOrErr
=
281 Ctx
->getMemoryManager().allocate(Ctx
->getJITLinkDylib(), Segments
))
282 Alloc
= std::move(*AllocOrErr
);
284 return AllocOrErr
.takeError();
287 dbgs() << "JIT linker got memory (working -> target):\n";
288 for (auto &KV
: Layout
) {
289 auto Prot
= static_cast<sys::Memory::ProtectionFlags
>(KV
.first
);
290 dbgs() << " " << Prot
<< ": "
291 << (const void *)Alloc
->getWorkingMemory(Prot
).data() << " -> "
292 << formatv("{0:x16}", Alloc
->getTargetMemory(Prot
)) << "\n";
296 // Update block target addresses.
297 for (auto &KV
: Layout
) {
298 auto &Prot
= KV
.first
;
299 auto &SL
= KV
.second
;
301 JITTargetAddress NextBlockAddr
=
302 Alloc
->getTargetMemory(static_cast<sys::Memory::ProtectionFlags
>(Prot
));
304 for (auto *SIList
: {&SL
.ContentBlocks
, &SL
.ZeroFillBlocks
})
305 for (auto *B
: *SIList
) {
306 NextBlockAddr
= alignToBlock(NextBlockAddr
, *B
);
307 B
->setAddress(NextBlockAddr
);
308 NextBlockAddr
+= B
->getSize();
312 return Error::success();
315 JITLinkContext::LookupMap
JITLinkerBase::getExternalSymbolNames() const {
316 // Identify unresolved external symbols.
317 JITLinkContext::LookupMap UnresolvedExternals
;
318 for (auto *Sym
: G
->external_symbols()) {
319 assert(Sym
->getAddress() == 0 &&
320 "External has already been assigned an address");
321 assert(Sym
->getName() != StringRef() && Sym
->getName() != "" &&
322 "Externals must be named");
323 SymbolLookupFlags LookupFlags
=
324 Sym
->getLinkage() == Linkage::Weak
325 ? SymbolLookupFlags::WeaklyReferencedSymbol
326 : SymbolLookupFlags::RequiredSymbol
;
327 UnresolvedExternals
[Sym
->getName()] = LookupFlags
;
329 return UnresolvedExternals
;
332 void JITLinkerBase::applyLookupResult(AsyncLookupResult Result
) {
333 for (auto *Sym
: G
->external_symbols()) {
334 assert(Sym
->getOffset() == 0 &&
335 "External symbol is not at the start of its addressable block");
336 assert(Sym
->getAddress() == 0 && "Symbol already resolved");
337 assert(!Sym
->isDefined() && "Symbol being resolved is already defined");
338 auto ResultI
= Result
.find(Sym
->getName());
339 if (ResultI
!= Result
.end())
340 Sym
->getAddressable().setAddress(ResultI
->second
.getAddress());
342 assert(Sym
->getLinkage() == Linkage::Weak
&&
343 "Failed to resolve non-weak reference");
347 dbgs() << "Externals after applying lookup result:\n";
348 for (auto *Sym
: G
->external_symbols())
349 dbgs() << " " << Sym
->getName() << ": "
350 << formatv("{0:x16}", Sym
->getAddress()) << "\n";
354 void JITLinkerBase::copyBlockContentToWorkingMemory(
355 const SegmentLayoutMap
&Layout
, JITLinkMemoryManager::Allocation
&Alloc
) {
357 LLVM_DEBUG(dbgs() << "Copying block content:\n");
358 for (auto &KV
: Layout
) {
359 auto &Prot
= KV
.first
;
360 auto &SegLayout
= KV
.second
;
363 Alloc
.getWorkingMemory(static_cast<sys::Memory::ProtectionFlags
>(Prot
));
364 char *LastBlockEnd
= SegMem
.data();
365 char *BlockDataPtr
= LastBlockEnd
;
368 dbgs() << " Processing segment "
369 << static_cast<sys::Memory::ProtectionFlags
>(Prot
) << " [ "
370 << (const void *)SegMem
.data() << " .. "
371 << (const void *)((char *)SegMem
.data() + SegMem
.size())
372 << " ]\n Processing content sections:\n";
375 for (auto *B
: SegLayout
.ContentBlocks
) {
376 LLVM_DEBUG(dbgs() << " " << *B
<< ":\n");
378 // Pad to alignment/alignment-offset.
379 BlockDataPtr
= alignToBlock(BlockDataPtr
, *B
);
382 dbgs() << " Bumped block pointer to " << (const void *)BlockDataPtr
383 << " to meet block alignment " << B
->getAlignment()
384 << " and alignment offset " << B
->getAlignmentOffset() << "\n";
387 // Zero pad up to alignment.
389 if (LastBlockEnd
!= BlockDataPtr
)
390 dbgs() << " Zero padding from " << (const void *)LastBlockEnd
391 << " to " << (const void *)BlockDataPtr
<< "\n";
394 while (LastBlockEnd
!= BlockDataPtr
)
397 // Copy initial block content.
399 dbgs() << " Copying block " << *B
<< " content, "
400 << B
->getContent().size() << " bytes, from "
401 << (const void *)B
->getContent().data() << " to "
402 << (const void *)BlockDataPtr
<< "\n";
404 memcpy(BlockDataPtr
, B
->getContent().data(), B
->getContent().size());
406 // Point the block's content to the fixed up buffer.
407 B
->setMutableContent({BlockDataPtr
, B
->getContent().size()});
409 // Update block end pointer.
410 LastBlockEnd
= BlockDataPtr
+ B
->getContent().size();
411 BlockDataPtr
= LastBlockEnd
;
414 // Zero pad the rest of the segment.
416 dbgs() << " Zero padding end of segment from "
417 << (const void *)LastBlockEnd
<< " to "
418 << (const void *)((char *)SegMem
.data() + SegMem
.size()) << "\n";
420 while (LastBlockEnd
!= SegMem
.data() + SegMem
.size())
425 void JITLinkerBase::deallocateAndBailOut(Error Err
) {
426 assert(Err
&& "Should not be bailing out on success value");
427 assert(Alloc
&& "can not call deallocateAndBailOut before allocation");
428 Ctx
->notifyFailed(joinErrors(std::move(Err
), Alloc
->deallocate()));
431 void prune(LinkGraph
&G
) {
432 std::vector
<Symbol
*> Worklist
;
433 DenseSet
<Block
*> VisitedBlocks
;
435 // Build the initial worklist from all symbols initially live.
436 for (auto *Sym
: G
.defined_symbols())
438 Worklist
.push_back(Sym
);
440 // Propagate live flags to all symbols reachable from the initial live set.
441 while (!Worklist
.empty()) {
442 auto *Sym
= Worklist
.back();
445 auto &B
= Sym
->getBlock();
447 // Skip addressables that we've visited before.
448 if (VisitedBlocks
.count(&B
))
451 VisitedBlocks
.insert(&B
);
453 for (auto &E
: Sym
->getBlock().edges()) {
454 // If the edge target is a defined symbol that is being newly marked live
455 // then add it to the worklist.
456 if (E
.getTarget().isDefined() && !E
.getTarget().isLive())
457 Worklist
.push_back(&E
.getTarget());
459 // Mark the target live.
460 E
.getTarget().setLive(true);
464 // Collect all defined symbols to remove, then remove them.
466 LLVM_DEBUG(dbgs() << "Dead-stripping defined symbols:\n");
467 std::vector
<Symbol
*> SymbolsToRemove
;
468 for (auto *Sym
: G
.defined_symbols())
470 SymbolsToRemove
.push_back(Sym
);
471 for (auto *Sym
: SymbolsToRemove
) {
472 LLVM_DEBUG(dbgs() << " " << *Sym
<< "...\n");
473 G
.removeDefinedSymbol(*Sym
);
477 // Delete any unused blocks.
479 LLVM_DEBUG(dbgs() << "Dead-stripping blocks:\n");
480 std::vector
<Block
*> BlocksToRemove
;
481 for (auto *B
: G
.blocks())
482 if (!VisitedBlocks
.count(B
))
483 BlocksToRemove
.push_back(B
);
484 for (auto *B
: BlocksToRemove
) {
485 LLVM_DEBUG(dbgs() << " " << *B
<< "...\n");
490 // Collect all external symbols to remove, then remove them.
492 LLVM_DEBUG(dbgs() << "Removing unused external symbols:\n");
493 std::vector
<Symbol
*> SymbolsToRemove
;
494 for (auto *Sym
: G
.external_symbols())
496 SymbolsToRemove
.push_back(Sym
);
497 for (auto *Sym
: SymbolsToRemove
) {
498 LLVM_DEBUG(dbgs() << " " << *Sym
<< "...\n");
499 G
.removeExternalSymbol(*Sym
);
504 } // end namespace jitlink
505 } // end namespace llvm