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