• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- llvm-jitlink-executor.cpp - Out-of-proc executor for llvm-jitlink -===//
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 // Simple out-of-process executor for llvm-jitlink.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h"
15 #include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
16 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
17 #include "llvm/Support/DynamicLibrary.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <sstream>
21 
22 #ifdef LLVM_ON_UNIX
23 
24 #include <netinet/in.h>
25 #include <sys/socket.h>
26 
27 #endif
28 
29 using namespace llvm;
30 using namespace llvm::orc;
31 
32 ExitOnError ExitOnErr;
33 
linkComponents()34 LLVM_ATTRIBUTE_USED void linkComponents() {
35   errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
36          << (void *)&llvm_orc_deregisterEHFrameSectionWrapper;
37 }
38 
printErrorAndExit(Twine ErrMsg)39 void printErrorAndExit(Twine ErrMsg) {
40   errs() << "error: " << ErrMsg.str() << "\n\n"
41          << "Usage:\n"
42          << "  llvm-jitlink-executor filedescs=<infd>,<outfd> [args...]\n"
43          << "  llvm-jitlink-executor listen=<host>:<port> [args...]\n";
44   exit(1);
45 }
46 
openListener(std::string Host,int Port)47 int openListener(std::string Host, int Port) {
48 #ifndef LLVM_ON_UNIX
49   // FIXME: Add TCP support for Windows.
50   printErrorAndExit("listen option not supported");
51   return 0;
52 #else
53   int SockFD = socket(PF_INET, SOCK_STREAM, 0);
54   struct sockaddr_in ServerAddr, ClientAddr;
55   socklen_t ClientAddrLen = sizeof(ClientAddr);
56   memset(&ServerAddr, 0, sizeof(ServerAddr));
57   ServerAddr.sin_family = PF_INET;
58   ServerAddr.sin_family = INADDR_ANY;
59   ServerAddr.sin_port = htons(Port);
60 
61   {
62     // lose the "Address already in use" error message
63     int Yes = 1;
64     if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1) {
65       errs() << "Error calling setsockopt.\n";
66       exit(1);
67     }
68   }
69 
70   if (bind(SockFD, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) {
71     errs() << "Error on binding.\n";
72     exit(1);
73   }
74 
75   listen(SockFD, 1);
76   return accept(SockFD, (struct sockaddr *)&ClientAddr, &ClientAddrLen);
77 #endif
78 }
79 
main(int argc,char * argv[])80 int main(int argc, char *argv[]) {
81 
82   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
83 
84   int InFD = 0;
85   int OutFD = 0;
86 
87   if (argc < 2)
88     printErrorAndExit("insufficient arguments");
89   else {
90     StringRef Arg1 = argv[1];
91     StringRef SpecifierType, Specifier;
92     std::tie(SpecifierType, Specifier) = Arg1.split('=');
93     if (SpecifierType == "filedescs") {
94       StringRef FD1Str, FD2Str;
95       std::tie(FD1Str, FD2Str) = Specifier.split(',');
96       if (FD1Str.getAsInteger(10, InFD))
97         printErrorAndExit(FD1Str + " is not a valid file descriptor");
98       if (FD2Str.getAsInteger(10, OutFD))
99         printErrorAndExit(FD2Str + " is not a valid file descriptor");
100     } else if (SpecifierType == "listen") {
101       StringRef Host, PortStr;
102       std::tie(Host, PortStr) = Specifier.split(':');
103 
104       int Port = 0;
105       if (PortStr.getAsInteger(10, Port))
106         printErrorAndExit("port" + PortStr + " is not a valid integer");
107 
108       InFD = OutFD = openListener(Host.str(), Port);
109     } else
110       printErrorAndExit("invalid specifier type \"" + SpecifierType + "\"");
111   }
112 
113   ExitOnErr.setBanner(std::string(argv[0]) + ":");
114 
115   using JITLinkExecutorEndpoint =
116       rpc::MultiThreadedRPCEndpoint<rpc::FDRawByteChannel>;
117 
118   rpc::registerStringError<rpc::FDRawByteChannel>();
119 
120   rpc::FDRawByteChannel C(InFD, OutFD);
121   JITLinkExecutorEndpoint EP(C, true);
122   OrcRPCTPCServer<JITLinkExecutorEndpoint> Server(EP);
123   Server.setProgramName(std::string("llvm-jitlink-executor"));
124 
125   ExitOnErr(Server.run());
126 
127   return 0;
128 }
129