15 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H 16 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H 36 #include <system_error> 38 #include <type_traits> 41 #define DEBUG_TYPE "orc-remote" 47 template <
typename ChannelT,
typename TargetT>
52 std::function<JITTargetAddress(const std::string &Name)>;
55 std::function<void(uint8_t *Addr, uint32_t Size)>;
61 SymbolLookup(
std::move(SymbolLookup)),
62 EHFramesRegister(
std::move(EHFramesRegister)),
63 EHFramesDeregister(
std::move(EHFramesDeregister)) {
64 using ThisT =
typename std::remove_reference<decltype(*this)>::type;
65 addHandler<exec::CallIntVoid>(*
this, &ThisT::handleCallIntVoid);
66 addHandler<exec::CallMain>(*
this, &ThisT::handleCallMain);
67 addHandler<exec::CallVoidVoid>(*
this, &ThisT::handleCallVoidVoid);
68 addHandler<mem::CreateRemoteAllocator>(*
this,
69 &ThisT::handleCreateRemoteAllocator);
70 addHandler<mem::DestroyRemoteAllocator>(
71 *
this, &ThisT::handleDestroyRemoteAllocator);
72 addHandler<mem::ReadMem>(*
this, &ThisT::handleReadMem);
73 addHandler<mem::ReserveMem>(*
this, &ThisT::handleReserveMem);
74 addHandler<mem::SetProtections>(*
this, &ThisT::handleSetProtections);
75 addHandler<mem::WriteMem>(*
this, &ThisT::handleWriteMem);
76 addHandler<mem::WritePtr>(*
this, &ThisT::handleWritePtr);
77 addHandler<eh::RegisterEHFrames>(*
this, &ThisT::handleRegisterEHFrames);
78 addHandler<eh::DeregisterEHFrames>(*
this, &ThisT::handleDeregisterEHFrames);
79 addHandler<stubs::CreateIndirectStubsOwner>(
80 *
this, &ThisT::handleCreateIndirectStubsOwner);
81 addHandler<stubs::DestroyIndirectStubsOwner>(
82 *
this, &ThisT::handleDestroyIndirectStubsOwner);
83 addHandler<stubs::EmitIndirectStubs>(*
this,
84 &ThisT::handleEmitIndirectStubs);
85 addHandler<stubs::EmitResolverBlock>(*
this,
86 &ThisT::handleEmitResolverBlock);
87 addHandler<stubs::EmitTrampolineBlock>(*
this,
88 &ThisT::handleEmitTrampolineBlock);
89 addHandler<utils::GetSymbolAddress>(*
this, &ThisT::handleGetSymbolAddress);
90 addHandler<utils::GetRemoteInfo>(*
this, &ThisT::handleGetRemoteInfo);
91 addHandler<utils::TerminateSession>(*
this, &ThisT::handleTerminateSession);
102 return callB<utils::RequestCompile>(TrampolineAddr);
113 Allocs = std::move(
Other.Allocs);
118 for (
auto &Alloc : Allocs)
130 assert(Allocs.find(MB.
base()) == Allocs.end() &&
"Duplicate alloc");
131 Allocs[MB.
base()] = std::move(MB);
135 Error setProtections(
void *block,
unsigned Flags) {
136 auto I = Allocs.find(block);
137 if (
I == Allocs.end())
144 std::map<void *, sys::MemoryBlock> Allocs;
149 static JITTargetAddress reenter(
void *JITTargetAddr,
void *TrampolineAddr) {
151 auto AddrOrErr =
T->requestCompile(static_cast<JITTargetAddress>(
152 reinterpret_cast<uintptr_t>(TrampolineAddr)));
154 assert(AddrOrErr &&
"Compile request failed");
159 using IntVoidFnTy = int (*)();
162 reinterpret_cast<IntVoidFnTy
>(
static_cast<uintptr_t
>(Addr));
172 std::vector<std::string>
Args) {
173 using MainFnTy = int (*)(int,
const char *[]);
175 MainFnTy Fn =
reinterpret_cast<MainFnTy
>(
static_cast<uintptr_t
>(Addr));
176 int ArgC = Args.size() + 1;
178 std::unique_ptr<const char *[]> ArgV(
new const char *[ArgC + 1]);
179 ArgV[0] =
"<jit process>";
180 for (
auto &
Arg : Args)
181 ArgV[Idx++] =
Arg.c_str();
183 LLVM_DEBUG(
for (
int Idx = 0; Idx < ArgC; ++Idx) {
184 llvm::dbgs() <<
"Arg " << Idx <<
": " << ArgV[Idx] <<
"\n";
188 int Result = Fn(ArgC, ArgV.get());
195 using VoidVoidFnTy = void (*)();
198 reinterpret_cast<VoidVoidFnTy
>(
static_cast<uintptr_t
>(Addr));
208 auto I = Allocators.find(Id);
209 if (
I != Allocators.end())
218 auto I = IndirectStubsOwners.find(Id);
219 if (
I != IndirectStubsOwners.end())
222 LLVM_DEBUG(
dbgs() <<
" Create indirect stubs owner " << Id <<
"\n");
223 IndirectStubsOwners[
Id] = ISBlockOwnerList();
228 uint8_t *Addr =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(TAddr));
230 <<
format(
"0x%016x", TAddr) <<
", Size = " << Size
232 EHFramesDeregister(Addr, Size);
237 auto I = Allocators.find(Id);
238 if (
I == Allocators.end())
247 auto I = IndirectStubsOwners.find(Id);
248 if (
I == IndirectStubsOwners.end())
251 IndirectStubsOwners.erase(
I);
258 LLVM_DEBUG(
dbgs() <<
" ISMgr " << Id <<
" request " << NumStubsRequired
261 auto StubOwnerItr = IndirectStubsOwners.find(Id);
262 if (StubOwnerItr == IndirectStubsOwners.end())
266 typename TargetT::IndirectStubsInfo IS;
268 TargetT::emitIndirectStubsBlock(IS, NumStubsRequired,
nullptr))
269 return std::move(Err);
272 reinterpret_cast<uintptr_t
>(IS.getStub(0)));
274 reinterpret_cast<uintptr_t
>(IS.getPtr(0)));
275 uint32_t NumStubsEmitted = IS.getNumStubs();
277 auto &BlockList = StubOwnerItr->second;
278 BlockList.push_back(std::move(IS));
280 return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
283 Error handleEmitResolverBlock() {
286 TargetT::ResolverCodeSize,
nullptr,
291 TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
295 ResolverBlock.getMemoryBlock(),
301 auto TrampolineBlock =
310 TargetT::TrampolineSize;
312 uint8_t *TrampolineMem =
static_cast<uint8_t *
>(TrampolineBlock.base());
313 TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
320 TrampolineBlocks.push_back(std::move(TrampolineBlock));
323 reinterpret_cast<uintptr_t
>(TrampolineMem));
325 return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
331 <<
"' = " <<
format(
"0x%016x", Addr) <<
"\n");
336 handleGetRemoteInfo() {
338 uint32_t PointerSize = TargetT::PointerSize;
340 uint32_t TrampolineSize = TargetT::TrampolineSize;
341 uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
343 <<
" triple = '" << ProcessTriple <<
"'\n" 344 <<
" pointer size = " << PointerSize <<
"\n" 345 <<
" page size = " << PageSize <<
"\n" 346 <<
" trampoline size = " << TrampolineSize <<
"\n" 347 <<
" indirect stub size = " << IndirectStubSize
349 return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
355 uint8_t *Src =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(RSrc));
358 <<
format(
"0x%016x", RSrc) <<
"\n");
360 std::vector<uint8_t> Buffer;
362 for (uint8_t *
P = Src; Size != 0; --
Size)
363 Buffer.push_back(*
P++);
369 uint8_t *Addr =
reinterpret_cast<uint8_t *
>(
static_cast<uintptr_t
>(TAddr));
371 <<
format(
"0x%016x", TAddr) <<
", Size = " << Size
373 EHFramesRegister(Addr, Size);
379 auto I = Allocators.find(Id);
380 if (
I == Allocators.end())
384 void *LocalAllocAddr =
nullptr;
385 if (
auto Err =
Allocator.allocate(LocalAllocAddr, Size, Align))
386 return std::move(Err);
388 LLVM_DEBUG(
dbgs() <<
" Allocator " << Id <<
" reserved " << LocalAllocAddr
389 <<
" (" << Size <<
" bytes, alignment " << Align
393 reinterpret_cast<uintptr_t
>(LocalAllocAddr));
400 auto I = Allocators.find(Id);
401 if (
I == Allocators.end())
405 void *LocalAddr =
reinterpret_cast<void *
>(
static_cast<uintptr_t
>(Addr));
406 LLVM_DEBUG(
dbgs() <<
" Allocator " << Id <<
" set permissions on " 407 << LocalAddr <<
" to " 411 return Allocator.setProtections(LocalAddr, Flags);
414 Error handleTerminateSession() {
415 TerminateFlag =
true;
427 <<
" = " <<
format(
"0x%016x", PtrVal) <<
"\n");
429 reinterpret_cast<uintptr_t *
>(
static_cast<uintptr_t
>(Addr));
430 *Ptr =
static_cast<uintptr_t
>(PtrVal);
436 std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
437 using ISBlockOwnerList = std::vector<typename TargetT::IndirectStubsInfo>;
438 std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
440 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
441 bool TerminateFlag =
false;
450 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
std::function< JITTargetAddress(const std::string &Name)> SymbolLookupFtor
This class represents lattice values for constants.
OrcRemoteTargetServer & operator=(const OrcRemoteTargetServer &)=delete
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
static std::error_code releaseMappedMemory(MemoryBlock &Block)
This method releases a block of memory that was allocated with the allocateMappedMemory method...
block Block Frequency true
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...
amdgpu Simplify well known AMD library false Value Value const Twine & Name
std::error_code orcError(OrcErrorCode ErrCode)
bool receivedTerminate() const
Tagged union holding either a T or a Error.
std::function< void(uint8_t *Addr, uint32_t Size)> EHFrameRegistrationFtor
uint64_t JITTargetAddress
Represents an address in the target process's address space.
JITTargetAddress getDst() const
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup, EHFrameRegistrationFtor EHFramesRegister, EHFrameRegistrationFtor EHFramesDeregister)
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.
This class encapsulates the notion of a memory block which has an address and a size.
Owning version of MemoryBlock.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
amdgpu Simplify well known AMD library false Value Value * Arg
Provides a library for accessing information about this process and other processes on the operating ...
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Expected< JITTargetAddress > requestCompile(JITTargetAddress TrampolineAddr)
SingleThreadedRPCEndpoint(rpc::RawByteChannel &C, bool LazyAutoNegotiation)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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...