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