1 //===-- OrcRPCTPCServer.h -- OrcRPCTargetProcessControl Server --*- 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 // OrcRPCTargetProcessControl server class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
14 #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
15
16 #include "llvm/ADT/BitmaskEnum.h"
17 #include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h"
18 #include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h"
19 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
20 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
21 #include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
22 #include "llvm/Support/DynamicLibrary.h"
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/Host.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/Memory.h"
27 #include "llvm/Support/Process.h"
28
29 #include <atomic>
30
31 namespace llvm {
32 namespace orc {
33
34 namespace orcrpctpc {
35
36 enum WireProtectionFlags : uint8_t {
37 WPF_None = 0,
38 WPF_Read = 1U << 0,
39 WPF_Write = 1U << 1,
40 WPF_Exec = 1U << 2,
41 LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec)
42 };
43
44 /// Convert from sys::Memory::ProtectionFlags
45 inline WireProtectionFlags
toWireProtectionFlags(sys::Memory::ProtectionFlags PF)46 toWireProtectionFlags(sys::Memory::ProtectionFlags PF) {
47 WireProtectionFlags WPF = WPF_None;
48 if (PF & sys::Memory::MF_READ)
49 WPF |= WPF_Read;
50 if (PF & sys::Memory::MF_WRITE)
51 WPF |= WPF_Write;
52 if (PF & sys::Memory::MF_EXEC)
53 WPF |= WPF_Exec;
54 return WPF;
55 }
56
57 inline sys::Memory::ProtectionFlags
fromWireProtectionFlags(WireProtectionFlags WPF)58 fromWireProtectionFlags(WireProtectionFlags WPF) {
59 int PF = 0;
60 if (WPF & WPF_Read)
61 PF |= sys::Memory::MF_READ;
62 if (WPF & WPF_Write)
63 PF |= sys::Memory::MF_WRITE;
64 if (WPF & WPF_Exec)
65 PF |= sys::Memory::MF_EXEC;
66 return static_cast<sys::Memory::ProtectionFlags>(PF);
67 }
68
69 struct ReserveMemRequestElement {
70 WireProtectionFlags Prot = WPF_None;
71 uint64_t Size = 0;
72 uint64_t Alignment = 0;
73 };
74
75 using ReserveMemRequest = std::vector<ReserveMemRequestElement>;
76
77 struct ReserveMemResultElement {
78 WireProtectionFlags Prot = WPF_None;
79 JITTargetAddress Address = 0;
80 uint64_t AllocatedSize = 0;
81 };
82
83 using ReserveMemResult = std::vector<ReserveMemResultElement>;
84
85 struct ReleaseOrFinalizeMemRequestElement {
86 WireProtectionFlags Prot = WPF_None;
87 JITTargetAddress Address = 0;
88 uint64_t Size = 0;
89 };
90
91 using ReleaseOrFinalizeMemRequest =
92 std::vector<ReleaseOrFinalizeMemRequestElement>;
93
94 } // end namespace orcrpctpc
95
96 namespace rpc {
97
98 template <> class RPCTypeName<tpctypes::UInt8Write> {
99 public:
getName()100 static const char *getName() { return "UInt8Write"; }
101 };
102
103 template <> class RPCTypeName<tpctypes::UInt16Write> {
104 public:
getName()105 static const char *getName() { return "UInt16Write"; }
106 };
107
108 template <> class RPCTypeName<tpctypes::UInt32Write> {
109 public:
getName()110 static const char *getName() { return "UInt32Write"; }
111 };
112
113 template <> class RPCTypeName<tpctypes::UInt64Write> {
114 public:
getName()115 static const char *getName() { return "UInt64Write"; }
116 };
117
118 template <> class RPCTypeName<tpctypes::BufferWrite> {
119 public:
getName()120 static const char *getName() { return "BufferWrite"; }
121 };
122
123 template <> class RPCTypeName<orcrpctpc::ReserveMemRequestElement> {
124 public:
getName()125 static const char *getName() { return "ReserveMemRequestElement"; }
126 };
127
128 template <> class RPCTypeName<orcrpctpc::ReserveMemResultElement> {
129 public:
getName()130 static const char *getName() { return "ReserveMemResultElement"; }
131 };
132
133 template <> class RPCTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
134 public:
getName()135 static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; }
136 };
137
138 template <> class RPCTypeName<tpctypes::WrapperFunctionResult> {
139 public:
getName()140 static const char *getName() { return "WrapperFunctionResult"; }
141 };
142
143 template <typename ChannelT, typename WriteT>
144 class SerializationTraits<
145 ChannelT, WriteT, WriteT,
146 std::enable_if_t<std::is_same<WriteT, tpctypes::UInt8Write>::value ||
147 std::is_same<WriteT, tpctypes::UInt16Write>::value ||
148 std::is_same<WriteT, tpctypes::UInt32Write>::value ||
149 std::is_same<WriteT, tpctypes::UInt64Write>::value>> {
150 public:
serialize(ChannelT & C,const WriteT & W)151 static Error serialize(ChannelT &C, const WriteT &W) {
152 return serializeSeq(C, W.Address, W.Value);
153 }
deserialize(ChannelT & C,WriteT & W)154 static Error deserialize(ChannelT &C, WriteT &W) {
155 return deserializeSeq(C, W.Address, W.Value);
156 }
157 };
158
159 template <typename ChannelT>
160 class SerializationTraits<
161 ChannelT, tpctypes::BufferWrite, tpctypes::BufferWrite,
162 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
163 public:
serialize(ChannelT & C,const tpctypes::BufferWrite & W)164 static Error serialize(ChannelT &C, const tpctypes::BufferWrite &W) {
165 uint64_t Size = W.Buffer.size();
166 if (auto Err = serializeSeq(C, W.Address, Size))
167 return Err;
168
169 return C.appendBytes(W.Buffer.data(), Size);
170 }
deserialize(ChannelT & C,tpctypes::BufferWrite & W)171 static Error deserialize(ChannelT &C, tpctypes::BufferWrite &W) {
172 JITTargetAddress Address;
173 uint64_t Size;
174
175 if (auto Err = deserializeSeq(C, Address, Size))
176 return Err;
177
178 char *Buffer = jitTargetAddressToPointer<char *>(Address);
179
180 if (auto Err = C.readBytes(Buffer, Size))
181 return Err;
182
183 W = {Address, StringRef(Buffer, Size)};
184 return Error::success();
185 }
186 };
187
188 template <typename ChannelT>
189 class SerializationTraits<ChannelT, orcrpctpc::ReserveMemRequestElement> {
190 public:
serialize(ChannelT & C,const orcrpctpc::ReserveMemRequestElement & E)191 static Error serialize(ChannelT &C,
192 const orcrpctpc::ReserveMemRequestElement &E) {
193 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Size, E.Alignment);
194 }
195
deserialize(ChannelT & C,orcrpctpc::ReserveMemRequestElement & E)196 static Error deserialize(ChannelT &C,
197 orcrpctpc::ReserveMemRequestElement &E) {
198 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Size,
199 E.Alignment);
200 }
201 };
202
203 template <typename ChannelT>
204 class SerializationTraits<ChannelT, orcrpctpc::ReserveMemResultElement> {
205 public:
serialize(ChannelT & C,const orcrpctpc::ReserveMemResultElement & E)206 static Error serialize(ChannelT &C,
207 const orcrpctpc::ReserveMemResultElement &E) {
208 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address,
209 E.AllocatedSize);
210 }
211
deserialize(ChannelT & C,orcrpctpc::ReserveMemResultElement & E)212 static Error deserialize(ChannelT &C, orcrpctpc::ReserveMemResultElement &E) {
213 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
214 E.AllocatedSize);
215 }
216 };
217
218 template <typename ChannelT>
219 class SerializationTraits<ChannelT,
220 orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
221 public:
222 static Error
serialize(ChannelT & C,const orcrpctpc::ReleaseOrFinalizeMemRequestElement & E)223 serialize(ChannelT &C,
224 const orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
225 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address, E.Size);
226 }
227
deserialize(ChannelT & C,orcrpctpc::ReleaseOrFinalizeMemRequestElement & E)228 static Error deserialize(ChannelT &C,
229 orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
230 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
231 E.Size);
232 }
233 };
234
235 template <typename ChannelT>
236 class SerializationTraits<
237 ChannelT, tpctypes::WrapperFunctionResult, tpctypes::WrapperFunctionResult,
238 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
239 public:
serialize(ChannelT & C,const tpctypes::WrapperFunctionResult & E)240 static Error serialize(ChannelT &C,
241 const tpctypes::WrapperFunctionResult &E) {
242 auto Data = E.getData();
243 if (auto Err = serializeSeq(C, static_cast<uint64_t>(Data.size())))
244 return Err;
245 if (Data.size() == 0)
246 return Error::success();
247 return C.appendBytes(reinterpret_cast<const char *>(Data.data()),
248 Data.size());
249 }
250
deserialize(ChannelT & C,tpctypes::WrapperFunctionResult & E)251 static Error deserialize(ChannelT &C, tpctypes::WrapperFunctionResult &E) {
252 tpctypes::CWrapperFunctionResult R;
253
254 R.Size = 0;
255 R.Data.ValuePtr = nullptr;
256 R.Destroy = nullptr;
257
258 if (auto Err = deserializeSeq(C, R.Size))
259 return Err;
260 if (R.Size == 0)
261 return Error::success();
262 R.Data.ValuePtr = new uint8_t[R.Size];
263 if (auto Err =
264 C.readBytes(reinterpret_cast<char *>(R.Data.ValuePtr), R.Size)) {
265 R.Destroy = tpctypes::WrapperFunctionResult::destroyWithDeleteArray;
266 return Err;
267 }
268
269 E = tpctypes::WrapperFunctionResult(R);
270 return Error::success();
271 }
272 };
273
274 } // end namespace rpc
275
276 namespace orcrpctpc {
277
278 using RemoteSymbolLookupSet = std::vector<std::pair<std::string, bool>>;
279 using RemoteLookupRequest =
280 std::pair<tpctypes::DylibHandle, RemoteSymbolLookupSet>;
281
282 class GetTargetTriple : public rpc::Function<GetTargetTriple, std::string()> {
283 public:
getName()284 static const char *getName() { return "GetTargetTriple"; }
285 };
286
287 class GetPageSize : public rpc::Function<GetPageSize, uint64_t()> {
288 public:
getName()289 static const char *getName() { return "GetPageSize"; }
290 };
291
292 class ReserveMem : public rpc::Function<ReserveMem, Expected<ReserveMemResult>(
293 ReserveMemRequest)> {
294 public:
getName()295 static const char *getName() { return "ReserveMem"; }
296 };
297
298 class FinalizeMem
299 : public rpc::Function<FinalizeMem, Error(ReleaseOrFinalizeMemRequest)> {
300 public:
getName()301 static const char *getName() { return "FinalizeMem"; }
302 };
303
304 class ReleaseMem
305 : public rpc::Function<ReleaseMem, Error(ReleaseOrFinalizeMemRequest)> {
306 public:
getName()307 static const char *getName() { return "ReleaseMem"; }
308 };
309
310 class WriteUInt8s
311 : public rpc::Function<WriteUInt8s,
312 Error(std::vector<tpctypes::UInt8Write>)> {
313 public:
getName()314 static const char *getName() { return "WriteUInt8s"; }
315 };
316
317 class WriteUInt16s
318 : public rpc::Function<WriteUInt16s,
319 Error(std::vector<tpctypes::UInt16Write>)> {
320 public:
getName()321 static const char *getName() { return "WriteUInt16s"; }
322 };
323
324 class WriteUInt32s
325 : public rpc::Function<WriteUInt32s,
326 Error(std::vector<tpctypes::UInt32Write>)> {
327 public:
getName()328 static const char *getName() { return "WriteUInt32s"; }
329 };
330
331 class WriteUInt64s
332 : public rpc::Function<WriteUInt64s,
333 Error(std::vector<tpctypes::UInt64Write>)> {
334 public:
getName()335 static const char *getName() { return "WriteUInt64s"; }
336 };
337
338 class WriteBuffers
339 : public rpc::Function<WriteBuffers,
340 Error(std::vector<tpctypes::BufferWrite>)> {
341 public:
getName()342 static const char *getName() { return "WriteBuffers"; }
343 };
344
345 class LoadDylib
346 : public rpc::Function<LoadDylib, Expected<tpctypes::DylibHandle>(
347 std::string DylibPath)> {
348 public:
getName()349 static const char *getName() { return "LoadDylib"; }
350 };
351
352 class LookupSymbols
353 : public rpc::Function<LookupSymbols,
354 Expected<std::vector<tpctypes::LookupResult>>(
355 std::vector<RemoteLookupRequest>)> {
356 public:
getName()357 static const char *getName() { return "LookupSymbols"; }
358 };
359
360 class RunMain
361 : public rpc::Function<RunMain, int32_t(JITTargetAddress MainAddr,
362 std::vector<std::string> Args)> {
363 public:
getName()364 static const char *getName() { return "RunMain"; }
365 };
366
367 class RunWrapper
368 : public rpc::Function<RunWrapper,
369 tpctypes::WrapperFunctionResult(
370 JITTargetAddress, std::vector<uint8_t>)> {
371 public:
getName()372 static const char *getName() { return "RunWrapper"; }
373 };
374
375 class CloseConnection : public rpc::Function<CloseConnection, void()> {
376 public:
getName()377 static const char *getName() { return "CloseConnection"; }
378 };
379
380 } // end namespace orcrpctpc
381
382 /// TargetProcessControl for a process connected via an ORC RPC Endpoint.
383 template <typename RPCEndpointT> class OrcRPCTPCServer {
384 public:
385 /// Create an OrcRPCTPCServer from the given endpoint.
OrcRPCTPCServer(RPCEndpointT & EP)386 OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) {
387 using ThisT = OrcRPCTPCServer<RPCEndpointT>;
388
389 TripleStr = sys::getProcessTriple();
390 PageSize = sys::Process::getPageSizeEstimate();
391
392 EP.template addHandler<orcrpctpc::GetTargetTriple>(*this,
393 &ThisT::getTargetTriple);
394 EP.template addHandler<orcrpctpc::GetPageSize>(*this, &ThisT::getPageSize);
395
396 EP.template addHandler<orcrpctpc::ReserveMem>(*this, &ThisT::reserveMemory);
397 EP.template addHandler<orcrpctpc::FinalizeMem>(*this,
398 &ThisT::finalizeMemory);
399 EP.template addHandler<orcrpctpc::ReleaseMem>(*this, &ThisT::releaseMemory);
400
401 EP.template addHandler<orcrpctpc::WriteUInt8s>(
402 handleWriteUInt<tpctypes::UInt8Write>);
403 EP.template addHandler<orcrpctpc::WriteUInt16s>(
404 handleWriteUInt<tpctypes::UInt16Write>);
405 EP.template addHandler<orcrpctpc::WriteUInt32s>(
406 handleWriteUInt<tpctypes::UInt32Write>);
407 EP.template addHandler<orcrpctpc::WriteUInt64s>(
408 handleWriteUInt<tpctypes::UInt64Write>);
409 EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer);
410
411 EP.template addHandler<orcrpctpc::LoadDylib>(*this, &ThisT::loadDylib);
412 EP.template addHandler<orcrpctpc::LookupSymbols>(*this,
413 &ThisT::lookupSymbols);
414
415 EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain);
416 EP.template addHandler<orcrpctpc::RunWrapper>(*this, &ThisT::runWrapper);
417
418 EP.template addHandler<orcrpctpc::CloseConnection>(*this,
419 &ThisT::closeConnection);
420 }
421
422 /// Set the ProgramName to be used as the first argv element when running
423 /// functions via runAsMain.
424 void setProgramName(Optional<std::string> ProgramName = None) {
425 this->ProgramName = std::move(ProgramName);
426 }
427
428 /// Get the RPC endpoint for this server.
getEndpoint()429 RPCEndpointT &getEndpoint() { return EP; }
430
431 /// Run the server loop.
run()432 Error run() {
433 while (!Finished) {
434 if (auto Err = EP.handleOne())
435 return Err;
436 }
437 return Error::success();
438 }
439
440 private:
getTargetTriple()441 std::string getTargetTriple() { return TripleStr; }
getPageSize()442 uint64_t getPageSize() { return PageSize; }
443
444 template <typename WriteT>
handleWriteUInt(const std::vector<WriteT> & Ws)445 static void handleWriteUInt(const std::vector<WriteT> &Ws) {
446 using ValueT = decltype(std::declval<WriteT>().Value);
447 for (auto &W : Ws)
448 *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value;
449 }
450
getProtStr(orcrpctpc::WireProtectionFlags WPF)451 std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) {
452 std::string Result;
453 Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-';
454 Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-';
455 Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-';
456 return Result;
457 }
458
handleWriteBuffer(const std::vector<tpctypes::BufferWrite> & Ws)459 static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite> &Ws) {
460 for (auto &W : Ws) {
461 memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
462 W.Buffer.size());
463 }
464 }
465
466 Expected<orcrpctpc::ReserveMemResult>
reserveMemory(const orcrpctpc::ReserveMemRequest & Request)467 reserveMemory(const orcrpctpc::ReserveMemRequest &Request) {
468 orcrpctpc::ReserveMemResult Allocs;
469 auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
470
471 uint64_t TotalSize = 0;
472
473 for (const auto &E : Request) {
474 uint64_t Size = alignTo(E.Size, PageSize);
475 uint16_t Align = E.Alignment;
476
477 if ((Align > PageSize) || (PageSize % Align))
478 return make_error<StringError>(
479 "Page alignmen does not satisfy requested alignment",
480 inconvertibleErrorCode());
481
482 TotalSize += Size;
483 }
484
485 // Allocate memory slab.
486 std::error_code EC;
487 auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF, EC);
488 if (EC)
489 return make_error<StringError>("Unable to allocate memory: " +
490 EC.message(),
491 inconvertibleErrorCode());
492
493 // Zero-fill the whole thing.
494 memset(MB.base(), 0, MB.allocatedSize());
495
496 // Carve up sections to return.
497 uint64_t SectionBase = 0;
498 for (const auto &E : Request) {
499 uint64_t SectionSize = alignTo(E.Size, PageSize);
500 Allocs.push_back({E.Prot,
501 pointerToJITTargetAddress(MB.base()) + SectionBase,
502 SectionSize});
503 SectionBase += SectionSize;
504 }
505
506 return Allocs;
507 }
508
finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & FMR)509 Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &FMR) {
510 for (const auto &E : FMR) {
511 sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
512
513 auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot);
514 if (auto EC =
515 sys::Memory::protectMappedMemory(MB, static_cast<unsigned>(PF)))
516 return make_error<StringError>("error protecting memory: " +
517 EC.message(),
518 inconvertibleErrorCode());
519 }
520 return Error::success();
521 }
522
releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & RMR)523 Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR) {
524 for (const auto &E : RMR) {
525 sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
526
527 if (auto EC = sys::Memory::releaseMappedMemory(MB))
528 return make_error<StringError>("error release memory: " + EC.message(),
529 inconvertibleErrorCode());
530 }
531 return Error::success();
532 }
533
loadDylib(const std::string & Path)534 Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) {
535 std::string ErrMsg;
536 const char *DLPath = !Path.empty() ? Path.c_str() : nullptr;
537 auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg);
538 if (!DL.isValid())
539 return make_error<StringError>(std::move(ErrMsg),
540 inconvertibleErrorCode());
541
542 tpctypes::DylibHandle H = Dylibs.size();
543 Dylibs[H] = std::move(DL);
544 return H;
545 }
546
547 Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> & Request)548 lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> &Request) {
549 std::vector<tpctypes::LookupResult> Result;
550
551 for (const auto &E : Request) {
552 auto I = Dylibs.find(E.first);
553 if (I == Dylibs.end())
554 return make_error<StringError>("Unrecognized handle",
555 inconvertibleErrorCode());
556 auto &DL = I->second;
557 Result.push_back({});
558
559 for (const auto &KV : E.second) {
560 auto &SymString = KV.first;
561 bool WeakReference = KV.second;
562
563 const char *Sym = SymString.c_str();
564 #ifdef __APPLE__
565 if (*Sym == '_')
566 ++Sym;
567 #endif
568
569 void *Addr = DL.getAddressOfSymbol(Sym);
570 if (!Addr && !WeakReference)
571 return make_error<StringError>(Twine("Missing definition for ") + Sym,
572 inconvertibleErrorCode());
573
574 Result.back().push_back(pointerToJITTargetAddress(Addr));
575 }
576 }
577
578 return Result;
579 }
580
runMain(JITTargetAddress MainFnAddr,const std::vector<std::string> & Args)581 int32_t runMain(JITTargetAddress MainFnAddr,
582 const std::vector<std::string> &Args) {
583 Optional<StringRef> ProgramNameOverride;
584 if (ProgramName)
585 ProgramNameOverride = *ProgramName;
586
587 return runAsMain(
588 jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr), Args,
589 ProgramNameOverride);
590 }
591
592 tpctypes::WrapperFunctionResult
runWrapper(JITTargetAddress WrapperFnAddr,const std::vector<uint8_t> & ArgBuffer)593 runWrapper(JITTargetAddress WrapperFnAddr,
594 const std::vector<uint8_t> &ArgBuffer) {
595 using WrapperFnTy = tpctypes::CWrapperFunctionResult (*)(
596 const uint8_t *Data, uint64_t Size);
597 auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
598 return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
599 }
600
closeConnection()601 void closeConnection() { Finished = true; }
602
603 std::string TripleStr;
604 uint64_t PageSize = 0;
605 Optional<std::string> ProgramName;
606 RPCEndpointT &EP;
607 std::atomic<bool> Finished{false};
608 DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs;
609 };
610
611 } // end namespace orc
612 } // end namespace llvm
613
614 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
615