ObjectLinkingLayer.cpp revision 360784
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
18using namespace llvm;
19using namespace llvm::jitlink;
20using namespace llvm::orc;
21
22namespace llvm {
23namespace orc {
24
25class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
26public:
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
179private:
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
329ObjectLinkingLayer::Plugin::~Plugin() {}
330
331ObjectLinkingLayer::ObjectLinkingLayer(
332    ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
333    : ObjectLayer(ES), MemMgr(std::move(MemMgr)) {}
334
335ObjectLinkingLayer::~ObjectLinkingLayer() {
336  if (auto Err = removeAllModules())
337    getExecutionSession().reportError(std::move(Err));
338}
339
340void 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
347void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
348                                          const Triple &TT,
349                                          PassConfiguration &PassConfig) {
350  for (auto &P : Plugins)
351    P->modifyPassConfig(MR, TT, PassConfig);
352}
353
354void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
355  for (auto &P : Plugins)
356    P->notifyLoaded(MR);
357}
358
359Error 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
376Error 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
396Error 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
422EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
423    EHFrameRegistrar &Registrar)
424    : Registrar(Registrar) {}
425
426void 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
439Error 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
459Error 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
472Error 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