xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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/Support/DynamicLibrary.h"
22 #include "llvm/Support/FormatVariadic.h"
23 #include "llvm/Support/Host.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Support/Memory.h"
26 #include "llvm/Support/Process.h"
27 
28 #include <atomic>
29 
30 namespace llvm {
31 namespace orc {
32 
33 namespace orcrpctpc {
34 
35 enum WireProtectionFlags : uint8_t {
36   WPF_None = 0,
37   WPF_Read = 1U << 0,
38   WPF_Write = 1U << 1,
39   WPF_Exec = 1U << 2,
40   LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec)
41 };
42 
43 /// Convert from sys::Memory::ProtectionFlags
44 inline WireProtectionFlags
toWireProtectionFlags(sys::Memory::ProtectionFlags PF)45 toWireProtectionFlags(sys::Memory::ProtectionFlags PF) {
46   WireProtectionFlags WPF = WPF_None;
47   if (PF & sys::Memory::MF_READ)
48     WPF |= WPF_Read;
49   if (PF & sys::Memory::MF_WRITE)
50     WPF |= WPF_Write;
51   if (PF & sys::Memory::MF_EXEC)
52     WPF |= WPF_Exec;
53   return WPF;
54 }
55 
56 inline sys::Memory::ProtectionFlags
fromWireProtectionFlags(WireProtectionFlags WPF)57 fromWireProtectionFlags(WireProtectionFlags WPF) {
58   int PF = 0;
59   if (WPF & WPF_Read)
60     PF |= sys::Memory::MF_READ;
61   if (WPF & WPF_Write)
62     PF |= sys::Memory::MF_WRITE;
63   if (WPF & WPF_Exec)
64     PF |= sys::Memory::MF_EXEC;
65   return static_cast<sys::Memory::ProtectionFlags>(PF);
66 }
67 
68 struct ReserveMemRequestElement {
69   WireProtectionFlags Prot = WPF_None;
70   uint64_t Size = 0;
71   uint64_t Alignment = 0;
72 };
73 
74 using ReserveMemRequest = std::vector<ReserveMemRequestElement>;
75 
76 struct ReserveMemResultElement {
77   WireProtectionFlags Prot = WPF_None;
78   JITTargetAddress Address = 0;
79   uint64_t AllocatedSize = 0;
80 };
81 
82 using ReserveMemResult = std::vector<ReserveMemResultElement>;
83 
84 struct ReleaseOrFinalizeMemRequestElement {
85   WireProtectionFlags Prot = WPF_None;
86   JITTargetAddress Address = 0;
87   uint64_t Size = 0;
88 };
89 
90 using ReleaseOrFinalizeMemRequest =
91     std::vector<ReleaseOrFinalizeMemRequestElement>;
92 
93 } // end namespace orcrpctpc
94 
95 namespace shared {
96 
97 template <> class SerializationTypeName<tpctypes::UInt8Write> {
98 public:
getName()99   static const char *getName() { return "UInt8Write"; }
100 };
101 
102 template <> class SerializationTypeName<tpctypes::UInt16Write> {
103 public:
getName()104   static const char *getName() { return "UInt16Write"; }
105 };
106 
107 template <> class SerializationTypeName<tpctypes::UInt32Write> {
108 public:
getName()109   static const char *getName() { return "UInt32Write"; }
110 };
111 
112 template <> class SerializationTypeName<tpctypes::UInt64Write> {
113 public:
getName()114   static const char *getName() { return "UInt64Write"; }
115 };
116 
117 template <> class SerializationTypeName<tpctypes::BufferWrite> {
118 public:
getName()119   static const char *getName() { return "BufferWrite"; }
120 };
121 
122 template <> class SerializationTypeName<orcrpctpc::ReserveMemRequestElement> {
123 public:
getName()124   static const char *getName() { return "ReserveMemRequestElement"; }
125 };
126 
127 template <> class SerializationTypeName<orcrpctpc::ReserveMemResultElement> {
128 public:
getName()129   static const char *getName() { return "ReserveMemResultElement"; }
130 };
131 
132 template <>
133 class SerializationTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
134 public:
getName()135   static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; }
136 };
137 
138 template <> class SerializationTypeName<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 shared
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
283     : public shared::RPCFunction<GetTargetTriple, std::string()> {
284 public:
getName()285   static const char *getName() { return "GetTargetTriple"; }
286 };
287 
288 class GetPageSize : public shared::RPCFunction<GetPageSize, uint64_t()> {
289 public:
getName()290   static const char *getName() { return "GetPageSize"; }
291 };
292 
293 class ReserveMem
294     : public shared::RPCFunction<ReserveMem, Expected<ReserveMemResult>(
295                                                  ReserveMemRequest)> {
296 public:
getName()297   static const char *getName() { return "ReserveMem"; }
298 };
299 
300 class FinalizeMem
301     : public shared::RPCFunction<FinalizeMem,
302                                  Error(ReleaseOrFinalizeMemRequest)> {
303 public:
getName()304   static const char *getName() { return "FinalizeMem"; }
305 };
306 
307 class ReleaseMem
308     : public shared::RPCFunction<ReleaseMem,
309                                  Error(ReleaseOrFinalizeMemRequest)> {
310 public:
getName()311   static const char *getName() { return "ReleaseMem"; }
312 };
313 
314 class WriteUInt8s
315     : public shared::RPCFunction<WriteUInt8s,
316                                  Error(std::vector<tpctypes::UInt8Write>)> {
317 public:
getName()318   static const char *getName() { return "WriteUInt8s"; }
319 };
320 
321 class WriteUInt16s
322     : public shared::RPCFunction<WriteUInt16s,
323                                  Error(std::vector<tpctypes::UInt16Write>)> {
324 public:
getName()325   static const char *getName() { return "WriteUInt16s"; }
326 };
327 
328 class WriteUInt32s
329     : public shared::RPCFunction<WriteUInt32s,
330                                  Error(std::vector<tpctypes::UInt32Write>)> {
331 public:
getName()332   static const char *getName() { return "WriteUInt32s"; }
333 };
334 
335 class WriteUInt64s
336     : public shared::RPCFunction<WriteUInt64s,
337                                  Error(std::vector<tpctypes::UInt64Write>)> {
338 public:
getName()339   static const char *getName() { return "WriteUInt64s"; }
340 };
341 
342 class WriteBuffers
343     : public shared::RPCFunction<WriteBuffers,
344                                  Error(std::vector<tpctypes::BufferWrite>)> {
345 public:
getName()346   static const char *getName() { return "WriteBuffers"; }
347 };
348 
349 class LoadDylib
350     : public shared::RPCFunction<LoadDylib, Expected<tpctypes::DylibHandle>(
351                                                 std::string DylibPath)> {
352 public:
getName()353   static const char *getName() { return "LoadDylib"; }
354 };
355 
356 class LookupSymbols
357     : public shared::RPCFunction<LookupSymbols,
358                                  Expected<std::vector<tpctypes::LookupResult>>(
359                                      std::vector<RemoteLookupRequest>)> {
360 public:
getName()361   static const char *getName() { return "LookupSymbols"; }
362 };
363 
364 class RunMain
365     : public shared::RPCFunction<RunMain,
366                                  int32_t(JITTargetAddress MainAddr,
367                                          std::vector<std::string> Args)> {
368 public:
getName()369   static const char *getName() { return "RunMain"; }
370 };
371 
372 class RunWrapper
373     : public shared::RPCFunction<RunWrapper,
374                                  tpctypes::WrapperFunctionResult(
375                                      JITTargetAddress, std::vector<uint8_t>)> {
376 public:
getName()377   static const char *getName() { return "RunWrapper"; }
378 };
379 
380 class CloseConnection : public shared::RPCFunction<CloseConnection, void()> {
381 public:
getName()382   static const char *getName() { return "CloseConnection"; }
383 };
384 
385 } // end namespace orcrpctpc
386 
387 /// TargetProcessControl for a process connected via an ORC RPC Endpoint.
388 template <typename RPCEndpointT> class OrcRPCTPCServer {
389 public:
390   /// Create an OrcRPCTPCServer from the given endpoint.
OrcRPCTPCServer(RPCEndpointT & EP)391   OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) {
392     using ThisT = OrcRPCTPCServer<RPCEndpointT>;
393 
394     TripleStr = sys::getProcessTriple();
395     PageSize = sys::Process::getPageSizeEstimate();
396 
397     EP.template addHandler<orcrpctpc::GetTargetTriple>(*this,
398                                                        &ThisT::getTargetTriple);
399     EP.template addHandler<orcrpctpc::GetPageSize>(*this, &ThisT::getPageSize);
400 
401     EP.template addHandler<orcrpctpc::ReserveMem>(*this, &ThisT::reserveMemory);
402     EP.template addHandler<orcrpctpc::FinalizeMem>(*this,
403                                                    &ThisT::finalizeMemory);
404     EP.template addHandler<orcrpctpc::ReleaseMem>(*this, &ThisT::releaseMemory);
405 
406     EP.template addHandler<orcrpctpc::WriteUInt8s>(
407         handleWriteUInt<tpctypes::UInt8Write>);
408     EP.template addHandler<orcrpctpc::WriteUInt16s>(
409         handleWriteUInt<tpctypes::UInt16Write>);
410     EP.template addHandler<orcrpctpc::WriteUInt32s>(
411         handleWriteUInt<tpctypes::UInt32Write>);
412     EP.template addHandler<orcrpctpc::WriteUInt64s>(
413         handleWriteUInt<tpctypes::UInt64Write>);
414     EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer);
415 
416     EP.template addHandler<orcrpctpc::LoadDylib>(*this, &ThisT::loadDylib);
417     EP.template addHandler<orcrpctpc::LookupSymbols>(*this,
418                                                      &ThisT::lookupSymbols);
419 
420     EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain);
421     EP.template addHandler<orcrpctpc::RunWrapper>(*this, &ThisT::runWrapper);
422 
423     EP.template addHandler<orcrpctpc::CloseConnection>(*this,
424                                                        &ThisT::closeConnection);
425   }
426 
427   /// Set the ProgramName to be used as the first argv element when running
428   /// functions via runAsMain.
429   void setProgramName(Optional<std::string> ProgramName = None) {
430     this->ProgramName = std::move(ProgramName);
431   }
432 
433   /// Get the RPC endpoint for this server.
getEndpoint()434   RPCEndpointT &getEndpoint() { return EP; }
435 
436   /// Run the server loop.
run()437   Error run() {
438     while (!Finished) {
439       if (auto Err = EP.handleOne())
440         return Err;
441     }
442     return Error::success();
443   }
444 
445 private:
getTargetTriple()446   std::string getTargetTriple() { return TripleStr; }
getPageSize()447   uint64_t getPageSize() { return PageSize; }
448 
449   template <typename WriteT>
handleWriteUInt(const std::vector<WriteT> & Ws)450   static void handleWriteUInt(const std::vector<WriteT> &Ws) {
451     using ValueT = decltype(std::declval<WriteT>().Value);
452     for (auto &W : Ws)
453       *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value;
454   }
455 
getProtStr(orcrpctpc::WireProtectionFlags WPF)456   std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) {
457     std::string Result;
458     Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-';
459     Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-';
460     Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-';
461     return Result;
462   }
463 
handleWriteBuffer(const std::vector<tpctypes::BufferWrite> & Ws)464   static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite> &Ws) {
465     for (auto &W : Ws) {
466       memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
467              W.Buffer.size());
468     }
469   }
470 
471   Expected<orcrpctpc::ReserveMemResult>
reserveMemory(const orcrpctpc::ReserveMemRequest & Request)472   reserveMemory(const orcrpctpc::ReserveMemRequest &Request) {
473     orcrpctpc::ReserveMemResult Allocs;
474     auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
475 
476     uint64_t TotalSize = 0;
477 
478     for (const auto &E : Request) {
479       uint64_t Size = alignTo(E.Size, PageSize);
480       uint16_t Align = E.Alignment;
481 
482       if ((Align > PageSize) || (PageSize % Align))
483         return make_error<StringError>(
484             "Page alignmen does not satisfy requested alignment",
485             inconvertibleErrorCode());
486 
487       TotalSize += Size;
488     }
489 
490     // Allocate memory slab.
491     std::error_code EC;
492     auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF, EC);
493     if (EC)
494       return make_error<StringError>("Unable to allocate memory: " +
495                                          EC.message(),
496                                      inconvertibleErrorCode());
497 
498     // Zero-fill the whole thing.
499     memset(MB.base(), 0, MB.allocatedSize());
500 
501     // Carve up sections to return.
502     uint64_t SectionBase = 0;
503     for (const auto &E : Request) {
504       uint64_t SectionSize = alignTo(E.Size, PageSize);
505       Allocs.push_back({E.Prot,
506                         pointerToJITTargetAddress(MB.base()) + SectionBase,
507                         SectionSize});
508       SectionBase += SectionSize;
509     }
510 
511     return Allocs;
512   }
513 
finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & FMR)514   Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &FMR) {
515     for (const auto &E : FMR) {
516       sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
517 
518       auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot);
519       if (auto EC =
520               sys::Memory::protectMappedMemory(MB, static_cast<unsigned>(PF)))
521         return make_error<StringError>("error protecting memory: " +
522                                            EC.message(),
523                                        inconvertibleErrorCode());
524     }
525     return Error::success();
526   }
527 
releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & RMR)528   Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR) {
529     for (const auto &E : RMR) {
530       sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
531 
532       if (auto EC = sys::Memory::releaseMappedMemory(MB))
533         return make_error<StringError>("error release memory: " + EC.message(),
534                                        inconvertibleErrorCode());
535     }
536     return Error::success();
537   }
538 
loadDylib(const std::string & Path)539   Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) {
540     std::string ErrMsg;
541     const char *DLPath = !Path.empty() ? Path.c_str() : nullptr;
542     auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg);
543     if (!DL.isValid())
544       return make_error<StringError>(std::move(ErrMsg),
545                                      inconvertibleErrorCode());
546 
547     tpctypes::DylibHandle H = Dylibs.size();
548     Dylibs[H] = std::move(DL);
549     return H;
550   }
551 
552   Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> & Request)553   lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> &Request) {
554     std::vector<tpctypes::LookupResult> Result;
555 
556     for (const auto &E : Request) {
557       auto I = Dylibs.find(E.first);
558       if (I == Dylibs.end())
559         return make_error<StringError>("Unrecognized handle",
560                                        inconvertibleErrorCode());
561       auto &DL = I->second;
562       Result.push_back({});
563 
564       for (const auto &KV : E.second) {
565         auto &SymString = KV.first;
566         bool WeakReference = KV.second;
567 
568         const char *Sym = SymString.c_str();
569 #ifdef __APPLE__
570         if (*Sym == '_')
571           ++Sym;
572 #endif
573 
574         void *Addr = DL.getAddressOfSymbol(Sym);
575         if (!Addr && !WeakReference)
576           return make_error<StringError>(Twine("Missing definition for ") + Sym,
577                                          inconvertibleErrorCode());
578 
579         Result.back().push_back(pointerToJITTargetAddress(Addr));
580       }
581     }
582 
583     return Result;
584   }
585 
runMain(JITTargetAddress MainFnAddr,const std::vector<std::string> & Args)586   int32_t runMain(JITTargetAddress MainFnAddr,
587                   const std::vector<std::string> &Args) {
588     Optional<StringRef> ProgramNameOverride;
589     if (ProgramName)
590       ProgramNameOverride = *ProgramName;
591 
592     return runAsMain(
593         jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr), Args,
594         ProgramNameOverride);
595   }
596 
597   tpctypes::WrapperFunctionResult
runWrapper(JITTargetAddress WrapperFnAddr,const std::vector<uint8_t> & ArgBuffer)598   runWrapper(JITTargetAddress WrapperFnAddr,
599              const std::vector<uint8_t> &ArgBuffer) {
600     using WrapperFnTy = tpctypes::CWrapperFunctionResult (*)(
601         const uint8_t *Data, uint64_t Size);
602     auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
603     return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
604   }
605 
closeConnection()606   void closeConnection() { Finished = true; }
607 
608   std::string TripleStr;
609   uint64_t PageSize = 0;
610   Optional<std::string> ProgramName;
611   RPCEndpointT &EP;
612   std::atomic<bool> Finished{false};
613   DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs;
614 };
615 
616 } // end namespace orc
617 } // end namespace llvm
618 
619 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
620