llvm.org GIT mirror llvm / f881fc9
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257816 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 4 years ago
9 changed file(s) with 169 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
143143 bool needsToReserveAllocationSpace() override { return true; }
144144
145145 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
146 size_t Size) override {}
147
148 void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
149 size_t Size) override {}
146 size_t Size) override {
147 UnfinalizedEHFrames.push_back(
148 std::make_pair(LoadAddr, static_cast(Size)));
149 }
150
151 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
152 size_t Size) override {
153 auto EC = Client.deregisterEHFrames(LoadAddr, Size);
154 // FIXME: Add error poll.
155 assert(!EC && "Failed to register remote EH frames.");
156 (void)EC;
157 }
150158
151159 void notifyObjectLoaded(RuntimeDyld &Dyld,
152160 const object::ObjectFile &Obj) override {
252260 }
253261 Unfinalized.clear();
254262
263 for (auto &EHFrame : UnfinalizedEHFrames) {
264 auto EC = Client.registerEHFrames(EHFrame.first, EHFrame.second);
265 // FIXME: Add error poll.
266 assert(!EC && "Failed to register remote EH frames.");
267 (void)EC;
268 }
269 UnfinalizedEHFrames.clear();
270
255271 return false;
256272 }
257273
330346 ResourceIdMgr::ResourceId Id;
331347 std::vector Unmapped;
332348 std::vector Unfinalized;
349 std::vector> UnfinalizedEHFrames;
333350 };
334351
335352 /// Remote indirect stubs manager.
619636 RemoteTrampolineSize, RemoteIndirectStubSize));
620637 }
621638
639 std::error_code deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
640 return call(Channel, Addr, Size);
641 }
642
622643 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
623644 if (auto EC = call(Channel, Id)) {
624645 // FIXME: This will be triggered by a removeModuleSet call: Propagate
713734 return EC;
714735
715736 return std::error_code();
737 }
738
739 std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
740 return call(Channel, RAddr, Size);
716741 }
717742
718743 std::error_code reserveMem(TargetAddress &RemoteAddr,
5555 CallVoidVoidResponseId,
5656 CreateRemoteAllocatorId,
5757 CreateIndirectStubsOwnerId,
58 DeregisterEHFramesId,
5859 DestroyRemoteAllocatorId,
5960 DestroyIndirectStubsOwnerId,
6061 EmitIndirectStubsId,
6869 GetRemoteInfoResponseId,
6970 ReadMemId,
7071 ReadMemResponseId,
72 RegisterEHFramesId,
7173 ReserveMemId,
7274 ReserveMemResponseId,
7375 RequestCompileId,
102104 typedef Procedure
103105 ResourceIdMgr::ResourceId /* StubsOwner ID */>
104106 CreateIndirectStubsOwner;
107
108 typedef Procedure
109 uint32_t /* Size */>
110 DeregisterEHFrames;
105111
106112 typedef Procedure
107113 ResourceIdMgr::ResourceId /* Allocator ID */>
149155
150156 typedef Procedure ReadMemResponse;
151157
158 typedef Procedure
159 uint32_t /* Size */>
160 RegisterEHFrames;
161
152162 typedef Procedure
153163 uint64_t /* Size */, uint32_t /* Align */>
154164 ReserveMem;
3434 typedef std::function
3535 SymbolLookupFtor;
3636
37 OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup)
38 : Channel(Channel), SymbolLookup(std::move(SymbolLookup)) {}
37 typedef std::function
38 EHFrameRegistrationFtor;
39
40 OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
41 EHFrameRegistrationFtor EHFramesRegister,
42 EHFrameRegistrationFtor EHFramesDeregister)
43 : Channel(Channel), SymbolLookup(std::move(SymbolLookup)),
44 EHFramesRegister(std::move(EHFramesRegister)),
45 EHFramesDeregister(std::move(EHFramesDeregister)) {}
3946
4047 std::error_code getNextProcId(JITProcId &Id) {
4148 return deserialize(Channel, Id);
5966 case CreateIndirectStubsOwnerId:
6067 return handle(
6168 Channel, *this, &ThisT::handleCreateIndirectStubsOwner);
69 case DeregisterEHFramesId:
70 return handle(Channel, *this,
71 &ThisT::handleDeregisterEHFrames);
6272 case DestroyRemoteAllocatorId:
6373 return handle(
6474 Channel, *this, &ThisT::handleDestroyRemoteAllocator);
8191 return handle(Channel, *this, &ThisT::handleGetRemoteInfo);
8292 case ReadMemId:
8393 return handle(Channel, *this, &ThisT::handleReadMem);
94 case RegisterEHFramesId:
95 return handle(Channel, *this,
96 &ThisT::handleRegisterEHFrames);
8497 case ReserveMemId:
8598 return handle(Channel, *this, &ThisT::handleReserveMem);
8699 case SetProtectionsId:
232245 return orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);
233246 DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
234247 IndirectStubsOwners[Id] = ISBlockOwnerList();
248 return std::error_code();
249 }
250
251 std::error_code handleDeregisterEHFrames(TargetAddress TAddr, uint32_t Size) {
252 uint8_t *Addr = reinterpret_cast(static_cast(TAddr));
253 DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
254 << ", Size = " << Size << " bytes\n");
255 EHFramesDeregister(Addr, Size);
235256 return std::error_code();
236257 }
237258
364385 return Channel.send();
365386 }
366387
388 std::error_code handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
389 uint8_t *Addr = reinterpret_cast(static_cast(TAddr));
390 DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
391 << ", Size = " << Size << " bytes\n");
392 EHFramesRegister(Addr, Size);
393 return std::error_code();
394 }
395
367396 std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
368397 uint32_t Align) {
369398 auto I = Allocators.find(Id);
415444
416445 ChannelT &Channel;
417446 SymbolLookupFtor SymbolLookup;
447 EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
418448 std::map Allocators;
419449 typedef std::vector ISBlockOwnerList;
420450 std::map IndirectStubsOwners;
6161 RTDyldMemoryManager() {}
6262 ~RTDyldMemoryManager() override;
6363
64 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
65 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
64 /// Register EH frames in the current process.
65 static void registerEHFramesInProcess(uint8_t *Addr, size_t Size);
66
67 /// Deregister EH frames in the current proces.
68 static void deregisterEHFramesInProcess(uint8_t *Addr, size_t Size);
69
70 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
71 registerEHFramesInProcess(Addr, Size);
72 }
73
74 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
75 registerEHFramesInProcess(Addr, Size);
76 }
6677
6778 /// This method returns the address of the specified function or variable in
6879 /// the current process.
3232 return "CreateRemoteAllocator";
3333 case CreateIndirectStubsOwnerId:
3434 return "CreateIndirectStubsOwner";
35 case DeregisterEHFramesId:
36 return "DeregisterEHFrames";
3537 case DestroyRemoteAllocatorId:
3638 return "DestroyRemoteAllocator";
3739 case DestroyIndirectStubsOwnerId:
5860 return "ReadMem";
5961 case ReadMemResponseId:
6062 return "ReadMemResponse";
63 case RegisterEHFramesId:
64 return "RegisterEHFrames";
6165 case ReserveMemId:
6266 return "ReserveMem";
6367 case ReserveMemResponseId:
9393 // This implementation handles frame registration for local targets.
9494 // Memory managers for remote targets should re-implement this function
9595 // and use the LoadAddr parameter.
96 void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
97 uint64_t LoadAddr,
98 size_t Size) {
96 void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
97 size_t Size) {
9998 // On OS X OS X __register_frame takes a single FDE as an argument.
10099 // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061768.html
101100 const char *P = (const char *)Addr;
105104 } while(P != End);
106105 }
107106
108 void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
109 uint64_t LoadAddr,
110 size_t Size) {
107 void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
108 size_t Size) {
111109 const char *P = (const char *)Addr;
112110 const char *End = P + Size;
113111 do {
117115
118116 #else
119117
120 void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
121 uint64_t LoadAddr,
122 size_t Size) {
118 void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
119 size_t Size) {
123120 // On Linux __register_frame takes a single argument:
124121 // a pointer to the start of the .eh_frame section.
125122
128125 __register_frame(Addr);
129126 }
130127
131 void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr,
132 uint64_t LoadAddr,
133 size_t Size) {
128 void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
129 size_t Size) {
134130 __deregister_frame(Addr);
135131 }
136132
0 ; RUN: %lli -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s
1 ; XFAIL: arm, cygwin, win32, mingw
2 declare i8* @__cxa_allocate_exception(i64)
3 declare void @__cxa_throw(i8*, i8*, i8*)
4 declare i32 @__gxx_personality_v0(...)
5 declare void @__cxa_end_catch()
6 declare i8* @__cxa_begin_catch(i8*)
7
8 @_ZTIi = external constant i8*
9
10 define void @throwException() {
11 %exception = tail call i8* @__cxa_allocate_exception(i64 4)
12 call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
13 unreachable
14 }
15
16 define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
17 entry:
18 invoke void @throwException()
19 to label %try.cont unwind label %lpad
20
21 lpad:
22 %p = landingpad { i8*, i32 }
23 catch i8* bitcast (i8** @_ZTIi to i8*)
24 %e = extractvalue { i8*, i32 } %p, 0
25 call i8* @__cxa_begin_catch(i8* %e)
26 call void @__cxa_end_catch()
27 br label %try.cont
28
29 try.cont:
30 ret i32 0
31 }
0 ; RUN: %lli -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s
1 ; XFAIL: arm, cygwin, win32, mingw
2 declare i8* @__cxa_allocate_exception(i64)
3 declare void @__cxa_throw(i8*, i8*, i8*)
4 declare i32 @__gxx_personality_v0(...)
5 declare void @__cxa_end_catch()
6 declare i8* @__cxa_begin_catch(i8*)
7
8 @_ZTIi = external constant i8*
9
10 define void @throwException() {
11 %exception = tail call i8* @__cxa_allocate_exception(i64 4)
12 call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
13 unreachable
14 }
15
16 define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
17 entry:
18 invoke void @throwException()
19 to label %try.cont unwind label %lpad
20
21 lpad:
22 %p = landingpad { i8*, i32 }
23 catch i8* bitcast (i8** @_ZTIi to i8*)
24 %e = extractvalue { i8*, i32 } %p, 0
25 call i8* @__cxa_begin_catch(i8* %e)
26 call void @__cxa_end_catch()
27 br label %try.cont
28
29 try.cont:
30 ret i32 0
31 }
4040 return RTDyldMemoryManager::getSymbolAddressInProcess(Name);
4141 };
4242
43 auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
44 RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size);
45 };
46
47 auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
48 RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size);
49 };
50
4351 FDRPCChannel Channel(InFD, OutFD);
4452 typedef remote::OrcRemoteTargetServer JITServer;
45 JITServer Server(Channel, SymbolLookup);
53 JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
4654
4755 while (1) {
4856 JITServer::JITProcId Id = JITServer::InvalidId;