1 //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
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
9 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
10 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
11 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
12 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
13 #include "llvm/Support/MemoryBuffer.h"
14 #include <string>
15 #include <vector>
16
17 #define DEBUG_TYPE "orc"
18
19 using namespace llvm;
20 using namespace llvm::jitlink;
21 using namespace llvm::orc;
22
23 namespace {
24
25 class LinkGraphMaterializationUnit : public MaterializationUnit {
26 public:
27 static std::unique_ptr<LinkGraphMaterializationUnit>
Create(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G)28 Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
29 auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
30 return std::unique_ptr<LinkGraphMaterializationUnit>(
31 new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
32 std::move(LGI)));
33 }
34
getName() const35 StringRef getName() const override { return G->getName(); }
materialize(std::unique_ptr<MaterializationResponsibility> MR)36 void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
37 ObjLinkingLayer.emit(std::move(MR), std::move(G));
38 }
39
40 private:
scanLinkGraph(ExecutionSession & ES,LinkGraph & G)41 static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
42
43 Interface LGI;
44
45 for (auto *Sym : G.defined_symbols()) {
46 // Skip local symbols.
47 if (Sym->getScope() == Scope::Local)
48 continue;
49 assert(Sym->hasName() && "Anonymous non-local symbol?");
50
51 JITSymbolFlags Flags;
52 if (Sym->getScope() == Scope::Default)
53 Flags |= JITSymbolFlags::Exported;
54
55 if (Sym->isCallable())
56 Flags |= JITSymbolFlags::Callable;
57
58 LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags;
59 }
60
61 if (hasInitializerSection(G))
62 LGI.InitSymbol = makeInitSymbol(ES, G);
63
64 return LGI;
65 }
66
makeInitSymbol(ExecutionSession & ES,LinkGraph & G)67 static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
68 std::string InitSymString;
69 raw_string_ostream(InitSymString)
70 << "$." << G.getName() << ".__inits" << Counter++;
71 return ES.intern(InitSymString);
72 }
73
LinkGraphMaterializationUnit(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G,Interface LGI)74 LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
75 std::unique_ptr<LinkGraph> G, Interface LGI)
76 : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
77 G(std::move(G)) {}
78
discard(const JITDylib & JD,const SymbolStringPtr & Name)79 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
80 for (auto *Sym : G->defined_symbols())
81 if (Sym->getName() == *Name) {
82 assert(Sym->getLinkage() == Linkage::Weak &&
83 "Discarding non-weak definition");
84 G->makeExternal(*Sym);
85 break;
86 }
87 }
88
89 ObjectLinkingLayer &ObjLinkingLayer;
90 std::unique_ptr<LinkGraph> G;
91 static std::atomic<uint64_t> Counter;
92 };
93
94 std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
95
96 } // end anonymous namespace
97
98 namespace llvm {
99 namespace orc {
100
101 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
102 public:
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer & Layer,std::unique_ptr<MaterializationResponsibility> MR,std::unique_ptr<MemoryBuffer> ObjBuffer)103 ObjectLinkingLayerJITLinkContext(
104 ObjectLinkingLayer &Layer,
105 std::unique_ptr<MaterializationResponsibility> MR,
106 std::unique_ptr<MemoryBuffer> ObjBuffer)
107 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
108 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
109
~ObjectLinkingLayerJITLinkContext()110 ~ObjectLinkingLayerJITLinkContext() {
111 // If there is an object buffer return function then use it to
112 // return ownership of the buffer.
113 if (Layer.ReturnObjectBuffer && ObjBuffer)
114 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
115 }
116
getMemoryManager()117 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
118
notifyMaterializing(LinkGraph & G)119 void notifyMaterializing(LinkGraph &G) {
120 for (auto &P : Layer.Plugins)
121 P->notifyMaterializing(*MR, G, *this,
122 ObjBuffer ? ObjBuffer->getMemBufferRef()
123 : MemoryBufferRef());
124 }
125
notifyFailed(Error Err)126 void notifyFailed(Error Err) override {
127 for (auto &P : Layer.Plugins)
128 Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
129 Layer.getExecutionSession().reportError(std::move(Err));
130 MR->failMaterialization();
131 }
132
lookup(const LookupMap & Symbols,std::unique_ptr<JITLinkAsyncLookupContinuation> LC)133 void lookup(const LookupMap &Symbols,
134 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
135
136 JITDylibSearchOrder LinkOrder;
137 MR->getTargetJITDylib().withLinkOrderDo(
138 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
139
140 auto &ES = Layer.getExecutionSession();
141
142 SymbolLookupSet LookupSet;
143 for (auto &KV : Symbols) {
144 orc::SymbolLookupFlags LookupFlags;
145 switch (KV.second) {
146 case jitlink::SymbolLookupFlags::RequiredSymbol:
147 LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
148 break;
149 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
150 LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
151 break;
152 }
153 LookupSet.add(ES.intern(KV.first), LookupFlags);
154 }
155
156 // OnResolve -- De-intern the symbols and pass the result to the linker.
157 auto OnResolve = [LookupContinuation =
158 std::move(LC)](Expected<SymbolMap> Result) mutable {
159 if (!Result)
160 LookupContinuation->run(Result.takeError());
161 else {
162 AsyncLookupResult LR;
163 for (auto &KV : *Result)
164 LR[*KV.first] = KV.second;
165 LookupContinuation->run(std::move(LR));
166 }
167 };
168
169 for (auto &KV : InternalNamedSymbolDeps) {
170 SymbolDependenceMap InternalDeps;
171 InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
172 MR->addDependencies(KV.first, InternalDeps);
173 }
174
175 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
176 SymbolState::Resolved, std::move(OnResolve),
177 [this](const SymbolDependenceMap &Deps) {
178 registerDependencies(Deps);
179 });
180 }
181
notifyResolved(LinkGraph & G)182 Error notifyResolved(LinkGraph &G) override {
183 auto &ES = Layer.getExecutionSession();
184
185 SymbolFlagsMap ExtraSymbolsToClaim;
186 bool AutoClaim = Layer.AutoClaimObjectSymbols;
187
188 SymbolMap InternedResult;
189 for (auto *Sym : G.defined_symbols())
190 if (Sym->hasName() && Sym->getScope() != Scope::Local) {
191 auto InternedName = ES.intern(Sym->getName());
192 JITSymbolFlags Flags;
193
194 if (Sym->isCallable())
195 Flags |= JITSymbolFlags::Callable;
196 if (Sym->getScope() == Scope::Default)
197 Flags |= JITSymbolFlags::Exported;
198 if (Sym->getLinkage() == Linkage::Weak)
199 Flags |= JITSymbolFlags::Weak;
200
201 InternedResult[InternedName] =
202 JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
203 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
204 assert(!ExtraSymbolsToClaim.count(InternedName) &&
205 "Duplicate symbol to claim?");
206 ExtraSymbolsToClaim[InternedName] = Flags;
207 }
208 }
209
210 for (auto *Sym : G.absolute_symbols())
211 if (Sym->hasName() && Sym->getScope() != Scope::Local) {
212 auto InternedName = ES.intern(Sym->getName());
213 JITSymbolFlags Flags;
214 if (Sym->isCallable())
215 Flags |= JITSymbolFlags::Callable;
216 if (Sym->getScope() == Scope::Default)
217 Flags |= JITSymbolFlags::Exported;
218 if (Sym->getLinkage() == Linkage::Weak)
219 Flags |= JITSymbolFlags::Weak;
220 InternedResult[InternedName] =
221 JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
222 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
223 assert(!ExtraSymbolsToClaim.count(InternedName) &&
224 "Duplicate symbol to claim?");
225 ExtraSymbolsToClaim[InternedName] = Flags;
226 }
227 }
228
229 if (!ExtraSymbolsToClaim.empty())
230 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
231 return Err;
232
233 {
234
235 // Check that InternedResult matches up with MR->getSymbols(), overriding
236 // flags if requested.
237 // This guards against faulty transformations / compilers / object caches.
238
239 // First check that there aren't any missing symbols.
240 size_t NumMaterializationSideEffectsOnlySymbols = 0;
241 SymbolNameVector ExtraSymbols;
242 SymbolNameVector MissingSymbols;
243 for (auto &KV : MR->getSymbols()) {
244
245 auto I = InternedResult.find(KV.first);
246
247 // If this is a materialization-side-effects only symbol then bump
248 // the counter and make sure it's *not* defined, otherwise make
249 // sure that it is defined.
250 if (KV.second.hasMaterializationSideEffectsOnly()) {
251 ++NumMaterializationSideEffectsOnlySymbols;
252 if (I != InternedResult.end())
253 ExtraSymbols.push_back(KV.first);
254 continue;
255 } else if (I == InternedResult.end())
256 MissingSymbols.push_back(KV.first);
257 else if (Layer.OverrideObjectFlags)
258 I->second.setFlags(KV.second);
259 }
260
261 // If there were missing symbols then report the error.
262 if (!MissingSymbols.empty())
263 return make_error<MissingSymbolDefinitions>(
264 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
265 std::move(MissingSymbols));
266
267 // If there are more definitions than expected, add them to the
268 // ExtraSymbols vector.
269 if (InternedResult.size() >
270 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
271 for (auto &KV : InternedResult)
272 if (!MR->getSymbols().count(KV.first))
273 ExtraSymbols.push_back(KV.first);
274 }
275
276 // If there were extra definitions then report the error.
277 if (!ExtraSymbols.empty())
278 return make_error<UnexpectedSymbolDefinitions>(
279 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
280 std::move(ExtraSymbols));
281 }
282
283 if (auto Err = MR->notifyResolved(InternedResult))
284 return Err;
285
286 Layer.notifyLoaded(*MR);
287 return Error::success();
288 }
289
notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A)290 void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
291 if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
292 Layer.getExecutionSession().reportError(std::move(Err));
293 MR->failMaterialization();
294 return;
295 }
296 if (auto Err = MR->notifyEmitted()) {
297 Layer.getExecutionSession().reportError(std::move(Err));
298 MR->failMaterialization();
299 }
300 }
301
getMarkLivePass(const Triple & TT) const302 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
303 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
304 }
305
modifyPassConfig(LinkGraph & LG,PassConfiguration & Config)306 Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {
307 // Add passes to mark duplicate defs as should-discard, and to walk the
308 // link graph to build the symbol dependence graph.
309 Config.PrePrunePasses.push_back([this](LinkGraph &G) {
310 return claimOrExternalizeWeakAndCommonSymbols(G);
311 });
312
313 Layer.modifyPassConfig(*MR, LG, Config);
314
315 Config.PostPrunePasses.push_back(
316 [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
317
318 return Error::success();
319 }
320
321 private:
322 // Symbol name dependencies:
323 // Internal: Defined in this graph.
324 // External: Defined externally.
325 struct BlockSymbolDependencies {
326 SymbolNameSet Internal, External;
327 };
328
329 // Lazily populated map of blocks to BlockSymbolDependencies values.
330 class BlockDependenciesMap {
331 public:
BlockDependenciesMap(ExecutionSession & ES,DenseMap<const Block *,DenseSet<Block * >> BlockDeps)332 BlockDependenciesMap(ExecutionSession &ES,
333 DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
334 : ES(ES), BlockDeps(std::move(BlockDeps)) {}
335
operator [](const Block & B)336 const BlockSymbolDependencies &operator[](const Block &B) {
337 // Check the cache first.
338 auto I = BlockTransitiveDepsCache.find(&B);
339 if (I != BlockTransitiveDepsCache.end())
340 return I->second;
341
342 // No value. Populate the cache.
343 BlockSymbolDependencies BTDCacheVal;
344 auto BDI = BlockDeps.find(&B);
345 assert(BDI != BlockDeps.end() && "No block dependencies");
346
347 for (auto *BDep : BDI->second) {
348 auto &BID = getBlockImmediateDeps(*BDep);
349 for (auto &ExternalDep : BID.External)
350 BTDCacheVal.External.insert(ExternalDep);
351 for (auto &InternalDep : BID.Internal)
352 BTDCacheVal.Internal.insert(InternalDep);
353 }
354
355 return BlockTransitiveDepsCache
356 .insert(std::make_pair(&B, std::move(BTDCacheVal)))
357 .first->second;
358 }
359
getInternedName(Symbol & Sym)360 SymbolStringPtr &getInternedName(Symbol &Sym) {
361 auto I = NameCache.find(&Sym);
362 if (I != NameCache.end())
363 return I->second;
364
365 return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
366 .first->second;
367 }
368
369 private:
getBlockImmediateDeps(Block & B)370 BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
371 // Check the cache first.
372 auto I = BlockImmediateDepsCache.find(&B);
373 if (I != BlockImmediateDepsCache.end())
374 return I->second;
375
376 BlockSymbolDependencies BIDCacheVal;
377 for (auto &E : B.edges()) {
378 auto &Tgt = E.getTarget();
379 if (Tgt.getScope() != Scope::Local) {
380 if (Tgt.isExternal())
381 BIDCacheVal.External.insert(getInternedName(Tgt));
382 else
383 BIDCacheVal.Internal.insert(getInternedName(Tgt));
384 }
385 }
386
387 return BlockImmediateDepsCache
388 .insert(std::make_pair(&B, std::move(BIDCacheVal)))
389 .first->second;
390 }
391
392 ExecutionSession &ES;
393 DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
394 DenseMap<const Symbol *, SymbolStringPtr> NameCache;
395 DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
396 DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
397 };
398
claimOrExternalizeWeakAndCommonSymbols(LinkGraph & G)399 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
400 auto &ES = Layer.getExecutionSession();
401
402 SymbolFlagsMap NewSymbolsToClaim;
403 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
404
405 auto ProcessSymbol = [&](Symbol *Sym) {
406 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
407 Sym->getScope() != Scope::Local) {
408 auto Name = ES.intern(Sym->getName());
409 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
410 JITSymbolFlags SF = JITSymbolFlags::Weak;
411 if (Sym->getScope() == Scope::Default)
412 SF |= JITSymbolFlags::Exported;
413 NewSymbolsToClaim[Name] = SF;
414 NameToSym.push_back(std::make_pair(std::move(Name), Sym));
415 }
416 }
417 };
418
419 for (auto *Sym : G.defined_symbols())
420 ProcessSymbol(Sym);
421 for (auto *Sym : G.absolute_symbols())
422 ProcessSymbol(Sym);
423
424 // Attempt to claim all weak defs that we're not already responsible for.
425 // This cannot fail -- any clashes will just result in rejection of our
426 // claim, at which point we'll externalize that symbol.
427 cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
428
429 // Walk the list of symbols that we just tried to claim. Symbols that we're
430 // responsible for are marked live. Symbols that we're not responsible for
431 // are turned into external references.
432 for (auto &KV : NameToSym) {
433 if (MR->getSymbols().count(KV.first))
434 KV.second->setLive(true);
435 else
436 G.makeExternal(*KV.second);
437 }
438
439 return Error::success();
440 }
441
markResponsibilitySymbolsLive(LinkGraph & G) const442 Error markResponsibilitySymbolsLive(LinkGraph &G) const {
443 auto &ES = Layer.getExecutionSession();
444 for (auto *Sym : G.defined_symbols())
445 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
446 Sym->setLive(true);
447 return Error::success();
448 }
449
computeNamedSymbolDependencies(LinkGraph & G)450 Error computeNamedSymbolDependencies(LinkGraph &G) {
451 auto &ES = MR->getTargetJITDylib().getExecutionSession();
452 auto BlockDeps = computeBlockNonLocalDeps(G);
453
454 // Compute dependencies for symbols defined in the JITLink graph.
455 for (auto *Sym : G.defined_symbols()) {
456
457 // Skip local symbols: we do not track dependencies for these.
458 if (Sym->getScope() == Scope::Local)
459 continue;
460 assert(Sym->hasName() &&
461 "Defined non-local jitlink::Symbol should have a name");
462
463 auto &SymDeps = BlockDeps[Sym->getBlock()];
464 if (SymDeps.External.empty() && SymDeps.Internal.empty())
465 continue;
466
467 auto SymName = ES.intern(Sym->getName());
468 if (!SymDeps.External.empty())
469 ExternalNamedSymbolDeps[SymName] = SymDeps.External;
470 if (!SymDeps.Internal.empty())
471 InternalNamedSymbolDeps[SymName] = SymDeps.Internal;
472 }
473
474 for (auto &P : Layer.Plugins) {
475 auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
476 if (SynthDeps.empty())
477 continue;
478
479 DenseSet<Block *> BlockVisited;
480 for (auto &KV : SynthDeps) {
481 auto &Name = KV.first;
482 auto &DepsForName = KV.second;
483 for (auto *Sym : DepsForName) {
484 if (Sym->getScope() == Scope::Local) {
485 auto &BDeps = BlockDeps[Sym->getBlock()];
486 for (auto &S : BDeps.Internal)
487 InternalNamedSymbolDeps[Name].insert(S);
488 for (auto &S : BDeps.External)
489 ExternalNamedSymbolDeps[Name].insert(S);
490 } else {
491 if (Sym->isExternal())
492 ExternalNamedSymbolDeps[Name].insert(
493 BlockDeps.getInternedName(*Sym));
494 else
495 InternalNamedSymbolDeps[Name].insert(
496 BlockDeps.getInternedName(*Sym));
497 }
498 }
499 }
500 }
501
502 return Error::success();
503 }
504
computeBlockNonLocalDeps(LinkGraph & G)505 BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
506 // First calculate the reachable-via-non-local-symbol blocks for each block.
507 struct BlockInfo {
508 DenseSet<Block *> Dependencies;
509 DenseSet<Block *> Dependants;
510 bool DependenciesChanged = true;
511 };
512 DenseMap<Block *, BlockInfo> BlockInfos;
513 SmallVector<Block *> WorkList;
514
515 // Pre-allocate map entries. This prevents any iterator/reference
516 // invalidation in the next loop.
517 for (auto *B : G.blocks())
518 (void)BlockInfos[B];
519
520 // Build initial worklist, record block dependencies/dependants and
521 // non-local symbol dependencies.
522 for (auto *B : G.blocks()) {
523 auto &BI = BlockInfos[B];
524 for (auto &E : B->edges()) {
525 if (E.getTarget().getScope() == Scope::Local &&
526 !E.getTarget().isAbsolute()) {
527 auto &TgtB = E.getTarget().getBlock();
528 if (&TgtB != B) {
529 BI.Dependencies.insert(&TgtB);
530 BlockInfos[&TgtB].Dependants.insert(B);
531 }
532 }
533 }
534
535 // If this node has both dependants and dependencies then add it to the
536 // worklist to propagate the dependencies to the dependants.
537 if (!BI.Dependants.empty() && !BI.Dependencies.empty())
538 WorkList.push_back(B);
539 }
540
541 // Propagate block-level dependencies through the block-dependence graph.
542 while (!WorkList.empty()) {
543 auto *B = WorkList.pop_back_val();
544
545 auto &BI = BlockInfos[B];
546 assert(BI.DependenciesChanged &&
547 "Block in worklist has unchanged dependencies");
548 BI.DependenciesChanged = false;
549 for (auto *Dependant : BI.Dependants) {
550 auto &DependantBI = BlockInfos[Dependant];
551 for (auto *Dependency : BI.Dependencies) {
552 if (Dependant != Dependency &&
553 DependantBI.Dependencies.insert(Dependency).second)
554 if (!DependantBI.DependenciesChanged) {
555 DependantBI.DependenciesChanged = true;
556 WorkList.push_back(Dependant);
557 }
558 }
559 }
560 }
561
562 DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
563 for (auto &KV : BlockInfos)
564 BlockDeps[KV.first] = std::move(KV.second.Dependencies);
565
566 return BlockDependenciesMap(Layer.getExecutionSession(),
567 std::move(BlockDeps));
568 }
569
registerDependencies(const SymbolDependenceMap & QueryDeps)570 void registerDependencies(const SymbolDependenceMap &QueryDeps) {
571 for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
572 auto &Name = NamedDepsEntry.first;
573 auto &NameDeps = NamedDepsEntry.second;
574 SymbolDependenceMap SymbolDeps;
575
576 for (const auto &QueryDepsEntry : QueryDeps) {
577 JITDylib &SourceJD = *QueryDepsEntry.first;
578 const SymbolNameSet &Symbols = QueryDepsEntry.second;
579 auto &DepsForJD = SymbolDeps[&SourceJD];
580
581 for (const auto &S : Symbols)
582 if (NameDeps.count(S))
583 DepsForJD.insert(S);
584
585 if (DepsForJD.empty())
586 SymbolDeps.erase(&SourceJD);
587 }
588
589 MR->addDependencies(Name, SymbolDeps);
590 }
591 }
592
593 ObjectLinkingLayer &Layer;
594 std::unique_ptr<MaterializationResponsibility> MR;
595 std::unique_ptr<MemoryBuffer> ObjBuffer;
596 DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
597 DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
598 };
599
600 ObjectLinkingLayer::Plugin::~Plugin() = default;
601
602 char ObjectLinkingLayer::ID;
603
604 using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
605
ObjectLinkingLayer(ExecutionSession & ES)606 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
607 : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
608 ES.registerResourceManager(*this);
609 }
610
ObjectLinkingLayer(ExecutionSession & ES,JITLinkMemoryManager & MemMgr)611 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
612 JITLinkMemoryManager &MemMgr)
613 : BaseT(ES), MemMgr(MemMgr) {
614 ES.registerResourceManager(*this);
615 }
616
ObjectLinkingLayer(ExecutionSession & ES,std::unique_ptr<JITLinkMemoryManager> MemMgr)617 ObjectLinkingLayer::ObjectLinkingLayer(
618 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
619 : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
620 ES.registerResourceManager(*this);
621 }
622
~ObjectLinkingLayer()623 ObjectLinkingLayer::~ObjectLinkingLayer() {
624 assert(Allocs.empty() && "Layer destroyed with resources still attached");
625 getExecutionSession().deregisterResourceManager(*this);
626 }
627
add(ResourceTrackerSP RT,std::unique_ptr<LinkGraph> G)628 Error ObjectLinkingLayer::add(ResourceTrackerSP RT,
629 std::unique_ptr<LinkGraph> G) {
630 auto &JD = RT->getJITDylib();
631 return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
632 std::move(RT));
633 }
634
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<MemoryBuffer> O)635 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
636 std::unique_ptr<MemoryBuffer> O) {
637 assert(O && "Object must not be null");
638 MemoryBufferRef ObjBuffer = O->getMemBufferRef();
639
640 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
641 *this, std::move(R), std::move(O));
642 if (auto G = createLinkGraphFromObject(ObjBuffer)) {
643 Ctx->notifyMaterializing(**G);
644 link(std::move(*G), std::move(Ctx));
645 } else {
646 Ctx->notifyFailed(G.takeError());
647 }
648 }
649
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<LinkGraph> G)650 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
651 std::unique_ptr<LinkGraph> G) {
652 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
653 *this, std::move(R), nullptr);
654 Ctx->notifyMaterializing(*G);
655 link(std::move(G), std::move(Ctx));
656 }
657
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)658 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
659 LinkGraph &G,
660 PassConfiguration &PassConfig) {
661 for (auto &P : Plugins)
662 P->modifyPassConfig(MR, G, PassConfig);
663 }
664
notifyLoaded(MaterializationResponsibility & MR)665 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
666 for (auto &P : Plugins)
667 P->notifyLoaded(MR);
668 }
669
notifyEmitted(MaterializationResponsibility & MR,FinalizedAlloc FA)670 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
671 FinalizedAlloc FA) {
672 Error Err = Error::success();
673 for (auto &P : Plugins)
674 Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
675
676 if (Err)
677 return Err;
678
679 return MR.withResourceKeyDo(
680 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
681 }
682
handleRemoveResources(JITDylib & JD,ResourceKey K)683 Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
684
685 {
686 Error Err = Error::success();
687 for (auto &P : Plugins)
688 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
689 if (Err)
690 return Err;
691 }
692
693 std::vector<FinalizedAlloc> AllocsToRemove;
694 getExecutionSession().runSessionLocked([&] {
695 auto I = Allocs.find(K);
696 if (I != Allocs.end()) {
697 std::swap(AllocsToRemove, I->second);
698 Allocs.erase(I);
699 }
700 });
701
702 if (AllocsToRemove.empty())
703 return Error::success();
704
705 return MemMgr.deallocate(std::move(AllocsToRemove));
706 }
707
handleTransferResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)708 void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
709 ResourceKey DstKey,
710 ResourceKey SrcKey) {
711 auto I = Allocs.find(SrcKey);
712 if (I != Allocs.end()) {
713 auto &SrcAllocs = I->second;
714 auto &DstAllocs = Allocs[DstKey];
715 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
716 for (auto &Alloc : SrcAllocs)
717 DstAllocs.push_back(std::move(Alloc));
718
719 // Erase SrcKey entry using value rather than iterator I: I may have been
720 // invalidated when we looked up DstKey.
721 Allocs.erase(SrcKey);
722 }
723
724 for (auto &P : Plugins)
725 P->notifyTransferringResources(JD, DstKey, SrcKey);
726 }
727
EHFrameRegistrationPlugin(ExecutionSession & ES,std::unique_ptr<EHFrameRegistrar> Registrar)728 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
729 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
730 : ES(ES), Registrar(std::move(Registrar)) {}
731
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)732 void EHFrameRegistrationPlugin::modifyPassConfig(
733 MaterializationResponsibility &MR, LinkGraph &G,
734 PassConfiguration &PassConfig) {
735
736 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
737 G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
738 if (Addr) {
739 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
740 assert(!InProcessLinks.count(&MR) &&
741 "Link for MR already being tracked?");
742 InProcessLinks[&MR] = {Addr, Size};
743 }
744 }));
745 }
746
notifyEmitted(MaterializationResponsibility & MR)747 Error EHFrameRegistrationPlugin::notifyEmitted(
748 MaterializationResponsibility &MR) {
749
750 ExecutorAddrRange EmittedRange;
751 {
752 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
753
754 auto EHFrameRangeItr = InProcessLinks.find(&MR);
755 if (EHFrameRangeItr == InProcessLinks.end())
756 return Error::success();
757
758 EmittedRange = EHFrameRangeItr->second;
759 assert(EmittedRange.Start && "eh-frame addr to register can not be null");
760 InProcessLinks.erase(EHFrameRangeItr);
761 }
762
763 if (auto Err = MR.withResourceKeyDo(
764 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
765 return Err;
766
767 return Registrar->registerEHFrames(EmittedRange);
768 }
769
notifyFailed(MaterializationResponsibility & MR)770 Error EHFrameRegistrationPlugin::notifyFailed(
771 MaterializationResponsibility &MR) {
772 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
773 InProcessLinks.erase(&MR);
774 return Error::success();
775 }
776
notifyRemovingResources(JITDylib & JD,ResourceKey K)777 Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
778 ResourceKey K) {
779 std::vector<ExecutorAddrRange> RangesToRemove;
780
781 ES.runSessionLocked([&] {
782 auto I = EHFrameRanges.find(K);
783 if (I != EHFrameRanges.end()) {
784 RangesToRemove = std::move(I->second);
785 EHFrameRanges.erase(I);
786 }
787 });
788
789 Error Err = Error::success();
790 while (!RangesToRemove.empty()) {
791 auto RangeToRemove = RangesToRemove.back();
792 RangesToRemove.pop_back();
793 assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
794 Err = joinErrors(std::move(Err),
795 Registrar->deregisterEHFrames(RangeToRemove));
796 }
797
798 return Err;
799 }
800
notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)801 void EHFrameRegistrationPlugin::notifyTransferringResources(
802 JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
803 auto SI = EHFrameRanges.find(SrcKey);
804 if (SI == EHFrameRanges.end())
805 return;
806
807 auto DI = EHFrameRanges.find(DstKey);
808 if (DI != EHFrameRanges.end()) {
809 auto &SrcRanges = SI->second;
810 auto &DstRanges = DI->second;
811 DstRanges.reserve(DstRanges.size() + SrcRanges.size());
812 for (auto &SrcRange : SrcRanges)
813 DstRanges.push_back(std::move(SrcRange));
814 EHFrameRanges.erase(SI);
815 } else {
816 // We need to move SrcKey's ranges over without invalidating the SI
817 // iterator.
818 auto Tmp = std::move(SI->second);
819 EHFrameRanges.erase(SI);
820 EHFrameRanges[DstKey] = std::move(Tmp);
821 }
822 }
823
824 } // End namespace orc.
825 } // End namespace llvm.
826