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