1*bb72f073SLang Hames //===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===//
2*bb72f073SLang Hames //
3*bb72f073SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bb72f073SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5*bb72f073SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bb72f073SLang Hames //
7*bb72f073SLang Hames //===----------------------------------------------------------------------===//
8*bb72f073SLang Hames 
9*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"
10*bb72f073SLang Hames 
11*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
12*bb72f073SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
13*bb72f073SLang Hames #include "llvm/Support/FormatVariadic.h"
14*bb72f073SLang Hames #include "llvm/Support/Host.h"
15*bb72f073SLang Hames #include "llvm/Support/Process.h"
16*bb72f073SLang Hames 
17*bb72f073SLang Hames #define DEBUG_TYPE "orc"
18*bb72f073SLang Hames 
19*bb72f073SLang Hames using namespace llvm::orc::shared;
20*bb72f073SLang Hames 
21*bb72f073SLang Hames namespace llvm {
22*bb72f073SLang Hames namespace orc {
23*bb72f073SLang Hames 
24*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
25*bb72f073SLang Hames reserveWrapper(const char *ArgData, size_t ArgSize) {
26*bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessAllocate>::handle(
27*bb72f073SLang Hames              ArgData, ArgSize,
28*bb72f073SLang Hames              [](uint64_t Size) -> Expected<ExecutorAddress> {
29*bb72f073SLang Hames                std::error_code EC;
30*bb72f073SLang Hames                auto MB = sys::Memory::allocateMappedMemory(
31*bb72f073SLang Hames                    Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
32*bb72f073SLang Hames                if (EC)
33*bb72f073SLang Hames                  return errorCodeToError(EC);
34*bb72f073SLang Hames                return ExecutorAddress::fromPtr(MB.base());
35*bb72f073SLang Hames              })
36*bb72f073SLang Hames       .release();
37*bb72f073SLang Hames }
38*bb72f073SLang Hames 
39*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
40*bb72f073SLang Hames finalizeWrapper(const char *ArgData, size_t ArgSize) {
41*bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessFinalize>::handle(
42*bb72f073SLang Hames              ArgData, ArgSize,
43*bb72f073SLang Hames              [](const tpctypes::FinalizeRequest &FR) -> Error {
44*bb72f073SLang Hames                for (auto &Seg : FR) {
45*bb72f073SLang Hames                  char *Mem = Seg.Addr.toPtr<char *>();
46*bb72f073SLang Hames                  memcpy(Mem, Seg.Content.data(), Seg.Content.size());
47*bb72f073SLang Hames                  memset(Mem + Seg.Content.size(), 0,
48*bb72f073SLang Hames                         Seg.Size - Seg.Content.size());
49*bb72f073SLang Hames                  assert(Seg.Size <= std::numeric_limits<size_t>::max());
50*bb72f073SLang Hames                  if (auto EC = sys::Memory::protectMappedMemory(
51*bb72f073SLang Hames                          {Mem, static_cast<size_t>(Seg.Size)},
52*bb72f073SLang Hames                          tpctypes::fromWireProtectionFlags(Seg.Prot)))
53*bb72f073SLang Hames                    return errorCodeToError(EC);
54*bb72f073SLang Hames                  if (Seg.Prot & tpctypes::WPF_Exec)
55*bb72f073SLang Hames                    sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
56*bb72f073SLang Hames                }
57*bb72f073SLang Hames                return Error::success();
58*bb72f073SLang Hames              })
59*bb72f073SLang Hames       .release();
60*bb72f073SLang Hames }
61*bb72f073SLang Hames 
62*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
63*bb72f073SLang Hames deallocateWrapper(const char *ArgData, size_t ArgSize) {
64*bb72f073SLang Hames   return WrapperFunction<SPSOrcTargetProcessDeallocate>::handle(
65*bb72f073SLang Hames              ArgData, ArgSize,
66*bb72f073SLang Hames              [](ExecutorAddress Base, uint64_t Size) -> Error {
67*bb72f073SLang Hames                sys::MemoryBlock MB(Base.toPtr<void *>(), Size);
68*bb72f073SLang Hames                if (auto EC = sys::Memory::releaseMappedMemory(MB))
69*bb72f073SLang Hames                  return errorCodeToError(EC);
70*bb72f073SLang Hames                return Error::success();
71*bb72f073SLang Hames              })
72*bb72f073SLang Hames       .release();
73*bb72f073SLang Hames }
74*bb72f073SLang Hames 
75*bb72f073SLang Hames template <typename WriteT, typename SPSWriteT>
76*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
77*bb72f073SLang Hames writeUIntsWrapper(const char *ArgData, size_t ArgSize) {
78*bb72f073SLang Hames   return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
79*bb72f073SLang Hames              ArgData, ArgSize,
80*bb72f073SLang Hames              [](std::vector<WriteT> Ws) {
81*bb72f073SLang Hames                for (auto &W : Ws)
82*bb72f073SLang Hames                  *jitTargetAddressToPointer<decltype(W.Value) *>(W.Address) =
83*bb72f073SLang Hames                      W.Value;
84*bb72f073SLang Hames              })
85*bb72f073SLang Hames       .release();
86*bb72f073SLang Hames }
87*bb72f073SLang Hames 
88*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
89*bb72f073SLang Hames writeBuffersWrapper(const char *ArgData, size_t ArgSize) {
90*bb72f073SLang Hames   return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
91*bb72f073SLang Hames              ArgData, ArgSize,
92*bb72f073SLang Hames              [](std::vector<tpctypes::BufferWrite> Ws) {
93*bb72f073SLang Hames                for (auto &W : Ws)
94*bb72f073SLang Hames                  memcpy(jitTargetAddressToPointer<char *>(W.Address),
95*bb72f073SLang Hames                         W.Buffer.data(), W.Buffer.size());
96*bb72f073SLang Hames              })
97*bb72f073SLang Hames       .release();
98*bb72f073SLang Hames }
99*bb72f073SLang Hames 
100*bb72f073SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult
101*bb72f073SLang Hames runAsMainWrapper(const char *ArgData, size_t ArgSize) {
102*bb72f073SLang Hames   return WrapperFunction<SPSRunAsMainSignature>::handle(
103*bb72f073SLang Hames              ArgData, ArgSize,
104*bb72f073SLang Hames              [](ExecutorAddress MainAddr,
105*bb72f073SLang Hames                 std::vector<std::string> Args) -> int64_t {
106*bb72f073SLang Hames                return runAsMain(MainAddr.toPtr<int (*)(int, char *[])>(), Args);
107*bb72f073SLang Hames              })
108*bb72f073SLang Hames       .release();
109*bb72f073SLang Hames }
110*bb72f073SLang Hames 
111*bb72f073SLang Hames SimpleRemoteEPCServer::Dispatcher::~Dispatcher() {}
112*bb72f073SLang Hames 
113*bb72f073SLang Hames #if LLVM_ENABLE_THREADS
114*bb72f073SLang Hames void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(
115*bb72f073SLang Hames     unique_function<void()> Work) {
116*bb72f073SLang Hames   {
117*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(DispatchMutex);
118*bb72f073SLang Hames     if (!Running)
119*bb72f073SLang Hames       return;
120*bb72f073SLang Hames     ++Outstanding;
121*bb72f073SLang Hames   }
122*bb72f073SLang Hames 
123*bb72f073SLang Hames   std::thread([this, Work = std::move(Work)]() mutable {
124*bb72f073SLang Hames     Work();
125*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(DispatchMutex);
126*bb72f073SLang Hames     --Outstanding;
127*bb72f073SLang Hames     OutstandingCV.notify_all();
128*bb72f073SLang Hames   }).detach();
129*bb72f073SLang Hames }
130*bb72f073SLang Hames 
131*bb72f073SLang Hames void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {
132*bb72f073SLang Hames   std::unique_lock<std::mutex> Lock(DispatchMutex);
133*bb72f073SLang Hames   Running = false;
134*bb72f073SLang Hames   OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
135*bb72f073SLang Hames }
136*bb72f073SLang Hames #endif
137*bb72f073SLang Hames 
138*bb72f073SLang Hames StringMap<ExecutorAddress> SimpleRemoteEPCServer::defaultBootstrapSymbols() {
139*bb72f073SLang Hames   StringMap<ExecutorAddress> DBS;
140*bb72f073SLang Hames 
141*bb72f073SLang Hames   DBS["__llvm_orc_memory_reserve"] = ExecutorAddress::fromPtr(&reserveWrapper);
142*bb72f073SLang Hames   DBS["__llvm_orc_memory_finalize"] =
143*bb72f073SLang Hames       ExecutorAddress::fromPtr(&finalizeWrapper);
144*bb72f073SLang Hames   DBS["__llvm_orc_memory_deallocate"] =
145*bb72f073SLang Hames       ExecutorAddress::fromPtr(&deallocateWrapper);
146*bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint8s"] = ExecutorAddress::fromPtr(
147*bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt8Write,
148*bb72f073SLang Hames                          shared::SPSMemoryAccessUInt8Write>);
149*bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint16s"] = ExecutorAddress::fromPtr(
150*bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt16Write,
151*bb72f073SLang Hames                          shared::SPSMemoryAccessUInt16Write>);
152*bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint32s"] = ExecutorAddress::fromPtr(
153*bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt32Write,
154*bb72f073SLang Hames                          shared::SPSMemoryAccessUInt32Write>);
155*bb72f073SLang Hames   DBS["__llvm_orc_memory_write_uint64s"] = ExecutorAddress::fromPtr(
156*bb72f073SLang Hames       &writeUIntsWrapper<tpctypes::UInt64Write,
157*bb72f073SLang Hames                          shared::SPSMemoryAccessUInt64Write>);
158*bb72f073SLang Hames   DBS["__llvm_orc_memory_write_buffers"] =
159*bb72f073SLang Hames       ExecutorAddress::fromPtr(&writeBuffersWrapper);
160*bb72f073SLang Hames   DBS["__llvm_orc_run_as_main"] = ExecutorAddress::fromPtr(&runAsMainWrapper);
161*bb72f073SLang Hames   DBS["__llvm_orc_load_dylib"] = ExecutorAddress::fromPtr(&loadDylibWrapper);
162*bb72f073SLang Hames   DBS["__llvm_orc_lookup_symbols"] =
163*bb72f073SLang Hames       ExecutorAddress::fromPtr(&lookupSymbolsWrapper);
164*bb72f073SLang Hames   return DBS;
165*bb72f073SLang Hames }
166*bb72f073SLang Hames 
167*bb72f073SLang Hames Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
168*bb72f073SLang Hames SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
169*bb72f073SLang Hames                                      ExecutorAddress TagAddr,
170*bb72f073SLang Hames                                      SimpleRemoteEPCArgBytesVector ArgBytes) {
171*bb72f073SLang Hames   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
172*bb72f073SLang Hames   if (static_cast<UT>(OpC) < static_cast<UT>(SimpleRemoteEPCOpcode::FirstOpC) ||
173*bb72f073SLang Hames       static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
174*bb72f073SLang Hames     return make_error<StringError>("Unexpected opcode",
175*bb72f073SLang Hames                                    inconvertibleErrorCode());
176*bb72f073SLang Hames 
177*bb72f073SLang Hames   // TODO: Clean detach message?
178*bb72f073SLang Hames   switch (OpC) {
179*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Setup:
180*bb72f073SLang Hames     return make_error<StringError>("Unexpected Setup opcode",
181*bb72f073SLang Hames                                    inconvertibleErrorCode());
182*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Hangup:
183*bb72f073SLang Hames     return SimpleRemoteEPCTransportClient::EndSession;
184*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::Result:
185*bb72f073SLang Hames     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
186*bb72f073SLang Hames       return std::move(Err);
187*bb72f073SLang Hames     break;
188*bb72f073SLang Hames   case SimpleRemoteEPCOpcode::CallWrapper:
189*bb72f073SLang Hames     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
190*bb72f073SLang Hames     break;
191*bb72f073SLang Hames   }
192*bb72f073SLang Hames   return ContinueSession;
193*bb72f073SLang Hames }
194*bb72f073SLang Hames 
195*bb72f073SLang Hames Error SimpleRemoteEPCServer::waitForDisconnect() {
196*bb72f073SLang Hames   std::unique_lock<std::mutex> Lock(ServerStateMutex);
197*bb72f073SLang Hames   ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; });
198*bb72f073SLang Hames   return std::move(ShutdownErr);
199*bb72f073SLang Hames }
200*bb72f073SLang Hames 
201*bb72f073SLang Hames void SimpleRemoteEPCServer::handleDisconnect(Error Err) {
202*bb72f073SLang Hames   PendingJITDispatchResultsMap TmpPending;
203*bb72f073SLang Hames 
204*bb72f073SLang Hames   {
205*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
206*bb72f073SLang Hames     std::swap(TmpPending, PendingJITDispatchResults);
207*bb72f073SLang Hames     RunState = ServerShuttingDown;
208*bb72f073SLang Hames   }
209*bb72f073SLang Hames 
210*bb72f073SLang Hames   // Send out-of-band errors to any waiting threads.
211*bb72f073SLang Hames   for (auto &KV : TmpPending)
212*bb72f073SLang Hames     KV.second->set_value(
213*bb72f073SLang Hames         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
214*bb72f073SLang Hames 
215*bb72f073SLang Hames   // TODO: Free attached resources.
216*bb72f073SLang Hames   // 1. Close libraries in DylibHandles.
217*bb72f073SLang Hames 
218*bb72f073SLang Hames   // Wait for dispatcher to clear.
219*bb72f073SLang Hames   D->shutdown();
220*bb72f073SLang Hames 
221*bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(ServerStateMutex);
222*bb72f073SLang Hames   ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err));
223*bb72f073SLang Hames   RunState = ServerShutDown;
224*bb72f073SLang Hames   ShutdownCV.notify_all();
225*bb72f073SLang Hames }
226*bb72f073SLang Hames 
227*bb72f073SLang Hames Error SimpleRemoteEPCServer::sendSetupMessage(
228*bb72f073SLang Hames     StringMap<ExecutorAddress> BootstrapSymbols) {
229*bb72f073SLang Hames 
230*bb72f073SLang Hames   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
231*bb72f073SLang Hames 
232*bb72f073SLang Hames   std::vector<char> SetupPacket;
233*bb72f073SLang Hames   SimpleRemoteEPCExecutorInfo EI;
234*bb72f073SLang Hames   EI.TargetTriple = sys::getProcessTriple();
235*bb72f073SLang Hames   if (auto PageSize = sys::Process::getPageSize())
236*bb72f073SLang Hames     EI.PageSize = *PageSize;
237*bb72f073SLang Hames   else
238*bb72f073SLang Hames     return PageSize.takeError();
239*bb72f073SLang Hames   EI.BootstrapSymbols = std::move(BootstrapSymbols);
240*bb72f073SLang Hames 
241*bb72f073SLang Hames   assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&
242*bb72f073SLang Hames          "Dispatch context name should not be set");
243*bb72f073SLang Hames   assert(!EI.BootstrapSymbols.count(DispatchFnName) &&
244*bb72f073SLang Hames          "Dispatch function name should not be set");
245*bb72f073SLang Hames   EI.BootstrapSymbols[ExecutorSessionObjectName] =
246*bb72f073SLang Hames       ExecutorAddress::fromPtr(this);
247*bb72f073SLang Hames   EI.BootstrapSymbols[DispatchFnName] =
248*bb72f073SLang Hames       ExecutorAddress::fromPtr(jitDispatchEntry);
249*bb72f073SLang Hames 
250*bb72f073SLang Hames   using SPSSerialize =
251*bb72f073SLang Hames       shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
252*bb72f073SLang Hames   auto SetupPacketBytes =
253*bb72f073SLang Hames       shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI));
254*bb72f073SLang Hames   shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size());
255*bb72f073SLang Hames   if (!SPSSerialize::serialize(OB, EI))
256*bb72f073SLang Hames     return make_error<StringError>("Could not send setup packet",
257*bb72f073SLang Hames                                    inconvertibleErrorCode());
258*bb72f073SLang Hames 
259*bb72f073SLang Hames   return T->sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddress(),
260*bb72f073SLang Hames                         {SetupPacketBytes.data(), SetupPacketBytes.size()});
261*bb72f073SLang Hames }
262*bb72f073SLang Hames 
263*bb72f073SLang Hames Error SimpleRemoteEPCServer::handleResult(
264*bb72f073SLang Hames     uint64_t SeqNo, ExecutorAddress TagAddr,
265*bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
266*bb72f073SLang Hames   std::promise<shared::WrapperFunctionResult> *P = nullptr;
267*bb72f073SLang Hames   {
268*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
269*bb72f073SLang Hames     auto I = PendingJITDispatchResults.find(SeqNo);
270*bb72f073SLang Hames     if (I == PendingJITDispatchResults.end())
271*bb72f073SLang Hames       return make_error<StringError>("No call for sequence number " +
272*bb72f073SLang Hames                                          Twine(SeqNo),
273*bb72f073SLang Hames                                      inconvertibleErrorCode());
274*bb72f073SLang Hames     P = I->second;
275*bb72f073SLang Hames     PendingJITDispatchResults.erase(I);
276*bb72f073SLang Hames     releaseSeqNo(SeqNo);
277*bb72f073SLang Hames   }
278*bb72f073SLang Hames   auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size());
279*bb72f073SLang Hames   memcpy(R.data(), ArgBytes.data(), ArgBytes.size());
280*bb72f073SLang Hames   P->set_value(std::move(R));
281*bb72f073SLang Hames   return Error::success();
282*bb72f073SLang Hames }
283*bb72f073SLang Hames 
284*bb72f073SLang Hames void SimpleRemoteEPCServer::handleCallWrapper(
285*bb72f073SLang Hames     uint64_t RemoteSeqNo, ExecutorAddress TagAddr,
286*bb72f073SLang Hames     SimpleRemoteEPCArgBytesVector ArgBytes) {
287*bb72f073SLang Hames   D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
288*bb72f073SLang Hames     using WrapperFnTy =
289*bb72f073SLang Hames         shared::detail::CWrapperFunctionResult (*)(const char *, size_t);
290*bb72f073SLang Hames     auto *Fn = TagAddr.toPtr<WrapperFnTy>();
291*bb72f073SLang Hames     shared::WrapperFunctionResult ResultBytes(
292*bb72f073SLang Hames         Fn(ArgBytes.data(), ArgBytes.size()));
293*bb72f073SLang Hames     if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
294*bb72f073SLang Hames                                   ExecutorAddress(),
295*bb72f073SLang Hames                                   {ResultBytes.data(), ResultBytes.size()}))
296*bb72f073SLang Hames       ReportError(std::move(Err));
297*bb72f073SLang Hames   });
298*bb72f073SLang Hames }
299*bb72f073SLang Hames 
300*bb72f073SLang Hames shared::detail::CWrapperFunctionResult
301*bb72f073SLang Hames SimpleRemoteEPCServer::loadDylibWrapper(const char *ArgData, size_t ArgSize) {
302*bb72f073SLang Hames   return shared::WrapperFunction<shared::SPSLoadDylibSignature>::handle(
303*bb72f073SLang Hames              ArgData, ArgSize,
304*bb72f073SLang Hames              [](ExecutorAddress ExecutorSessionObj, std::string Path,
305*bb72f073SLang Hames                 uint64_t Flags) -> Expected<uint64_t> {
306*bb72f073SLang Hames                return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>()
307*bb72f073SLang Hames                    ->loadDylib(Path, Flags);
308*bb72f073SLang Hames              })
309*bb72f073SLang Hames       .release();
310*bb72f073SLang Hames }
311*bb72f073SLang Hames 
312*bb72f073SLang Hames shared::detail::CWrapperFunctionResult
313*bb72f073SLang Hames SimpleRemoteEPCServer::lookupSymbolsWrapper(const char *ArgData,
314*bb72f073SLang Hames                                             size_t ArgSize) {
315*bb72f073SLang Hames   return shared::WrapperFunction<shared::SPSLookupSymbolsSignature>::handle(
316*bb72f073SLang Hames              ArgData, ArgSize,
317*bb72f073SLang Hames              [](ExecutorAddress ExecutorSessionObj,
318*bb72f073SLang Hames                 std::vector<RemoteSymbolLookup> Lookup) {
319*bb72f073SLang Hames                return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>()
320*bb72f073SLang Hames                    ->lookupSymbols(Lookup);
321*bb72f073SLang Hames              })
322*bb72f073SLang Hames       .release();
323*bb72f073SLang Hames }
324*bb72f073SLang Hames 
325*bb72f073SLang Hames Expected<tpctypes::DylibHandle>
326*bb72f073SLang Hames SimpleRemoteEPCServer::loadDylib(const std::string &Path, uint64_t Mode) {
327*bb72f073SLang Hames   std::string ErrMsg;
328*bb72f073SLang Hames   const char *P = Path.empty() ? nullptr : Path.c_str();
329*bb72f073SLang Hames   auto DL = sys::DynamicLibrary::getPermanentLibrary(P, &ErrMsg);
330*bb72f073SLang Hames   if (!DL.isValid())
331*bb72f073SLang Hames     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
332*bb72f073SLang Hames   std::lock_guard<std::mutex> Lock(ServerStateMutex);
333*bb72f073SLang Hames   uint64_t Id = Dylibs.size();
334*bb72f073SLang Hames   Dylibs.push_back(std::move(DL));
335*bb72f073SLang Hames   return Id;
336*bb72f073SLang Hames }
337*bb72f073SLang Hames 
338*bb72f073SLang Hames Expected<std::vector<std::vector<ExecutorAddress>>>
339*bb72f073SLang Hames SimpleRemoteEPCServer::lookupSymbols(const std::vector<RemoteSymbolLookup> &L) {
340*bb72f073SLang Hames   std::vector<std::vector<ExecutorAddress>> Result;
341*bb72f073SLang Hames 
342*bb72f073SLang Hames   for (const auto &E : L) {
343*bb72f073SLang Hames     if (E.H >= Dylibs.size())
344*bb72f073SLang Hames       return make_error<StringError>("Unrecognized handle",
345*bb72f073SLang Hames                                      inconvertibleErrorCode());
346*bb72f073SLang Hames     auto &DL = Dylibs[E.H];
347*bb72f073SLang Hames     Result.push_back({});
348*bb72f073SLang Hames 
349*bb72f073SLang Hames     for (const auto &Sym : E.Symbols) {
350*bb72f073SLang Hames 
351*bb72f073SLang Hames       const char *DemangledSymName = Sym.Name.c_str();
352*bb72f073SLang Hames #ifdef __APPLE__
353*bb72f073SLang Hames       if (*DemangledSymName == '_')
354*bb72f073SLang Hames         ++DemangledSymName;
355*bb72f073SLang Hames #endif
356*bb72f073SLang Hames 
357*bb72f073SLang Hames       void *Addr = DL.getAddressOfSymbol(DemangledSymName);
358*bb72f073SLang Hames       if (!Addr && Sym.Required)
359*bb72f073SLang Hames         return make_error<StringError>(Twine("Missing definition for ") +
360*bb72f073SLang Hames                                            DemangledSymName,
361*bb72f073SLang Hames                                        inconvertibleErrorCode());
362*bb72f073SLang Hames 
363*bb72f073SLang Hames       Result.back().push_back(ExecutorAddress::fromPtr(Addr));
364*bb72f073SLang Hames     }
365*bb72f073SLang Hames   }
366*bb72f073SLang Hames 
367*bb72f073SLang Hames   return std::move(Result);
368*bb72f073SLang Hames }
369*bb72f073SLang Hames 
370*bb72f073SLang Hames shared::WrapperFunctionResult
371*bb72f073SLang Hames SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData,
372*bb72f073SLang Hames                                      size_t ArgSize) {
373*bb72f073SLang Hames   uint64_t SeqNo;
374*bb72f073SLang Hames   std::promise<shared::WrapperFunctionResult> ResultP;
375*bb72f073SLang Hames   auto ResultF = ResultP.get_future();
376*bb72f073SLang Hames   {
377*bb72f073SLang Hames     std::lock_guard<std::mutex> Lock(ServerStateMutex);
378*bb72f073SLang Hames     if (RunState != ServerRunning)
379*bb72f073SLang Hames       return shared::WrapperFunctionResult::createOutOfBandError(
380*bb72f073SLang Hames           "jit_dispatch not available (EPC server shut down)");
381*bb72f073SLang Hames 
382*bb72f073SLang Hames     SeqNo = getNextSeqNo();
383*bb72f073SLang Hames     assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use");
384*bb72f073SLang Hames     PendingJITDispatchResults[SeqNo] = &ResultP;
385*bb72f073SLang Hames   }
386*bb72f073SLang Hames 
387*bb72f073SLang Hames   if (auto Err =
388*bb72f073SLang Hames           T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
389*bb72f073SLang Hames                          ExecutorAddress::fromPtr(FnTag), {ArgData, ArgSize}))
390*bb72f073SLang Hames     ReportError(std::move(Err));
391*bb72f073SLang Hames 
392*bb72f073SLang Hames   return ResultF.get();
393*bb72f073SLang Hames }
394*bb72f073SLang Hames 
395*bb72f073SLang Hames shared::detail::CWrapperFunctionResult
396*bb72f073SLang Hames SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag,
397*bb72f073SLang Hames                                         const char *ArgData, size_t ArgSize) {
398*bb72f073SLang Hames   return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx)
399*bb72f073SLang Hames       ->doJITDispatch(FnTag, ArgData, ArgSize)
400*bb72f073SLang Hames       .release();
401*bb72f073SLang Hames }
402*bb72f073SLang Hames 
403*bb72f073SLang Hames } // end namespace orc
404*bb72f073SLang Hames } // end namespace llvm
405