[llvm] r370074 - [JITLink][ORC] Track eh-frame section size for registration/deregistration.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 27 08:50:32 PDT 2019


Author: lhames
Date: Tue Aug 27 08:50:32 2019
New Revision: 370074

URL: http://llvm.org/viewvc/llvm-project?rev=370074&view=rev
Log:
[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.

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
    llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
    llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
    llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h?rev=370074&r1=370073&r2=370074&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h Tue Aug 27 08:50:32 2019
@@ -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)>;
-
-/// 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.
+using StoreFrameRangeFunction =
+  std::function<void(JITTargetAddress EHFrameSectionAddr,
+                     size_t EHFrameSectionSize)>;
+
+/// 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

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h?rev=370074&r1=370073&r2=370074&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h Tue Aug 27 08:50:32 2019
@@ -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

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp?rev=370074&r1=370073&r2=370074&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp Tue Aug 27 08:50:32 2019
@@ -451,11 +451,13 @@ static Error deregisterFrameWrapper(cons
 
 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
 
 #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
 #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::InProcessEHFr
 
 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();
   };
 

Modified: llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp?rev=370074&r1=370073&r2=370074&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp Tue Aug 27 08:50:32 2019
@@ -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::modifyPa
   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;




More information about the llvm-commits mailing list