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