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