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/Shared/SimpleRemoteEPCUtils.h" 15 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" 16 #include "llvm/Support/FileSystem.h" 17 #include "llvm/Support/Path.h" 18 19 #ifdef LLVM_ON_UNIX 20 #include <netdb.h> 21 #include <netinet/in.h> 22 #include <sys/socket.h> 23 #include <unistd.h> 24 #endif // LLVM_ON_UNIX 25 26 using namespace llvm; 27 using namespace llvm::orc; 28 29 Error addDebugSupport(ObjectLayer &ObjLayer) { 30 ExecutionSession &ES = ObjLayer.getExecutionSession(); 31 auto Registrar = createJITLoaderGDBRegistrar(ES); 32 if (!Registrar) 33 return Registrar.takeError(); 34 35 auto *ObjLinkingLayer = cast<ObjectLinkingLayer>(&ObjLayer); 36 if (!ObjLinkingLayer) 37 return createStringError(inconvertibleErrorCode(), 38 "No debug support for given object layer type"); 39 40 ObjLinkingLayer->addPlugin( 41 std::make_unique<DebugObjectManagerPlugin>(ES, std::move(*Registrar))); 42 return Error::success(); 43 } 44 45 Expected<std::unique_ptr<DefinitionGenerator>> 46 loadDylib(ExecutionSession &ES, StringRef RemotePath) { 47 if (auto Handle = ES.getExecutorProcessControl().loadDylib(RemotePath.data())) 48 return std::make_unique<EPCDynamicLibrarySearchGenerator>(ES, *Handle); 49 else 50 return Handle.takeError(); 51 } 52 53 static void findLocalExecutorHelper() {} 54 std::string findLocalExecutor(const char *HostArgv0) { 55 // This just needs to be some static symbol in the binary; C++ doesn't 56 // allow taking the address of ::main however. 57 uintptr_t UIntPtr = reinterpret_cast<uintptr_t>(&findLocalExecutorHelper); 58 void *VoidPtr = reinterpret_cast<void *>(UIntPtr); 59 SmallString<256> FullName(sys::fs::getMainExecutable(HostArgv0, VoidPtr)); 60 sys::path::remove_filename(FullName); 61 sys::path::append(FullName, "llvm-jitlink-executor"); 62 return FullName.str().str(); 63 } 64 65 #ifndef LLVM_ON_UNIX 66 67 // FIXME: Add support for Windows. 68 Expected<std::pair<std::unique_ptr<SimpleRemoteEPC>, uint64_t>> 69 launchLocalExecutor(StringRef ExecutablePath) { 70 return make_error<StringError>( 71 "Remote JITing not yet supported on non-unix platforms", 72 inconvertibleErrorCode()); 73 } 74 75 // FIXME: Add support for Windows. 76 Expected<std::unique_ptr<SimpleRemoteEPC>> 77 connectTCPSocket(StringRef NetworkAddress) { 78 return make_error<StringError>( 79 "Remote JITing not yet supported on non-unix platforms", 80 inconvertibleErrorCode()); 81 } 82 83 #else 84 85 Expected<std::pair<std::unique_ptr<SimpleRemoteEPC>, uint64_t>> 86 launchLocalExecutor(StringRef ExecutablePath) { 87 constexpr int ReadEnd = 0; 88 constexpr int WriteEnd = 1; 89 90 if (!sys::fs::can_execute(ExecutablePath)) 91 return make_error<StringError>( 92 formatv("Specified executor invalid: {0}", ExecutablePath), 93 inconvertibleErrorCode()); 94 95 // Pipe FDs. 96 int ToExecutor[2]; 97 int FromExecutor[2]; 98 99 // Create pipes to/from the executor.. 100 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0) 101 return make_error<StringError>("Unable to create pipe for executor", 102 inconvertibleErrorCode()); 103 104 pid_t ProcessID = fork(); 105 if (ProcessID == 0) { 106 // In the child... 107 108 // Close the parent ends of the pipes 109 close(ToExecutor[WriteEnd]); 110 close(FromExecutor[ReadEnd]); 111 112 // Execute the child process. 113 std::unique_ptr<char[]> ExecPath, FDSpecifier; 114 { 115 ExecPath = std::make_unique<char[]>(ExecutablePath.size() + 1); 116 strcpy(ExecPath.get(), ExecutablePath.data()); 117 118 std::string FDSpecifierStr("filedescs="); 119 FDSpecifierStr += utostr(ToExecutor[ReadEnd]); 120 FDSpecifierStr += ','; 121 FDSpecifierStr += utostr(FromExecutor[WriteEnd]); 122 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1); 123 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str()); 124 } 125 126 char *const Args[] = {ExecPath.get(), FDSpecifier.get(), nullptr}; 127 int RC = execvp(ExecPath.get(), Args); 128 if (RC != 0) 129 return make_error<StringError>( 130 "Unable to launch out-of-process executor '" + ExecutablePath + "'\n", 131 inconvertibleErrorCode()); 132 133 llvm_unreachable("Fork won't return in success case"); 134 } 135 // else we're the parent... 136 137 // Close the child ends of the pipes 138 close(ToExecutor[ReadEnd]); 139 close(FromExecutor[WriteEnd]); 140 141 auto EPC = SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>( 142 std::make_unique<DynamicThreadPoolTaskDispatcher>(), 143 SimpleRemoteEPC::Setup(), 144 FromExecutor[ReadEnd], ToExecutor[WriteEnd]); 145 if (!EPC) 146 return EPC.takeError(); 147 148 return std::make_pair(std::move(*EPC), static_cast<uint64_t>(ProcessID)); 149 } 150 151 static Expected<int> connectTCPSocketImpl(std::string Host, 152 std::string PortStr) { 153 addrinfo *AI; 154 addrinfo Hints{}; 155 Hints.ai_family = AF_INET; 156 Hints.ai_socktype = SOCK_STREAM; 157 Hints.ai_flags = AI_NUMERICSERV; 158 159 if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI)) 160 return make_error<StringError>( 161 formatv("address resolution failed ({0})", gai_strerror(EC)), 162 inconvertibleErrorCode()); 163 164 // Cycle through the returned addrinfo structures and connect to the first 165 // reachable endpoint. 166 int SockFD; 167 addrinfo *Server; 168 for (Server = AI; Server != nullptr; Server = Server->ai_next) { 169 // If socket fails, maybe it's because the address family is not supported. 170 // Skip to the next addrinfo structure. 171 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) 172 continue; 173 174 // If connect works, we exit the loop with a working socket. 175 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0) 176 break; 177 178 close(SockFD); 179 } 180 freeaddrinfo(AI); 181 182 // Did we reach the end of the loop without connecting to a valid endpoint? 183 if (Server == nullptr) 184 return make_error<StringError>("invalid hostname", 185 inconvertibleErrorCode()); 186 187 return SockFD; 188 } 189 190 Expected<std::unique_ptr<SimpleRemoteEPC>> 191 connectTCPSocket(StringRef NetworkAddress) { 192 auto CreateErr = [NetworkAddress](StringRef Details) { 193 return make_error<StringError>( 194 formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress, 195 Details), 196 inconvertibleErrorCode()); 197 }; 198 199 StringRef Host, PortStr; 200 std::tie(Host, PortStr) = NetworkAddress.split(':'); 201 if (Host.empty()) 202 return CreateErr("host name cannot be empty"); 203 if (PortStr.empty()) 204 return CreateErr("port cannot be empty"); 205 int Port = 0; 206 if (PortStr.getAsInteger(10, Port)) 207 return CreateErr("port number is not a valid integer"); 208 209 Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str()); 210 if (!SockFD) 211 return CreateErr(toString(SockFD.takeError())); 212 213 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>( 214 std::make_unique<DynamicThreadPoolTaskDispatcher>(), 215 SimpleRemoteEPC::Setup(), *SockFD); 216 } 217 218 #endif 219