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