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

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 14 14:21:51 PST 2016


On Thu, Jan 14, 2016 at 2:02 PM, Lang Hames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> 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.ation list t
> @@ -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
>

Do these two tests actually verify any particular behavior? Perhaps the
catch block could return 0 and the non-exceptional exit could return
non-zero, then the zero exit (that lit will check) demonstrates that the
exception occurred and was handled correctly?

(semi-relatedly: How would these tests behave if the rest of the patch was
reverted? I guess it probably crashes somewhere in the EH runtime code?)


> +; 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;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160114/4259f64d/attachment.html>


More information about the llvm-commits mailing list