1 //===---- OrcRemoteTargetClient.h - Orc Remote-target Client ----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the OrcRemoteTargetClient class and helpers. This class 11 // can be used to communicate over an RawByteChannel with an 12 // OrcRemoteTargetServer instance to support remote-JITing. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H 17 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H 18 19 #include "IndirectionUtils.h" 20 #include "OrcRemoteTargetRPCAPI.h" 21 #include "llvm/ExecutionEngine/RuntimeDyld.h" 22 #include <system_error> 23 24 #define DEBUG_TYPE "orc-remote" 25 26 namespace llvm { 27 namespace orc { 28 namespace remote { 29 30 /// This class provides utilities (including memory manager, indirect stubs 31 /// manager, and compile callback manager types) that support remote JITing 32 /// in ORC. 33 /// 34 /// Each of the utility classes talks to a JIT server (an instance of the 35 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out 36 /// its actions. 37 template <typename ChannelT> 38 class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI { 39 public: 40 /// Remote memory manager. 41 class RCMemoryManager : public RuntimeDyld::MemoryManager { 42 public: 43 RCMemoryManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id) 44 : Client(Client), Id(Id) { 45 DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); 46 } 47 48 RCMemoryManager(const RCMemoryManager &) = delete; 49 RCMemoryManager &operator=(const RCMemoryManager &) = delete; 50 RCMemoryManager(RCMemoryManager &&) = default; 51 RCMemoryManager &operator=(RCMemoryManager &&) = default; 52 53 ~RCMemoryManager() override { 54 Client.destroyRemoteAllocator(Id); 55 DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); 56 } 57 58 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 59 unsigned SectionID, 60 StringRef SectionName) override { 61 Unmapped.back().CodeAllocs.emplace_back(Size, Alignment); 62 uint8_t *Alloc = reinterpret_cast<uint8_t *>( 63 Unmapped.back().CodeAllocs.back().getLocalAddress()); 64 DEBUG(dbgs() << "Allocator " << Id << " allocated code for " 65 << SectionName << ": " << Alloc << " (" << Size 66 << " bytes, alignment " << Alignment << ")\n"); 67 return Alloc; 68 } 69 70 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 71 unsigned SectionID, StringRef SectionName, 72 bool IsReadOnly) override { 73 if (IsReadOnly) { 74 Unmapped.back().RODataAllocs.emplace_back(Size, Alignment); 75 uint8_t *Alloc = reinterpret_cast<uint8_t *>( 76 Unmapped.back().RODataAllocs.back().getLocalAddress()); 77 DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for " 78 << SectionName << ": " << Alloc << " (" << Size 79 << " bytes, alignment " << Alignment << ")\n"); 80 return Alloc; 81 } // else... 82 83 Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment); 84 uint8_t *Alloc = reinterpret_cast<uint8_t *>( 85 Unmapped.back().RWDataAllocs.back().getLocalAddress()); 86 DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for " 87 << SectionName << ": " << Alloc << " (" << Size 88 << " bytes, alignment " << Alignment << ")\n"); 89 return Alloc; 90 } 91 92 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, 93 uintptr_t RODataSize, uint32_t RODataAlign, 94 uintptr_t RWDataSize, 95 uint32_t RWDataAlign) override { 96 Unmapped.push_back(ObjectAllocs()); 97 98 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n"); 99 100 if (CodeSize != 0) { 101 if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign)) 102 Unmapped.back().RemoteCodeAddr = *AddrOrErr; 103 else { 104 // FIXME; Add error to poll. 105 assert(!AddrOrErr.takeError() && "Failed reserving remote memory."); 106 } 107 108 DEBUG(dbgs() << " code: " 109 << format("0x%016x", Unmapped.back().RemoteCodeAddr) 110 << " (" << CodeSize << " bytes, alignment " << CodeAlign 111 << ")\n"); 112 } 113 114 if (RODataSize != 0) { 115 if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign)) 116 Unmapped.back().RemoteRODataAddr = *AddrOrErr; 117 else { 118 // FIXME; Add error to poll. 119 assert(!AddrOrErr.takeError() && "Failed reserving remote memory."); 120 } 121 122 DEBUG(dbgs() << " ro-data: " 123 << format("0x%016x", Unmapped.back().RemoteRODataAddr) 124 << " (" << RODataSize << " bytes, alignment " 125 << RODataAlign << ")\n"); 126 } 127 128 if (RWDataSize != 0) { 129 if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign)) 130 Unmapped.back().RemoteRWDataAddr = *AddrOrErr; 131 else { 132 // FIXME; Add error to poll. 133 assert(!AddrOrErr.takeError() && "Failed reserving remote memory."); 134 } 135 136 DEBUG(dbgs() << " rw-data: " 137 << format("0x%016x", Unmapped.back().RemoteRWDataAddr) 138 << " (" << RWDataSize << " bytes, alignment " 139 << RWDataAlign << ")\n"); 140 } 141 } 142 143 bool needsToReserveAllocationSpace() override { return true; } 144 145 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, 146 size_t Size) override { 147 UnfinalizedEHFrames.push_back({LoadAddr, Size}); 148 } 149 150 void deregisterEHFrames() override { 151 for (auto &Frame : RegisteredEHFrames) { 152 // FIXME: Add error poll. 153 llvm::cantFail(Client.deregisterEHFrames(Frame.Addr, Frame.Size)); 154 } 155 } 156 157 void notifyObjectLoaded(RuntimeDyld &Dyld, 158 const object::ObjectFile &Obj) override { 159 DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n"); 160 for (auto &ObjAllocs : Unmapped) { 161 { 162 JITTargetAddress NextCodeAddr = ObjAllocs.RemoteCodeAddr; 163 for (auto &Alloc : ObjAllocs.CodeAllocs) { 164 NextCodeAddr = alignTo(NextCodeAddr, Alloc.getAlign()); 165 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextCodeAddr); 166 DEBUG(dbgs() << " code: " 167 << static_cast<void *>(Alloc.getLocalAddress()) 168 << " -> " << format("0x%016x", NextCodeAddr) << "\n"); 169 Alloc.setRemoteAddress(NextCodeAddr); 170 NextCodeAddr += Alloc.getSize(); 171 } 172 } 173 { 174 JITTargetAddress NextRODataAddr = ObjAllocs.RemoteRODataAddr; 175 for (auto &Alloc : ObjAllocs.RODataAllocs) { 176 NextRODataAddr = alignTo(NextRODataAddr, Alloc.getAlign()); 177 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRODataAddr); 178 DEBUG(dbgs() << " ro-data: " 179 << static_cast<void *>(Alloc.getLocalAddress()) 180 << " -> " << format("0x%016x", NextRODataAddr) 181 << "\n"); 182 Alloc.setRemoteAddress(NextRODataAddr); 183 NextRODataAddr += Alloc.getSize(); 184 } 185 } 186 { 187 JITTargetAddress NextRWDataAddr = ObjAllocs.RemoteRWDataAddr; 188 for (auto &Alloc : ObjAllocs.RWDataAllocs) { 189 NextRWDataAddr = alignTo(NextRWDataAddr, Alloc.getAlign()); 190 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRWDataAddr); 191 DEBUG(dbgs() << " rw-data: " 192 << static_cast<void *>(Alloc.getLocalAddress()) 193 << " -> " << format("0x%016x", NextRWDataAddr) 194 << "\n"); 195 Alloc.setRemoteAddress(NextRWDataAddr); 196 NextRWDataAddr += Alloc.getSize(); 197 } 198 } 199 Unfinalized.push_back(std::move(ObjAllocs)); 200 } 201 Unmapped.clear(); 202 } 203 204 bool finalizeMemory(std::string *ErrMsg = nullptr) override { 205 DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n"); 206 207 for (auto &ObjAllocs : Unfinalized) { 208 209 for (auto &Alloc : ObjAllocs.CodeAllocs) { 210 DEBUG(dbgs() << " copying code: " 211 << static_cast<void *>(Alloc.getLocalAddress()) << " -> " 212 << format("0x%016x", Alloc.getRemoteAddress()) << " (" 213 << Alloc.getSize() << " bytes)\n"); 214 if (auto Err = 215 Client.writeMem(Alloc.getRemoteAddress(), 216 Alloc.getLocalAddress(), Alloc.getSize())) { 217 // FIXME: Replace this once finalizeMemory can return an Error. 218 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 219 if (ErrMsg) { 220 raw_string_ostream ErrOut(*ErrMsg); 221 EIB.log(ErrOut); 222 } 223 }); 224 return true; 225 } 226 } 227 228 if (ObjAllocs.RemoteCodeAddr) { 229 DEBUG(dbgs() << " setting R-X permissions on code block: " 230 << format("0x%016x", ObjAllocs.RemoteCodeAddr) << "\n"); 231 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteCodeAddr, 232 sys::Memory::MF_READ | 233 sys::Memory::MF_EXEC)) { 234 // FIXME: Replace this once finalizeMemory can return an Error. 235 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 236 if (ErrMsg) { 237 raw_string_ostream ErrOut(*ErrMsg); 238 EIB.log(ErrOut); 239 } 240 }); 241 return true; 242 } 243 } 244 245 for (auto &Alloc : ObjAllocs.RODataAllocs) { 246 DEBUG(dbgs() << " copying ro-data: " 247 << static_cast<void *>(Alloc.getLocalAddress()) << " -> " 248 << format("0x%016x", Alloc.getRemoteAddress()) << " (" 249 << Alloc.getSize() << " bytes)\n"); 250 if (auto Err = 251 Client.writeMem(Alloc.getRemoteAddress(), 252 Alloc.getLocalAddress(), Alloc.getSize())) { 253 // FIXME: Replace this once finalizeMemory can return an Error. 254 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 255 if (ErrMsg) { 256 raw_string_ostream ErrOut(*ErrMsg); 257 EIB.log(ErrOut); 258 } 259 }); 260 return true; 261 } 262 } 263 264 if (ObjAllocs.RemoteRODataAddr) { 265 DEBUG(dbgs() << " setting R-- permissions on ro-data block: " 266 << format("0x%016x", ObjAllocs.RemoteRODataAddr) 267 << "\n"); 268 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRODataAddr, 269 sys::Memory::MF_READ)) { 270 // FIXME: Replace this once finalizeMemory can return an Error. 271 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 272 if (ErrMsg) { 273 raw_string_ostream ErrOut(*ErrMsg); 274 EIB.log(ErrOut); 275 } 276 }); 277 return false; 278 } 279 } 280 281 for (auto &Alloc : ObjAllocs.RWDataAllocs) { 282 DEBUG(dbgs() << " copying rw-data: " 283 << static_cast<void *>(Alloc.getLocalAddress()) << " -> " 284 << format("0x%016x", Alloc.getRemoteAddress()) << " (" 285 << Alloc.getSize() << " bytes)\n"); 286 if (auto Err = 287 Client.writeMem(Alloc.getRemoteAddress(), 288 Alloc.getLocalAddress(), Alloc.getSize())) { 289 // FIXME: Replace this once finalizeMemory can return an Error. 290 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 291 if (ErrMsg) { 292 raw_string_ostream ErrOut(*ErrMsg); 293 EIB.log(ErrOut); 294 } 295 }); 296 return false; 297 } 298 } 299 300 if (ObjAllocs.RemoteRWDataAddr) { 301 DEBUG(dbgs() << " setting RW- permissions on rw-data block: " 302 << format("0x%016x", ObjAllocs.RemoteRWDataAddr) 303 << "\n"); 304 if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr, 305 sys::Memory::MF_READ | 306 sys::Memory::MF_WRITE)) { 307 // FIXME: Replace this once finalizeMemory can return an Error. 308 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 309 if (ErrMsg) { 310 raw_string_ostream ErrOut(*ErrMsg); 311 EIB.log(ErrOut); 312 } 313 }); 314 return false; 315 } 316 } 317 } 318 Unfinalized.clear(); 319 320 for (auto &EHFrame : UnfinalizedEHFrames) { 321 if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) { 322 // FIXME: Replace this once finalizeMemory can return an Error. 323 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { 324 if (ErrMsg) { 325 raw_string_ostream ErrOut(*ErrMsg); 326 EIB.log(ErrOut); 327 } 328 }); 329 return false; 330 } 331 } 332 RegisteredEHFrames = std::move(UnfinalizedEHFrames); 333 UnfinalizedEHFrames = {}; 334 335 return false; 336 } 337 338 private: 339 class Alloc { 340 public: 341 Alloc(uint64_t Size, unsigned Align) 342 : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {} 343 344 Alloc(const Alloc &) = delete; 345 Alloc &operator=(const Alloc &) = delete; 346 Alloc(Alloc &&) = default; 347 Alloc &operator=(Alloc &&) = default; 348 349 uint64_t getSize() const { return Size; } 350 351 unsigned getAlign() const { return Align; } 352 353 char *getLocalAddress() const { 354 uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get()); 355 LocalAddr = alignTo(LocalAddr, Align); 356 return reinterpret_cast<char *>(LocalAddr); 357 } 358 359 void setRemoteAddress(JITTargetAddress RemoteAddr) { 360 this->RemoteAddr = RemoteAddr; 361 } 362 363 JITTargetAddress getRemoteAddress() const { return RemoteAddr; } 364 365 private: 366 uint64_t Size; 367 unsigned Align; 368 std::unique_ptr<char[]> Contents; 369 JITTargetAddress RemoteAddr = 0; 370 }; 371 372 struct ObjectAllocs { 373 ObjectAllocs() = default; 374 ObjectAllocs(const ObjectAllocs &) = delete; 375 ObjectAllocs &operator=(const ObjectAllocs &) = delete; 376 ObjectAllocs(ObjectAllocs &&) = default; 377 ObjectAllocs &operator=(ObjectAllocs &&) = default; 378 379 JITTargetAddress RemoteCodeAddr = 0; 380 JITTargetAddress RemoteRODataAddr = 0; 381 JITTargetAddress RemoteRWDataAddr = 0; 382 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs; 383 }; 384 385 OrcRemoteTargetClient &Client; 386 ResourceIdMgr::ResourceId Id; 387 std::vector<ObjectAllocs> Unmapped; 388 std::vector<ObjectAllocs> Unfinalized; 389 390 struct EHFrame { 391 JITTargetAddress Addr; 392 uint64_t Size; 393 }; 394 std::vector<EHFrame> UnfinalizedEHFrames; 395 std::vector<EHFrame> RegisteredEHFrames; 396 }; 397 398 /// Remote indirect stubs manager. 399 class RCIndirectStubsManager : public IndirectStubsManager { 400 public: 401 RCIndirectStubsManager(OrcRemoteTargetClient &Remote, 402 ResourceIdMgr::ResourceId Id) 403 : Remote(Remote), Id(Id) {} 404 405 ~RCIndirectStubsManager() override { 406 if (auto Err = Remote.destroyIndirectStubsManager(Id)) { 407 // FIXME: Thread this error back to clients. 408 consumeError(std::move(Err)); 409 } 410 } 411 412 Error createStub(StringRef StubName, JITTargetAddress StubAddr, 413 JITSymbolFlags StubFlags) override { 414 if (auto Err = reserveStubs(1)) 415 return Err; 416 417 return createStubInternal(StubName, StubAddr, StubFlags); 418 } 419 420 Error createStubs(const StubInitsMap &StubInits) override { 421 if (auto Err = reserveStubs(StubInits.size())) 422 return Err; 423 424 for (auto &Entry : StubInits) 425 if (auto Err = createStubInternal(Entry.first(), Entry.second.first, 426 Entry.second.second)) 427 return Err; 428 429 return Error::success(); 430 } 431 432 JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { 433 auto I = StubIndexes.find(Name); 434 if (I == StubIndexes.end()) 435 return nullptr; 436 auto Key = I->second.first; 437 auto Flags = I->second.second; 438 auto StubSymbol = JITSymbol(getStubAddr(Key), Flags); 439 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported()) 440 return nullptr; 441 return StubSymbol; 442 } 443 444 JITSymbol findPointer(StringRef Name) override { 445 auto I = StubIndexes.find(Name); 446 if (I == StubIndexes.end()) 447 return nullptr; 448 auto Key = I->second.first; 449 auto Flags = I->second.second; 450 return JITSymbol(getPtrAddr(Key), Flags); 451 } 452 453 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override { 454 auto I = StubIndexes.find(Name); 455 assert(I != StubIndexes.end() && "No stub pointer for symbol"); 456 auto Key = I->second.first; 457 return Remote.writePointer(getPtrAddr(Key), NewAddr); 458 } 459 460 private: 461 struct RemoteIndirectStubsInfo { 462 JITTargetAddress StubBase; 463 JITTargetAddress PtrBase; 464 unsigned NumStubs; 465 }; 466 467 OrcRemoteTargetClient &Remote; 468 ResourceIdMgr::ResourceId Id; 469 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos; 470 typedef std::pair<uint16_t, uint16_t> StubKey; 471 std::vector<StubKey> FreeStubs; 472 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes; 473 474 Error reserveStubs(unsigned NumStubs) { 475 if (NumStubs <= FreeStubs.size()) 476 return Error::success(); 477 478 unsigned NewStubsRequired = NumStubs - FreeStubs.size(); 479 JITTargetAddress StubBase; 480 JITTargetAddress PtrBase; 481 unsigned NumStubsEmitted; 482 483 if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired)) 484 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr; 485 else 486 return StubInfoOrErr.takeError(); 487 488 unsigned NewBlockId = RemoteIndirectStubsInfos.size(); 489 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted}); 490 491 for (unsigned I = 0; I < NumStubsEmitted; ++I) 492 FreeStubs.push_back(std::make_pair(NewBlockId, I)); 493 494 return Error::success(); 495 } 496 497 Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr, 498 JITSymbolFlags StubFlags) { 499 auto Key = FreeStubs.back(); 500 FreeStubs.pop_back(); 501 StubIndexes[StubName] = std::make_pair(Key, StubFlags); 502 return Remote.writePointer(getPtrAddr(Key), InitAddr); 503 } 504 505 JITTargetAddress getStubAddr(StubKey K) { 506 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 && 507 "Missing stub address"); 508 return RemoteIndirectStubsInfos[K.first].StubBase + 509 K.second * Remote.getIndirectStubSize(); 510 } 511 512 JITTargetAddress getPtrAddr(StubKey K) { 513 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 && 514 "Missing pointer address"); 515 return RemoteIndirectStubsInfos[K.first].PtrBase + 516 K.second * Remote.getPointerSize(); 517 } 518 }; 519 520 /// Remote compile callback manager. 521 class RCCompileCallbackManager : public JITCompileCallbackManager { 522 public: 523 RCCompileCallbackManager(JITTargetAddress ErrorHandlerAddress, 524 OrcRemoteTargetClient &Remote) 525 : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {} 526 527 private: 528 void grow() override { 529 JITTargetAddress BlockAddr = 0; 530 uint32_t NumTrampolines = 0; 531 if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock()) 532 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr; 533 else { 534 // FIXME: Return error. 535 llvm_unreachable("Failed to create trampolines"); 536 } 537 538 uint32_t TrampolineSize = Remote.getTrampolineSize(); 539 for (unsigned I = 0; I < NumTrampolines; ++I) 540 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize)); 541 } 542 543 OrcRemoteTargetClient &Remote; 544 }; 545 546 /// Create an OrcRemoteTargetClient. 547 /// Channel is the ChannelT instance to communicate on. It is assumed that 548 /// the channel is ready to be read from and written to. 549 static Expected<std::unique_ptr<OrcRemoteTargetClient>> 550 Create(ChannelT &Channel) { 551 Error Err = Error::success(); 552 std::unique_ptr<OrcRemoteTargetClient> Client( 553 new OrcRemoteTargetClient(Channel, Err)); 554 if (Err) 555 return std::move(Err); 556 return std::move(Client); 557 } 558 559 /// Call the int(void) function at the given address in the target and return 560 /// its result. 561 Expected<int> callIntVoid(JITTargetAddress Addr) { 562 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n"); 563 return callB<CallIntVoid>(Addr); 564 } 565 566 /// Call the int(int, char*[]) function at the given address in the target and 567 /// return its result. 568 Expected<int> callMain(JITTargetAddress Addr, 569 const std::vector<std::string> &Args) { 570 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr) 571 << "\n"); 572 return callB<CallMain>(Addr, Args); 573 } 574 575 /// Call the void() function at the given address in the target and wait for 576 /// it to finish. 577 Error callVoidVoid(JITTargetAddress Addr) { 578 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr) 579 << "\n"); 580 return callB<CallVoidVoid>(Addr); 581 } 582 583 /// Create an RCMemoryManager which will allocate its memory on the remote 584 /// target. 585 Error createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) { 586 assert(!MM && "MemoryManager should be null before creation."); 587 588 auto Id = AllocatorIds.getNext(); 589 if (auto Err = callB<CreateRemoteAllocator>(Id)) 590 return Err; 591 MM = llvm::make_unique<RCMemoryManager>(*this, Id); 592 return Error::success(); 593 } 594 595 /// Create an RCIndirectStubsManager that will allocate stubs on the remote 596 /// target. 597 Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) { 598 assert(!I && "Indirect stubs manager should be null before creation."); 599 auto Id = IndirectStubOwnerIds.getNext(); 600 if (auto Err = callB<CreateIndirectStubsOwner>(Id)) 601 return Err; 602 I = llvm::make_unique<RCIndirectStubsManager>(*this, Id); 603 return Error::success(); 604 } 605 606 Expected<RCCompileCallbackManager &> 607 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) { 608 // Check for an 'out-of-band' error, e.g. from an MM destructor. 609 if (ExistingError) 610 return std::move(ExistingError); 611 612 // Emit the resolver block on the JIT server. 613 if (auto Err = callB<EmitResolverBlock>()) 614 return std::move(Err); 615 616 // Create the callback manager. 617 CallbackManager.emplace(ErrorHandlerAddress, *this); 618 RCCompileCallbackManager &Mgr = *CallbackManager; 619 return Mgr; 620 } 621 622 /// Search for symbols in the remote process. Note: This should be used by 623 /// symbol resolvers *after* they've searched the local symbol table in the 624 /// JIT stack. 625 Expected<JITTargetAddress> getSymbolAddress(StringRef Name) { 626 // Check for an 'out-of-band' error, e.g. from an MM destructor. 627 if (ExistingError) 628 return std::move(ExistingError); 629 630 return callB<GetSymbolAddress>(Name); 631 } 632 633 /// Get the triple for the remote target. 634 const std::string &getTargetTriple() const { return RemoteTargetTriple; } 635 636 Error terminateSession() { return callB<TerminateSession>(); } 637 638 private: 639 OrcRemoteTargetClient(ChannelT &Channel, Error &Err) 640 : OrcRemoteTargetRPCAPI(Channel) { 641 ErrorAsOutParameter EAO(&Err); 642 643 addHandler<RequestCompile>( 644 [this](JITTargetAddress Addr) -> JITTargetAddress { 645 if (CallbackManager) 646 return CallbackManager->executeCompileCallback(Addr); 647 return 0; 648 }); 649 650 if (auto RIOrErr = callB<GetRemoteInfo>()) { 651 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize, 652 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr; 653 Err = Error::success(); 654 } else { 655 Err = joinErrors(RIOrErr.takeError(), std::move(ExistingError)); 656 } 657 } 658 659 Error deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) { 660 return callB<RegisterEHFrames>(Addr, Size); 661 } 662 663 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { 664 if (auto Err = callB<DestroyRemoteAllocator>(Id)) { 665 // FIXME: This will be triggered by a removeModuleSet call: Propagate 666 // error return up through that. 667 llvm_unreachable("Failed to destroy remote allocator."); 668 AllocatorIds.release(Id); 669 } 670 } 671 672 Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) { 673 IndirectStubOwnerIds.release(Id); 674 return callB<DestroyIndirectStubsOwner>(Id); 675 } 676 677 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>> 678 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { 679 return callB<EmitIndirectStubs>(Id, NumStubsRequired); 680 } 681 682 Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() { 683 // Check for an 'out-of-band' error, e.g. from an MM destructor. 684 if (ExistingError) 685 return std::move(ExistingError); 686 687 return callB<EmitTrampolineBlock>(); 688 } 689 690 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; } 691 uint32_t getPageSize() const { return RemotePageSize; } 692 uint32_t getPointerSize() const { return RemotePointerSize; } 693 694 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; } 695 696 Expected<std::vector<char>> readMem(char *Dst, JITTargetAddress Src, 697 uint64_t Size) { 698 // Check for an 'out-of-band' error, e.g. from an MM destructor. 699 if (ExistingError) 700 return std::move(ExistingError); 701 702 return callB<ReadMem>(Src, Size); 703 } 704 705 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) { 706 return callB<RegisterEHFrames>(RAddr, Size); 707 } 708 709 Expected<JITTargetAddress> reserveMem(ResourceIdMgr::ResourceId Id, 710 uint64_t Size, uint32_t Align) { 711 712 // Check for an 'out-of-band' error, e.g. from an MM destructor. 713 if (ExistingError) 714 return std::move(ExistingError); 715 716 return callB<ReserveMem>(Id, Size, Align); 717 } 718 719 Error setProtections(ResourceIdMgr::ResourceId Id, 720 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) { 721 return callB<SetProtections>(Id, RemoteSegAddr, ProtFlags); 722 } 723 724 Error writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) { 725 // Check for an 'out-of-band' error, e.g. from an MM destructor. 726 if (ExistingError) 727 return std::move(ExistingError); 728 729 return callB<WriteMem>(DirectBufferWriter(Src, Addr, Size)); 730 } 731 732 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) { 733 // Check for an 'out-of-band' error, e.g. from an MM destructor. 734 if (ExistingError) 735 return std::move(ExistingError); 736 737 return callB<WritePtr>(Addr, PtrVal); 738 } 739 740 static Error doNothing() { return Error::success(); } 741 742 Error ExistingError = Error::success(); 743 std::string RemoteTargetTriple; 744 uint32_t RemotePointerSize = 0; 745 uint32_t RemotePageSize = 0; 746 uint32_t RemoteTrampolineSize = 0; 747 uint32_t RemoteIndirectStubSize = 0; 748 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds; 749 Optional<RCCompileCallbackManager> CallbackManager; 750 }; 751 752 } // end namespace remote 753 } // end namespace orc 754 } // end namespace llvm 755 756 #undef DEBUG_TYPE 757 758 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H 759