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