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