1 //===---- OrcRemoteTargetClient.h - Orc Remote-target Client ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the OrcRemoteTargetClient class and helpers. This class
11 // can be used to communicate over an RPCChannel with an OrcRemoteTargetServer
12 // instance to support remote-JITing.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
17 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
19 #include "IndirectionUtils.h"
20 #include "OrcRemoteTargetRPCAPI.h"
22 #define DEBUG_TYPE "orc-remote"
28 /// This class provides utilities (including memory manager, indirect stubs
29 /// manager, and compile callback manager types) that support remote JITing
32 /// Each of the utility classes talks to a JIT server (an instance of the
33 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
35 template <typename ChannelT>
36 class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
38 /// Remote memory manager.
39 class RCMemoryManager : public RuntimeDyld::MemoryManager {
41 RCMemoryManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)
42 : Client(Client), Id(Id) {
43 DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
47 Client.destroyRemoteAllocator(Id);
48 DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
51 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
53 StringRef SectionName) override {
54 Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
55 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
56 Unmapped.back().CodeAllocs.back().getLocalAddress());
57 DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
58 << SectionName << ": " << Alloc << " (" << Size
59 << " bytes, alignment " << Alignment << ")\n");
63 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
64 unsigned SectionID, StringRef SectionName,
65 bool IsReadOnly) override {
67 Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
68 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
69 Unmapped.back().RODataAllocs.back().getLocalAddress());
70 DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
71 << SectionName << ": " << Alloc << " (" << Size
72 << " bytes, alignment " << Alignment << ")\n");
76 Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
77 uint8_t *Alloc = reinterpret_cast<uint8_t *>(
78 Unmapped.back().RWDataAllocs.back().getLocalAddress());
79 DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
80 << SectionName << ": " << Alloc << " (" << Size
81 << " bytes, alignment " << Alignment << "\n");
85 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
86 uintptr_t RODataSize, uint32_t RODataAlign,
88 uint32_t RWDataAlign) override {
89 Unmapped.push_back(ObjectAllocs());
91 DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
94 if (std::error_code EC = Client.reserveMem(
95 Unmapped.back().RemoteCodeAddr, Id, CodeSize, CodeAlign)) {
97 // FIXME; Add error to poll.
98 llvm_unreachable("Failed reserving remote memory.");
100 DEBUG(dbgs() << " code: "
101 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
102 << " (" << CodeSize << " bytes, alignment " << CodeAlign
106 if (RODataSize != 0) {
107 if (auto EC = Client.reserveMem(Unmapped.back().RemoteRODataAddr, Id,
108 RODataSize, RODataAlign)) {
109 // FIXME; Add error to poll.
110 llvm_unreachable("Failed reserving remote memory.");
112 DEBUG(dbgs() << " ro-data: "
113 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
114 << " (" << RODataSize << " bytes, alignment "
115 << RODataAlign << ")\n");
118 if (RWDataSize != 0) {
119 if (auto EC = Client.reserveMem(Unmapped.back().RemoteRWDataAddr, Id,
120 RWDataSize, RWDataAlign)) {
121 // FIXME; Add error to poll.
122 llvm_unreachable("Failed reserving remote memory.");
124 DEBUG(dbgs() << " rw-data: "
125 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
126 << " (" << RWDataSize << " bytes, alignment "
127 << RWDataAlign << ")\n");
131 bool needsToReserveAllocationSpace() override { return true; }
133 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
134 size_t Size) override {}
136 void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
137 size_t Size) override {}
139 void notifyObjectLoaded(RuntimeDyld &Dyld,
140 const object::ObjectFile &Obj) override {
141 DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
142 for (auto &ObjAllocs : Unmapped) {
144 TargetAddress NextCodeAddr = ObjAllocs.RemoteCodeAddr;
145 for (auto &Alloc : ObjAllocs.CodeAllocs) {
146 NextCodeAddr = RoundUpToAlignment(NextCodeAddr, Alloc.getAlign());
147 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextCodeAddr);
148 DEBUG(dbgs() << " code: "
149 << static_cast<void *>(Alloc.getLocalAddress())
150 << " -> " << format("0x%016x", NextCodeAddr) << "\n");
151 Alloc.setRemoteAddress(NextCodeAddr);
152 NextCodeAddr += Alloc.getSize();
156 TargetAddress NextRODataAddr = ObjAllocs.RemoteRODataAddr;
157 for (auto &Alloc : ObjAllocs.RODataAllocs) {
159 RoundUpToAlignment(NextRODataAddr, Alloc.getAlign());
160 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRODataAddr);
161 DEBUG(dbgs() << " ro-data: "
162 << static_cast<void *>(Alloc.getLocalAddress())
163 << " -> " << format("0x%016x", NextRODataAddr)
165 Alloc.setRemoteAddress(NextRODataAddr);
166 NextRODataAddr += Alloc.getSize();
170 TargetAddress NextRWDataAddr = ObjAllocs.RemoteRWDataAddr;
171 for (auto &Alloc : ObjAllocs.RWDataAllocs) {
173 RoundUpToAlignment(NextRWDataAddr, Alloc.getAlign());
174 Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRWDataAddr);
175 DEBUG(dbgs() << " rw-data: "
176 << static_cast<void *>(Alloc.getLocalAddress())
177 << " -> " << format("0x%016x", NextRWDataAddr)
179 Alloc.setRemoteAddress(NextRWDataAddr);
180 NextRWDataAddr += Alloc.getSize();
183 Unfinalized.push_back(std::move(ObjAllocs));
188 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
189 DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
191 for (auto &ObjAllocs : Unfinalized) {
193 for (auto &Alloc : ObjAllocs.CodeAllocs) {
194 DEBUG(dbgs() << " copying code: "
195 << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
196 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
197 << Alloc.getSize() << " bytes)\n");
198 Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
202 if (ObjAllocs.RemoteCodeAddr) {
203 DEBUG(dbgs() << " setting R-X permissions on code block: "
204 << format("0x%016x", ObjAllocs.RemoteCodeAddr) << "\n");
205 Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
206 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
209 for (auto &Alloc : ObjAllocs.RODataAllocs) {
210 DEBUG(dbgs() << " copying ro-data: "
211 << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
212 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
213 << Alloc.getSize() << " bytes)\n");
214 Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
218 if (ObjAllocs.RemoteRODataAddr) {
219 DEBUG(dbgs() << " setting R-- permissions on ro-data block: "
220 << format("0x%016x", ObjAllocs.RemoteRODataAddr)
222 Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
223 sys::Memory::MF_READ);
226 for (auto &Alloc : ObjAllocs.RWDataAllocs) {
227 DEBUG(dbgs() << " copying rw-data: "
228 << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
229 << format("0x%016x", Alloc.getRemoteAddress()) << " ("
230 << Alloc.getSize() << " bytes)\n");
231 Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
235 if (ObjAllocs.RemoteRWDataAddr) {
236 DEBUG(dbgs() << " setting RW- permissions on rw-data block: "
237 << format("0x%016x", ObjAllocs.RemoteRWDataAddr)
239 Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
240 sys::Memory::MF_READ | sys::Memory::MF_WRITE);
251 Alloc(uint64_t Size, unsigned Align)
252 : Size(Size), Align(Align), Contents(new char[Size + Align - 1]),
256 : Size(std::move(Other.Size)), Align(std::move(Other.Align)),
257 Contents(std::move(Other.Contents)),
258 RemoteAddr(std::move(Other.RemoteAddr)) {}
260 Alloc &operator=(Alloc &&Other) {
261 Size = std::move(Other.Size);
262 Align = std::move(Other.Align);
263 Contents = std::move(Other.Contents);
264 RemoteAddr = std::move(Other.RemoteAddr);
268 uint64_t getSize() const { return Size; }
270 unsigned getAlign() const { return Align; }
272 char *getLocalAddress() const {
273 uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
274 LocalAddr = RoundUpToAlignment(LocalAddr, Align);
275 return reinterpret_cast<char *>(LocalAddr);
278 void setRemoteAddress(TargetAddress RemoteAddr) {
279 this->RemoteAddr = RemoteAddr;
282 TargetAddress getRemoteAddress() const { return RemoteAddr; }
287 std::unique_ptr<char[]> Contents;
288 TargetAddress RemoteAddr;
291 struct ObjectAllocs {
293 : RemoteCodeAddr(0), RemoteRODataAddr(0), RemoteRWDataAddr(0) {}
294 TargetAddress RemoteCodeAddr;
295 TargetAddress RemoteRODataAddr;
296 TargetAddress RemoteRWDataAddr;
297 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
300 OrcRemoteTargetClient &Client;
301 ResourceIdMgr::ResourceId Id;
302 std::vector<ObjectAllocs> Unmapped;
303 std::vector<ObjectAllocs> Unfinalized;
306 /// Remote indirect stubs manager.
307 class RCIndirectStubsManager : public IndirectStubsManager {
309 RCIndirectStubsManager(OrcRemoteTargetClient &Remote,
310 ResourceIdMgr::ResourceId Id)
311 : Remote(Remote), Id(Id) {}
313 ~RCIndirectStubsManager() { Remote.destroyIndirectStubsManager(Id); }
315 std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
316 JITSymbolFlags StubFlags) override {
317 if (auto EC = reserveStubs(1))
320 return createStubInternal(StubName, StubAddr, StubFlags);
323 std::error_code createStubs(const StubInitsMap &StubInits) override {
324 if (auto EC = reserveStubs(StubInits.size()))
327 for (auto &Entry : StubInits)
328 if (auto EC = createStubInternal(Entry.first(), Entry.second.first,
329 Entry.second.second))
332 return std::error_code();
335 JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
336 auto I = StubIndexes.find(Name);
337 if (I == StubIndexes.end())
339 auto Key = I->second.first;
340 auto Flags = I->second.second;
341 auto StubSymbol = JITSymbol(getStubAddr(Key), Flags);
342 if (ExportedStubsOnly && !StubSymbol.isExported())
347 JITSymbol findPointer(StringRef Name) override {
348 auto I = StubIndexes.find(Name);
349 if (I == StubIndexes.end())
351 auto Key = I->second.first;
352 auto Flags = I->second.second;
353 return JITSymbol(getPtrAddr(Key), Flags);
356 std::error_code updatePointer(StringRef Name,
357 TargetAddress NewAddr) override {
358 auto I = StubIndexes.find(Name);
359 assert(I != StubIndexes.end() && "No stub pointer for symbol");
360 auto Key = I->second.first;
361 return Remote.writePointer(getPtrAddr(Key), NewAddr);
365 struct RemoteIndirectStubsInfo {
366 RemoteIndirectStubsInfo(TargetAddress StubBase, TargetAddress PtrBase,
368 : StubBase(StubBase), PtrBase(PtrBase), NumStubs(NumStubs) {}
369 TargetAddress StubBase;
370 TargetAddress PtrBase;
374 OrcRemoteTargetClient &Remote;
375 ResourceIdMgr::ResourceId Id;
376 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
377 typedef std::pair<uint16_t, uint16_t> StubKey;
378 std::vector<StubKey> FreeStubs;
379 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
381 std::error_code reserveStubs(unsigned NumStubs) {
382 if (NumStubs <= FreeStubs.size())
383 return std::error_code();
385 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
386 TargetAddress StubBase;
387 TargetAddress PtrBase;
388 unsigned NumStubsEmitted;
390 Remote.emitIndirectStubs(StubBase, PtrBase, NumStubsEmitted, Id,
393 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
394 RemoteIndirectStubsInfos.push_back(
395 RemoteIndirectStubsInfo(StubBase, PtrBase, NumStubsEmitted));
397 for (unsigned I = 0; I < NumStubsEmitted; ++I)
398 FreeStubs.push_back(std::make_pair(NewBlockId, I));
400 return std::error_code();
403 std::error_code createStubInternal(StringRef StubName,
404 TargetAddress InitAddr,
405 JITSymbolFlags StubFlags) {
406 auto Key = FreeStubs.back();
407 FreeStubs.pop_back();
408 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
409 return Remote.writePointer(getPtrAddr(Key), InitAddr);
412 TargetAddress getStubAddr(StubKey K) {
413 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
414 "Missing stub address");
415 return RemoteIndirectStubsInfos[K.first].StubBase +
416 K.second * Remote.getIndirectStubSize();
419 TargetAddress getPtrAddr(StubKey K) {
420 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
421 "Missing pointer address");
422 return RemoteIndirectStubsInfos[K.first].PtrBase +
423 K.second * Remote.getPointerSize();
427 /// Remote compile callback manager.
428 class RCCompileCallbackManager : public JITCompileCallbackManager {
430 RCCompileCallbackManager(TargetAddress ErrorHandlerAddress,
431 OrcRemoteTargetClient &Remote)
432 : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {
433 assert(!Remote.CompileCallback && "Compile callback already set");
434 Remote.CompileCallback = [this](TargetAddress TrampolineAddr) {
435 return executeCompileCallback(TrampolineAddr);
437 Remote.emitResolverBlock();
442 TargetAddress BlockAddr = 0;
443 uint32_t NumTrampolines = 0;
444 auto EC = Remote.emitTrampolineBlock(BlockAddr, NumTrampolines);
445 assert(!EC && "Failed to create trampolines");
447 uint32_t TrampolineSize = Remote.getTrampolineSize();
448 for (unsigned I = 0; I < NumTrampolines; ++I)
449 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
452 OrcRemoteTargetClient &Remote;
455 /// Create an OrcRemoteTargetClient.
456 /// Channel is the ChannelT instance to communicate on. It is assumed that
457 /// the channel is ready to be read from and written to.
458 static ErrorOr<OrcRemoteTargetClient> Create(ChannelT &Channel) {
460 OrcRemoteTargetClient H(Channel, EC);
466 /// Call the int(void) function at the given address in the target and return
468 std::error_code callIntVoid(int &Result, TargetAddress Addr) {
469 DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
471 if (auto EC = call<CallIntVoid>(Channel, Addr))
475 if (auto EC = listenForCompileRequests(NextProcId))
478 if (NextProcId != CallIntVoidResponseId)
479 return orcError(OrcErrorCode::UnexpectedRPCCall);
481 return handle<CallIntVoidResponse>(Channel, [&](int R) {
483 DEBUG(dbgs() << "Result: " << R << "\n");
484 return std::error_code();
488 /// Call the int(int, char*[]) function at the given address in the target and
489 /// return its result.
490 std::error_code callMain(int &Result, TargetAddress Addr,
491 const std::vector<std::string> &Args) {
492 DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
495 if (auto EC = call<CallMain>(Channel, Addr, Args))
499 if (auto EC = listenForCompileRequests(NextProcId))
502 if (NextProcId != CallMainResponseId)
503 return orcError(OrcErrorCode::UnexpectedRPCCall);
505 return handle<CallMainResponse>(Channel, [&](int R) {
507 DEBUG(dbgs() << "Result: " << R << "\n");
508 return std::error_code();
512 /// Call the void() function at the given address in the target and wait for
514 std::error_code callVoidVoid(TargetAddress Addr) {
515 DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
518 if (auto EC = call<CallVoidVoid>(Channel, Addr))
522 if (auto EC = listenForCompileRequests(NextProcId))
525 if (NextProcId != CallVoidVoidResponseId)
526 return orcError(OrcErrorCode::UnexpectedRPCCall);
528 return handle<CallVoidVoidResponse>(Channel, doNothing);
531 /// Create an RCMemoryManager which will allocate its memory on the remote
534 createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
535 assert(!MM && "MemoryManager should be null before creation.");
537 auto Id = AllocatorIds.getNext();
538 if (auto EC = call<CreateRemoteAllocator>(Channel, Id))
540 MM = llvm::make_unique<RCMemoryManager>(*this, Id);
541 return std::error_code();
544 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
547 createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
548 assert(!I && "Indirect stubs manager should be null before creation.");
549 auto Id = IndirectStubOwnerIds.getNext();
550 if (auto EC = call<CreateIndirectStubsOwner>(Channel, Id))
552 I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
553 return std::error_code();
556 /// Search for symbols in the remote process. Note: This should be used by
557 /// symbol resolvers *after* they've searched the local symbol table in the
559 std::error_code getSymbolAddress(TargetAddress &Addr, StringRef Name) {
560 // Check for an 'out-of-band' error, e.g. from an MM destructor.
562 return ExistingError;
564 // Request remote symbol address.
565 if (auto EC = call<GetSymbolAddress>(Channel, Name))
568 return expect<GetSymbolAddressResponse>(Channel, [&](TargetAddress &A) {
570 DEBUG(dbgs() << "Remote address lookup " << Name << " = "
571 << format("0x%016x", Addr) << "\n");
572 return std::error_code();
576 /// Get the triple for the remote target.
577 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
579 std::error_code terminateSession() { return call<TerminateSession>(Channel); }
582 OrcRemoteTargetClient(ChannelT &Channel, std::error_code &EC)
583 : Channel(Channel), RemotePointerSize(0), RemotePageSize(0),
584 RemoteTrampolineSize(0), RemoteIndirectStubSize(0) {
585 if ((EC = call<GetRemoteInfo>(Channel)))
588 EC = expect<GetRemoteInfoResponse>(
589 Channel, readArgs(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
590 RemoteTrampolineSize, RemoteIndirectStubSize));
593 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
594 if (auto EC = call<DestroyRemoteAllocator>(Channel, Id)) {
595 // FIXME: This will be triggered by a removeModuleSet call: Propagate
596 // error return up through that.
597 llvm_unreachable("Failed to destroy remote allocator.");
598 AllocatorIds.release(Id);
602 std::error_code destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
603 IndirectStubOwnerIds.release(Id);
604 return call<DestroyIndirectStubsOwner>(Channel, Id);
607 std::error_code emitIndirectStubs(TargetAddress &StubBase,
608 TargetAddress &PtrBase,
609 uint32_t &NumStubsEmitted,
610 ResourceIdMgr::ResourceId Id,
611 uint32_t NumStubsRequired) {
612 if (auto EC = call<EmitIndirectStubs>(Channel, Id, NumStubsRequired))
615 return expect<EmitIndirectStubsResponse>(
616 Channel, readArgs(StubBase, PtrBase, NumStubsEmitted));
619 std::error_code emitResolverBlock() {
620 // Check for an 'out-of-band' error, e.g. from an MM destructor.
622 return ExistingError;
624 return call<EmitResolverBlock>(Channel);
627 std::error_code emitTrampolineBlock(TargetAddress &BlockAddr,
628 uint32_t &NumTrampolines) {
629 // Check for an 'out-of-band' error, e.g. from an MM destructor.
631 return ExistingError;
633 if (auto EC = call<EmitTrampolineBlock>(Channel))
636 return expect<EmitTrampolineBlockResponse>(
637 Channel, [&](TargetAddress BAddr, uint32_t NTrampolines) {
639 NumTrampolines = NTrampolines;
640 return std::error_code();
644 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
645 uint32_t getPageSize() const { return RemotePageSize; }
646 uint32_t getPointerSize() const { return RemotePointerSize; }
648 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
650 std::error_code listenForCompileRequests(uint32_t &NextId) {
651 // Check for an 'out-of-band' error, e.g. from an MM destructor.
653 return ExistingError;
655 if (auto EC = getNextProcId(Channel, NextId))
658 while (NextId == RequestCompileId) {
659 TargetAddress TrampolineAddr = 0;
660 if (auto EC = handle<RequestCompile>(Channel, readArgs(TrampolineAddr)))
663 TargetAddress ImplAddr = CompileCallback(TrampolineAddr);
664 if (auto EC = call<RequestCompileResponse>(Channel, ImplAddr))
667 if (auto EC = getNextProcId(Channel, NextId))
671 return std::error_code();
674 std::error_code readMem(char *Dst, TargetAddress Src, uint64_t Size) {
675 // Check for an 'out-of-band' error, e.g. from an MM destructor.
677 return ExistingError;
679 if (auto EC = call<ReadMem>(Channel, Src, Size))
682 if (auto EC = expect<ReadMemResponse>(
683 Channel, [&]() { return Channel.readBytes(Dst, Size); }))
686 return std::error_code();
689 std::error_code reserveMem(TargetAddress &RemoteAddr,
690 ResourceIdMgr::ResourceId Id, uint64_t Size,
693 // Check for an 'out-of-band' error, e.g. from an MM destructor.
695 return ExistingError;
697 if (auto EC = call<ReserveMem>(Channel, Id, Size, Align))
700 if (auto EC = expect<ReserveMemResponse>(Channel, [&](TargetAddress Addr) {
702 return std::error_code();
706 return std::error_code();
709 std::error_code setProtections(ResourceIdMgr::ResourceId Id,
710 TargetAddress RemoteSegAddr,
711 unsigned ProtFlags) {
712 return call<SetProtections>(Channel, Id, RemoteSegAddr, ProtFlags);
715 std::error_code writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
716 // Check for an 'out-of-band' error, e.g. from an MM destructor.
718 return ExistingError;
720 // Make the send call.
721 if (auto EC = call<WriteMem>(Channel, Addr, Size))
724 // Follow this up with the section contents.
725 if (auto EC = Channel.appendBytes(Src, Size))
728 return Channel.send();
731 std::error_code writePointer(TargetAddress Addr, TargetAddress PtrVal) {
732 // Check for an 'out-of-band' error, e.g. from an MM destructor.
734 return ExistingError;
736 return call<WritePtr>(Channel, Addr, PtrVal);
739 static std::error_code doNothing() { return std::error_code(); }
742 std::error_code ExistingError;
743 std::string RemoteTargetTriple;
744 uint32_t RemotePointerSize;
745 uint32_t RemotePageSize;
746 uint32_t RemoteTrampolineSize;
747 uint32_t RemoteIndirectStubSize;
748 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
749 std::function<TargetAddress(TargetAddress)> CompileCallback;
752 } // end namespace remote
753 } // end namespace orc
754 } // end namespace llvm