1 //===-- RemoteJITUtils.cpp - Utilities for remote-JITing --------*- C++ -*-===// 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 "RemoteJITUtils.h" 10 11 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 12 #include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h" 13 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" 14 #include "llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h" 15 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h" 16 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" 17 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/Path.h" 19 #include "llvm/Support/ToolOutputFile.h" 20 21 #ifdef LLVM_ON_UNIX 22 #include <netdb.h> 23 #include <netinet/in.h> 24 #include <sys/socket.h> 25 #include <unistd.h> 26 #endif // LLVM_ON_UNIX 27 28 using namespace llvm; 29 using namespace llvm::orc; 30 31 namespace llvm { 32 namespace orc { 33 34 class RemoteExecutorProcessControl 35 : public OrcRPCExecutorProcessControlBase< 36 shared::MultiThreadedRPCEndpoint<JITLinkExecutor::RPCChannel>> { 37 public: 38 using RPCChannel = JITLinkExecutor::RPCChannel; 39 using RPCEndpoint = shared::MultiThreadedRPCEndpoint<RPCChannel>; 40 41 private: 42 using ThisT = RemoteExecutorProcessControl; 43 using BaseT = OrcRPCExecutorProcessControlBase<RPCEndpoint>; 44 using MemoryAccess = OrcRPCEPCMemoryAccess<ThisT>; 45 using MemoryManager = OrcRPCEPCJITLinkMemoryManager<ThisT>; 46 47 public: 48 using BaseT::initializeORCRPCEPCBase; 49 50 RemoteExecutorProcessControl(ExecutionSession &ES, 51 std::unique_ptr<RPCChannel> Channel, 52 std::unique_ptr<RPCEndpoint> Endpoint); 53 54 void initializeMemoryManagement(); 55 Error disconnect() override; 56 57 private: 58 std::unique_ptr<RPCChannel> Channel; 59 std::unique_ptr<RPCEndpoint> Endpoint; 60 std::unique_ptr<MemoryAccess> OwnedMemAccess; 61 std::unique_ptr<MemoryManager> OwnedMemMgr; 62 std::atomic<bool> Finished{false}; 63 std::thread ListenerThread; 64 }; 65 66 RemoteExecutorProcessControl::RemoteExecutorProcessControl( 67 ExecutionSession &ES, std::unique_ptr<RPCChannel> Channel, 68 std::unique_ptr<RPCEndpoint> Endpoint) 69 : BaseT(ES.getSymbolStringPool(), *Endpoint, 70 [&ES](Error Err) { ES.reportError(std::move(Err)); }), 71 Channel(std::move(Channel)), Endpoint(std::move(Endpoint)) { 72 73 ListenerThread = std::thread([&]() { 74 while (!Finished) { 75 if (auto Err = this->Endpoint->handleOne()) { 76 reportError(std::move(Err)); 77 return; 78 } 79 } 80 }); 81 } 82 83 void RemoteExecutorProcessControl::initializeMemoryManagement() { 84 OwnedMemAccess = std::make_unique<MemoryAccess>(*this); 85 OwnedMemMgr = std::make_unique<MemoryManager>(*this); 86 87 // Base class needs non-owning access. 88 MemAccess = OwnedMemAccess.get(); 89 MemMgr = OwnedMemMgr.get(); 90 } 91 92 Error RemoteExecutorProcessControl::disconnect() { 93 std::promise<MSVCPError> P; 94 auto F = P.get_future(); 95 auto Err = closeConnection([&](Error Err) -> Error { 96 P.set_value(std::move(Err)); 97 Finished = true; 98 return Error::success(); 99 }); 100 ListenerThread.join(); 101 return joinErrors(std::move(Err), F.get()); 102 } 103 104 } // namespace orc 105 } // namespace llvm 106 107 JITLinkExecutor::JITLinkExecutor() = default; 108 JITLinkExecutor::~JITLinkExecutor() = default; 109 110 Expected<std::unique_ptr<ObjectLayer>> 111 JITLinkExecutor::operator()(ExecutionSession &ES, const Triple &TT) { 112 return std::make_unique<ObjectLinkingLayer>(ES, EPC->getMemMgr()); 113 } 114 115 Error JITLinkExecutor::addDebugSupport(ObjectLayer &ObjLayer) { 116 auto Registrar = createJITLoaderGDBRegistrar(*EPC); 117 if (!Registrar) 118 return Registrar.takeError(); 119 120 cast<ObjectLinkingLayer>(&ObjLayer)->addPlugin( 121 std::make_unique<DebugObjectManagerPlugin>(ObjLayer.getExecutionSession(), 122 std::move(*Registrar))); 123 124 return Error::success(); 125 } 126 127 Expected<std::unique_ptr<DefinitionGenerator>> 128 JITLinkExecutor::loadDylib(StringRef RemotePath) { 129 if (auto Handle = EPC->loadDylib(RemotePath.data())) 130 return std::make_unique<EPCDynamicLibrarySearchGenerator>(*EPC, *Handle); 131 else 132 return Handle.takeError(); 133 } 134 135 Expected<int> JITLinkExecutor::runAsMain(JITEvaluatedSymbol MainSym, 136 ArrayRef<std::string> Args) { 137 return EPC->runAsMain(MainSym.getAddress(), Args); 138 } 139 140 Error JITLinkExecutor::disconnect() { return EPC->disconnect(); } 141 142 static std::string defaultPath(const char *HostArgv0, StringRef ExecutorName) { 143 // This just needs to be some symbol in the binary; C++ doesn't 144 // allow taking the address of ::main however. 145 void *P = (void *)(intptr_t)defaultPath; 146 SmallString<256> FullName(sys::fs::getMainExecutable(HostArgv0, P)); 147 sys::path::remove_filename(FullName); 148 sys::path::append(FullName, ExecutorName); 149 return FullName.str().str(); 150 } 151 152 Expected<std::unique_ptr<ChildProcessJITLinkExecutor>> 153 JITLinkExecutor::FindLocal(const char *HostArgv) { 154 std::string BestGuess = defaultPath(HostArgv, "llvm-jitlink-executor"); 155 auto Executor = CreateLocal(BestGuess); 156 if (!Executor) { 157 consumeError(Executor.takeError()); 158 return make_error<StringError>( 159 formatv("Unable to find usable executor: {0}", BestGuess), 160 inconvertibleErrorCode()); 161 } 162 return Executor; 163 } 164 165 Expected<std::unique_ptr<ChildProcessJITLinkExecutor>> 166 JITLinkExecutor::CreateLocal(std::string ExecutablePath) { 167 if (!sys::fs::can_execute(ExecutablePath)) 168 return make_error<StringError>( 169 formatv("Specified executor invalid: {0}", ExecutablePath), 170 inconvertibleErrorCode()); 171 return std::unique_ptr<ChildProcessJITLinkExecutor>( 172 new ChildProcessJITLinkExecutor(std::move(ExecutablePath))); 173 } 174 175 TCPSocketJITLinkExecutor::TCPSocketJITLinkExecutor( 176 std::unique_ptr<RemoteExecutorProcessControl> EPC) { 177 this->EPC = std::move(EPC); 178 } 179 180 #ifndef LLVM_ON_UNIX 181 182 // FIXME: Add support for Windows. 183 Error ChildProcessJITLinkExecutor::launch(ExecutionSession &ES) { 184 return make_error<StringError>( 185 "Remote JITing not yet supported on non-unix platforms", 186 inconvertibleErrorCode()); 187 } 188 189 // FIXME: Add support for Windows. 190 Expected<std::unique_ptr<TCPSocketJITLinkExecutor>> 191 JITLinkExecutor::ConnectTCPSocket(StringRef NetworkAddress, 192 ExecutionSession &ES) { 193 return make_error<StringError>( 194 "Remote JITing not yet supported on non-unix platforms", 195 inconvertibleErrorCode()); 196 } 197 198 #else 199 200 Error ChildProcessJITLinkExecutor::launch(ExecutionSession &ES) { 201 constexpr int ReadEnd = 0; 202 constexpr int WriteEnd = 1; 203 204 // Pipe FDs. 205 int ToExecutor[2]; 206 int FromExecutor[2]; 207 208 // Create pipes to/from the executor.. 209 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0) 210 return make_error<StringError>("Unable to create pipe for executor", 211 inconvertibleErrorCode()); 212 213 ProcessID = fork(); 214 if (ProcessID == 0) { 215 // In the child... 216 217 // Close the parent ends of the pipes 218 close(ToExecutor[WriteEnd]); 219 close(FromExecutor[ReadEnd]); 220 221 // Execute the child process. 222 std::unique_ptr<char[]> ExecPath, FDSpecifier; 223 { 224 ExecPath = std::make_unique<char[]>(ExecutablePath.size() + 1); 225 strcpy(ExecPath.get(), ExecutablePath.data()); 226 227 std::string FDSpecifierStr("filedescs="); 228 FDSpecifierStr += utostr(ToExecutor[ReadEnd]); 229 FDSpecifierStr += ','; 230 FDSpecifierStr += utostr(FromExecutor[WriteEnd]); 231 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1); 232 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str()); 233 } 234 235 char *const Args[] = {ExecPath.get(), FDSpecifier.get(), nullptr}; 236 int RC = execvp(ExecPath.get(), Args); 237 if (RC != 0) 238 return make_error<StringError>( 239 "Unable to launch out-of-process executor '" + ExecutablePath + "'\n", 240 inconvertibleErrorCode()); 241 242 llvm_unreachable("Fork won't return in success case"); 243 } 244 // else we're the parent... 245 246 // Close the child ends of the pipes 247 close(ToExecutor[ReadEnd]); 248 close(FromExecutor[WriteEnd]); 249 250 auto Channel = 251 std::make_unique<RPCChannel>(FromExecutor[ReadEnd], ToExecutor[WriteEnd]); 252 auto Endpoint = std::make_unique<RemoteExecutorProcessControl::RPCEndpoint>( 253 *Channel, true); 254 255 EPC = std::make_unique<RemoteExecutorProcessControl>(ES, std::move(Channel), 256 std::move(Endpoint)); 257 258 if (auto Err = EPC->initializeORCRPCEPCBase()) 259 return joinErrors(std::move(Err), EPC->disconnect()); 260 261 EPC->initializeMemoryManagement(); 262 263 shared::registerStringError<RPCChannel>(); 264 return Error::success(); 265 } 266 267 static Expected<int> connectTCPSocketImpl(std::string Host, 268 std::string PortStr) { 269 addrinfo *AI; 270 addrinfo Hints{}; 271 Hints.ai_family = AF_INET; 272 Hints.ai_socktype = SOCK_STREAM; 273 Hints.ai_flags = AI_NUMERICSERV; 274 275 if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI)) 276 return make_error<StringError>( 277 formatv("address resolution failed ({0})", gai_strerror(EC)), 278 inconvertibleErrorCode()); 279 280 // Cycle through the returned addrinfo structures and connect to the first 281 // reachable endpoint. 282 int SockFD; 283 addrinfo *Server; 284 for (Server = AI; Server != nullptr; Server = Server->ai_next) { 285 // If socket fails, maybe it's because the address family is not supported. 286 // Skip to the next addrinfo structure. 287 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) 288 continue; 289 290 // If connect works, we exit the loop with a working socket. 291 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0) 292 break; 293 294 close(SockFD); 295 } 296 freeaddrinfo(AI); 297 298 // Did we reach the end of the loop without connecting to a valid endpoint? 299 if (Server == nullptr) 300 return make_error<StringError>("invalid hostname", 301 inconvertibleErrorCode()); 302 303 return SockFD; 304 } 305 306 Expected<std::unique_ptr<TCPSocketJITLinkExecutor>> 307 JITLinkExecutor::ConnectTCPSocket(StringRef NetworkAddress, 308 ExecutionSession &ES) { 309 auto CreateErr = [NetworkAddress](StringRef Details) { 310 return make_error<StringError>( 311 formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress, 312 Details), 313 inconvertibleErrorCode()); 314 }; 315 316 StringRef Host, PortStr; 317 std::tie(Host, PortStr) = NetworkAddress.split(':'); 318 if (Host.empty()) 319 return CreateErr("host name cannot be empty"); 320 if (PortStr.empty()) 321 return CreateErr("port cannot be empty"); 322 int Port = 0; 323 if (PortStr.getAsInteger(10, Port)) 324 return CreateErr("port number is not a valid integer"); 325 326 Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str()); 327 if (!SockFD) 328 return CreateErr(toString(SockFD.takeError())); 329 330 auto Channel = std::make_unique<RPCChannel>(*SockFD, *SockFD); 331 auto Endpoint = std::make_unique<RemoteExecutorProcessControl::RPCEndpoint>( 332 *Channel, true); 333 334 auto EPC = std::make_unique<RemoteExecutorProcessControl>( 335 ES, std::move(Channel), std::move(Endpoint)); 336 337 if (auto Err = EPC->initializeORCRPCEPCBase()) 338 return joinErrors(std::move(Err), EPC->disconnect()); 339 340 EPC->initializeMemoryManagement(); 341 shared::registerStringError<RPCChannel>(); 342 343 return std::unique_ptr<TCPSocketJITLinkExecutor>( 344 new TCPSocketJITLinkExecutor(std::move(EPC))); 345 } 346 347 #endif 348