xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/EHFrameRegistrationPlugin.cpp (revision 6d12b954a7df11e32acf110950d88bac282079b8)
1 //===--------- EHFrameRegistrationPlugin.cpp - Register eh-frames ---------===//
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/EHFrameRegistrationPlugin.h"
10 
11 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
12 
13 #define DEBUG_TYPE "orc"
14 
15 using namespace llvm::jitlink;
16 
17 namespace llvm::orc {
18 
19 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
20     ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
21     : ES(ES), Registrar(std::move(Registrar)) {}
22 
23 void EHFrameRegistrationPlugin::modifyPassConfig(
24     MaterializationResponsibility &MR, LinkGraph &G,
25     PassConfiguration &PassConfig) {
26 
27   PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
28       G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
29         if (Addr) {
30           std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
31           assert(!InProcessLinks.count(&MR) &&
32                  "Link for MR already being tracked?");
33           InProcessLinks[&MR] = {Addr, Size};
34         }
35       }));
36 }
37 
38 Error EHFrameRegistrationPlugin::notifyEmitted(
39     MaterializationResponsibility &MR) {
40 
41   ExecutorAddrRange EmittedRange;
42   {
43     std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
44 
45     auto EHFrameRangeItr = InProcessLinks.find(&MR);
46     if (EHFrameRangeItr == InProcessLinks.end())
47       return Error::success();
48 
49     EmittedRange = EHFrameRangeItr->second;
50     assert(EmittedRange.Start && "eh-frame addr to register can not be null");
51     InProcessLinks.erase(EHFrameRangeItr);
52   }
53 
54   if (auto Err = MR.withResourceKeyDo(
55           [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
56     return Err;
57 
58   return Registrar->registerEHFrames(EmittedRange);
59 }
60 
61 Error EHFrameRegistrationPlugin::notifyFailed(
62     MaterializationResponsibility &MR) {
63   std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
64   InProcessLinks.erase(&MR);
65   return Error::success();
66 }
67 
68 Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
69                                                          ResourceKey K) {
70   std::vector<ExecutorAddrRange> RangesToRemove;
71 
72   ES.runSessionLocked([&] {
73     auto I = EHFrameRanges.find(K);
74     if (I != EHFrameRanges.end()) {
75       RangesToRemove = std::move(I->second);
76       EHFrameRanges.erase(I);
77     }
78   });
79 
80   Error Err = Error::success();
81   while (!RangesToRemove.empty()) {
82     auto RangeToRemove = RangesToRemove.back();
83     RangesToRemove.pop_back();
84     assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
85     Err = joinErrors(std::move(Err),
86                      Registrar->deregisterEHFrames(RangeToRemove));
87   }
88 
89   return Err;
90 }
91 
92 void EHFrameRegistrationPlugin::notifyTransferringResources(
93     JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
94   auto SI = EHFrameRanges.find(SrcKey);
95   if (SI == EHFrameRanges.end())
96     return;
97 
98   auto DI = EHFrameRanges.find(DstKey);
99   if (DI != EHFrameRanges.end()) {
100     auto &SrcRanges = SI->second;
101     auto &DstRanges = DI->second;
102     DstRanges.reserve(DstRanges.size() + SrcRanges.size());
103     for (auto &SrcRange : SrcRanges)
104       DstRanges.push_back(std::move(SrcRange));
105     EHFrameRanges.erase(SI);
106   } else {
107     // We need to move SrcKey's ranges over without invalidating the SI
108     // iterator.
109     auto Tmp = std::move(SI->second);
110     EHFrameRanges.erase(SI);
111     EHFrameRanges[DstKey] = std::move(Tmp);
112   }
113 }
114 
115 } // namespace llvm::orc
116