xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision ca6f58486ffda249a4330f5a9e20266ea8a40806)
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     if (auto Err = MR.notifyResolved(InternedResult)) {
148       Layer.getExecutionSession().reportError(std::move(Err));
149       MR.failMaterialization();
150       return;
151     }
152     Layer.notifyLoaded(MR);
153   }
154 
155   void notifyFinalized(
156       std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
157     if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
158       Layer.getExecutionSession().reportError(std::move(Err));
159       MR.failMaterialization();
160       return;
161     }
162     if (auto Err = MR.notifyEmitted()) {
163       Layer.getExecutionSession().reportError(std::move(Err));
164       MR.failMaterialization();
165     }
166   }
167 
168   LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
169     return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
170   }
171 
172   Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
173     // Add passes to mark duplicate defs as should-discard, and to walk the
174     // link graph to build the symbol dependence graph.
175     Config.PrePrunePasses.push_back(
176         [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
177 
178     Layer.modifyPassConfig(MR, TT, Config);
179 
180     Config.PostPrunePasses.push_back(
181         [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
182 
183     return Error::success();
184   }
185 
186 private:
187   using JITLinkSymbolSet = DenseSet<const Symbol *>;
188   using LocalToNamedDependenciesMap = DenseMap<const Symbol *, JITLinkSymbolSet>;
189 
190   Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
191     auto &ES = Layer.getExecutionSession();
192     for (auto *Sym : G.defined_symbols())
193       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
194         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
195           G.makeExternal(*Sym);
196       }
197 
198     for (auto *Sym : G.absolute_symbols())
199       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
200         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
201           G.makeExternal(*Sym);
202       }
203 
204     return Error::success();
205   }
206 
207   Error markResponsibilitySymbolsLive(LinkGraph &G) const {
208     auto &ES = Layer.getExecutionSession();
209     for (auto *Sym : G.defined_symbols())
210       if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
211         Sym->setLive(true);
212     return Error::success();
213   }
214 
215   Error computeNamedSymbolDependencies(LinkGraph &G) {
216     auto &ES = MR.getTargetJITDylib().getExecutionSession();
217     auto LocalDeps = computeLocalDeps(G);
218 
219     for (auto *Sym : G.defined_symbols()) {
220 
221       // Skip local symbols: we do not track dependencies for these.
222       if (Sym->getScope() == Scope::Local)
223         continue;
224       assert(Sym->hasName() &&
225              "Defined non-local jitlink::Symbol should have a name");
226 
227       SymbolNameSet ExternalSymDeps, InternalSymDeps;
228 
229       // Find internal and external named symbol dependencies.
230       for (auto &E : Sym->getBlock().edges()) {
231         auto &TargetSym = E.getTarget();
232 
233         if (TargetSym.getScope() != Scope::Local) {
234           if (TargetSym.isExternal())
235             ExternalSymDeps.insert(ES.intern(TargetSym.getName()));
236           else if (&TargetSym != Sym)
237             InternalSymDeps.insert(ES.intern(TargetSym.getName()));
238         } else {
239           assert(TargetSym.isDefined() &&
240                  "local symbols must be defined");
241           auto I = LocalDeps.find(&TargetSym);
242           if (I != LocalDeps.end())
243             for (auto &S : I->second) {
244               assert(S->hasName() &&
245                      "LocalDeps should only contain named values");
246               if (S->isExternal())
247                 ExternalSymDeps.insert(ES.intern(S->getName()));
248               else if (S != Sym)
249                 InternalSymDeps.insert(ES.intern(S->getName()));
250             }
251         }
252       }
253 
254       if (ExternalSymDeps.empty() && InternalSymDeps.empty())
255         continue;
256 
257       auto SymName = ES.intern(Sym->getName());
258       if (!ExternalSymDeps.empty())
259         ExternalNamedSymbolDeps[SymName] = std::move(ExternalSymDeps);
260       if (!InternalSymDeps.empty())
261         InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps);
262     }
263 
264     return Error::success();
265   }
266 
267   LocalToNamedDependenciesMap computeLocalDeps(LinkGraph &G) {
268     LocalToNamedDependenciesMap DepMap;
269 
270     // For all local symbols:
271     // (1) Add their named dependencies.
272     // (2) Add them to the worklist for further iteration if they have any
273     //     depend on any other local symbols.
274     struct WorklistEntry {
275       WorklistEntry(Symbol *Sym, DenseSet<Symbol *> LocalDeps)
276           : Sym(Sym), LocalDeps(std::move(LocalDeps)) {}
277 
278       Symbol *Sym = nullptr;
279       DenseSet<Symbol *> LocalDeps;
280     };
281     std::vector<WorklistEntry> Worklist;
282     for (auto *Sym : G.defined_symbols())
283       if (Sym->getScope() == Scope::Local) {
284         auto &SymNamedDeps = DepMap[Sym];
285         DenseSet<Symbol *> LocalDeps;
286 
287         for (auto &E : Sym->getBlock().edges()) {
288           auto &TargetSym = E.getTarget();
289           if (TargetSym.getScope() != Scope::Local)
290             SymNamedDeps.insert(&TargetSym);
291           else {
292             assert(TargetSym.isDefined() &&
293                    "local symbols must be defined");
294             LocalDeps.insert(&TargetSym);
295           }
296         }
297 
298         if (!LocalDeps.empty())
299           Worklist.push_back(WorklistEntry(Sym, std::move(LocalDeps)));
300       }
301 
302     // Loop over all local symbols with local dependencies, propagating
303     // their respective non-local dependencies. Iterate until we hit a stable
304     // state.
305     bool Changed;
306     do {
307       Changed = false;
308       for (auto &WLEntry : Worklist) {
309         auto *Sym = WLEntry.Sym;
310         auto &NamedDeps = DepMap[Sym];
311         auto &LocalDeps = WLEntry.LocalDeps;
312 
313         for (auto *TargetSym : LocalDeps) {
314           auto I = DepMap.find(TargetSym);
315           if (I != DepMap.end())
316             for (const auto &S : I->second)
317               Changed |= NamedDeps.insert(S).second;
318         }
319       }
320     } while (Changed);
321 
322     return DepMap;
323   }
324 
325   void registerDependencies(const SymbolDependenceMap &QueryDeps) {
326     for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
327       auto &Name = NamedDepsEntry.first;
328       auto &NameDeps = NamedDepsEntry.second;
329       SymbolDependenceMap SymbolDeps;
330 
331       for (const auto &QueryDepsEntry : QueryDeps) {
332         JITDylib &SourceJD = *QueryDepsEntry.first;
333         const SymbolNameSet &Symbols = QueryDepsEntry.second;
334         auto &DepsForJD = SymbolDeps[&SourceJD];
335 
336         for (const auto &S : Symbols)
337           if (NameDeps.count(S))
338             DepsForJD.insert(S);
339 
340         if (DepsForJD.empty())
341           SymbolDeps.erase(&SourceJD);
342       }
343 
344       MR.addDependencies(Name, SymbolDeps);
345     }
346   }
347 
348   ObjectLinkingLayer &Layer;
349   MaterializationResponsibility MR;
350   std::unique_ptr<MemoryBuffer> ObjBuffer;
351   DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
352   DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
353 };
354 
355 ObjectLinkingLayer::Plugin::~Plugin() {}
356 
357 ObjectLinkingLayer::ObjectLinkingLayer(
358     ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
359     : ObjectLayer(ES), MemMgr(std::move(MemMgr)) {}
360 
361 ObjectLinkingLayer::~ObjectLinkingLayer() {
362   if (auto Err = removeAllModules())
363     getExecutionSession().reportError(std::move(Err));
364 }
365 
366 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
367                               std::unique_ptr<MemoryBuffer> O) {
368   assert(O && "Object must not be null");
369   jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
370       *this, std::move(R), std::move(O)));
371 }
372 
373 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
374                                           const Triple &TT,
375                                           PassConfiguration &PassConfig) {
376   for (auto &P : Plugins)
377     P->modifyPassConfig(MR, TT, PassConfig);
378 }
379 
380 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
381   for (auto &P : Plugins)
382     P->notifyLoaded(MR);
383 }
384 
385 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
386                                         AllocPtr Alloc) {
387   Error Err = Error::success();
388   for (auto &P : Plugins)
389     Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
390 
391   if (Err)
392     return Err;
393 
394   {
395     std::lock_guard<std::mutex> Lock(LayerMutex);
396     UntrackedAllocs.push_back(std::move(Alloc));
397   }
398 
399   return Error::success();
400 }
401 
402 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
403   Error Err = Error::success();
404 
405   for (auto &P : Plugins)
406     Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
407 
408   AllocPtr Alloc;
409 
410   {
411     std::lock_guard<std::mutex> Lock(LayerMutex);
412     auto AllocItr = TrackedAllocs.find(K);
413     Alloc = std::move(AllocItr->second);
414     TrackedAllocs.erase(AllocItr);
415   }
416 
417   assert(Alloc && "No allocation for key K");
418 
419   return joinErrors(std::move(Err), Alloc->deallocate());
420 }
421 
422 Error ObjectLinkingLayer::removeAllModules() {
423 
424   Error Err = Error::success();
425 
426   for (auto &P : Plugins)
427     Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
428 
429   std::vector<AllocPtr> Allocs;
430   {
431     std::lock_guard<std::mutex> Lock(LayerMutex);
432     Allocs = std::move(UntrackedAllocs);
433 
434     for (auto &KV : TrackedAllocs)
435       Allocs.push_back(std::move(KV.second));
436 
437     TrackedAllocs.clear();
438   }
439 
440   while (!Allocs.empty()) {
441     Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
442     Allocs.pop_back();
443   }
444 
445   return Err;
446 }
447 
448 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
449     EHFrameRegistrar &Registrar)
450     : Registrar(Registrar) {}
451 
452 void EHFrameRegistrationPlugin::modifyPassConfig(
453     MaterializationResponsibility &MR, const Triple &TT,
454     PassConfiguration &PassConfig) {
455   assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
456 
457   PassConfig.PostFixupPasses.push_back(
458       createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
459                                                 size_t Size) {
460         if (Addr)
461           InProcessLinks[&MR] = { Addr, Size };
462       }));
463 }
464 
465 Error EHFrameRegistrationPlugin::notifyEmitted(
466     MaterializationResponsibility &MR) {
467 
468   auto EHFrameRangeItr = InProcessLinks.find(&MR);
469   if (EHFrameRangeItr == InProcessLinks.end())
470     return Error::success();
471 
472   auto EHFrameRange = EHFrameRangeItr->second;
473   assert(EHFrameRange.Addr &&
474          "eh-frame addr to register can not be null");
475 
476   InProcessLinks.erase(EHFrameRangeItr);
477   if (auto Key = MR.getVModuleKey())
478     TrackedEHFrameRanges[Key] = EHFrameRange;
479   else
480     UntrackedEHFrameRanges.push_back(EHFrameRange);
481 
482   return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
483 }
484 
485 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
486   auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
487   if (EHFrameRangeItr == TrackedEHFrameRanges.end())
488     return Error::success();
489 
490   auto EHFrameRange = EHFrameRangeItr->second;
491   assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
492 
493   TrackedEHFrameRanges.erase(EHFrameRangeItr);
494 
495   return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
496 }
497 
498 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
499 
500   std::vector<EHFrameRange> EHFrameRanges =
501     std::move(UntrackedEHFrameRanges);
502   EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
503 
504   for (auto &KV : TrackedEHFrameRanges)
505     EHFrameRanges.push_back(KV.second);
506 
507   TrackedEHFrameRanges.clear();
508 
509   Error Err = Error::success();
510 
511   while (!EHFrameRanges.empty()) {
512     auto EHFrameRange = EHFrameRanges.back();
513     assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
514     EHFrameRanges.pop_back();
515     Err = joinErrors(std::move(Err),
516                      Registrar.deregisterEHFrames(EHFrameRange.Addr,
517                                                   EHFrameRange.Size));
518   }
519 
520   return Err;
521 }
522 
523 } // End namespace orc.
524 } // End namespace llvm.
525