diff options
9 files changed, 168 insertions, 20 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index 08a9dd218e4..defae248dba 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -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) { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h index 96dc2425102..3a8dbf000a6 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h @@ -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; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index 5247661e49c..969b5cc2e4d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -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; diff --git a/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index c5006962550..a6871663657 100644 --- a/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -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. diff --git a/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp b/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp index 064633b4e49..d17723f0fc1 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp @@ -33,6 +33,8 @@ const char *OrcRemoteTargetRPCAPI::getJITProcIdName(JITProcId Id) { return "CreateRemoteAllocator"; case CreateIndirectStubsOwnerId: return "CreateIndirectStubsOwner"; + case DeregisterEHFramesId: + return "DeregisterEHFrames"; case DestroyRemoteAllocatorId: return "DestroyRemoteAllocator"; case DestroyIndirectStubsOwnerId: @@ -59,6 +61,8 @@ const char *OrcRemoteTargetRPCAPI::getJITProcIdName(JITProcId Id) { return "ReadMem"; case ReadMemResponseId: return "ReadMemResponse"; + case RegisterEHFramesId: + return "RegisterEHFrames"; case ReserveMemId: return "ReserveMem"; case ReserveMemResponseId: diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index ecd99004bad..a9f8ab7bb88 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -94,9 +94,8 @@ static const char *processFDE(const char *Entry, bool isDeregister) { // 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::registerEHFrames(uint8_t *Addr, } 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::deregisterEHFrames(uint8_t *Addr, #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::registerEHFrames(uint8_t *Addr, __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); } diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll b/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll new file mode 100644 index 00000000000..f772e1c03e6 --- /dev/null +++ b/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll @@ -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*) + +@_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 +} diff --git a/llvm/test/ExecutionEngine/OrcMCJIT/remote/eh.ll b/llvm/test/ExecutionEngine/OrcMCJIT/remote/eh.ll new file mode 100644 index 00000000000..f772e1c03e6 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcMCJIT/remote/eh.ll @@ -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*) + +@_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 +} diff --git a/llvm/tools/lli/ChildTarget/ChildTarget.cpp b/llvm/tools/lli/ChildTarget/ChildTarget.cpp index 0b75e20f83e..93925d6aa87 100644 --- a/llvm/tools/lli/ChildTarget/ChildTarget.cpp +++ b/llvm/tools/lli/ChildTarget/ChildTarget.cpp @@ -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; |