xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision 214a9f0dd4814988b55311dd777d0ef3ad1830ee)
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 
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
13 
14 #include <vector>
15 
16 #define DEBUG_TYPE "orc"
17 
18 using namespace llvm;
19 using namespace llvm::jitlink;
20 using namespace llvm::orc;
21 
22 namespace llvm {
23 namespace orc {
24 
25 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
26 public:
27   ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
28                                    MaterializationResponsibility MR,
29                                    std::unique_ptr<MemoryBuffer> ObjBuffer)
30       : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
31 
32   ~ObjectLinkingLayerJITLinkContext() {
33     // If there is an object buffer return function then use it to
34     // return ownership of the buffer.
35     if (Layer.ReturnObjectBuffer)
36       Layer.ReturnObjectBuffer(std::move(ObjBuffer));
37   }
38 
39   JITLinkMemoryManager &getMemoryManager() override { return *Layer.MemMgr; }
40 
41   MemoryBufferRef getObjectBuffer() const override {
42     return ObjBuffer->getMemBufferRef();
43   }
44 
45   void notifyFailed(Error Err) override {
46     Layer.getExecutionSession().reportError(std::move(Err));
47     MR.failMaterialization();
48   }
49 
50   void lookup(const LookupMap &Symbols,
51               std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
52 
53     JITDylibSearchOrder SearchOrder;
54     MR.getTargetJITDylib().withSearchOrderDo(
55         [&](const JITDylibSearchOrder &O) { SearchOrder = O; });
56 
57     auto &ES = Layer.getExecutionSession();
58 
59     SymbolLookupSet LookupSet;
60     for (auto &KV : Symbols) {
61       orc::SymbolLookupFlags LookupFlags;
62       switch (KV.second) {
63       case jitlink::SymbolLookupFlags::RequiredSymbol:
64         LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
65         break;
66       case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
67         LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
68         break;
69       }
70       LookupSet.add(ES.intern(KV.first), LookupFlags);
71     }
72 
73     // OnResolve -- De-intern the symbols and pass the result to the linker.
74     auto OnResolve = [this, LookupContinuation = std::move(LC)](
75                          Expected<SymbolMap> Result) mutable {
76       auto Main = Layer.getExecutionSession().intern("_main");
77       if (!Result)
78         LookupContinuation->run(Result.takeError());
79       else {
80         AsyncLookupResult LR;
81         for (auto &KV : *Result)
82           LR[*KV.first] = KV.second;
83         LookupContinuation->run(std::move(LR));
84       }
85     };
86 
87     for (auto &KV : InternalNamedSymbolDeps) {
88       SymbolDependenceMap InternalDeps;
89       InternalDeps[&MR.getTargetJITDylib()] = std::move(KV.second);
90       MR.addDependencies(KV.first, InternalDeps);
91     }
92 
93     ES.lookup(LookupKind::Static, SearchOrder, std::move(LookupSet),
94               SymbolState::Resolved, std::move(OnResolve),
95               [this](const SymbolDependenceMap &Deps) {
96                 registerDependencies(Deps);
97               });
98   }
99 
100   void notifyResolved(LinkGraph &G) override {
101     auto &ES = Layer.getExecutionSession();
102 
103     SymbolFlagsMap ExtraSymbolsToClaim;
104     bool AutoClaim = Layer.AutoClaimObjectSymbols;
105 
106     SymbolMap InternedResult;
107     for (auto *Sym : G.defined_symbols())
108       if (Sym->hasName() && Sym->getScope() != Scope::Local) {
109         auto InternedName = ES.intern(Sym->getName());
110         JITSymbolFlags Flags;
111 
112         if (Sym->isCallable())
113           Flags |= JITSymbolFlags::Callable;
114         if (Sym->getScope() == Scope::Default)
115           Flags |= JITSymbolFlags::Exported;
116 
117         InternedResult[InternedName] =
118             JITEvaluatedSymbol(Sym->getAddress(), Flags);
119         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
120           assert(!ExtraSymbolsToClaim.count(InternedName) &&
121                  "Duplicate symbol to claim?");
122           ExtraSymbolsToClaim[InternedName] = Flags;
123         }
124       }
125 
126     for (auto *Sym : G.absolute_symbols())
127       if (Sym->hasName()) {
128         auto InternedName = ES.intern(Sym->getName());
129         JITSymbolFlags Flags;
130         Flags |= JITSymbolFlags::Absolute;
131         if (Sym->isCallable())
132           Flags |= JITSymbolFlags::Callable;
133         if (Sym->getLinkage() == Linkage::Weak)
134           Flags |= JITSymbolFlags::Weak;
135         InternedResult[InternedName] =
136             JITEvaluatedSymbol(Sym->getAddress(), Flags);
137         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
138           assert(!ExtraSymbolsToClaim.count(InternedName) &&
139                  "Duplicate symbol to claim?");
140           ExtraSymbolsToClaim[InternedName] = Flags;
141         }
142       }
143 
144     if (!ExtraSymbolsToClaim.empty())
145       if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
146         return notifyFailed(std::move(Err));
147 
148     if (const auto &InitSym = MR.getInitializerSymbol())
149       InternedResult[InitSym] = JITEvaluatedSymbol();
150 
151     {
152       // Check that InternedResult matches up with MR.getSymbols().
153       // This guards against faulty transformations / compilers / object caches.
154 
155       if (InternedResult.size() > MR.getSymbols().size()) {
156         SymbolNameVector ExtraSymbols;
157         for (auto &KV : InternedResult)
158           if (!MR.getSymbols().count(KV.first))
159             ExtraSymbols.push_back(KV.first);
160         ES.reportError(
161           make_error<UnexpectedSymbolDefinitions>(G.getName(),
162                                                   std::move(ExtraSymbols)));
163         MR.failMaterialization();
164         return;
165       }
166 
167       SymbolNameVector MissingSymbols;
168       for (auto &KV : MR.getSymbols())
169         if (!InternedResult.count(KV.first))
170           MissingSymbols.push_back(KV.first);
171 
172       if (!MissingSymbols.empty()) {
173         ES.reportError(
174           make_error<MissingSymbolDefinitions>(G.getName(),
175                                                std::move(MissingSymbols)));
176         MR.failMaterialization();
177         return;
178       }
179     }
180 
181     if (auto Err = MR.notifyResolved(InternedResult)) {
182       Layer.getExecutionSession().reportError(std::move(Err));
183       MR.failMaterialization();
184       return;
185     }
186     Layer.notifyLoaded(MR);
187   }
188 
189   void notifyFinalized(
190       std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
191     if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
192       Layer.getExecutionSession().reportError(std::move(Err));
193       MR.failMaterialization();
194       return;
195     }
196     if (auto Err = MR.notifyEmitted()) {
197       Layer.getExecutionSession().reportError(std::move(Err));
198       MR.failMaterialization();
199     }
200   }
201 
202   LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
203     return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
204   }
205 
206   Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
207     // Add passes to mark duplicate defs as should-discard, and to walk the
208     // link graph to build the symbol dependence graph.
209     Config.PrePrunePasses.push_back(
210         [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
211 
212     Layer.modifyPassConfig(MR, TT, Config);
213 
214     Config.PostPrunePasses.push_back(
215         [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
216 
217     return Error::success();
218   }
219 
220 private:
221   struct LocalSymbolNamedDependencies {
222     SymbolNameSet Internal, External;
223   };
224 
225   using LocalSymbolNamedDependenciesMap =
226       DenseMap<const Symbol *, LocalSymbolNamedDependencies>;
227 
228   Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
229     auto &ES = Layer.getExecutionSession();
230     for (auto *Sym : G.defined_symbols())
231       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
232         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
233           G.makeExternal(*Sym);
234       }
235 
236     for (auto *Sym : G.absolute_symbols())
237       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
238         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
239           G.makeExternal(*Sym);
240       }
241 
242     return Error::success();
243   }
244 
245   Error markResponsibilitySymbolsLive(LinkGraph &G) const {
246     auto &ES = Layer.getExecutionSession();
247     for (auto *Sym : G.defined_symbols())
248       if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
249         Sym->setLive(true);
250     return Error::success();
251   }
252 
253   Error computeNamedSymbolDependencies(LinkGraph &G) {
254     auto &ES = MR.getTargetJITDylib().getExecutionSession();
255     auto LocalDeps = computeLocalDeps(G);
256 
257     // Compute dependencies for symbols defined in the JITLink graph.
258     for (auto *Sym : G.defined_symbols()) {
259 
260       // Skip local symbols: we do not track dependencies for these.
261       if (Sym->getScope() == Scope::Local)
262         continue;
263       assert(Sym->hasName() &&
264              "Defined non-local jitlink::Symbol should have a name");
265 
266       SymbolNameSet ExternalSymDeps, InternalSymDeps;
267 
268       // Find internal and external named symbol dependencies.
269       for (auto &E : Sym->getBlock().edges()) {
270         auto &TargetSym = E.getTarget();
271 
272         if (TargetSym.getScope() != Scope::Local) {
273           if (TargetSym.isExternal())
274             ExternalSymDeps.insert(ES.intern(TargetSym.getName()));
275           else if (&TargetSym != Sym)
276             InternalSymDeps.insert(ES.intern(TargetSym.getName()));
277         } else {
278           assert(TargetSym.isDefined() &&
279                  "local symbols must be defined");
280           auto I = LocalDeps.find(&TargetSym);
281           if (I != LocalDeps.end()) {
282             for (auto &S : I->second.External)
283               ExternalSymDeps.insert(S);
284             for (auto &S : I->second.Internal)
285               InternalSymDeps.insert(S);
286           }
287         }
288       }
289 
290       if (ExternalSymDeps.empty() && InternalSymDeps.empty())
291         continue;
292 
293       auto SymName = ES.intern(Sym->getName());
294       if (!ExternalSymDeps.empty())
295         ExternalNamedSymbolDeps[SymName] = std::move(ExternalSymDeps);
296       if (!InternalSymDeps.empty())
297         InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps);
298     }
299 
300     for (auto &P : Layer.Plugins) {
301       auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(MR);
302       if (SyntheticLocalDeps.empty())
303         continue;
304 
305       for (auto &KV : SyntheticLocalDeps) {
306         auto &Name = KV.first;
307         auto &LocalDepsForName = KV.second;
308         for (auto *Local : LocalDepsForName) {
309           assert(Local->getScope() == Scope::Local &&
310                  "Dependence on non-local symbol");
311           auto LocalNamedDepsItr = LocalDeps.find(Local);
312           if (LocalNamedDepsItr == LocalDeps.end())
313             continue;
314           for (auto &S : LocalNamedDepsItr->second.Internal)
315             InternalNamedSymbolDeps[Name].insert(S);
316           for (auto &S : LocalNamedDepsItr->second.External)
317             ExternalNamedSymbolDeps[Name].insert(S);
318         }
319       }
320     }
321 
322     return Error::success();
323   }
324 
325   LocalSymbolNamedDependenciesMap computeLocalDeps(LinkGraph &G) {
326     DenseMap<jitlink::Symbol *, DenseSet<jitlink::Symbol *>> DepMap;
327 
328     // For all local symbols:
329     // (1) Add their named dependencies.
330     // (2) Add them to the worklist for further iteration if they have any
331     //     depend on any other local symbols.
332     struct WorklistEntry {
333       WorklistEntry(Symbol *Sym, DenseSet<Symbol *> LocalDeps)
334           : Sym(Sym), LocalDeps(std::move(LocalDeps)) {}
335 
336       Symbol *Sym = nullptr;
337       DenseSet<Symbol *> LocalDeps;
338     };
339     std::vector<WorklistEntry> Worklist;
340     for (auto *Sym : G.defined_symbols())
341       if (Sym->getScope() == Scope::Local) {
342         auto &SymNamedDeps = DepMap[Sym];
343         DenseSet<Symbol *> LocalDeps;
344 
345         for (auto &E : Sym->getBlock().edges()) {
346           auto &TargetSym = E.getTarget();
347           if (TargetSym.getScope() != Scope::Local)
348             SymNamedDeps.insert(&TargetSym);
349           else {
350             assert(TargetSym.isDefined() &&
351                    "local symbols must be defined");
352             LocalDeps.insert(&TargetSym);
353           }
354         }
355 
356         if (!LocalDeps.empty())
357           Worklist.push_back(WorklistEntry(Sym, std::move(LocalDeps)));
358       }
359 
360     // Loop over all local symbols with local dependencies, propagating
361     // their respective non-local dependencies. Iterate until we hit a stable
362     // state.
363     bool Changed;
364     do {
365       Changed = false;
366       for (auto &WLEntry : Worklist) {
367         auto *Sym = WLEntry.Sym;
368         auto &NamedDeps = DepMap[Sym];
369         auto &LocalDeps = WLEntry.LocalDeps;
370 
371         for (auto *TargetSym : LocalDeps) {
372           auto I = DepMap.find(TargetSym);
373           if (I != DepMap.end())
374             for (const auto &S : I->second)
375               Changed |= NamedDeps.insert(S).second;
376         }
377       }
378     } while (Changed);
379 
380     // Intern the results to produce a mapping of jitlink::Symbol* to internal
381     // and external symbol names.
382     auto &ES = Layer.getExecutionSession();
383     LocalSymbolNamedDependenciesMap Result;
384     for (auto &KV : DepMap) {
385       auto *Local = KV.first;
386       assert(Local->getScope() == Scope::Local &&
387              "DepMap keys should all be local symbols");
388       auto &LocalNamedDeps = Result[Local];
389       for (auto *Named : KV.second) {
390         assert(Named->getScope() != Scope::Local &&
391                "DepMap values should all be non-local symbol sets");
392         if (Named->isExternal())
393           LocalNamedDeps.External.insert(ES.intern(Named->getName()));
394         else
395           LocalNamedDeps.Internal.insert(ES.intern(Named->getName()));
396       }
397     }
398 
399     return Result;
400   }
401 
402   void registerDependencies(const SymbolDependenceMap &QueryDeps) {
403     for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
404       auto &Name = NamedDepsEntry.first;
405       auto &NameDeps = NamedDepsEntry.second;
406       SymbolDependenceMap SymbolDeps;
407 
408       for (const auto &QueryDepsEntry : QueryDeps) {
409         JITDylib &SourceJD = *QueryDepsEntry.first;
410         const SymbolNameSet &Symbols = QueryDepsEntry.second;
411         auto &DepsForJD = SymbolDeps[&SourceJD];
412 
413         for (const auto &S : Symbols)
414           if (NameDeps.count(S))
415             DepsForJD.insert(S);
416 
417         if (DepsForJD.empty())
418           SymbolDeps.erase(&SourceJD);
419       }
420 
421       MR.addDependencies(Name, SymbolDeps);
422     }
423   }
424 
425   ObjectLinkingLayer &Layer;
426   MaterializationResponsibility MR;
427   std::unique_ptr<MemoryBuffer> ObjBuffer;
428   DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
429   DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
430 };
431 
432 ObjectLinkingLayer::Plugin::~Plugin() {}
433 
434 ObjectLinkingLayer::ObjectLinkingLayer(
435     ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
436     : ObjectLayer(ES), MemMgr(std::move(MemMgr)) {}
437 
438 ObjectLinkingLayer::~ObjectLinkingLayer() {
439   if (auto Err = removeAllModules())
440     getExecutionSession().reportError(std::move(Err));
441 }
442 
443 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
444                               std::unique_ptr<MemoryBuffer> O) {
445   assert(O && "Object must not be null");
446   jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
447       *this, std::move(R), std::move(O)));
448 }
449 
450 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
451                                           const Triple &TT,
452                                           PassConfiguration &PassConfig) {
453   for (auto &P : Plugins)
454     P->modifyPassConfig(MR, TT, PassConfig);
455 }
456 
457 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
458   for (auto &P : Plugins)
459     P->notifyLoaded(MR);
460 }
461 
462 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
463                                         AllocPtr Alloc) {
464   Error Err = Error::success();
465   for (auto &P : Plugins)
466     Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
467 
468   if (Err)
469     return Err;
470 
471   {
472     std::lock_guard<std::mutex> Lock(LayerMutex);
473     UntrackedAllocs.push_back(std::move(Alloc));
474   }
475 
476   return Error::success();
477 }
478 
479 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
480   Error Err = Error::success();
481 
482   for (auto &P : Plugins)
483     Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
484 
485   AllocPtr Alloc;
486 
487   {
488     std::lock_guard<std::mutex> Lock(LayerMutex);
489     auto AllocItr = TrackedAllocs.find(K);
490     Alloc = std::move(AllocItr->second);
491     TrackedAllocs.erase(AllocItr);
492   }
493 
494   assert(Alloc && "No allocation for key K");
495 
496   return joinErrors(std::move(Err), Alloc->deallocate());
497 }
498 
499 Error ObjectLinkingLayer::removeAllModules() {
500 
501   Error Err = Error::success();
502 
503   for (auto &P : Plugins)
504     Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
505 
506   std::vector<AllocPtr> Allocs;
507   {
508     std::lock_guard<std::mutex> Lock(LayerMutex);
509     Allocs = std::move(UntrackedAllocs);
510 
511     for (auto &KV : TrackedAllocs)
512       Allocs.push_back(std::move(KV.second));
513 
514     TrackedAllocs.clear();
515   }
516 
517   while (!Allocs.empty()) {
518     Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
519     Allocs.pop_back();
520   }
521 
522   return Err;
523 }
524 
525 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
526     EHFrameRegistrar &Registrar)
527     : Registrar(Registrar) {}
528 
529 void EHFrameRegistrationPlugin::modifyPassConfig(
530     MaterializationResponsibility &MR, const Triple &TT,
531     PassConfiguration &PassConfig) {
532 
533   PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
534       TT, [this, &MR](JITTargetAddress Addr, size_t Size) {
535         if (Addr) {
536           std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
537           assert(!InProcessLinks.count(&MR) &&
538                  "Link for MR already being tracked?");
539           InProcessLinks[&MR] = {Addr, Size};
540         }
541       }));
542 }
543 
544 Error EHFrameRegistrationPlugin::notifyEmitted(
545     MaterializationResponsibility &MR) {
546   std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
547 
548   auto EHFrameRangeItr = InProcessLinks.find(&MR);
549   if (EHFrameRangeItr == InProcessLinks.end())
550     return Error::success();
551 
552   auto EHFrameRange = EHFrameRangeItr->second;
553   assert(EHFrameRange.Addr &&
554          "eh-frame addr to register can not be null");
555 
556   InProcessLinks.erase(EHFrameRangeItr);
557   if (auto Key = MR.getVModuleKey())
558     TrackedEHFrameRanges[Key] = EHFrameRange;
559   else
560     UntrackedEHFrameRanges.push_back(EHFrameRange);
561 
562   return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
563 }
564 
565 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
566   std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
567 
568   auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
569   if (EHFrameRangeItr == TrackedEHFrameRanges.end())
570     return Error::success();
571 
572   auto EHFrameRange = EHFrameRangeItr->second;
573   assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
574 
575   TrackedEHFrameRanges.erase(EHFrameRangeItr);
576 
577   return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
578 }
579 
580 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
581   std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
582 
583   std::vector<EHFrameRange> EHFrameRanges =
584     std::move(UntrackedEHFrameRanges);
585   EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
586 
587   for (auto &KV : TrackedEHFrameRanges)
588     EHFrameRanges.push_back(KV.second);
589 
590   TrackedEHFrameRanges.clear();
591 
592   Error Err = Error::success();
593 
594   while (!EHFrameRanges.empty()) {
595     auto EHFrameRange = EHFrameRanges.back();
596     assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
597     EHFrameRanges.pop_back();
598     Err = joinErrors(std::move(Err),
599                      Registrar.deregisterEHFrames(EHFrameRange.Addr,
600                                                   EHFrameRange.Size));
601   }
602 
603   return Err;
604 }
605 
606 } // End namespace orc.
607 } // End namespace llvm.
608