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(std::unique_ptr<RPCChannel> Channel,
51                                std::unique_ptr<RPCEndpoint> Endpoint,
52                                BaseT::ErrorReporter ReportError);
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     std::unique_ptr<RPCChannel> Channel, std::unique_ptr<RPCEndpoint> Endpoint,
68     BaseT::ErrorReporter ReportError)
69     : BaseT(std::make_shared<SymbolStringPool>(), *Endpoint,
70             std::move(ReportError)),
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   assert(EPC && "RemoteExecutorProcessControl must be initialized");
113   return std::make_unique<ObjectLinkingLayer>(ES, EPC->getMemMgr());
114 }
115 
116 std::unique_ptr<ExecutionSession> JITLinkExecutor::startSession() {
117   assert(OwnedEPC && "RemoteExecutorProcessControl must be initialized");
118   return std::make_unique<ExecutionSession>(std::move(OwnedEPC));
119 }
120 
121 Error JITLinkExecutor::addDebugSupport(ObjectLayer &ObjLayer) {
122   auto Registrar = createJITLoaderGDBRegistrar(EPC->getExecutionSession());
123   if (!Registrar)
124     return Registrar.takeError();
125 
126   cast<ObjectLinkingLayer>(&ObjLayer)->addPlugin(
127       std::make_unique<DebugObjectManagerPlugin>(ObjLayer.getExecutionSession(),
128                                                  std::move(*Registrar)));
129 
130   return Error::success();
131 }
132 
133 Expected<std::unique_ptr<DefinitionGenerator>>
134 JITLinkExecutor::loadDylib(StringRef RemotePath) {
135   if (auto Handle = EPC->loadDylib(RemotePath.data()))
136     return std::make_unique<EPCDynamicLibrarySearchGenerator>(
137         EPC->getExecutionSession(), *Handle);
138   else
139     return Handle.takeError();
140 }
141 
142 Expected<int> JITLinkExecutor::runAsMain(JITEvaluatedSymbol MainSym,
143                                          ArrayRef<std::string> Args) {
144   return EPC->runAsMain(MainSym.getAddress(), Args);
145 }
146 
147 Error JITLinkExecutor::disconnect() { return EPC->disconnect(); }
148 
149 static std::string defaultPath(const char *HostArgv0, StringRef ExecutorName) {
150   // This just needs to be some symbol in the binary; C++ doesn't
151   // allow taking the address of ::main however.
152   void *P = (void *)(intptr_t)defaultPath;
153   SmallString<256> FullName(sys::fs::getMainExecutable(HostArgv0, P));
154   sys::path::remove_filename(FullName);
155   sys::path::append(FullName, ExecutorName);
156   return FullName.str().str();
157 }
158 
159 Expected<std::unique_ptr<ChildProcessJITLinkExecutor>>
160 JITLinkExecutor::FindLocal(const char *HostArgv) {
161   std::string BestGuess = defaultPath(HostArgv, "llvm-jitlink-executor");
162   auto Executor = CreateLocal(BestGuess);
163   if (!Executor) {
164     consumeError(Executor.takeError());
165     return make_error<StringError>(
166         formatv("Unable to find usable executor: {0}", BestGuess),
167         inconvertibleErrorCode());
168   }
169   return Executor;
170 }
171 
172 Expected<std::unique_ptr<ChildProcessJITLinkExecutor>>
173 JITLinkExecutor::CreateLocal(std::string ExecutablePath) {
174   if (!sys::fs::can_execute(ExecutablePath))
175     return make_error<StringError>(
176         formatv("Specified executor invalid: {0}", ExecutablePath),
177         inconvertibleErrorCode());
178   return std::unique_ptr<ChildProcessJITLinkExecutor>(
179       new ChildProcessJITLinkExecutor(std::move(ExecutablePath)));
180 }
181 
182 TCPSocketJITLinkExecutor::TCPSocketJITLinkExecutor(
183     std::unique_ptr<RemoteExecutorProcessControl> EPC) {
184   this->OwnedEPC = std::move(EPC);
185   this->EPC = this->OwnedEPC.get();
186 }
187 
188 #ifndef LLVM_ON_UNIX
189 
190 // FIXME: Add support for Windows.
191 Error ChildProcessJITLinkExecutor::launch(ExecutionSession &ES) {
192   return make_error<StringError>(
193       "Remote JITing not yet supported on non-unix platforms",
194       inconvertibleErrorCode());
195 }
196 
197 // FIXME: Add support for Windows.
198 Expected<std::unique_ptr<TCPSocketJITLinkExecutor>>
199 JITLinkExecutor::ConnectTCPSocket(StringRef NetworkAddress,
200                                   ExecutionSession &ES) {
201   return make_error<StringError>(
202       "Remote JITing not yet supported on non-unix platforms",
203       inconvertibleErrorCode());
204 }
205 
206 #else
207 
208 Error ChildProcessJITLinkExecutor::launch(
209     unique_function<void(Error)> ErrorReporter) {
210   constexpr int ReadEnd = 0;
211   constexpr int WriteEnd = 1;
212 
213   // Pipe FDs.
214   int ToExecutor[2];
215   int FromExecutor[2];
216 
217   // Create pipes to/from the executor..
218   if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
219     return make_error<StringError>("Unable to create pipe for executor",
220                                    inconvertibleErrorCode());
221 
222   ProcessID = fork();
223   if (ProcessID == 0) {
224     // In the child...
225 
226     // Close the parent ends of the pipes
227     close(ToExecutor[WriteEnd]);
228     close(FromExecutor[ReadEnd]);
229 
230     // Execute the child process.
231     std::unique_ptr<char[]> ExecPath, FDSpecifier;
232     {
233       ExecPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
234       strcpy(ExecPath.get(), ExecutablePath.data());
235 
236       std::string FDSpecifierStr("filedescs=");
237       FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
238       FDSpecifierStr += ',';
239       FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
240       FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
241       strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
242     }
243 
244     char *const Args[] = {ExecPath.get(), FDSpecifier.get(), nullptr};
245     int RC = execvp(ExecPath.get(), Args);
246     if (RC != 0)
247       return make_error<StringError>(
248           "Unable to launch out-of-process executor '" + ExecutablePath + "'\n",
249           inconvertibleErrorCode());
250 
251     llvm_unreachable("Fork won't return in success case");
252   }
253   // else we're the parent...
254 
255   // Close the child ends of the pipes
256   close(ToExecutor[ReadEnd]);
257   close(FromExecutor[WriteEnd]);
258 
259   auto Channel =
260       std::make_unique<RPCChannel>(FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
261   auto Endpoint = std::make_unique<RemoteExecutorProcessControl::RPCEndpoint>(
262       *Channel, true);
263 
264   OwnedEPC = std::make_unique<RemoteExecutorProcessControl>(
265       std::move(Channel), std::move(Endpoint), std::move(ErrorReporter));
266 
267   if (auto Err = OwnedEPC->initializeORCRPCEPCBase())
268     return joinErrors(std::move(Err), OwnedEPC->disconnect());
269 
270   OwnedEPC->initializeMemoryManagement();
271   EPC = OwnedEPC.get();
272 
273   shared::registerStringError<RPCChannel>();
274   return Error::success();
275 }
276 
277 static Expected<int> connectTCPSocketImpl(std::string Host,
278                                           std::string PortStr) {
279   addrinfo *AI;
280   addrinfo Hints{};
281   Hints.ai_family = AF_INET;
282   Hints.ai_socktype = SOCK_STREAM;
283   Hints.ai_flags = AI_NUMERICSERV;
284 
285   if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
286     return make_error<StringError>(
287         formatv("address resolution failed ({0})", gai_strerror(EC)),
288         inconvertibleErrorCode());
289 
290   // Cycle through the returned addrinfo structures and connect to the first
291   // reachable endpoint.
292   int SockFD;
293   addrinfo *Server;
294   for (Server = AI; Server != nullptr; Server = Server->ai_next) {
295     // If socket fails, maybe it's because the address family is not supported.
296     // Skip to the next addrinfo structure.
297     if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
298       continue;
299 
300     // If connect works, we exit the loop with a working socket.
301     if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
302       break;
303 
304     close(SockFD);
305   }
306   freeaddrinfo(AI);
307 
308   // Did we reach the end of the loop without connecting to a valid endpoint?
309   if (Server == nullptr)
310     return make_error<StringError>("invalid hostname",
311                                    inconvertibleErrorCode());
312 
313   return SockFD;
314 }
315 
316 Expected<std::unique_ptr<TCPSocketJITLinkExecutor>>
317 JITLinkExecutor::ConnectTCPSocket(StringRef NetworkAddress,
318                                   unique_function<void(Error)> ErrorReporter) {
319   auto CreateErr = [NetworkAddress](StringRef Details) {
320     return make_error<StringError>(
321         formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
322                 Details),
323         inconvertibleErrorCode());
324   };
325 
326   StringRef Host, PortStr;
327   std::tie(Host, PortStr) = NetworkAddress.split(':');
328   if (Host.empty())
329     return CreateErr("host name cannot be empty");
330   if (PortStr.empty())
331     return CreateErr("port cannot be empty");
332   int Port = 0;
333   if (PortStr.getAsInteger(10, Port))
334     return CreateErr("port number is not a valid integer");
335 
336   Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
337   if (!SockFD)
338     return CreateErr(toString(SockFD.takeError()));
339 
340   auto Channel = std::make_unique<RPCChannel>(*SockFD, *SockFD);
341   auto Endpoint = std::make_unique<RemoteExecutorProcessControl::RPCEndpoint>(
342       *Channel, true);
343 
344   auto EPC = std::make_unique<RemoteExecutorProcessControl>(
345       std::move(Channel), std::move(Endpoint), std::move(ErrorReporter));
346 
347   if (auto Err = EPC->initializeORCRPCEPCBase())
348     return joinErrors(std::move(Err), EPC->disconnect());
349 
350   EPC->initializeMemoryManagement();
351   shared::registerStringError<RPCChannel>();
352 
353   return std::unique_ptr<TCPSocketJITLinkExecutor>(
354       new TCPSocketJITLinkExecutor(std::move(EPC)));
355 }
356 
357 #endif
358