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