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