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