[llvm] r257816 - [Orc] Add support for EH-frame registration to the Orc Remote Target utility

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 14 14:02:03 PST 2016


Author: lhames
Date: Thu Jan 14 16:02:03 2016
New Revision: 257816

URL: http://llvm.org/viewvc/llvm-project?rev=257816&view=rev
Log:
[Orc] Add support for EH-frame registration to the Orc Remote Target utility
classes.

OrcRemoteTargetClient::RCMemoryManager will now register EH frames with the
server automatically. This allows remote-execution of code that uses exceptions.


Added:
    llvm/trunk/test/ExecutionEngine/MCJIT/remote/eh.ll
    llvm/trunk/test/ExecutionEngine/OrcMCJIT/remote/eh.ll
Modified:
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
    llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
    llvm/trunk/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
    llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h Thu Jan 14 16:02:03 2016
@@ -144,10 +144,18 @@ public:
     bool needsToReserveAllocationSpace() override { return true; }
 
     void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
-                          size_t Size) override {}
+                          size_t Size) override {
+      UnfinalizedEHFrames.push_back(
+          std::make_pair(LoadAddr, static_cast<uint32_t>(Size)));
+    }
 
-    void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
-                            size_t Size) override {}
+    void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+                            size_t Size) override {
+      auto EC = Client.deregisterEHFrames(LoadAddr, Size);
+      // FIXME: Add error poll.
+      assert(!EC && "Failed to register remote EH frames.");
+      (void)EC;
+    }
 
     void notifyObjectLoaded(RuntimeDyld &Dyld,
                             const object::ObjectFile &Obj) override {
@@ -253,6 +261,14 @@ public:
       }
       Unfinalized.clear();
 
+      for (auto &EHFrame : UnfinalizedEHFrames) {
+        auto EC = Client.registerEHFrames(EHFrame.first, EHFrame.second);
+        // FIXME: Add error poll.
+        assert(!EC && "Failed to register remote EH frames.");
+        (void)EC;
+      }
+      UnfinalizedEHFrames.clear();
+
       return false;
     }
 
@@ -331,6 +347,7 @@ public:
     ResourceIdMgr::ResourceId Id;
     std::vector<ObjectAllocs> Unmapped;
     std::vector<ObjectAllocs> Unfinalized;
+    std::vector<std::pair<uint64_t, uint32_t>> UnfinalizedEHFrames;
   };
 
   /// Remote indirect stubs manager.
@@ -620,6 +637,10 @@ private:
                           RemoteTrampolineSize, RemoteIndirectStubSize));
   }
 
+  std::error_code deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
+    return call<RegisterEHFrames>(Channel, Addr, Size);
+  }
+
   void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
     if (auto EC = call<DestroyRemoteAllocator>(Channel, Id)) {
       // FIXME: This will be triggered by a removeModuleSet call: Propagate
@@ -716,6 +737,10 @@ private:
     return std::error_code();
   }
 
+  std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
+    return call<RegisterEHFrames>(Channel, RAddr, Size);
+  }
+
   std::error_code reserveMem(TargetAddress &RemoteAddr,
                              ResourceIdMgr::ResourceId Id, uint64_t Size,
                              uint32_t Align) {

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h Thu Jan 14 16:02:03 2016
@@ -56,6 +56,7 @@ public:
     CallVoidVoidResponseId,
     CreateRemoteAllocatorId,
     CreateIndirectStubsOwnerId,
+    DeregisterEHFramesId,
     DestroyRemoteAllocatorId,
     DestroyIndirectStubsOwnerId,
     EmitIndirectStubsId,
@@ -69,6 +70,7 @@ public:
     GetRemoteInfoResponseId,
     ReadMemId,
     ReadMemResponseId,
+    RegisterEHFramesId,
     ReserveMemId,
     ReserveMemResponseId,
     RequestCompileId,
@@ -104,6 +106,10 @@ public:
                     ResourceIdMgr::ResourceId /* StubsOwner ID */>
       CreateIndirectStubsOwner;
 
+  typedef Procedure<DeregisterEHFramesId, TargetAddress /* Addr */,
+                    uint32_t /* Size */>
+      DeregisterEHFrames;
+
   typedef Procedure<DestroyRemoteAllocatorId,
                     ResourceIdMgr::ResourceId /* Allocator ID */>
       DestroyRemoteAllocator;
@@ -150,6 +156,10 @@ public:
 
   typedef Procedure<ReadMemResponseId> ReadMemResponse;
 
+  typedef Procedure<RegisterEHFramesId, TargetAddress /* Addr */,
+                    uint32_t /* Size */>
+      RegisterEHFrames;
+
   typedef Procedure<ReserveMemId, ResourceIdMgr::ResourceId /* Id */,
                     uint64_t /* Size */, uint32_t /* Align */>
       ReserveMem;

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h Thu Jan 14 16:02:03 2016
@@ -35,8 +35,15 @@ public:
   typedef std::function<TargetAddress(const std::string &Name)>
       SymbolLookupFtor;
 
-  OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup)
-      : Channel(Channel), SymbolLookup(std::move(SymbolLookup)) {}
+  typedef std::function<void(uint8_t *Addr, uint32_t Size)>
+      EHFrameRegistrationFtor;
+
+  OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
+                        EHFrameRegistrationFtor EHFramesRegister,
+                        EHFrameRegistrationFtor EHFramesDeregister)
+      : Channel(Channel), SymbolLookup(std::move(SymbolLookup)),
+        EHFramesRegister(std::move(EHFramesRegister)),
+        EHFramesDeregister(std::move(EHFramesDeregister)) {}
 
   std::error_code getNextProcId(JITProcId &Id) {
     return deserialize(Channel, Id);
@@ -60,6 +67,9 @@ public:
     case CreateIndirectStubsOwnerId:
       return handle<CreateIndirectStubsOwner>(
           Channel, *this, &ThisT::handleCreateIndirectStubsOwner);
+    case DeregisterEHFramesId:
+      return handle<DeregisterEHFrames>(Channel, *this,
+                                        &ThisT::handleDeregisterEHFrames);
     case DestroyRemoteAllocatorId:
       return handle<DestroyRemoteAllocator>(
           Channel, *this, &ThisT::handleDestroyRemoteAllocator);
@@ -82,6 +92,9 @@ public:
       return handle<GetRemoteInfo>(Channel, *this, &ThisT::handleGetRemoteInfo);
     case ReadMemId:
       return handle<ReadMem>(Channel, *this, &ThisT::handleReadMem);
+    case RegisterEHFramesId:
+      return handle<RegisterEHFrames>(Channel, *this,
+                                      &ThisT::handleRegisterEHFrames);
     case ReserveMemId:
       return handle<ReserveMem>(Channel, *this, &ThisT::handleReserveMem);
     case SetProtectionsId:
@@ -236,6 +249,14 @@ private:
     return std::error_code();
   }
 
+  std::error_code handleDeregisterEHFrames(TargetAddress TAddr, uint32_t Size) {
+    uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
+    DEBUG(dbgs() << "  Registering EH frames at " << format("0x%016x", TAddr)
+                 << ", Size = " << Size << " bytes\n");
+    EHFramesDeregister(Addr, Size);
+    return std::error_code();
+  }
+
   std::error_code handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
     auto I = Allocators.find(Id);
     if (I == Allocators.end())
@@ -365,6 +386,14 @@ private:
     return Channel.send();
   }
 
+  std::error_code handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
+    uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
+    DEBUG(dbgs() << "  Registering EH frames at " << format("0x%016x", TAddr)
+                 << ", Size = " << Size << " bytes\n");
+    EHFramesRegister(Addr, Size);
+    return std::error_code();
+  }
+
   std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
                                    uint32_t Align) {
     auto I = Allocators.find(Id);
@@ -416,6 +445,7 @@ private:
 
   ChannelT &Channel;
   SymbolLookupFtor SymbolLookup;
+  EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
   std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
   typedef std::vector<typename TargetT::IndirectStubsInfo> ISBlockOwnerList;
   std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;

Modified: llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/RTDyldMemoryManager.h Thu Jan 14 16:02:03 2016
@@ -62,8 +62,19 @@ public:
   RTDyldMemoryManager() {}
   ~RTDyldMemoryManager() override;
 
-  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
-  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
+  /// Register EH frames in the current process.
+  static void registerEHFramesInProcess(uint8_t *Addr, size_t Size);
+
+  /// Deregister EH frames in the current proces.
+  static void deregisterEHFramesInProcess(uint8_t *Addr, size_t Size);
+
+  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
+    registerEHFramesInProcess(Addr, Size);
+  }
+
+  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
+    registerEHFramesInProcess(Addr, Size);
+  }
 
   /// This method returns the address of the specified function or variable in
   /// the current process.

Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp Thu Jan 14 16:02:03 2016
@@ -33,6 +33,8 @@ const char *OrcRemoteTargetRPCAPI::getJI
     return "CreateRemoteAllocator";
   case CreateIndirectStubsOwnerId:
     return "CreateIndirectStubsOwner";
+  case DeregisterEHFramesId:
+    return "DeregisterEHFrames";
   case DestroyRemoteAllocatorId:
     return "DestroyRemoteAllocator";
   case DestroyIndirectStubsOwnerId:
@@ -59,6 +61,8 @@ const char *OrcRemoteTargetRPCAPI::getJI
     return "ReadMem";
   case ReadMemResponseId:
     return "ReadMemResponse";
+  case RegisterEHFramesId:
+    return "RegisterEHFrames";
   case ReserveMemId:
     return "ReserveMem";
   case ReserveMemResponseId:

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp Thu Jan 14 16:02:03 2016
@@ -94,9 +94,8 @@ static const char *processFDE(const char
 // This implementation handles frame registration for local targets.
 // Memory managers for remote targets should re-implement this function
 // and use the LoadAddr parameter.
-void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
-                                           uint64_t LoadAddr,
-                                           size_t Size) {
+void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
+                                                    size_t Size) {
   // On OS X OS X __register_frame takes a single FDE as an argument.
   // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061768.html
   const char *P = (const char *)Addr;
@@ -106,9 +105,8 @@ void RTDyldMemoryManager::registerEHFram
   } while(P != End);
 }
 
-void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
-                                           uint64_t LoadAddr,
-                                           size_t Size) {
+void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
+                                                      size_t Size) {
   const char *P = (const char *)Addr;
   const char *End = P + Size;
   do  {
@@ -118,9 +116,8 @@ void RTDyldMemoryManager::deregisterEHFr
 
 #else
 
-void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
-                                           uint64_t LoadAddr,
-                                           size_t Size) {
+void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
+                                                    size_t Size) {
   // On Linux __register_frame takes a single argument: 
   // a pointer to the start of the .eh_frame section.
 
@@ -129,9 +126,8 @@ void RTDyldMemoryManager::registerEHFram
   __register_frame(Addr);
 }
 
-void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
-                                           uint64_t LoadAddr,
-                                           size_t Size) {
+void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
+                                                      size_t Size) {
   __deregister_frame(Addr);
 }
 

Added: llvm/trunk/test/ExecutionEngine/MCJIT/remote/eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/remote/eh.ll?rev=257816&view=auto
==============================================================================
--- llvm/trunk/test/ExecutionEngine/MCJIT/remote/eh.ll (added)
+++ llvm/trunk/test/ExecutionEngine/MCJIT/remote/eh.ll Thu Jan 14 16:02:03 2016
@@ -0,0 +1,32 @@
+; RUN: %lli -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s
+; XFAIL: arm, cygwin, win32, mingw
+declare i8* @__cxa_allocate_exception(i64)
+declare void @__cxa_throw(i8*, i8*, i8*)
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_end_catch()
+declare i8* @__cxa_begin_catch(i8*)
+
+ at _ZTIi = external constant i8*
+
+define void @throwException() {
+  %exception = tail call i8* @__cxa_allocate_exception(i64 4)
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+  unreachable
+}
+
+define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  invoke void @throwException()
+          to label %try.cont unwind label %lpad
+
+lpad:
+  %p = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %e = extractvalue { i8*, i32 } %p, 0
+  call i8* @__cxa_begin_catch(i8* %e)
+  call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret i32 0
+}

Added: llvm/trunk/test/ExecutionEngine/OrcMCJIT/remote/eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/OrcMCJIT/remote/eh.ll?rev=257816&view=auto
==============================================================================
--- llvm/trunk/test/ExecutionEngine/OrcMCJIT/remote/eh.ll (added)
+++ llvm/trunk/test/ExecutionEngine/OrcMCJIT/remote/eh.ll Thu Jan 14 16:02:03 2016
@@ -0,0 +1,32 @@
+; RUN: %lli -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s
+; XFAIL: arm, cygwin, win32, mingw
+declare i8* @__cxa_allocate_exception(i64)
+declare void @__cxa_throw(i8*, i8*, i8*)
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_end_catch()
+declare i8* @__cxa_begin_catch(i8*)
+
+ at _ZTIi = external constant i8*
+
+define void @throwException() {
+  %exception = tail call i8* @__cxa_allocate_exception(i64 4)
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+  unreachable
+}
+
+define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  invoke void @throwException()
+          to label %try.cont unwind label %lpad
+
+lpad:
+  %p = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %e = extractvalue { i8*, i32 } %p, 0
+  call i8* @__cxa_begin_catch(i8* %e)
+  call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret i32 0
+}

Modified: llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp?rev=257816&r1=257815&r2=257816&view=diff
==============================================================================
--- llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp (original)
+++ llvm/trunk/tools/lli/ChildTarget/ChildTarget.cpp Thu Jan 14 16:02:03 2016
@@ -41,9 +41,17 @@ int main(int argc, char *argv[]) {
     return RTDyldMemoryManager::getSymbolAddressInProcess(Name);
   };
 
+  auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
+    RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size);
+  };
+
+  auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
+    RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size);
+  };
+
   FDRPCChannel Channel(InFD, OutFD);
   typedef remote::OrcRemoteTargetServer<FDRPCChannel, HostOrcArch> JITServer;
-  JITServer Server(Channel, SymbolLookup);
+  JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
 
   while (1) {
     JITServer::JITProcId Id = JITServer::InvalidId;




More information about the llvm-commits mailing list