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