blob: 739e5ba47c1214a56f4a6ab0ba4175029e21bf80 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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
45namespace llvm {
46namespace orc {
47namespace 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.
56class OrcRemoteTargetClient
57 : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
58public:
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);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010066 LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010067 }
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());
Andrew Scullcdfcccc2018-10-05 20:58:37 +010082 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
83 << SectionName << ": " << Alloc << " (" << Size
84 << " bytes, alignment " << Alignment << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010085 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());
Andrew Scullcdfcccc2018-10-05 20:58:37 +010095 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
96 << SectionName << ": " << Alloc << " (" << Size
97 << " bytes, alignment " << Alignment << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098 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());
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100104 LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
105 << SectionName << ": " << Alloc << " (" << Size
106 << " bytes, alignment " << Alignment << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100107 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100116 LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100117
118 if (CodeSize != 0) {
119 Unmapped.back().RemoteCodeAddr =
120 Client.reserveMem(Id, CodeSize, CodeAlign);
121
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100122 LLVM_DEBUG(dbgs() << " code: "
123 << format("0x%016x", Unmapped.back().RemoteCodeAddr)
124 << " (" << CodeSize << " bytes, alignment "
125 << CodeAlign << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100126 }
127
128 if (RODataSize != 0) {
129 Unmapped.back().RemoteRODataAddr =
130 Client.reserveMem(Id, RODataSize, RODataAlign);
131
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100132 LLVM_DEBUG(dbgs() << " ro-data: "
133 << format("0x%016x", Unmapped.back().RemoteRODataAddr)
134 << " (" << RODataSize << " bytes, alignment "
135 << RODataAlign << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100136 }
137
138 if (RWDataSize != 0) {
139 Unmapped.back().RemoteRWDataAddr =
140 Client.reserveMem(Id, RWDataSize, RWDataAlign);
141
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100142 LLVM_DEBUG(dbgs() << " rw-data: "
143 << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
144 << " (" << RWDataSize << " bytes, alignment "
145 << RWDataAlign << ")\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100146 }
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 {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100165 LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100166 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 {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100179 LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100180
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) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100264 LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100265 }
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);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100273 LLVM_DEBUG(dbgs() << " "
274 << static_cast<void *>(Alloc.getLocalAddress())
275 << " -> " << format("0x%016x", NextAddr) << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100276 Alloc.setRemoteAddress(NextAddr);
277
278 // Only advance NextAddr if it was non-null to begin with,
279 // otherwise leave it as null.
280 if (NextAddr)
281 NextAddr += Alloc.getSize();
282 }
283 }
284
285 // Copies data for each alloc in the list, then set permissions on the
286 // segment.
287 bool copyAndProtect(const std::vector<Alloc> &Allocs,
288 JITTargetAddress RemoteSegmentAddr,
289 unsigned Permissions) {
290 if (RemoteSegmentAddr) {
291 assert(!Allocs.empty() && "No sections in allocated segment");
292
293 for (auto &Alloc : Allocs) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100294 LLVM_DEBUG(dbgs() << " copying section: "
295 << static_cast<void *>(Alloc.getLocalAddress())
296 << " -> "
297 << format("0x%016x", Alloc.getRemoteAddress())
298 << " (" << Alloc.getSize() << " bytes)\n";);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100299
300 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
301 Alloc.getSize()))
302 return true;
303 }
304
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100305 LLVM_DEBUG(dbgs() << " setting "
306 << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
307 << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
308 << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
309 << " permissions on block: "
310 << format("0x%016x", RemoteSegmentAddr) << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100311 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
312 return true;
313 }
314 return false;
315 }
316
317 OrcRemoteTargetClient &Client;
318 ResourceIdMgr::ResourceId Id;
319 std::vector<ObjectAllocs> Unmapped;
320 std::vector<ObjectAllocs> Unfinalized;
321
322 struct EHFrame {
323 JITTargetAddress Addr;
324 uint64_t Size;
325 };
326 std::vector<EHFrame> UnfinalizedEHFrames;
327 std::vector<EHFrame> RegisteredEHFrames;
328 };
329
330 /// Remote indirect stubs manager.
331 class RemoteIndirectStubsManager : public IndirectStubsManager {
332 public:
333 RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
334 ResourceIdMgr::ResourceId Id)
335 : Client(Client), Id(Id) {}
336
337 ~RemoteIndirectStubsManager() override {
338 Client.destroyIndirectStubsManager(Id);
339 }
340
341 Error createStub(StringRef StubName, JITTargetAddress StubAddr,
342 JITSymbolFlags StubFlags) override {
343 if (auto Err = reserveStubs(1))
344 return Err;
345
346 return createStubInternal(StubName, StubAddr, StubFlags);
347 }
348
349 Error createStubs(const StubInitsMap &StubInits) override {
350 if (auto Err = reserveStubs(StubInits.size()))
351 return Err;
352
353 for (auto &Entry : StubInits)
354 if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
355 Entry.second.second))
356 return Err;
357
358 return Error::success();
359 }
360
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100361 JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100362 auto I = StubIndexes.find(Name);
363 if (I == StubIndexes.end())
364 return nullptr;
365 auto Key = I->second.first;
366 auto Flags = I->second.second;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100367 auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100368 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
369 return nullptr;
370 return StubSymbol;
371 }
372
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100373 JITEvaluatedSymbol findPointer(StringRef Name) override {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100374 auto I = StubIndexes.find(Name);
375 if (I == StubIndexes.end())
376 return nullptr;
377 auto Key = I->second.first;
378 auto Flags = I->second.second;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100379 return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100380 }
381
382 Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
383 auto I = StubIndexes.find(Name);
384 assert(I != StubIndexes.end() && "No stub pointer for symbol");
385 auto Key = I->second.first;
386 return Client.writePointer(getPtrAddr(Key), NewAddr);
387 }
388
389 private:
390 struct RemoteIndirectStubsInfo {
391 JITTargetAddress StubBase;
392 JITTargetAddress PtrBase;
393 unsigned NumStubs;
394 };
395
396 using StubKey = std::pair<uint16_t, uint16_t>;
397
398 Error reserveStubs(unsigned NumStubs) {
399 if (NumStubs <= FreeStubs.size())
400 return Error::success();
401
402 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
403 JITTargetAddress StubBase;
404 JITTargetAddress PtrBase;
405 unsigned NumStubsEmitted;
406
407 if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
408 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
409 else
410 return StubInfoOrErr.takeError();
411
412 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
413 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
414
415 for (unsigned I = 0; I < NumStubsEmitted; ++I)
416 FreeStubs.push_back(std::make_pair(NewBlockId, I));
417
418 return Error::success();
419 }
420
421 Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
422 JITSymbolFlags StubFlags) {
423 auto Key = FreeStubs.back();
424 FreeStubs.pop_back();
425 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
426 return Client.writePointer(getPtrAddr(Key), InitAddr);
427 }
428
429 JITTargetAddress getStubAddr(StubKey K) {
430 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
431 "Missing stub address");
432 return RemoteIndirectStubsInfos[K.first].StubBase +
433 K.second * Client.getIndirectStubSize();
434 }
435
436 JITTargetAddress getPtrAddr(StubKey K) {
437 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
438 "Missing pointer address");
439 return RemoteIndirectStubsInfos[K.first].PtrBase +
440 K.second * Client.getPointerSize();
441 }
442
443 OrcRemoteTargetClient &Client;
444 ResourceIdMgr::ResourceId Id;
445 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
446 std::vector<StubKey> FreeStubs;
447 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
448 };
449
450 /// Remote compile callback manager.
451 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
452 public:
453 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100454 ExecutionSession &ES,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100455 JITTargetAddress ErrorHandlerAddress)
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100456 : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100457
458 private:
459 Error grow() override {
460 JITTargetAddress BlockAddr = 0;
461 uint32_t NumTrampolines = 0;
462 if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
463 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
464 else
465 return TrampolineInfoOrErr.takeError();
466
467 uint32_t TrampolineSize = Client.getTrampolineSize();
468 for (unsigned I = 0; I < NumTrampolines; ++I)
469 this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
470
471 return Error::success();
472 }
473
474 OrcRemoteTargetClient &Client;
475 };
476
477 /// Create an OrcRemoteTargetClient.
478 /// Channel is the ChannelT instance to communicate on. It is assumed that
479 /// the channel is ready to be read from and written to.
480 static Expected<std::unique_ptr<OrcRemoteTargetClient>>
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100481 Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100482 Error Err = Error::success();
483 auto Client = std::unique_ptr<OrcRemoteTargetClient>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100484 new OrcRemoteTargetClient(Channel, ES, Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100485 if (Err)
486 return std::move(Err);
487 return std::move(Client);
488 }
489
490 /// Call the int(void) function at the given address in the target and return
491 /// its result.
492 Expected<int> callIntVoid(JITTargetAddress Addr) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100493 LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
494 << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100495 return callB<exec::CallIntVoid>(Addr);
496 }
497
498 /// Call the int(int, char*[]) function at the given address in the target and
499 /// return its result.
500 Expected<int> callMain(JITTargetAddress Addr,
501 const std::vector<std::string> &Args) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100502 LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
503 << format("0x%016x", Addr) << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100504 return callB<exec::CallMain>(Addr, Args);
505 }
506
507 /// Call the void() function at the given address in the target and wait for
508 /// it to finish.
509 Error callVoidVoid(JITTargetAddress Addr) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100510 LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
511 << "\n");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100512 return callB<exec::CallVoidVoid>(Addr);
513 }
514
515 /// Create an RCMemoryManager which will allocate its memory on the remote
516 /// target.
517 Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
518 createRemoteMemoryManager() {
519 auto Id = AllocatorIds.getNext();
520 if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
521 return std::move(Err);
522 return std::unique_ptr<RemoteRTDyldMemoryManager>(
523 new RemoteRTDyldMemoryManager(*this, Id));
524 }
525
526 /// Create an RCIndirectStubsManager that will allocate stubs on the remote
527 /// target.
528 Expected<std::unique_ptr<RemoteIndirectStubsManager>>
529 createIndirectStubsManager() {
530 auto Id = IndirectStubOwnerIds.getNext();
531 if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
532 return std::move(Err);
533 return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
534 }
535
536 Expected<RemoteCompileCallbackManager &>
537 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100538 assert(!CallbackManager && "CallbackManager already obtained");
539
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100540 // Emit the resolver block on the JIT server.
541 if (auto Err = callB<stubs::EmitResolverBlock>())
542 return std::move(Err);
543
544 // Create the callback manager.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100545 CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100546 RemoteCompileCallbackManager &Mgr = *CallbackManager;
547 return Mgr;
548 }
549
550 /// Search for symbols in the remote process. Note: This should be used by
551 /// symbol resolvers *after* they've searched the local symbol table in the
552 /// JIT stack.
553 Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
554 return callB<utils::GetSymbolAddress>(Name);
555 }
556
557 /// Get the triple for the remote target.
558 const std::string &getTargetTriple() const { return RemoteTargetTriple; }
559
560 Error terminateSession() { return callB<utils::TerminateSession>(); }
561
562private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100563 OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
564 Error &Err)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100565 : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100566 ES(ES) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100567 ErrorAsOutParameter EAO(&Err);
568
569 addHandler<utils::RequestCompile>(
570 [this](JITTargetAddress Addr) -> JITTargetAddress {
571 if (CallbackManager)
572 return CallbackManager->executeCompileCallback(Addr);
573 return 0;
574 });
575
576 if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
577 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
578 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
579 Err = Error::success();
580 } else
581 Err = RIOrErr.takeError();
582 }
583
584 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
585 if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100586 ES.reportError(std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100587 }
588
589 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
590 if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
591 // FIXME: This will be triggered by a removeModuleSet call: Propagate
592 // error return up through that.
593 llvm_unreachable("Failed to destroy remote allocator.");
594 AllocatorIds.release(Id);
595 }
596 }
597
598 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
599 IndirectStubOwnerIds.release(Id);
600 if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100601 ES.reportError(std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100602 }
603
604 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
605 emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
606 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
607 }
608
609 Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
610 return callB<stubs::EmitTrampolineBlock>();
611 }
612
613 uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
614 uint32_t getPageSize() const { return RemotePageSize; }
615 uint32_t getPointerSize() const { return RemotePointerSize; }
616
617 uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
618
619 Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
620 uint64_t Size) {
621 return callB<mem::ReadMem>(Src, Size);
622 }
623
624 Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
625 // FIXME: Duplicate error and report it via ReportError too?
626 return callB<eh::RegisterEHFrames>(RAddr, Size);
627 }
628
629 JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
630 uint32_t Align) {
631 if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
632 return *AddrOrErr;
633 else {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100634 ES.reportError(AddrOrErr.takeError());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100635 return 0;
636 }
637 }
638
639 bool setProtections(ResourceIdMgr::ResourceId Id,
640 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
641 if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100642 ES.reportError(std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100643 return true;
644 } else
645 return false;
646 }
647
648 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
649 if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100650 ES.reportError(std::move(Err));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100651 return true;
652 } else
653 return false;
654 }
655
656 Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
657 return callB<mem::WritePtr>(Addr, PtrVal);
658 }
659
660 static Error doNothing() { return Error::success(); }
661
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100662 ExecutionSession &ES;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100663 std::function<void(Error)> ReportError;
664 std::string RemoteTargetTriple;
665 uint32_t RemotePointerSize = 0;
666 uint32_t RemotePageSize = 0;
667 uint32_t RemoteTrampolineSize = 0;
668 uint32_t RemoteIndirectStubSize = 0;
669 ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
670 Optional<RemoteCompileCallbackManager> CallbackManager;
671};
672
673} // end namespace remote
674} // end namespace orc
675} // end namespace llvm
676
677#undef DEBUG_TYPE
678
679#endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H