diff options
author | Lang Hames <lhames@gmail.com> | 2019-08-27 15:50:32 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2019-08-27 15:50:32 +0000 |
commit | c48f1f6da690b721a211f6d5083b6a929b58e803 (patch) | |
tree | 1f6d54f630a619ad89e4e1dcdff084b91c2df88e | |
parent | f260630e8f4c07613c11ea9f4b884e58c9683f03 (diff) | |
download | bcm5719-llvm-c48f1f6da690b721a211f6d5083b6a929b58e803.tar.gz bcm5719-llvm-c48f1f6da690b721a211f6d5083b6a929b58e803.zip |
[JITLink][ORC] Track eh-frame section size for registration/deregistration.
On MachO, processing of the eh-frame section should stop if the end of the
__eh_frame section is reached, regardless of whether or not there is a null CFI
length field at the end of the section. This patch tracks the eh-frame section
size and threads it through the appropriate APIs so that processing can be
terminated correctly.
No testcase yet: This patch is all API plumbing (rather than modification of
linked memory) which the existing infrastructure does not provide a way of
testing. Committing without a testcase until I have an idea of how to write
one.
llvm-svn: 370074
4 files changed, 89 insertions, 55 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h index 8d2f641254b..37293dfb8ed 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h @@ -22,17 +22,21 @@ namespace llvm { namespace jitlink { /// Registers all FDEs in the given eh-frame section with the current process. -Error registerEHFrameSection(const void *EHFrameSectionAddr); +Error registerEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize); /// Deregisters all FDEs in the given eh-frame section with the current process. -Error deregisterEHFrameSection(const void *EHFrameSectionAddr); +Error deregisterEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize); /// Supports registration/deregistration of EH-frames in a target process. class EHFrameRegistrar { public: virtual ~EHFrameRegistrar(); - virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) = 0; - virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) = 0; + virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) = 0; + virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) = 0; }; /// Registers / Deregisters EH-frames in the current process. @@ -48,31 +52,38 @@ public: InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete; InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete; - Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) override { + Error registerEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) override { return registerEHFrameSection( - jitTargetAddressToPointer<void *>(EHFrameSectionAddr)); + jitTargetAddressToPointer<void *>(EHFrameSectionAddr), + EHFrameSectionSize); } - Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) override { + Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize) override { return deregisterEHFrameSection( - jitTargetAddressToPointer<void *>(EHFrameSectionAddr)); + jitTargetAddressToPointer<void *>(EHFrameSectionAddr), + EHFrameSectionSize); } private: InProcessEHFrameRegistrar(); }; -using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>; +using StoreFrameRangeFunction = + std::function<void(JITTargetAddress EHFrameSectionAddr, + size_t EHFrameSectionSize)>; -/// Creates a pass that records the address of the EH frame section. If no -/// eh-frame section is found, it will set EHFrameAddr to zero. +/// Creates a pass that records the address and size of the EH frame section. +/// If no eh-frame section is found then the address and size will both be given +/// as zero. /// /// Authors of JITLinkContexts can use this function to register a post-fixup -/// pass that records the address of the eh-frame section. This address can +/// pass that records the range of the eh-frame section. This range can /// be used after finalization to register and deregister the frame. AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT, - StoreFrameAddressFunction StoreFrameAddress); + StoreFrameRangeFunction StoreFrameRange); } // end namespace jitlink } // end namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index c1e7d27f446..0605ee3bb0b 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -153,10 +153,16 @@ public: Error notifyRemovingAllModules() override; private: + + struct EHFrameRange { + JITTargetAddress Addr = 0; + size_t Size; + }; + jitlink::EHFrameRegistrar &Registrar; - DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks; - DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs; - std::vector<JITTargetAddress> UntrackedEHFrameAddrs; + DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks; + DenseMap<VModuleKey, EHFrameRange> TrackedEHFrameRanges; + std::vector<EHFrameRange> UntrackedEHFrameRanges; }; } // end namespace orc diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp index 25f0e9040ff..f373f2d92b0 100644 --- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp @@ -451,11 +451,13 @@ static Error deregisterFrameWrapper(const void *P) { template <typename HandleFDEFn> Error walkAppleEHFrameSection(const char *const SectionStart, + size_t SectionSize, HandleFDEFn HandleFDE) { const char *CurCFIRecord = SectionStart; + const char *End = SectionStart + SectionSize; uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); - while (Size != 0) { + while (CurCFIRecord != End && Size != 0) { const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); if (Size == 0xffffffff) Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; @@ -484,10 +486,12 @@ Error walkAppleEHFrameSection(const char *const SectionStart, #endif // __APPLE__ -Error registerEHFrameSection(const void *EHFrameSectionAddr) { +Error registerEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize) { #ifdef __APPLE__ // On Darwin __register_frame has to be called for each FDE entry. return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), + EHFrameSectionSize, registerFrameWrapper); #else // On Linux __register_frame takes a single argument: @@ -499,9 +503,11 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr) { #endif } -Error deregisterEHFrameSection(const void *EHFrameSectionAddr) { +Error deregisterEHFrameSection(const void *EHFrameSectionAddr, + size_t EHFrameSectionSize) { #ifdef __APPLE__ return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), + EHFrameSectionSize, deregisterFrameWrapper); #else return deregisterFrameWrapper(EHFrameSectionAddr); @@ -519,21 +525,29 @@ InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {} AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT, - StoreFrameAddressFunction StoreFrameAddress) { + StoreFrameRangeFunction StoreRangeAddress) { const char *EHFrameSectionName = nullptr; if (TT.getObjectFormat() == Triple::MachO) EHFrameSectionName = "__eh_frame"; else EHFrameSectionName = ".eh_frame"; - auto RecordEHFrame = [EHFrameSectionName, - StoreFrameAddress](AtomGraph &G) -> Error { + auto RecordEHFrame = + [EHFrameSectionName, + StoreFrameRange = std::move(StoreRangeAddress)](AtomGraph &G) -> Error { // Search for a non-empty eh-frame and record the address of the first atom // in it. JITTargetAddress Addr = 0; - if (auto *S = G.findSectionByName(EHFrameSectionName)) - Addr = S->getRange().getStart(); - StoreFrameAddress(Addr); + size_t Size = 0; + if (auto *S = G.findSectionByName(EHFrameSectionName)) { + auto R = S->getRange(); + Addr = R.getStart(); + Size = R.getSize(); + } + if (Addr == 0 && Size != 0) + return make_error<JITLinkError>("__eh_frame section can not have zero " + "address with non-zero size"); + StoreFrameRange(Addr, Size); return Error::success(); }; diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index 0d0b8a9c227..e1b8d52acb4 100644 --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -58,7 +58,8 @@ public: auto SharedLookupContinuation = std::make_shared<JITLinkAsyncLookupContinuation>( std::move(LookupContinuation)); - auto OnResolve = [SharedLookupContinuation](Expected<SymbolMap> Result) { + auto OnResolve = [this, SharedLookupContinuation](Expected<SymbolMap> Result) { + auto Main = Layer.getExecutionSession().intern("_main"); if (!Result) (*SharedLookupContinuation)(Result.takeError()); else { @@ -126,19 +127,16 @@ public: if (!ExtraSymbolsToClaim.empty()) if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim)) return notifyFailed(std::move(Err)); - if (auto Err = MR.notifyResolved(InternedResult)) { Layer.getExecutionSession().reportError(std::move(Err)); MR.failMaterialization(); return; } - Layer.notifyLoaded(MR); } void notifyFinalized( std::unique_ptr<JITLinkMemoryManager::Allocation> A) override { - if (auto Err = Layer.notifyEmitted(MR, std::move(A))) { Layer.getExecutionSession().reportError(std::move(Err)); MR.failMaterialization(); @@ -425,61 +423,66 @@ void EHFrameRegistrationPlugin::modifyPassConfig( assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?"); PassConfig.PostFixupPasses.push_back( - createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) { + createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr, + size_t Size) { if (Addr) - InProcessLinks[&MR] = Addr; + InProcessLinks[&MR] = { Addr, Size }; })); } Error EHFrameRegistrationPlugin::notifyEmitted( MaterializationResponsibility &MR) { - auto EHFrameAddrItr = InProcessLinks.find(&MR); - if (EHFrameAddrItr == InProcessLinks.end()) + auto EHFrameRangeItr = InProcessLinks.find(&MR); + if (EHFrameRangeItr == InProcessLinks.end()) return Error::success(); - auto EHFrameAddr = EHFrameAddrItr->second; - assert(EHFrameAddr && "eh-frame addr to register can not be null"); + auto EHFrameRange = EHFrameRangeItr->second; + assert(EHFrameRange.Addr && + "eh-frame addr to register can not be null"); - InProcessLinks.erase(EHFrameAddrItr); + InProcessLinks.erase(EHFrameRangeItr); if (auto Key = MR.getVModuleKey()) - TrackedEHFrameAddrs[Key] = EHFrameAddr; + TrackedEHFrameRanges[Key] = EHFrameRange; else - UntrackedEHFrameAddrs.push_back(EHFrameAddr); + UntrackedEHFrameRanges.push_back(EHFrameRange); - return Registrar.registerEHFrames(EHFrameAddr); + return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size); } Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { - auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K); - if (EHFrameAddrItr == TrackedEHFrameAddrs.end()) + auto EHFrameRangeItr = TrackedEHFrameRanges.find(K); + if (EHFrameRangeItr == TrackedEHFrameRanges.end()) return Error::success(); - auto EHFrameAddr = EHFrameAddrItr->second; - assert(EHFrameAddr && "Tracked eh-frame addr must not be null"); + auto EHFrameRange = EHFrameRangeItr->second; + assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null"); - TrackedEHFrameAddrs.erase(EHFrameAddrItr); + TrackedEHFrameRanges.erase(EHFrameRangeItr); - return Registrar.deregisterEHFrames(EHFrameAddr); + return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size); } Error EHFrameRegistrationPlugin::notifyRemovingAllModules() { - std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs); - EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size()); + std::vector<EHFrameRange> EHFrameRanges = + std::move(UntrackedEHFrameRanges); + EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size()); - for (auto &KV : TrackedEHFrameAddrs) - EHFrameAddrs.push_back(KV.second); + for (auto &KV : TrackedEHFrameRanges) + EHFrameRanges.push_back(KV.second); - TrackedEHFrameAddrs.clear(); + TrackedEHFrameRanges.clear(); Error Err = Error::success(); - while (!EHFrameAddrs.empty()) { - auto EHFrameAddr = EHFrameAddrs.back(); - assert(EHFrameAddr && "Untracked eh-frame addr must not be null"); - EHFrameAddrs.pop_back(); - Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr)); + while (!EHFrameRanges.empty()) { + auto EHFrameRange = EHFrameRanges.back(); + assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null"); + EHFrameRanges.pop_back(); + Err = joinErrors(std::move(Err), + Registrar.deregisterEHFrames(EHFrameRange.Addr, + EHFrameRange.Size)); } return Err; |