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