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