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 void SimpleRemoteEPCServer::ThreadDispatcher::dispatch( 114 unique_function<void()> Work) { 115 { 116 std::lock_guard<std::mutex> Lock(DispatchMutex); 117 if (!Running) 118 return; 119 ++Outstanding; 120 } 121 122 std::thread([this, Work = std::move(Work)]() mutable { 123 Work(); 124 std::lock_guard<std::mutex> Lock(DispatchMutex); 125 --Outstanding; 126 OutstandingCV.notify_all(); 127 }).detach(); 128 } 129 130 void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() { 131 std::unique_lock<std::mutex> Lock(DispatchMutex); 132 Running = false; 133 OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 134 } 135 136 StringMap<ExecutorAddress> SimpleRemoteEPCServer::defaultBootstrapSymbols() { 137 StringMap<ExecutorAddress> DBS; 138 139 DBS["__llvm_orc_memory_reserve"] = ExecutorAddress::fromPtr(&reserveWrapper); 140 DBS["__llvm_orc_memory_finalize"] = 141 ExecutorAddress::fromPtr(&finalizeWrapper); 142 DBS["__llvm_orc_memory_deallocate"] = 143 ExecutorAddress::fromPtr(&deallocateWrapper); 144 DBS["__llvm_orc_memory_write_uint8s"] = ExecutorAddress::fromPtr( 145 &writeUIntsWrapper<tpctypes::UInt8Write, 146 shared::SPSMemoryAccessUInt8Write>); 147 DBS["__llvm_orc_memory_write_uint16s"] = ExecutorAddress::fromPtr( 148 &writeUIntsWrapper<tpctypes::UInt16Write, 149 shared::SPSMemoryAccessUInt16Write>); 150 DBS["__llvm_orc_memory_write_uint32s"] = ExecutorAddress::fromPtr( 151 &writeUIntsWrapper<tpctypes::UInt32Write, 152 shared::SPSMemoryAccessUInt32Write>); 153 DBS["__llvm_orc_memory_write_uint64s"] = ExecutorAddress::fromPtr( 154 &writeUIntsWrapper<tpctypes::UInt64Write, 155 shared::SPSMemoryAccessUInt64Write>); 156 DBS["__llvm_orc_memory_write_buffers"] = 157 ExecutorAddress::fromPtr(&writeBuffersWrapper); 158 DBS["__llvm_orc_run_as_main"] = ExecutorAddress::fromPtr(&runAsMainWrapper); 159 DBS["__llvm_orc_load_dylib"] = ExecutorAddress::fromPtr(&loadDylibWrapper); 160 DBS["__llvm_orc_lookup_symbols"] = 161 ExecutorAddress::fromPtr(&lookupSymbolsWrapper); 162 return DBS; 163 } 164 165 Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 166 SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 167 ExecutorAddress TagAddr, 168 SimpleRemoteEPCArgBytesVector ArgBytes) { 169 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 170 if (static_cast<UT>(OpC) < static_cast<UT>(SimpleRemoteEPCOpcode::FirstOpC) || 171 static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 172 return make_error<StringError>("Unexpected opcode", 173 inconvertibleErrorCode()); 174 175 // TODO: Clean detach message? 176 switch (OpC) { 177 case SimpleRemoteEPCOpcode::Setup: 178 return make_error<StringError>("Unexpected Setup opcode", 179 inconvertibleErrorCode()); 180 case SimpleRemoteEPCOpcode::Hangup: 181 return SimpleRemoteEPCTransportClient::EndSession; 182 case SimpleRemoteEPCOpcode::Result: 183 if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 184 return std::move(Err); 185 break; 186 case SimpleRemoteEPCOpcode::CallWrapper: 187 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 188 break; 189 } 190 return ContinueSession; 191 } 192 193 Error SimpleRemoteEPCServer::waitForDisconnect() { 194 std::unique_lock<std::mutex> Lock(ServerStateMutex); 195 ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; }); 196 return std::move(ShutdownErr); 197 } 198 199 void SimpleRemoteEPCServer::handleDisconnect(Error Err) { 200 PendingJITDispatchResultsMap TmpPending; 201 202 { 203 std::lock_guard<std::mutex> Lock(ServerStateMutex); 204 std::swap(TmpPending, PendingJITDispatchResults); 205 RunState = ServerShuttingDown; 206 } 207 208 // Send out-of-band errors to any waiting threads. 209 for (auto &KV : TmpPending) 210 KV.second->set_value( 211 shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 212 213 // TODO: Free attached resources. 214 // 1. Close libraries in DylibHandles. 215 216 // Wait for dispatcher to clear. 217 D->shutdown(); 218 219 std::lock_guard<std::mutex> Lock(ServerStateMutex); 220 ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err)); 221 RunState = ServerShutDown; 222 ShutdownCV.notify_all(); 223 } 224 225 Error SimpleRemoteEPCServer::sendSetupMessage( 226 StringMap<ExecutorAddress> BootstrapSymbols) { 227 228 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 229 230 std::vector<char> SetupPacket; 231 SimpleRemoteEPCExecutorInfo EI; 232 EI.TargetTriple = sys::getProcessTriple(); 233 if (auto PageSize = sys::Process::getPageSize()) 234 EI.PageSize = *PageSize; 235 else 236 return PageSize.takeError(); 237 EI.BootstrapSymbols = std::move(BootstrapSymbols); 238 239 assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) && 240 "Dispatch context name should not be set"); 241 assert(!EI.BootstrapSymbols.count(DispatchFnName) && 242 "Dispatch function name should not be set"); 243 EI.BootstrapSymbols[ExecutorSessionObjectName] = 244 ExecutorAddress::fromPtr(this); 245 EI.BootstrapSymbols[DispatchFnName] = 246 ExecutorAddress::fromPtr(jitDispatchEntry); 247 248 using SPSSerialize = 249 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 250 auto SetupPacketBytes = 251 shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI)); 252 shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size()); 253 if (!SPSSerialize::serialize(OB, EI)) 254 return make_error<StringError>("Could not send setup packet", 255 inconvertibleErrorCode()); 256 257 return T->sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddress(), 258 {SetupPacketBytes.data(), SetupPacketBytes.size()}); 259 } 260 261 Error SimpleRemoteEPCServer::handleResult( 262 uint64_t SeqNo, ExecutorAddress TagAddr, 263 SimpleRemoteEPCArgBytesVector ArgBytes) { 264 std::promise<shared::WrapperFunctionResult> *P = nullptr; 265 { 266 std::lock_guard<std::mutex> Lock(ServerStateMutex); 267 auto I = PendingJITDispatchResults.find(SeqNo); 268 if (I == PendingJITDispatchResults.end()) 269 return make_error<StringError>("No call for sequence number " + 270 Twine(SeqNo), 271 inconvertibleErrorCode()); 272 P = I->second; 273 PendingJITDispatchResults.erase(I); 274 releaseSeqNo(SeqNo); 275 } 276 auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size()); 277 memcpy(R.data(), ArgBytes.data(), ArgBytes.size()); 278 P->set_value(std::move(R)); 279 return Error::success(); 280 } 281 282 void SimpleRemoteEPCServer::handleCallWrapper( 283 uint64_t RemoteSeqNo, ExecutorAddress TagAddr, 284 SimpleRemoteEPCArgBytesVector ArgBytes) { 285 D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() { 286 using WrapperFnTy = 287 shared::detail::CWrapperFunctionResult (*)(const char *, size_t); 288 auto *Fn = TagAddr.toPtr<WrapperFnTy>(); 289 shared::WrapperFunctionResult ResultBytes( 290 Fn(ArgBytes.data(), ArgBytes.size())); 291 if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 292 ExecutorAddress(), 293 {ResultBytes.data(), ResultBytes.size()})) 294 ReportError(std::move(Err)); 295 }); 296 } 297 298 shared::detail::CWrapperFunctionResult 299 SimpleRemoteEPCServer::loadDylibWrapper(const char *ArgData, size_t ArgSize) { 300 return shared::WrapperFunction<shared::SPSLoadDylibSignature>::handle( 301 ArgData, ArgSize, 302 [](ExecutorAddress ExecutorSessionObj, std::string Path, 303 uint64_t Flags) -> Expected<uint64_t> { 304 return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>() 305 ->loadDylib(Path, Flags); 306 }) 307 .release(); 308 } 309 310 shared::detail::CWrapperFunctionResult 311 SimpleRemoteEPCServer::lookupSymbolsWrapper(const char *ArgData, 312 size_t ArgSize) { 313 return shared::WrapperFunction<shared::SPSLookupSymbolsSignature>::handle( 314 ArgData, ArgSize, 315 [](ExecutorAddress ExecutorSessionObj, 316 std::vector<RemoteSymbolLookup> Lookup) { 317 return ExecutorSessionObj.toPtr<SimpleRemoteEPCServer *>() 318 ->lookupSymbols(Lookup); 319 }) 320 .release(); 321 } 322 323 Expected<tpctypes::DylibHandle> 324 SimpleRemoteEPCServer::loadDylib(const std::string &Path, uint64_t Mode) { 325 std::string ErrMsg; 326 const char *P = Path.empty() ? nullptr : Path.c_str(); 327 auto DL = sys::DynamicLibrary::getPermanentLibrary(P, &ErrMsg); 328 if (!DL.isValid()) 329 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 330 std::lock_guard<std::mutex> Lock(ServerStateMutex); 331 uint64_t Id = Dylibs.size(); 332 Dylibs.push_back(std::move(DL)); 333 return Id; 334 } 335 336 Expected<std::vector<std::vector<ExecutorAddress>>> 337 SimpleRemoteEPCServer::lookupSymbols(const std::vector<RemoteSymbolLookup> &L) { 338 std::vector<std::vector<ExecutorAddress>> Result; 339 340 for (const auto &E : L) { 341 if (E.H >= Dylibs.size()) 342 return make_error<StringError>("Unrecognized handle", 343 inconvertibleErrorCode()); 344 auto &DL = Dylibs[E.H]; 345 Result.push_back({}); 346 347 for (const auto &Sym : E.Symbols) { 348 349 const char *DemangledSymName = Sym.Name.c_str(); 350 #ifdef __APPLE__ 351 if (*DemangledSymName == '_') 352 ++DemangledSymName; 353 #endif 354 355 void *Addr = DL.getAddressOfSymbol(DemangledSymName); 356 if (!Addr && Sym.Required) 357 return make_error<StringError>(Twine("Missing definition for ") + 358 DemangledSymName, 359 inconvertibleErrorCode()); 360 361 Result.back().push_back(ExecutorAddress::fromPtr(Addr)); 362 } 363 } 364 365 return std::move(Result); 366 } 367 368 shared::WrapperFunctionResult 369 SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData, 370 size_t ArgSize) { 371 uint64_t SeqNo; 372 std::promise<shared::WrapperFunctionResult> ResultP; 373 auto ResultF = ResultP.get_future(); 374 { 375 std::lock_guard<std::mutex> Lock(ServerStateMutex); 376 if (RunState != ServerRunning) 377 return shared::WrapperFunctionResult::createOutOfBandError( 378 "jit_dispatch not available (EPC server shut down)"); 379 380 SeqNo = getNextSeqNo(); 381 assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use"); 382 PendingJITDispatchResults[SeqNo] = &ResultP; 383 } 384 385 if (auto Err = 386 T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 387 ExecutorAddress::fromPtr(FnTag), {ArgData, ArgSize})) 388 ReportError(std::move(Err)); 389 390 return ResultF.get(); 391 } 392 393 shared::detail::CWrapperFunctionResult 394 SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag, 395 const char *ArgData, size_t ArgSize) { 396 return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx) 397 ->doJITDispatch(FnTag, ArgData, ArgSize) 398 .release(); 399 } 400 401 } // end namespace orc 402 } // end namespace llvm 403