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