LLVM  9.0.0svn
OrcRemoteTargetClient.h
Go to the documentation of this file.
1 //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the OrcRemoteTargetClient class and helpers. This class
10 // can be used to communicate over an RawByteChannel with an
11 // OrcRemoteTargetServer instance to support remote-JITing.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
16 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
17 
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/Error.h"
29 #include "llvm/Support/Format.h"
31 #include "llvm/Support/Memory.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstdint>
36 #include <memory>
37 #include <string>
38 #include <tuple>
39 #include <utility>
40 #include <vector>
41 
42 #define DEBUG_TYPE "orc-remote"
43 
44 namespace llvm {
45 namespace orc {
46 namespace remote {
47 
48 /// This class provides utilities (including memory manager, indirect stubs
49 /// manager, and compile callback manager types) that support remote JITing
50 /// in ORC.
51 ///
52 /// Each of the utility classes talks to a JIT server (an instance of the
53 /// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
54 /// its actions.
56  : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
57 public:
58  /// Remote-mapped RuntimeDyld-compatible memory manager.
60  friend class OrcRemoteTargetClient;
61 
62  public:
64  Client.destroyRemoteAllocator(Id);
65  LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
66  }
67 
70  operator=(const RemoteRTDyldMemoryManager &) = delete;
73 
74  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
75  unsigned SectionID,
76  StringRef SectionName) override {
77  Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
78  uint8_t *Alloc = reinterpret_cast<uint8_t *>(
79  Unmapped.back().CodeAllocs.back().getLocalAddress());
80  LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
81  << SectionName << ": " << Alloc << " (" << Size
82  << " bytes, alignment " << Alignment << ")\n");
83  return Alloc;
84  }
85 
86  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
87  unsigned SectionID, StringRef SectionName,
88  bool IsReadOnly) override {
89  if (IsReadOnly) {
90  Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
91  uint8_t *Alloc = reinterpret_cast<uint8_t *>(
92  Unmapped.back().RODataAllocs.back().getLocalAddress());
93  LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
94  << SectionName << ": " << Alloc << " (" << Size
95  << " bytes, alignment " << Alignment << ")\n");
96  return Alloc;
97  } // else...
98 
99  Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
100  uint8_t *Alloc = reinterpret_cast<uint8_t *>(
101  Unmapped.back().RWDataAllocs.back().getLocalAddress());
102  LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
103  << SectionName << ": " << Alloc << " (" << Size
104  << " bytes, alignment " << Alignment << ")\n");
105  return Alloc;
106  }
107 
108  void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
109  uintptr_t RODataSize, uint32_t RODataAlign,
110  uintptr_t RWDataSize,
111  uint32_t RWDataAlign) override {
112  Unmapped.push_back(ObjectAllocs());
113 
114  LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
115 
116  if (CodeSize != 0) {
117  Unmapped.back().RemoteCodeAddr =
118  Client.reserveMem(Id, CodeSize, CodeAlign);
119 
120  LLVM_DEBUG(
121  dbgs() << " code: "
122  << format("0x%016" PRIx64, Unmapped.back().RemoteCodeAddr)
123  << " (" << CodeSize << " bytes, alignment " << CodeAlign
124  << ")\n");
125  }
126 
127  if (RODataSize != 0) {
128  Unmapped.back().RemoteRODataAddr =
129  Client.reserveMem(Id, RODataSize, RODataAlign);
130 
131  LLVM_DEBUG(
132  dbgs() << " ro-data: "
133  << format("0x%016" PRIx64, Unmapped.back().RemoteRODataAddr)
134  << " (" << RODataSize << " bytes, alignment " << RODataAlign
135  << ")\n");
136  }
137 
138  if (RWDataSize != 0) {
139  Unmapped.back().RemoteRWDataAddr =
140  Client.reserveMem(Id, RWDataSize, RWDataAlign);
141 
142  LLVM_DEBUG(
143  dbgs() << " rw-data: "
144  << format("0x%016" PRIx64, Unmapped.back().RemoteRWDataAddr)
145  << " (" << RWDataSize << " bytes, alignment " << RWDataAlign
146  << ")\n");
147  }
148  }
149 
150  bool needsToReserveAllocationSpace() override { return true; }
151 
152  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
153  size_t Size) override {
154  UnfinalizedEHFrames.push_back({LoadAddr, Size});
155  }
156 
157  void deregisterEHFrames() override {
158  for (auto &Frame : RegisteredEHFrames) {
159  // FIXME: Add error poll.
160  Client.deregisterEHFrames(Frame.Addr, Frame.Size);
161  }
162  }
163 
165  const object::ObjectFile &Obj) override {
166  LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
167  for (auto &ObjAllocs : Unmapped) {
168  mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
169  ObjAllocs.RemoteCodeAddr);
170  mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
171  ObjAllocs.RemoteRODataAddr);
172  mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
173  ObjAllocs.RemoteRWDataAddr);
174  Unfinalized.push_back(std::move(ObjAllocs));
175  }
176  Unmapped.clear();
177  }
178 
179  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
180  LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
181 
182  for (auto &ObjAllocs : Unfinalized) {
183  if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
185  return true;
186 
187  if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
189  return true;
190 
191  if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
193  return true;
194  }
195  Unfinalized.clear();
196 
197  for (auto &EHFrame : UnfinalizedEHFrames) {
198  if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
199  // FIXME: Replace this once finalizeMemory can return an Error.
200  handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
201  if (ErrMsg) {
202  raw_string_ostream ErrOut(*ErrMsg);
203  EIB.log(ErrOut);
204  }
205  });
206  return false;
207  }
208  }
209  RegisteredEHFrames = std::move(UnfinalizedEHFrames);
210  UnfinalizedEHFrames = {};
211 
212  return false;
213  }
214 
215  private:
216  class Alloc {
217  public:
218  Alloc(uint64_t Size, unsigned Align)
219  : Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
220 
221  Alloc(const Alloc &) = delete;
222  Alloc &operator=(const Alloc &) = delete;
223  Alloc(Alloc &&) = default;
224  Alloc &operator=(Alloc &&) = default;
225 
226  uint64_t getSize() const { return Size; }
227 
228  unsigned getAlign() const { return Align; }
229 
230  char *getLocalAddress() const {
231  uintptr_t LocalAddr = reinterpret_cast<uintptr_t>(Contents.get());
232  LocalAddr = alignTo(LocalAddr, Align);
233  return reinterpret_cast<char *>(LocalAddr);
234  }
235 
236  void setRemoteAddress(JITTargetAddress RemoteAddr) {
237  this->RemoteAddr = RemoteAddr;
238  }
239 
240  JITTargetAddress getRemoteAddress() const { return RemoteAddr; }
241 
242  private:
243  uint64_t Size;
244  unsigned Align;
245  std::unique_ptr<char[]> Contents;
246  JITTargetAddress RemoteAddr = 0;
247  };
248 
249  struct ObjectAllocs {
250  ObjectAllocs() = default;
251  ObjectAllocs(const ObjectAllocs &) = delete;
252  ObjectAllocs &operator=(const ObjectAllocs &) = delete;
253  ObjectAllocs(ObjectAllocs &&) = default;
254  ObjectAllocs &operator=(ObjectAllocs &&) = default;
255 
256  JITTargetAddress RemoteCodeAddr = 0;
257  JITTargetAddress RemoteRODataAddr = 0;
258  JITTargetAddress RemoteRWDataAddr = 0;
259  std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
260  };
261 
264  : Client(Client), Id(Id) {
265  LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
266  }
267 
268  // Maps all allocations in Allocs to aligned blocks
269  void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
270  JITTargetAddress NextAddr) {
271  for (auto &Alloc : Allocs) {
272  NextAddr = alignTo(NextAddr, Alloc.getAlign());
273  Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
274  LLVM_DEBUG(
275  dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
276  << " -> " << format("0x%016" PRIx64, NextAddr) << "\n");
277  Alloc.setRemoteAddress(NextAddr);
278 
279  // Only advance NextAddr if it was non-null to begin with,
280  // otherwise leave it as null.
281  if (NextAddr)
282  NextAddr += Alloc.getSize();
283  }
284  }
285 
286  // Copies data for each alloc in the list, then set permissions on the
287  // segment.
288  bool copyAndProtect(const std::vector<Alloc> &Allocs,
289  JITTargetAddress RemoteSegmentAddr,
290  unsigned Permissions) {
291  if (RemoteSegmentAddr) {
292  assert(!Allocs.empty() && "No sections in allocated segment");
293 
294  for (auto &Alloc : Allocs) {
295  LLVM_DEBUG(dbgs() << " copying section: "
296  << static_cast<void *>(Alloc.getLocalAddress())
297  << " -> "
298  << format("0x%016" PRIx64, Alloc.getRemoteAddress())
299  << " (" << Alloc.getSize() << " bytes)\n";);
300 
301  if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
302  Alloc.getSize()))
303  return true;
304  }
305 
306  LLVM_DEBUG(dbgs() << " setting "
307  << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
308  << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
309  << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
310  << " permissions on block: "
311  << format("0x%016" PRIx64, RemoteSegmentAddr)
312  << "\n");
313  if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
314  return true;
315  }
316  return false;
317  }
318 
319  OrcRemoteTargetClient &Client;
321  std::vector<ObjectAllocs> Unmapped;
322  std::vector<ObjectAllocs> Unfinalized;
323 
324  struct EHFrame {
325  JITTargetAddress Addr;
326  uint64_t Size;
327  };
328  std::vector<EHFrame> UnfinalizedEHFrames;
329  std::vector<EHFrame> RegisteredEHFrames;
330  };
331 
332  /// Remote indirect stubs manager.
334  public:
337  : Client(Client), Id(Id) {}
338 
340  Client.destroyIndirectStubsManager(Id);
341  }
342 
344  JITSymbolFlags StubFlags) override {
345  if (auto Err = reserveStubs(1))
346  return Err;
347 
348  return createStubInternal(StubName, StubAddr, StubFlags);
349  }
350 
351  Error createStubs(const StubInitsMap &StubInits) override {
352  if (auto Err = reserveStubs(StubInits.size()))
353  return Err;
354 
355  for (auto &Entry : StubInits)
356  if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
357  Entry.second.second))
358  return Err;
359 
360  return Error::success();
361  }
362 
363  JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
364  auto I = StubIndexes.find(Name);
365  if (I == StubIndexes.end())
366  return nullptr;
367  auto Key = I->second.first;
368  auto Flags = I->second.second;
369  auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
370  if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
371  return nullptr;
372  return StubSymbol;
373  }
374 
376  auto I = StubIndexes.find(Name);
377  if (I == StubIndexes.end())
378  return nullptr;
379  auto Key = I->second.first;
380  auto Flags = I->second.second;
381  return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
382  }
383 
385  auto I = StubIndexes.find(Name);
386  assert(I != StubIndexes.end() && "No stub pointer for symbol");
387  auto Key = I->second.first;
388  return Client.writePointer(getPtrAddr(Key), NewAddr);
389  }
390 
391  private:
392  struct RemoteIndirectStubsInfo {
393  JITTargetAddress StubBase;
394  JITTargetAddress PtrBase;
395  unsigned NumStubs;
396  };
397 
398  using StubKey = std::pair<uint16_t, uint16_t>;
399 
400  Error reserveStubs(unsigned NumStubs) {
401  if (NumStubs <= FreeStubs.size())
402  return Error::success();
403 
404  unsigned NewStubsRequired = NumStubs - FreeStubs.size();
405  JITTargetAddress StubBase;
406  JITTargetAddress PtrBase;
407  unsigned NumStubsEmitted;
408 
409  if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
410  std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
411  else
412  return StubInfoOrErr.takeError();
413 
414  unsigned NewBlockId = RemoteIndirectStubsInfos.size();
415  RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
416 
417  for (unsigned I = 0; I < NumStubsEmitted; ++I)
418  FreeStubs.push_back(std::make_pair(NewBlockId, I));
419 
420  return Error::success();
421  }
422 
423  Error createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
424  JITSymbolFlags StubFlags) {
425  auto Key = FreeStubs.back();
426  FreeStubs.pop_back();
427  StubIndexes[StubName] = std::make_pair(Key, StubFlags);
428  return Client.writePointer(getPtrAddr(Key), InitAddr);
429  }
430 
431  JITTargetAddress getStubAddr(StubKey K) {
432  assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
433  "Missing stub address");
434  return RemoteIndirectStubsInfos[K.first].StubBase +
435  K.second * Client.getIndirectStubSize();
436  }
437 
438  JITTargetAddress getPtrAddr(StubKey K) {
439  assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
440  "Missing pointer address");
441  return RemoteIndirectStubsInfos[K.first].PtrBase +
442  K.second * Client.getPointerSize();
443  }
444 
445  OrcRemoteTargetClient &Client;
447  std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
448  std::vector<StubKey> FreeStubs;
450  };
451 
453  public:
454  RemoteTrampolinePool(OrcRemoteTargetClient &Client) : Client(Client) {}
455 
457  std::lock_guard<std::mutex> Lock(RTPMutex);
458  if (AvailableTrampolines.empty()) {
459  if (auto Err = grow())
460  return std::move(Err);
461  }
462  assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
463  auto TrampolineAddr = AvailableTrampolines.back();
464  AvailableTrampolines.pop_back();
465  return TrampolineAddr;
466  }
467 
468  private:
469  Error grow() {
470  JITTargetAddress BlockAddr = 0;
471  uint32_t NumTrampolines = 0;
472  if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
473  std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
474  else
475  return TrampolineInfoOrErr.takeError();
476 
477  uint32_t TrampolineSize = Client.getTrampolineSize();
478  for (unsigned I = 0; I < NumTrampolines; ++I)
479  this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
480 
481  return Error::success();
482  }
483 
484  std::mutex RTPMutex;
485  OrcRemoteTargetClient &Client;
486  std::vector<JITTargetAddress> AvailableTrampolines;
487  };
488 
489  /// Remote compile callback manager.
491  public:
493  ExecutionSession &ES,
494  JITTargetAddress ErrorHandlerAddress)
496  llvm::make_unique<RemoteTrampolinePool>(Client), ES,
497  ErrorHandlerAddress) {}
498  };
499 
500  /// Create an OrcRemoteTargetClient.
501  /// Channel is the ChannelT instance to communicate on. It is assumed that
502  /// the channel is ready to be read from and written to.
505  Error Err = Error::success();
506  auto Client = std::unique_ptr<OrcRemoteTargetClient>(
507  new OrcRemoteTargetClient(Channel, ES, Err));
508  if (Err)
509  return std::move(Err);
510  return std::move(Client);
511  }
512 
513  /// Call the int(void) function at the given address in the target and return
514  /// its result.
516  LLVM_DEBUG(dbgs() << "Calling int(*)(void) "
517  << format("0x%016" PRIx64, Addr) << "\n");
518  return callB<exec::CallIntVoid>(Addr);
519  }
520 
521  /// Call the int(int, char*[]) function at the given address in the target and
522  /// return its result.
524  const std::vector<std::string> &Args) {
525  LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
526  << format("0x%016" PRIx64, Addr) << "\n");
527  return callB<exec::CallMain>(Addr, Args);
528  }
529 
530  /// Call the void() function at the given address in the target and wait for
531  /// it to finish.
533  LLVM_DEBUG(dbgs() << "Calling void(*)(void) "
534  << format("0x%016" PRIx64, Addr) << "\n");
535  return callB<exec::CallVoidVoid>(Addr);
536  }
537 
538  /// Create an RCMemoryManager which will allocate its memory on the remote
539  /// target.
542  auto Id = AllocatorIds.getNext();
543  if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
544  return std::move(Err);
545  return std::unique_ptr<RemoteRTDyldMemoryManager>(
546  new RemoteRTDyldMemoryManager(*this, Id));
547  }
548 
549  /// Create an RCIndirectStubsManager that will allocate stubs on the remote
550  /// target.
553  auto Id = IndirectStubOwnerIds.getNext();
554  if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
555  return std::move(Err);
556  return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
557  }
558 
561  assert(!CallbackManager && "CallbackManager already obtained");
562 
563  // Emit the resolver block on the JIT server.
564  if (auto Err = callB<stubs::EmitResolverBlock>())
565  return std::move(Err);
566 
567  // Create the callback manager.
568  CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
569  RemoteCompileCallbackManager &Mgr = *CallbackManager;
570  return Mgr;
571  }
572 
573  /// Search for symbols in the remote process. Note: This should be used by
574  /// symbol resolvers *after* they've searched the local symbol table in the
575  /// JIT stack.
577  return callB<utils::GetSymbolAddress>(Name);
578  }
579 
580  /// Get the triple for the remote target.
581  const std::string &getTargetTriple() const { return RemoteTargetTriple; }
582 
583  Error terminateSession() { return callB<utils::TerminateSession>(); }
584 
585 private:
587  Error &Err)
589  ES(ES) {
590  ErrorAsOutParameter EAO(&Err);
591 
592  addHandler<utils::RequestCompile>(
593  [this](JITTargetAddress Addr) -> JITTargetAddress {
594  if (CallbackManager)
595  return CallbackManager->executeCompileCallback(Addr);
596  return 0;
597  });
598 
599  if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
600  std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
601  RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
602  Err = Error::success();
603  } else
604  Err = RIOrErr.takeError();
605  }
606 
608  if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
609  ES.reportError(std::move(Err));
610  }
611 
612  void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
613  if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
614  // FIXME: This will be triggered by a removeModuleSet call: Propagate
615  // error return up through that.
616  llvm_unreachable("Failed to destroy remote allocator.");
617  AllocatorIds.release(Id);
618  }
619  }
620 
621  void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
622  IndirectStubOwnerIds.release(Id);
623  if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
624  ES.reportError(std::move(Err));
625  }
626 
628  emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
629  return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
630  }
631 
632  Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
633  return callB<stubs::EmitTrampolineBlock>();
634  }
635 
636  uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
637  uint32_t getPageSize() const { return RemotePageSize; }
638  uint32_t getPointerSize() const { return RemotePointerSize; }
639 
640  uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
641 
642  Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
643  uint64_t Size) {
644  return callB<mem::ReadMem>(Src, Size);
645  }
646 
648  // FIXME: Duplicate error and report it via ReportError too?
649  return callB<eh::RegisterEHFrames>(RAddr, Size);
650  }
651 
652  JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
653  uint32_t Align) {
654  if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
655  return *AddrOrErr;
656  else {
657  ES.reportError(AddrOrErr.takeError());
658  return 0;
659  }
660  }
661 
662  bool setProtections(ResourceIdMgr::ResourceId Id,
663  JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
664  if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
665  ES.reportError(std::move(Err));
666  return true;
667  } else
668  return false;
669  }
670 
671  bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
672  if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
673  ES.reportError(std::move(Err));
674  return true;
675  } else
676  return false;
677  }
678 
679  Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
680  return callB<mem::WritePtr>(Addr, PtrVal);
681  }
682 
683  static Error doNothing() { return Error::success(); }
684 
685  ExecutionSession &ES;
686  std::function<void(Error)> ReportError;
687  std::string RemoteTargetTriple;
688  uint32_t RemotePointerSize = 0;
689  uint32_t RemotePageSize = 0;
690  uint32_t RemoteTrampolineSize = 0;
691  uint32_t RemoteIndirectStubSize = 0;
692  ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
694 };
695 
696 } // end namespace remote
697 } // end namespace orc
698 } // end namespace llvm
699 
700 #undef DEBUG_TYPE
701 
702 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H
bool needsToReserveAllocationSpace() override
Override to return true to enable the reserveAllocationSpace callback.
Error createStubs(const StubInitsMap &StubInits) override
Create StubInits.size() stubs with the given names, target addresses, and flags.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Base class for managing collections of named indirect stubs.
bool getAlign(const Function &F, unsigned index, unsigned &align)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:123
Interface for byte-streams to be used with RPC.
Expected< std::unique_ptr< RemoteRTDyldMemoryManager > > createRemoteMemoryManager()
Create an RCMemoryManager which will allocate its memory on the remote target.
static sys::Mutex Lock
This class is the base class for all object file types.
Definition: ObjectFile.h:226
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:684
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:1403
RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &)=delete
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...
Base class for error info classes.
Definition: Error.h:48
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.
JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override
Find the stub with the given name.
Target-independent base class for compile callback management.
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 ...
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...
Error createStub(StringRef StubName, JITTargetAddress StubAddr, JITSymbolFlags StubFlags) override
Create a single stub with the given name, target address and flags.
unsigned size() const
Definition: StringMap.h:111
RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress)
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
Base class for pools of compiler re-entry trampolines.
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
Error callVoidVoid(JITTargetAddress Addr)
Call the void() function at the given address in the target and wait for it to finish.
Key
PAL metadata keys.
Expected< JITTargetAddress > getSymbolAddress(StringRef Name)
Search for symbols in the remote process.
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:40
const std::string & getTargetTriple() const
Get the triple for the remote target.
This class provides utilities (including memory manager, indirect stubs manager, and compile callback...
Flags for symbols in the JIT.
Definition: JITSymbol.h:55
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:904
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override
Change the value of the implementation pointer for the stub.
bool finalizeMemory(std::string *ErrMsg=nullptr) override
This method is called when object loading is complete and section page permissions can be applied...
An ExecutionSession represents a running JIT program.
Definition: Core.h:700
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:219
Expected< RemoteCompileCallbackManager & > enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress)
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:208
Expected< JITTargetAddress > getTrampoline() override
Get an available trampoline address.
Helper for Errors used as out-parameters.
Definition: Error.h:1021
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:765
RemoteRTDyldMemoryManager & operator=(const RemoteRTDyldMemoryManager &)=delete
#define I(x, y, z)
Definition: MD5.cpp:58
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.
uint32_t Size
Definition: Profile.cpp:46
Expected< int > callIntVoid(JITTargetAddress Addr)
Call the int(void) function at the given address in the target and return its result.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
JITEvaluatedSymbol findPointer(StringRef Name) override
Find the implementation-pointer for the stub.
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:482
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Remote-mapped RuntimeDyld-compatible memory manager.
static Expected< std::unique_ptr< OrcRemoteTargetClient > > Create(rpc::RawByteChannel &Channel, ExecutionSession &ES)
Create an OrcRemoteTargetClient.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress)
Map a section to its target address space value.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override
Register the EH frames with the runtime so that c++ exceptions work.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Expected< std::unique_ptr< RemoteIndirectStubsManager > > createIndirectStubsManager()
Create an RCIndirectStubsManager that will allocate stubs on the remote target.
RemoteIndirectStubsManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)