• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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