xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision 4e920e58e6bc3bf4450b0aae6e225943957de195)
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   JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
33 
34   MemoryBufferRef getObjectBuffer() const override {
35     return ObjBuffer->getMemBufferRef();
36   }
37 
38   void notifyFailed(Error Err) override {
39     Layer.getExecutionSession().reportError(std::move(Err));
40     MR.failMaterialization();
41   }
42 
43   void lookup(const DenseSet<StringRef> &Symbols,
44               std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
45 
46     JITDylibSearchList SearchOrder;
47     MR.getTargetJITDylib().withSearchOrderDo(
48         [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
49 
50     auto &ES = Layer.getExecutionSession();
51 
52     SymbolNameSet InternedSymbols;
53     for (auto &S : Symbols)
54       InternedSymbols.insert(ES.intern(S));
55 
56     // OnResolve -- De-intern the symbols and pass the result to the linker.
57     auto OnResolve = [this, LookupContinuation = std::move(LC)](
58                          Expected<SymbolMap> Result) mutable {
59       auto Main = Layer.getExecutionSession().intern("_main");
60       if (!Result)
61         LookupContinuation->run(Result.takeError());
62       else {
63         AsyncLookupResult LR;
64         for (auto &KV : *Result)
65           LR[*KV.first] = KV.second;
66         LookupContinuation->run(std::move(LR));
67       }
68     };
69 
70     ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
71               std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
72                 registerDependencies(Deps);
73               });
74   }
75 
76   void notifyResolved(LinkGraph &G) override {
77     auto &ES = Layer.getExecutionSession();
78 
79     SymbolFlagsMap ExtraSymbolsToClaim;
80     bool AutoClaim = Layer.AutoClaimObjectSymbols;
81 
82     SymbolMap InternedResult;
83     for (auto *Sym : G.defined_symbols())
84       if (Sym->hasName() && Sym->getScope() != Scope::Local) {
85         auto InternedName = ES.intern(Sym->getName());
86         JITSymbolFlags Flags;
87 
88         if (Sym->isCallable())
89           Flags |= JITSymbolFlags::Callable;
90         if (Sym->getScope() == Scope::Default)
91           Flags |= JITSymbolFlags::Exported;
92 
93         InternedResult[InternedName] =
94             JITEvaluatedSymbol(Sym->getAddress(), Flags);
95         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
96           assert(!ExtraSymbolsToClaim.count(InternedName) &&
97                  "Duplicate symbol to claim?");
98           ExtraSymbolsToClaim[InternedName] = Flags;
99         }
100       }
101 
102     for (auto *Sym : G.absolute_symbols())
103       if (Sym->hasName()) {
104         auto InternedName = ES.intern(Sym->getName());
105         JITSymbolFlags Flags;
106         Flags |= JITSymbolFlags::Absolute;
107         if (Sym->isCallable())
108           Flags |= JITSymbolFlags::Callable;
109         if (Sym->getLinkage() == Linkage::Weak)
110           Flags |= JITSymbolFlags::Weak;
111         InternedResult[InternedName] =
112             JITEvaluatedSymbol(Sym->getAddress(), Flags);
113         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
114           assert(!ExtraSymbolsToClaim.count(InternedName) &&
115                  "Duplicate symbol to claim?");
116           ExtraSymbolsToClaim[InternedName] = Flags;
117         }
118       }
119 
120     if (!ExtraSymbolsToClaim.empty())
121       if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
122         return notifyFailed(std::move(Err));
123     if (auto Err = MR.notifyResolved(InternedResult)) {
124       Layer.getExecutionSession().reportError(std::move(Err));
125       MR.failMaterialization();
126       return;
127     }
128     Layer.notifyLoaded(MR);
129   }
130 
131   void notifyFinalized(
132       std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
133     if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
134       Layer.getExecutionSession().reportError(std::move(Err));
135       MR.failMaterialization();
136       return;
137     }
138     if (auto Err = MR.notifyEmitted()) {
139       Layer.getExecutionSession().reportError(std::move(Err));
140       MR.failMaterialization();
141     }
142   }
143 
144   LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
145     return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
146   }
147 
148   Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
149     // Add passes to mark duplicate defs as should-discard, and to walk the
150     // link graph to build the symbol dependence graph.
151     Config.PrePrunePasses.push_back(
152         [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
153     Config.PostPrunePasses.push_back(
154         [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
155 
156     Layer.modifyPassConfig(MR, TT, Config);
157 
158     return Error::success();
159   }
160 
161 private:
162   using AnonToNamedDependenciesMap = DenseMap<const Symbol *, SymbolNameSet>;
163 
164   Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
165     auto &ES = Layer.getExecutionSession();
166     for (auto *Sym : G.defined_symbols())
167       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
168         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
169           G.makeExternal(*Sym);
170       }
171 
172     for (auto *Sym : G.absolute_symbols())
173       if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
174         if (!MR.getSymbols().count(ES.intern(Sym->getName())))
175           G.makeExternal(*Sym);
176       }
177 
178     return Error::success();
179   }
180 
181   Error markResponsibilitySymbolsLive(LinkGraph &G) const {
182     auto &ES = Layer.getExecutionSession();
183     for (auto *Sym : G.defined_symbols())
184       if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
185         Sym->setLive(true);
186     return Error::success();
187   }
188 
189   Error computeNamedSymbolDependencies(LinkGraph &G) {
190     auto &ES = MR.getTargetJITDylib().getExecutionSession();
191     auto AnonDeps = computeAnonDeps(G);
192 
193     for (auto *Sym : G.defined_symbols()) {
194 
195       // Skip anonymous and non-global atoms: we do not need dependencies for
196       // these.
197       if (Sym->getScope() == Scope::Local)
198         continue;
199 
200       auto SymName = ES.intern(Sym->getName());
201       SymbolNameSet &SymDeps = NamedSymbolDeps[SymName];
202 
203       for (auto &E : Sym->getBlock().edges()) {
204         auto &TargetSym = E.getTarget();
205 
206         if (TargetSym.getScope() != Scope::Local)
207           SymDeps.insert(ES.intern(TargetSym.getName()));
208         else {
209           assert(TargetSym.isDefined() &&
210                  "Anonymous/local symbols must be defined");
211           auto I = AnonDeps.find(&TargetSym);
212           if (I != AnonDeps.end())
213             for (auto &S : I->second)
214               SymDeps.insert(S);
215         }
216       }
217     }
218 
219     return Error::success();
220   }
221 
222   AnonToNamedDependenciesMap computeAnonDeps(LinkGraph &G) {
223 
224     auto &ES = MR.getTargetJITDylib().getExecutionSession();
225     AnonToNamedDependenciesMap DepMap;
226 
227     // For all anonymous symbols:
228     // (1) Add their named dependencies.
229     // (2) Add them to the worklist for further iteration if they have any
230     //     depend on any other anonymous symbols.
231     struct WorklistEntry {
232       WorklistEntry(Symbol *Sym, DenseSet<Symbol *> SymAnonDeps)
233           : Sym(Sym), SymAnonDeps(std::move(SymAnonDeps)) {}
234 
235       Symbol *Sym = nullptr;
236       DenseSet<Symbol *> SymAnonDeps;
237     };
238     std::vector<WorklistEntry> Worklist;
239     for (auto *Sym : G.defined_symbols())
240       if (!Sym->hasName()) {
241         auto &SymNamedDeps = DepMap[Sym];
242         DenseSet<Symbol *> SymAnonDeps;
243 
244         for (auto &E : Sym->getBlock().edges()) {
245           auto &TargetSym = E.getTarget();
246           if (TargetSym.hasName())
247             SymNamedDeps.insert(ES.intern(TargetSym.getName()));
248           else {
249             assert(TargetSym.isDefined() &&
250                    "Anonymous symbols must be defined");
251             SymAnonDeps.insert(&TargetSym);
252           }
253         }
254 
255         if (!SymAnonDeps.empty())
256           Worklist.push_back(WorklistEntry(Sym, std::move(SymAnonDeps)));
257       }
258 
259     // Loop over all anonymous symbols with anonymous dependencies, propagating
260     // their respective *named* dependencies. Iterate until we hit a stable
261     // state.
262     bool Changed;
263     do {
264       Changed = false;
265       for (auto &WLEntry : Worklist) {
266         auto *Sym = WLEntry.Sym;
267         auto &SymNamedDeps = DepMap[Sym];
268         auto &SymAnonDeps = WLEntry.SymAnonDeps;
269 
270         for (auto *TargetSym : SymAnonDeps) {
271           auto I = DepMap.find(TargetSym);
272           if (I != DepMap.end())
273             for (const auto &S : I->second)
274               Changed |= SymNamedDeps.insert(S).second;
275         }
276       }
277     } while (Changed);
278 
279     return DepMap;
280   }
281 
282   void registerDependencies(const SymbolDependenceMap &QueryDeps) {
283     for (auto &NamedDepsEntry : NamedSymbolDeps) {
284       auto &Name = NamedDepsEntry.first;
285       auto &NameDeps = NamedDepsEntry.second;
286       SymbolDependenceMap SymbolDeps;
287 
288       for (const auto &QueryDepsEntry : QueryDeps) {
289         JITDylib &SourceJD = *QueryDepsEntry.first;
290         const SymbolNameSet &Symbols = QueryDepsEntry.second;
291         auto &DepsForJD = SymbolDeps[&SourceJD];
292 
293         for (const auto &S : Symbols)
294           if (NameDeps.count(S))
295             DepsForJD.insert(S);
296 
297         if (DepsForJD.empty())
298           SymbolDeps.erase(&SourceJD);
299       }
300 
301       MR.addDependencies(Name, SymbolDeps);
302     }
303   }
304 
305   ObjectLinkingLayer &Layer;
306   MaterializationResponsibility MR;
307   std::unique_ptr<MemoryBuffer> ObjBuffer;
308   DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
309 };
310 
311 ObjectLinkingLayer::Plugin::~Plugin() {}
312 
313 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
314                                        JITLinkMemoryManager &MemMgr)
315     : ObjectLayer(ES), MemMgr(MemMgr) {}
316 
317 ObjectLinkingLayer::~ObjectLinkingLayer() {
318   if (auto Err = removeAllModules())
319     getExecutionSession().reportError(std::move(Err));
320 }
321 
322 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
323                               std::unique_ptr<MemoryBuffer> O) {
324   assert(O && "Object must not be null");
325   jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
326       *this, std::move(R), std::move(O)));
327 }
328 
329 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
330                                           const Triple &TT,
331                                           PassConfiguration &PassConfig) {
332   for (auto &P : Plugins)
333     P->modifyPassConfig(MR, TT, PassConfig);
334 }
335 
336 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
337   for (auto &P : Plugins)
338     P->notifyLoaded(MR);
339 }
340 
341 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
342                                         AllocPtr Alloc) {
343   Error Err = Error::success();
344   for (auto &P : Plugins)
345     Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
346 
347   if (Err)
348     return Err;
349 
350   {
351     std::lock_guard<std::mutex> Lock(LayerMutex);
352     UntrackedAllocs.push_back(std::move(Alloc));
353   }
354 
355   return Error::success();
356 }
357 
358 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
359   Error Err = Error::success();
360 
361   for (auto &P : Plugins)
362     Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
363 
364   AllocPtr Alloc;
365 
366   {
367     std::lock_guard<std::mutex> Lock(LayerMutex);
368     auto AllocItr = TrackedAllocs.find(K);
369     Alloc = std::move(AllocItr->second);
370     TrackedAllocs.erase(AllocItr);
371   }
372 
373   assert(Alloc && "No allocation for key K");
374 
375   return joinErrors(std::move(Err), Alloc->deallocate());
376 }
377 
378 Error ObjectLinkingLayer::removeAllModules() {
379 
380   Error Err = Error::success();
381 
382   for (auto &P : Plugins)
383     Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
384 
385   std::vector<AllocPtr> Allocs;
386   {
387     std::lock_guard<std::mutex> Lock(LayerMutex);
388     Allocs = std::move(UntrackedAllocs);
389 
390     for (auto &KV : TrackedAllocs)
391       Allocs.push_back(std::move(KV.second));
392 
393     TrackedAllocs.clear();
394   }
395 
396   while (!Allocs.empty()) {
397     Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
398     Allocs.pop_back();
399   }
400 
401   return Err;
402 }
403 
404 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
405     EHFrameRegistrar &Registrar)
406     : Registrar(Registrar) {}
407 
408 void EHFrameRegistrationPlugin::modifyPassConfig(
409     MaterializationResponsibility &MR, const Triple &TT,
410     PassConfiguration &PassConfig) {
411   assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
412 
413   PassConfig.PostFixupPasses.push_back(
414       createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
415                                                 size_t Size) {
416         if (Addr)
417           InProcessLinks[&MR] = { Addr, Size };
418       }));
419 }
420 
421 Error EHFrameRegistrationPlugin::notifyEmitted(
422     MaterializationResponsibility &MR) {
423 
424   auto EHFrameRangeItr = InProcessLinks.find(&MR);
425   if (EHFrameRangeItr == InProcessLinks.end())
426     return Error::success();
427 
428   auto EHFrameRange = EHFrameRangeItr->second;
429   assert(EHFrameRange.Addr &&
430          "eh-frame addr to register can not be null");
431 
432   InProcessLinks.erase(EHFrameRangeItr);
433   if (auto Key = MR.getVModuleKey())
434     TrackedEHFrameRanges[Key] = EHFrameRange;
435   else
436     UntrackedEHFrameRanges.push_back(EHFrameRange);
437 
438   return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
439 }
440 
441 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
442   auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
443   if (EHFrameRangeItr == TrackedEHFrameRanges.end())
444     return Error::success();
445 
446   auto EHFrameRange = EHFrameRangeItr->second;
447   assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
448 
449   TrackedEHFrameRanges.erase(EHFrameRangeItr);
450 
451   return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
452 }
453 
454 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
455 
456   std::vector<EHFrameRange> EHFrameRanges =
457     std::move(UntrackedEHFrameRanges);
458   EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
459 
460   for (auto &KV : TrackedEHFrameRanges)
461     EHFrameRanges.push_back(KV.second);
462 
463   TrackedEHFrameRanges.clear();
464 
465   Error Err = Error::success();
466 
467   while (!EHFrameRanges.empty()) {
468     auto EHFrameRange = EHFrameRanges.back();
469     assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
470     EHFrameRanges.pop_back();
471     Err = joinErrors(std::move(Err),
472                      Registrar.deregisterEHFrames(EHFrameRange.Addr,
473                                                   EHFrameRange.Size));
474   }
475 
476   return Err;
477 }
478 
479 } // End namespace orc.
480 } // End namespace llvm.
481