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