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/Support/FormatVariadic.h" 13 #include "llvm/Support/Host.h" 14 #include "llvm/Support/Process.h" 15 16 #include "OrcRTBootstrap.h" 17 18 #define DEBUG_TYPE "orc" 19 20 using namespace llvm::orc::shared; 21 22 namespace llvm { 23 namespace orc { 24 25 SimpleRemoteEPCServer::Dispatcher::~Dispatcher() {} 26 27 #if LLVM_ENABLE_THREADS 28 void SimpleRemoteEPCServer::ThreadDispatcher::dispatch( 29 unique_function<void()> Work) { 30 { 31 std::lock_guard<std::mutex> Lock(DispatchMutex); 32 if (!Running) 33 return; 34 ++Outstanding; 35 } 36 37 std::thread([this, Work = std::move(Work)]() mutable { 38 Work(); 39 std::lock_guard<std::mutex> Lock(DispatchMutex); 40 --Outstanding; 41 OutstandingCV.notify_all(); 42 }).detach(); 43 } 44 45 void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() { 46 std::unique_lock<std::mutex> Lock(DispatchMutex); 47 Running = false; 48 OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 49 } 50 #endif 51 52 StringMap<ExecutorAddress> SimpleRemoteEPCServer::defaultBootstrapSymbols() { 53 StringMap<ExecutorAddress> DBS; 54 rt_bootstrap::addTo(DBS); 55 DBS["__llvm_orc_load_dylib"] = ExecutorAddress::fromPtr(&loadDylibWrapper); 56 DBS["__llvm_orc_lookup_symbols"] = 57 ExecutorAddress::fromPtr(&lookupSymbolsWrapper); 58 return DBS; 59 } 60 61 Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 62 SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 63 ExecutorAddress TagAddr, 64 SimpleRemoteEPCArgBytesVector ArgBytes) { 65 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 66 if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 67 return make_error<StringError>("Unexpected opcode", 68 inconvertibleErrorCode()); 69 70 // TODO: Clean detach message? 71 switch (OpC) { 72 case SimpleRemoteEPCOpcode::Setup: 73 return make_error<StringError>("Unexpected Setup opcode", 74 inconvertibleErrorCode()); 75 case SimpleRemoteEPCOpcode::Hangup: 76 return SimpleRemoteEPCTransportClient::EndSession; 77 case SimpleRemoteEPCOpcode::Result: 78 if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 79 return std::move(Err); 80 break; 81 case SimpleRemoteEPCOpcode::CallWrapper: 82 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 83 break; 84 } 85 return ContinueSession; 86 } 87 88 Error SimpleRemoteEPCServer::waitForDisconnect() { 89 std::unique_lock<std::mutex> Lock(ServerStateMutex); 90 ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; }); 91 return std::move(ShutdownErr); 92 } 93 94 void SimpleRemoteEPCServer::handleDisconnect(Error Err) { 95 PendingJITDispatchResultsMap TmpPending; 96 97 { 98 std::lock_guard<std::mutex> Lock(ServerStateMutex); 99 std::swap(TmpPending, PendingJITDispatchResults); 100 RunState = ServerShuttingDown; 101 } 102 103 // Send out-of-band errors to any waiting threads. 104 for (auto &KV : TmpPending) 105 KV.second->set_value( 106 shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 107 108 // TODO: Free attached resources. 109 // 1. Close libraries in DylibHandles. 110 111 // Wait for dispatcher to clear. 112 D->shutdown(); 113 114 std::lock_guard<std::mutex> Lock(ServerStateMutex); 115 ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err)); 116 RunState = ServerShutDown; 117 ShutdownCV.notify_all(); 118 } 119 120 Error SimpleRemoteEPCServer::sendSetupMessage( 121 StringMap<ExecutorAddress> BootstrapSymbols) { 122 123 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 124 125 std::vector<char> SetupPacket; 126 SimpleRemoteEPCExecutorInfo EI; 127 EI.TargetTriple = sys::getProcessTriple(); 128 if (auto PageSize = sys::Process::getPageSize()) 129 EI.PageSize = *PageSize; 130 else 131 return PageSize.takeError(); 132 EI.BootstrapSymbols = std::move(BootstrapSymbols); 133 134 assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) && 135 "Dispatch context name should not be set"); 136 assert(!EI.BootstrapSymbols.count(DispatchFnName) && 137 "Dispatch function name should not be set"); 138 EI.BootstrapSymbols[ExecutorSessionObjectName] = 139 ExecutorAddress::fromPtr(this); 140 EI.BootstrapSymbols[DispatchFnName] = 141 ExecutorAddress::fromPtr(jitDispatchEntry); 142 143 using SPSSerialize = 144 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 145 auto SetupPacketBytes = 146 shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI)); 147 shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size()); 148 if (!SPSSerialize::serialize(OB, EI)) 149 return make_error<StringError>("Could not send setup packet", 150 inconvertibleErrorCode()); 151 152 return T->sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddress(), 153 {SetupPacketBytes.data(), SetupPacketBytes.size()}); 154 } 155 156 Error SimpleRemoteEPCServer::handleResult( 157 uint64_t SeqNo, ExecutorAddress TagAddr, 158 SimpleRemoteEPCArgBytesVector ArgBytes) { 159 std::promise<shared::WrapperFunctionResult> *P = nullptr; 160 { 161 std::lock_guard<std::mutex> Lock(ServerStateMutex); 162 auto I = PendingJITDispatchResults.find(SeqNo); 163 if (I == PendingJITDispatchResults.end()) 164 return make_error<StringError>("No call for sequence number " + 165 Twine(SeqNo), 166 inconvertibleErrorCode()); 167 P = I->second; 168 PendingJITDispatchResults.erase(I); 169 releaseSeqNo(SeqNo); 170 } 171 auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size()); 172 memcpy(R.data(), ArgBytes.data(), ArgBytes.size()); 173 P->set_value(std::move(R)); 174 return Error::success(); 175 } 176 177 void SimpleRemoteEPCServer::handleCallWrapper( 178 uint64_t RemoteSeqNo, ExecutorAddress TagAddr, 179 SimpleRemoteEPCArgBytesVector ArgBytes) { 180 D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() { 181 using WrapperFnTy = 182 shared::detail::CWrapperFunctionResult (*)(const char *, size_t); 183 auto *Fn = TagAddr.toPtr<WrapperFnTy>(); 184 shared::WrapperFunctionResult ResultBytes( 185 Fn(ArgBytes.data(), ArgBytes.size())); 186 if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 187 ExecutorAddress(), 188 {ResultBytes.data(), ResultBytes.size()})) 189 ReportError(std::move(Err)); 190 }); 191 } 192 193 shared::detail::CWrapperFunctionResult 194 SimpleRemoteEPCServer::loadDylibWrapper(const char *ArgData, size_t ArgSize) { 195 return shared::WrapperFunction<shared::SPSLoadDylibSignature>::handle( 196 ArgData, ArgSize, 197 [](ExecutorAddress ExecutorSessionObj, std::string Path, 198 uint64_t Flags) -> Expected<uint64_t> { 199 return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>() 200 ->loadDylib(Path, Flags); 201 }) 202 .release(); 203 } 204 205 shared::detail::CWrapperFunctionResult 206 SimpleRemoteEPCServer::lookupSymbolsWrapper(const char *ArgData, 207 size_t ArgSize) { 208 return shared::WrapperFunction<shared::SPSLookupSymbolsSignature>::handle( 209 ArgData, ArgSize, 210 [](ExecutorAddress ExecutorSessionObj, 211 std::vector<RemoteSymbolLookup> Lookup) { 212 return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>() 213 ->lookupSymbols(Lookup); 214 }) 215 .release(); 216 } 217 218 Expected<tpctypes::DylibHandle> 219 SimpleRemoteEPCServer::loadDylib(const std::string &Path, uint64_t Mode) { 220 std::string ErrMsg; 221 const char *P = Path.empty() ? nullptr : Path.c_str(); 222 auto DL = sys::DynamicLibrary::getPermanentLibrary(P, &ErrMsg); 223 if (!DL.isValid()) 224 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 225 std::lock_guard<std::mutex> Lock(ServerStateMutex); 226 uint64_t Id = Dylibs.size(); 227 Dylibs.push_back(std::move(DL)); 228 return Id; 229 } 230 231 Expected<std::vector<std::vector<ExecutorAddress>>> 232 SimpleRemoteEPCServer::lookupSymbols(const std::vector<RemoteSymbolLookup> &L) { 233 std::vector<std::vector<ExecutorAddress>> Result; 234 235 for (const auto &E : L) { 236 if (E.H >= Dylibs.size()) 237 return make_error<StringError>("Unrecognized handle", 238 inconvertibleErrorCode()); 239 auto &DL = Dylibs[E.H]; 240 Result.push_back({}); 241 242 for (const auto &Sym : E.Symbols) { 243 244 const char *DemangledSymName = Sym.Name.c_str(); 245 #ifdef __APPLE__ 246 if (*DemangledSymName == '_') 247 ++DemangledSymName; 248 #endif 249 250 void *Addr = DL.getAddressOfSymbol(DemangledSymName); 251 if (!Addr && Sym.Required) 252 return make_error<StringError>(Twine("Missing definition for ") + 253 DemangledSymName, 254 inconvertibleErrorCode()); 255 256 Result.back().push_back(ExecutorAddress::fromPtr(Addr)); 257 } 258 } 259 260 return std::move(Result); 261 } 262 263 shared::WrapperFunctionResult 264 SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData, 265 size_t ArgSize) { 266 uint64_t SeqNo; 267 std::promise<shared::WrapperFunctionResult> ResultP; 268 auto ResultF = ResultP.get_future(); 269 { 270 std::lock_guard<std::mutex> Lock(ServerStateMutex); 271 if (RunState != ServerRunning) 272 return shared::WrapperFunctionResult::createOutOfBandError( 273 "jit_dispatch not available (EPC server shut down)"); 274 275 SeqNo = getNextSeqNo(); 276 assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use"); 277 PendingJITDispatchResults[SeqNo] = &ResultP; 278 } 279 280 if (auto Err = 281 T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 282 ExecutorAddress::fromPtr(FnTag), {ArgData, ArgSize})) 283 ReportError(std::move(Err)); 284 285 return ResultF.get(); 286 } 287 288 shared::detail::CWrapperFunctionResult 289 SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag, 290 const char *ArgData, size_t ArgSize) { 291 return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx) 292 ->doJITDispatch(FnTag, ArgData, ArgSize) 293 .release(); 294 } 295 296 } // end namespace orc 297 } // end namespace llvm 298