15 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H
16 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H
37 #include <system_error>
39 #include <type_traits>
42 #define DEBUG_TYPE "orc-remote"
48 template <
typename ChannelT,
typename TargetT>
51 typedef std::function<JITTargetAddress(const std::string &Name)>
54 typedef std::function<void(uint8_t *Addr, uint32_t Size)>
61 EHFramesRegister(std::move(EHFramesRegister)),
62 EHFramesDeregister(std::move(EHFramesDeregister)),
63 TerminateFlag(
false) {
65 using ThisT =
typename std::remove_reference<decltype(*this)>::type;
66 addHandler<CallIntVoid>(*
this, &ThisT::handleCallIntVoid);
67 addHandler<CallMain>(*
this, &ThisT::handleCallMain);
68 addHandler<CallVoidVoid>(*
this, &ThisT::handleCallVoidVoid);
69 addHandler<CreateRemoteAllocator>(*
this,
70 &ThisT::handleCreateRemoteAllocator);
71 addHandler<CreateIndirectStubsOwner>(
72 *
this, &ThisT::handleCreateIndirectStubsOwner);
73 addHandler<DeregisterEHFrames>(*
this, &ThisT::handleDeregisterEHFrames);
74 addHandler<DestroyRemoteAllocator>(*
this,
75 &ThisT::handleDestroyRemoteAllocator);
76 addHandler<DestroyIndirectStubsOwner>(
77 *
this, &ThisT::handleDestroyIndirectStubsOwner);
78 addHandler<EmitIndirectStubs>(*
this, &ThisT::handleEmitIndirectStubs);
79 addHandler<EmitResolverBlock>(*
this, &ThisT::handleEmitResolverBlock);
80 addHandler<EmitTrampolineBlock>(*
this, &ThisT::handleEmitTrampolineBlock);
81 addHandler<GetSymbolAddress>(*
this, &ThisT::handleGetSymbolAddress);
82 addHandler<GetRemoteInfo>(*
this, &ThisT::handleGetRemoteInfo);
83 addHandler<ReadMem>(*
this, &ThisT::handleReadMem);
84 addHandler<RegisterEHFrames>(*
this, &ThisT::handleRegisterEHFrames);
85 addHandler<ReserveMem>(*
this, &ThisT::handleReserveMem);
86 addHandler<SetProtections>(*
this, &ThisT::handleSetProtections);
87 addHandler<TerminateSession>(*
this, &ThisT::handleTerminateSession);
88 addHandler<WriteMem>(*
this, &ThisT::handleWriteMem);
89 addHandler<WritePtr>(*
this, &ThisT::handleWritePtr);
100 return callB<RequestCompile>(TrampolineAddr);
110 Allocs = std::move(
Other.Allocs);
115 for (
auto &Alloc : Allocs)
127 assert(Allocs.find(MB.base()) == Allocs.end() &&
"Duplicate alloc");
128 Allocs[MB.base()] = std::move(MB);
132 Error setProtections(
void *block,
unsigned Flags) {
133 auto I = Allocs.find(block);
134 if (
I == Allocs.end())
141 std::map<void *, sys::MemoryBlock> Allocs;
146 static JITTargetAddress reenter(
void *JITTargetAddr,
void *TrampolineAddr) {
148 auto AddrOrErr =
T->requestCompile(static_cast<JITTargetAddress>(
149 reinterpret_cast<uintptr_t>(TrampolineAddr)));
151 assert(AddrOrErr &&
"Compile request failed");
156 typedef int (*IntVoidFnTy)();
158 reinterpret_cast<IntVoidFnTy
>(
static_cast<uintptr_t
>(Addr));
162 DEBUG(
dbgs() <<
" Result = " << Result <<
"\n");
168 std::vector<std::string>
Args) {
169 typedef int (*MainFnTy)(int,
const char *[]);
171 MainFnTy Fn =
reinterpret_cast<MainFnTy
>(
static_cast<uintptr_t
>(Addr));
172 int ArgC = Args.size() + 1;
174 std::unique_ptr<const char *[]> ArgV(
new const char *[ArgC + 1]);
175 ArgV[0] =
"<jit process>";
176 for (
auto &Arg : Args)
177 ArgV[Idx++] = Arg.c_str();
180 int Result = Fn(ArgC, ArgV.get());
181 DEBUG(
dbgs() <<
" Result = " << Result <<
"\n");
187 typedef void (*VoidVoidFnTy)();
189 reinterpret_cast<VoidVoidFnTy
>(
static_cast<uintptr_t
>(Addr));
199 auto I = Allocators.find(Id);
200 if (
I != Allocators.end())
202 DEBUG(
dbgs() <<
" Created allocator " << Id <<
"\n");
208 auto I = IndirectStubsOwners.find(Id);
209 if (
I != IndirectStubsOwners.end())
211 DEBUG(
dbgs() <<
" Create indirect stubs owner " << Id <<
"\n");
212 IndirectStubsOwners[
Id] = ISBlockOwnerList();
217 uint8_t *Addr =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(TAddr));
218 DEBUG(
dbgs() <<
" Registering EH frames at " <<
format(
"0x%016x", TAddr)
219 <<
", Size = " << Size <<
" bytes\n");
220 EHFramesDeregister(Addr, Size);
225 auto I = Allocators.find(Id);
226 if (
I == Allocators.end())
229 DEBUG(
dbgs() <<
" Destroyed allocator " << Id <<
"\n");
234 auto I = IndirectStubsOwners.find(Id);
235 if (
I == IndirectStubsOwners.end())
237 IndirectStubsOwners.erase(
I);
241 Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
244 DEBUG(
dbgs() <<
" ISMgr " << Id <<
" request " << NumStubsRequired
247 auto StubOwnerItr = IndirectStubsOwners.find(Id);
248 if (StubOwnerItr == IndirectStubsOwners.end())
251 typename TargetT::IndirectStubsInfo IS;
253 TargetT::emitIndirectStubsBlock(IS, NumStubsRequired,
nullptr))
254 return std::move(Err);
257 reinterpret_cast<uintptr_t
>(IS.getStub(0)));
259 reinterpret_cast<uintptr_t
>(IS.getPtr(0)));
260 uint32_t NumStubsEmitted = IS.getNumStubs();
262 auto &BlockList = StubOwnerItr->second;
263 BlockList.push_back(std::move(IS));
265 return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
268 Error handleEmitResolverBlock() {
271 TargetT::ResolverCodeSize,
nullptr,
276 TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.
base()),
284 Expected<std::tuple<JITTargetAddress, uint32_t>> handleEmitTrampolineBlock() {
286 auto TrampolineBlock =
295 TargetT::TrampolineSize;
297 uint8_t *TrampolineMem =
static_cast<uint8_t *
>(TrampolineBlock.base());
298 TargetT::writeTrampolines(TrampolineMem, ResolverBlock.
base(),
305 TrampolineBlocks.push_back(std::move(TrampolineBlock));
308 reinterpret_cast<uintptr_t
>(TrampolineMem));
310 return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
313 Expected<JITTargetAddress> handleGetSymbolAddress(
const std::string &
Name) {
315 DEBUG(
dbgs() <<
" Symbol '" << Name <<
"' = " <<
format(
"0x%016x", Addr)
320 Expected<std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>>
321 handleGetRemoteInfo() {
323 uint32_t PointerSize = TargetT::PointerSize;
325 uint32_t TrampolineSize = TargetT::TrampolineSize;
326 uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
328 <<
" triple = '" << ProcessTriple <<
"'\n"
329 <<
" pointer size = " << PointerSize <<
"\n"
330 <<
" page size = " << PageSize <<
"\n"
331 <<
" trampoline size = " << TrampolineSize <<
"\n"
332 <<
" indirect stub size = " << IndirectStubSize <<
"\n");
333 return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
339 uint8_t *Src =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(RSrc));
341 DEBUG(
dbgs() <<
" Reading " << Size <<
" bytes from "
342 <<
format(
"0x%016x", RSrc) <<
"\n");
344 std::vector<uint8_t> Buffer;
346 for (uint8_t *
P = Src; Size != 0; --Size)
347 Buffer.push_back(*
P++);
353 uint8_t *Addr =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(TAddr));
354 DEBUG(
dbgs() <<
" Registering EH frames at " <<
format(
"0x%016x", TAddr)
355 <<
", Size = " << Size <<
" bytes\n");
356 EHFramesRegister(Addr, Size);
362 auto I = Allocators.find(Id);
363 if (
I == Allocators.end())
366 void *LocalAllocAddr =
nullptr;
367 if (
auto Err =
Allocator.allocate(LocalAllocAddr, Size, Align))
368 return std::move(Err);
370 DEBUG(
dbgs() <<
" Allocator " << Id <<
" reserved " << LocalAllocAddr
371 <<
" (" << Size <<
" bytes, alignment " << Align <<
")\n");
374 reinterpret_cast<uintptr_t
>(LocalAllocAddr));
381 auto I = Allocators.find(Id);
382 if (
I == Allocators.end())
385 void *LocalAddr =
reinterpret_cast<void *
>(
static_cast<uintptr_t
>(Addr));
386 DEBUG(
dbgs() <<
" Allocator " << Id <<
" set permissions on " << LocalAddr
390 return Allocator.setProtections(LocalAddr, Flags);
393 Error handleTerminateSession() {
394 TerminateFlag =
true;
398 Error handleWriteMem(DirectBufferWriter DBW) {
399 DEBUG(
dbgs() <<
" Writing " << DBW.getSize() <<
" bytes to "
400 <<
format(
"0x%016x", DBW.getDst()) <<
"\n");
405 DEBUG(
dbgs() <<
" Writing pointer *" <<
format(
"0x%016x", Addr) <<
" = "
406 <<
format(
"0x%016x", PtrVal) <<
"\n");
408 reinterpret_cast<uintptr_t *
>(
static_cast<uintptr_t
>(Addr));
409 *Ptr =
static_cast<uintptr_t
>(PtrVal);
415 std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
416 typedef std::vector<typename TargetT::IndirectStubsInfo> ISBlockOwnerList;
417 std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
418 sys::OwningMemoryBlock ResolverBlock;
419 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
std::function< JITTargetAddress(const std::string &Name)> SymbolLookupFtor
OrcRemoteTargetServer & operator=(const OrcRemoteTargetServer &)=delete
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method...
static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e...
struct fuzzer::@269 Flags
Tagged union holding either a T or a Error.
bool receivedTerminate() const
Function Alias Analysis false
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096))
MemoryBlock getMemoryBlock() const
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Greedy Register Allocator
uint64_t JITTargetAddress
Represents an address in the target process's address space.
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup, EHFrameRegistrationFtor EHFramesRegister, EHFrameRegistrationFtor EHFramesDeregister)
std::function< void(uint8_t *Addr, uint32_t Size)> EHFrameRegistrationFtor
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
static unsigned getPageSize()
static ErrorSuccess success()
Create a success value.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Provides a library for accessing information about this process and other processes on the operating ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Error orcError(OrcErrorCode ErrCode)
Expected< JITTargetAddress > requestCompile(JITTargetAddress TrampolineAddr)
static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags...