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
) {
27 // Build the link graph.
28 if (auto GraphOrErr
= buildGraph(Ctx
->getObjectBuffer()))
29 G
= std::move(*GraphOrErr
);
31 return Ctx
->notifyFailed(GraphOrErr
.takeError());
32 assert(G
&& "Graph should have been created by buildGraph above");
34 // Prune and optimize the graph.
35 if (auto Err
= runPasses(Passes
.PrePrunePasses
))
36 return Ctx
->notifyFailed(std::move(Err
));
39 dbgs() << "Link graph \"" << G
->getName() << "\" pre-pruning:\n";
46 dbgs() << "Link graph \"" << G
->getName() << "\" post-pruning:\n";
50 // Run post-pruning passes.
51 if (auto Err
= runPasses(Passes
.PostPrunePasses
))
52 return Ctx
->notifyFailed(std::move(Err
));
54 // Sort blocks into segments.
55 auto Layout
= layOutBlocks();
57 // Allocate memory for segments.
58 if (auto Err
= allocateSegments(Layout
))
59 return Ctx
->notifyFailed(std::move(Err
));
61 // Notify client that the defined symbols have been assigned addresses.
62 Ctx
->notifyResolved(*G
);
64 auto ExternalSymbols
= getExternalSymbolNames();
66 // We're about to hand off ownership of ourself to the continuation. Grab a
67 // pointer to the context so that we can call it to initiate the lookup.
69 // FIXME: Once callee expressions are defined to be sequenced before argument
70 // expressions (c++17) we can simplify all this to:
72 // Ctx->lookup(std::move(UnresolvedExternals),
73 // [Self=std::move(Self)](Expected<AsyncLookupResult> Result) {
74 // Self->linkPhase2(std::move(Self), std::move(Result));
76 auto *TmpCtx
= Ctx
.get();
77 TmpCtx
->lookup(std::move(ExternalSymbols
),
78 createLookupContinuation(
79 [S
= std::move(Self
), L
= std::move(Layout
)](
80 Expected
<AsyncLookupResult
> LookupResult
) mutable {
82 TmpSelf
.linkPhase2(std::move(S
), std::move(LookupResult
),
87 void JITLinkerBase::linkPhase2(std::unique_ptr
<JITLinkerBase
> Self
,
88 Expected
<AsyncLookupResult
> LR
,
89 SegmentLayoutMap Layout
) {
90 // If the lookup failed, bail out.
92 return deallocateAndBailOut(LR
.takeError());
94 // Assign addresses to external addressables.
95 applyLookupResult(*LR
);
98 dbgs() << "Link graph \"" << G
->getName() << "\" before copy-and-fixup:\n";
102 // Copy block content to working memory and fix up.
103 if (auto Err
= copyAndFixUpBlocks(Layout
, *Alloc
))
104 return deallocateAndBailOut(std::move(Err
));
107 dbgs() << "Link graph \"" << G
->getName() << "\" after copy-and-fixup:\n";
111 if (auto Err
= runPasses(Passes
.PostFixupPasses
))
112 return deallocateAndBailOut(std::move(Err
));
114 // FIXME: Use move capture once we have c++14.
115 auto *UnownedSelf
= Self
.release();
116 auto Phase3Continuation
= [UnownedSelf
](Error Err
) {
117 std::unique_ptr
<JITLinkerBase
> Self(UnownedSelf
);
118 UnownedSelf
->linkPhase3(std::move(Self
), std::move(Err
));
121 Alloc
->finalizeAsync(std::move(Phase3Continuation
));
124 void JITLinkerBase::linkPhase3(std::unique_ptr
<JITLinkerBase
> Self
, Error Err
) {
126 return deallocateAndBailOut(std::move(Err
));
127 Ctx
->notifyFinalized(std::move(Alloc
));
130 Error
JITLinkerBase::runPasses(LinkGraphPassList
&Passes
) {
131 for (auto &P
: Passes
)
132 if (auto Err
= P(*G
))
134 return Error::success();
137 JITLinkerBase::SegmentLayoutMap
JITLinkerBase::layOutBlocks() {
139 SegmentLayoutMap Layout
;
141 /// Partition blocks based on permissions and content vs. zero-fill.
142 for (auto *B
: G
->blocks()) {
143 auto &SegLists
= Layout
[B
->getSection().getProtectionFlags()];
144 if (!B
->isZeroFill())
145 SegLists
.ContentBlocks
.push_back(B
);
147 SegLists
.ZeroFillBlocks
.push_back(B
);
150 /// Sort blocks within each list.
151 for (auto &KV
: Layout
) {
153 auto CompareBlocks
= [](const Block
*LHS
, const Block
*RHS
) {
154 if (LHS
->getSection().getOrdinal() != RHS
->getSection().getOrdinal())
155 return LHS
->getSection().getOrdinal() < RHS
->getSection().getOrdinal();
156 return LHS
->getOrdinal() < RHS
->getOrdinal();
159 auto &SegLists
= KV
.second
;
160 llvm::sort(SegLists
.ContentBlocks
, CompareBlocks
);
161 llvm::sort(SegLists
.ZeroFillBlocks
, CompareBlocks
);
165 dbgs() << "Segment ordering:\n";
166 for (auto &KV
: Layout
) {
167 dbgs() << " Segment "
168 << static_cast<sys::Memory::ProtectionFlags
>(KV
.first
) << ":\n";
169 auto &SL
= KV
.second
;
171 {std::make_pair(&SL
.ContentBlocks
, "content block"),
172 std::make_pair(&SL
.ZeroFillBlocks
, "zero-fill block")}) {
173 dbgs() << " " << SIEntry
.second
<< ":\n";
174 for (auto *B
: *SIEntry
.first
)
175 dbgs() << " " << *B
<< "\n";
183 Error
JITLinkerBase::allocateSegments(const SegmentLayoutMap
&Layout
) {
185 // Compute segment sizes and allocate memory.
186 LLVM_DEBUG(dbgs() << "JIT linker requesting: { ");
187 JITLinkMemoryManager::SegmentsRequestMap Segments
;
188 for (auto &KV
: Layout
) {
189 auto &Prot
= KV
.first
;
190 auto &SegLists
= KV
.second
;
192 uint64_t SegAlign
= 1;
194 // Calculate segment content size.
195 size_t SegContentSize
= 0;
196 for (auto *B
: SegLists
.ContentBlocks
) {
197 SegAlign
= std::max(SegAlign
, B
->getAlignment());
198 SegContentSize
= alignToBlock(SegContentSize
, *B
);
199 SegContentSize
+= B
->getSize();
202 uint64_t SegZeroFillStart
= SegContentSize
;
203 uint64_t SegZeroFillEnd
= SegZeroFillStart
;
205 for (auto *B
: SegLists
.ZeroFillBlocks
) {
206 SegAlign
= std::max(SegAlign
, B
->getAlignment());
207 SegZeroFillEnd
= alignToBlock(SegZeroFillEnd
, *B
);
208 SegZeroFillEnd
+= B
->getSize();
211 Segments
[Prot
] = {SegAlign
, SegContentSize
,
212 SegZeroFillEnd
- SegZeroFillStart
};
215 dbgs() << (&KV
== &*Layout
.begin() ? "" : "; ")
216 << static_cast<sys::Memory::ProtectionFlags
>(Prot
)
217 << ": alignment = " << SegAlign
218 << ", content size = " << SegContentSize
219 << ", zero-fill size = " << (SegZeroFillEnd
- SegZeroFillStart
);
222 LLVM_DEBUG(dbgs() << " }\n");
224 if (auto AllocOrErr
= Ctx
->getMemoryManager().allocate(Segments
))
225 Alloc
= std::move(*AllocOrErr
);
227 return AllocOrErr
.takeError();
230 dbgs() << "JIT linker got working memory:\n";
231 for (auto &KV
: Layout
) {
232 auto Prot
= static_cast<sys::Memory::ProtectionFlags
>(KV
.first
);
233 dbgs() << " " << Prot
<< ": "
234 << (const void *)Alloc
->getWorkingMemory(Prot
).data() << "\n";
238 // Update block target addresses.
239 for (auto &KV
: Layout
) {
240 auto &Prot
= KV
.first
;
241 auto &SL
= KV
.second
;
243 JITTargetAddress NextBlockAddr
=
244 Alloc
->getTargetMemory(static_cast<sys::Memory::ProtectionFlags
>(Prot
));
246 for (auto *SIList
: {&SL
.ContentBlocks
, &SL
.ZeroFillBlocks
})
247 for (auto *B
: *SIList
) {
248 NextBlockAddr
= alignToBlock(NextBlockAddr
, *B
);
249 B
->setAddress(NextBlockAddr
);
250 NextBlockAddr
+= B
->getSize();
254 return Error::success();
257 DenseSet
<StringRef
> JITLinkerBase::getExternalSymbolNames() const {
258 // Identify unresolved external symbols.
259 DenseSet
<StringRef
> UnresolvedExternals
;
260 for (auto *Sym
: G
->external_symbols()) {
261 assert(Sym
->getAddress() == 0 &&
262 "External has already been assigned an address");
263 assert(Sym
->getName() != StringRef() && Sym
->getName() != "" &&
264 "Externals must be named");
265 UnresolvedExternals
.insert(Sym
->getName());
267 return UnresolvedExternals
;
270 void JITLinkerBase::applyLookupResult(AsyncLookupResult Result
) {
271 for (auto *Sym
: G
->external_symbols()) {
272 assert(Sym
->getAddress() == 0 && "Symbol already resolved");
273 assert(!Sym
->isDefined() && "Symbol being resolved is already defined");
274 assert(Result
.count(Sym
->getName()) && "Missing resolution for symbol");
275 Sym
->getAddressable().setAddress(Result
[Sym
->getName()].getAddress());
279 dbgs() << "Externals after applying lookup result:\n";
280 for (auto *Sym
: G
->external_symbols())
281 dbgs() << " " << Sym
->getName() << ": "
282 << formatv("{0:x16}", Sym
->getAddress()) << "\n";
284 assert(llvm::all_of(G
->external_symbols(),
285 [](Symbol
*Sym
) { return Sym
->getAddress() != 0; }) &&
286 "All symbols should have been resolved by this point");
289 void JITLinkerBase::deallocateAndBailOut(Error Err
) {
290 assert(Err
&& "Should not be bailing out on success value");
291 assert(Alloc
&& "can not call deallocateAndBailOut before allocation");
292 Ctx
->notifyFailed(joinErrors(std::move(Err
), Alloc
->deallocate()));
295 void JITLinkerBase::dumpGraph(raw_ostream
&OS
) {
296 assert(G
&& "Graph is not set yet");
297 G
->dump(dbgs(), [this](Edge::Kind K
) { return getEdgeKindName(K
); });
300 void prune(LinkGraph
&G
) {
301 std::vector
<Symbol
*> Worklist
;
302 DenseSet
<Block
*> VisitedBlocks
;
304 // Build the initial worklist from all symbols initially live.
305 for (auto *Sym
: G
.defined_symbols())
307 Worklist
.push_back(Sym
);
309 // Propagate live flags to all symbols reachable from the initial live set.
310 while (!Worklist
.empty()) {
311 auto *Sym
= Worklist
.back();
314 auto &B
= Sym
->getBlock();
316 // Skip addressables that we've visited before.
317 if (VisitedBlocks
.count(&B
))
320 VisitedBlocks
.insert(&B
);
322 for (auto &E
: Sym
->getBlock().edges()) {
323 if (E
.getTarget().isDefined() && !E
.getTarget().isLive()) {
324 E
.getTarget().setLive(true);
325 Worklist
.push_back(&E
.getTarget());
330 // Collect all the symbols to remove, then remove them.
332 LLVM_DEBUG(dbgs() << "Dead-stripping symbols:\n");
333 std::vector
<Symbol
*> SymbolsToRemove
;
334 for (auto *Sym
: G
.defined_symbols())
336 SymbolsToRemove
.push_back(Sym
);
337 for (auto *Sym
: SymbolsToRemove
) {
338 LLVM_DEBUG(dbgs() << " " << *Sym
<< "...\n");
339 G
.removeDefinedSymbol(*Sym
);
343 // Delete any unused blocks.
345 LLVM_DEBUG(dbgs() << "Dead-stripping blocks:\n");
346 std::vector
<Block
*> BlocksToRemove
;
347 for (auto *B
: G
.blocks())
348 if (!VisitedBlocks
.count(B
))
349 BlocksToRemove
.push_back(B
);
350 for (auto *B
: BlocksToRemove
) {
351 LLVM_DEBUG(dbgs() << " " << *B
<< "...\n");
357 } // end namespace jitlink
358 } // end namespace llvm