1 //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===// 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/SimpleRemoteEPC.h" 10 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h" 11 #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h" 12 #include "llvm/Support/FormatVariadic.h" 13 14 #define DEBUG_TYPE "orc" 15 16 namespace llvm { 17 namespace orc { 18 namespace shared { 19 20 template <> 21 class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement, 22 SymbolLookupSet::value_type> { 23 public: 24 static size_t size(const SymbolLookupSet::value_type &V) { 25 return SPSArgList<SPSString, bool>::size( 26 *V.first, V.second == SymbolLookupFlags::RequiredSymbol); 27 } 28 29 static bool serialize(SPSOutputBuffer &OB, 30 const SymbolLookupSet::value_type &V) { 31 return SPSArgList<SPSString, bool>::serialize( 32 OB, *V.first, V.second == SymbolLookupFlags::RequiredSymbol); 33 } 34 }; 35 36 template <> 37 class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement, 38 SymbolLookupSet> { 39 public: 40 static constexpr bool available = true; 41 }; 42 43 template <> 44 class SPSSerializationTraits<SPSRemoteSymbolLookup, 45 ExecutorProcessControl::LookupRequest> { 46 using MemberSerialization = 47 SPSArgList<SPSExecutorAddress, SPSRemoteSymbolLookupSet>; 48 49 public: 50 static size_t size(const ExecutorProcessControl::LookupRequest &LR) { 51 return MemberSerialization::size(ExecutorAddress(LR.Handle), LR.Symbols); 52 } 53 54 static bool serialize(SPSOutputBuffer &OB, 55 const ExecutorProcessControl::LookupRequest &LR) { 56 return MemberSerialization::serialize(OB, ExecutorAddress(LR.Handle), 57 LR.Symbols); 58 } 59 }; 60 61 } // end namespace shared 62 63 SimpleRemoteEPC::~SimpleRemoteEPC() { 64 assert(Disconnected && "Destroyed without disconnection"); 65 } 66 67 Error SimpleRemoteEPC::setup(std::unique_ptr<SimpleRemoteEPCTransport> T, 68 const SimpleRemoteEPCExecutorInfo &EI) { 69 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 70 LLVM_DEBUG({ 71 dbgs() << "SimpleRemoteEPC received setup message:\n" 72 << " Triple: " << EI.TargetTriple << "\n" 73 << " Page size: " << EI.PageSize << "\n" 74 << " Bootstrap symbols:\n"; 75 for (const auto &KV : EI.BootstrapSymbols) 76 dbgs() << " " << KV.first() << ": " 77 << formatv("{0:x16}", KV.second.getValue()) << "\n"; 78 }); 79 this->T = std::move(T); 80 TargetTriple = Triple(EI.TargetTriple); 81 PageSize = EI.PageSize; 82 83 if (auto Err = EI.getBootstrapSymbols( 84 {{JDI.JITDispatchContextAddress, ExecutorSessionObjectName}, 85 {JDI.JITDispatchFunctionAddress, DispatchFnName}, 86 {LoadDylibAddr, "__llvm_orc_load_dylib"}, 87 {LookupSymbolsAddr, "__llvm_orc_lookup_symbols"}, 88 {RunAsMainAddr, "__llvm_orc_run_as_main"}})) 89 return Err; 90 91 if (!MemMgr) 92 if (auto Err = setupDefaultMemoryManager(EI)) 93 return Err; 94 if (!MemAccess) 95 if (auto Err = setupDefaultMemoryAccess(EI)) 96 return Err; 97 98 return Error::success(); 99 } 100 101 Expected<tpctypes::DylibHandle> 102 SimpleRemoteEPC::loadDylib(const char *DylibPath) { 103 Expected<tpctypes::DylibHandle> H((tpctypes::DylibHandle())); 104 if (auto Err = callSPSWrapper<shared::SPSLoadDylibSignature>( 105 LoadDylibAddr.getValue(), H, JDI.JITDispatchContextAddress, 106 StringRef(DylibPath), (uint64_t)0)) 107 return std::move(Err); 108 return H; 109 } 110 111 Expected<std::vector<tpctypes::LookupResult>> 112 SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) { 113 Expected<std::vector<tpctypes::LookupResult>> R( 114 (std::vector<tpctypes::LookupResult>())); 115 116 if (auto Err = callSPSWrapper<shared::SPSLookupSymbolsSignature>( 117 LookupSymbolsAddr.getValue(), R, JDI.JITDispatchContextAddress, 118 Request)) 119 return std::move(Err); 120 return R; 121 } 122 123 Expected<int32_t> SimpleRemoteEPC::runAsMain(JITTargetAddress MainFnAddr, 124 ArrayRef<std::string> Args) { 125 int64_t Result = 0; 126 if (auto Err = callSPSWrapper<shared::SPSRunAsMainSignature>( 127 RunAsMainAddr.getValue(), Result, ExecutorAddress(MainFnAddr), Args)) 128 return std::move(Err); 129 return Result; 130 } 131 132 void SimpleRemoteEPC::callWrapperAsync(SendResultFunction OnComplete, 133 JITTargetAddress WrapperFnAddr, 134 ArrayRef<char> ArgBuffer) { 135 uint64_t SeqNo; 136 { 137 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 138 SeqNo = getNextSeqNo(); 139 assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use"); 140 PendingCallWrapperResults[SeqNo] = std::move(OnComplete); 141 } 142 143 if (auto Err = T->sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 144 ExecutorAddress(WrapperFnAddr), ArgBuffer)) { 145 getExecutionSession().reportError(std::move(Err)); 146 } 147 } 148 149 Error SimpleRemoteEPC::disconnect() { 150 Disconnected = true; 151 T->disconnect(); 152 return Error::success(); 153 } 154 155 Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 156 SimpleRemoteEPC::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 157 ExecutorAddress TagAddr, 158 SimpleRemoteEPCArgBytesVector ArgBytes) { 159 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 160 if (static_cast<UT>(OpC) < static_cast<UT>(SimpleRemoteEPCOpcode::FirstOpC) || 161 static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 162 return make_error<StringError>("Unexpected opcode", 163 inconvertibleErrorCode()); 164 165 switch (OpC) { 166 case SimpleRemoteEPCOpcode::Setup: 167 if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes))) 168 return std::move(Err); 169 break; 170 case SimpleRemoteEPCOpcode::Hangup: 171 // FIXME: Put EPC into 'detached' state. 172 return SimpleRemoteEPCTransportClient::EndSession; 173 case SimpleRemoteEPCOpcode::Result: 174 if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 175 return std::move(Err); 176 break; 177 case SimpleRemoteEPCOpcode::CallWrapper: 178 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 179 break; 180 } 181 return ContinueSession; 182 } 183 184 void SimpleRemoteEPC::handleDisconnect(Error Err) { 185 PendingCallWrapperResultsMap TmpPending; 186 187 { 188 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 189 std::swap(TmpPending, PendingCallWrapperResults); 190 } 191 192 for (auto &KV : TmpPending) 193 KV.second( 194 shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 195 196 if (Err) { 197 // FIXME: Move ReportError to EPC. 198 if (ES) 199 ES->reportError(std::move(Err)); 200 else 201 logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPC: "); 202 } 203 } 204 205 void SimpleRemoteEPC::setMemoryManager( 206 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 207 OwnedMemMgr = std::move(MemMgr); 208 this->MemMgr = OwnedMemMgr.get(); 209 } 210 211 void SimpleRemoteEPC::setMemoryAccess(std::unique_ptr<MemoryAccess> MemAccess) { 212 OwnedMemAccess = std::move(MemAccess); 213 this->MemAccess = OwnedMemAccess.get(); 214 } 215 216 Error SimpleRemoteEPC::setupDefaultMemoryManager( 217 const SimpleRemoteEPCExecutorInfo &EI) { 218 219 EPCGenericJITLinkMemoryManager::FuncAddrs FAs; 220 221 if (auto Err = EI.getBootstrapSymbols( 222 {{FAs.Reserve, "__llvm_orc_memory_reserve"}, 223 {FAs.Finalize, "__llvm_orc_memory_finalize"}, 224 {FAs.Deallocate, "__llvm_orc_memory_deallocate"}})) 225 return Err; 226 227 setMemoryManager( 228 std::make_unique<EPCGenericJITLinkMemoryManager>(*this, FAs)); 229 return Error::success(); 230 } 231 232 Error SimpleRemoteEPC::setupDefaultMemoryAccess( 233 const SimpleRemoteEPCExecutorInfo &EI) { 234 235 return Error::success(); 236 } 237 238 Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddress TagAddr, 239 SimpleRemoteEPCArgBytesVector ArgBytes) { 240 if (SeqNo != 0) 241 return make_error<StringError>("Setup packet SeqNo not zero", 242 inconvertibleErrorCode()); 243 244 if (TagAddr) 245 return make_error<StringError>("Setup packet TagAddr not zero", 246 inconvertibleErrorCode()); 247 248 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 249 auto I = PendingCallWrapperResults.find(0); 250 assert(PendingCallWrapperResults.size() == 1 && 251 I != PendingCallWrapperResults.end() && 252 "Setup message handler not connectly set up"); 253 auto SetupMsgHandler = std::move(I->second); 254 PendingCallWrapperResults.erase(I); 255 256 auto WFR = 257 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 258 SetupMsgHandler(std::move(WFR)); 259 return Error::success(); 260 } 261 262 void SimpleRemoteEPC::prepareToReceiveSetupMessage( 263 std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> &ExecInfoP) { 264 PendingCallWrapperResults[0] = 265 [&](shared::WrapperFunctionResult SetupMsgBytes) { 266 if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) { 267 ExecInfoP.set_value( 268 make_error<StringError>(ErrMsg, inconvertibleErrorCode())); 269 return; 270 } 271 using SPSSerialize = 272 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 273 shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size()); 274 SimpleRemoteEPCExecutorInfo EI; 275 if (SPSSerialize::deserialize(IB, EI)) 276 ExecInfoP.set_value(EI); 277 else 278 ExecInfoP.set_value(make_error<StringError>( 279 "Could not deserialize setup message", inconvertibleErrorCode())); 280 }; 281 } 282 283 Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddress TagAddr, 284 SimpleRemoteEPCArgBytesVector ArgBytes) { 285 SendResultFunction SendResult; 286 287 if (TagAddr) 288 return make_error<StringError>("Unexpected TagAddr in result message", 289 inconvertibleErrorCode()); 290 291 { 292 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex); 293 auto I = PendingCallWrapperResults.find(SeqNo); 294 if (I == PendingCallWrapperResults.end()) 295 return make_error<StringError>("No call for sequence number " + 296 Twine(SeqNo), 297 inconvertibleErrorCode()); 298 SendResult = std::move(I->second); 299 PendingCallWrapperResults.erase(I); 300 releaseSeqNo(SeqNo); 301 } 302 303 auto WFR = 304 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size()); 305 SendResult(std::move(WFR)); 306 return Error::success(); 307 } 308 309 void SimpleRemoteEPC::handleCallWrapper( 310 uint64_t RemoteSeqNo, ExecutorAddress TagAddr, 311 SimpleRemoteEPCArgBytesVector ArgBytes) { 312 assert(ES && "No ExecutionSession attached"); 313 ES->runJITDispatchHandler( 314 [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) { 315 if (auto Err = 316 T->sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 317 ExecutorAddress(), {WFR.data(), WFR.size()})) 318 getExecutionSession().reportError(std::move(Err)); 319 }, 320 TagAddr.getValue(), ArgBytes); 321 } 322 323 } // end namespace orc 324 } // end namespace llvm 325