xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision 0929924b610c8365202e04e3482ecda88e895a1a)
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 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  
236  private:
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  
448  ObjectLinkingLayer::Plugin::~Plugin() {}
449  
450  ObjectLinkingLayer::ObjectLinkingLayer(
451      ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
452      : ObjectLayer(ES), MemMgr(std::move(MemMgr)) {}
453  
454  ObjectLinkingLayer::~ObjectLinkingLayer() {
455    if (auto Err = removeAllModules())
456      getExecutionSession().reportError(std::move(Err));
457  }
458  
459  void 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  
466  void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
467                                            const Triple &TT,
468                                            PassConfiguration &PassConfig) {
469    for (auto &P : Plugins)
470      P->modifyPassConfig(MR, TT, PassConfig);
471  }
472  
473  void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
474    for (auto &P : Plugins)
475      P->notifyLoaded(MR);
476  }
477  
478  Error 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  
495  Error 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  
515  Error 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  
541  EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
542      EHFrameRegistrar &Registrar)
543      : Registrar(Registrar) {}
544  
545  void 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  
560  Error 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  
581  Error 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  
596  Error 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