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