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