1 //===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===//
3 // This file implements a replacement execve() to spawn off LLVM programs to run
4 // transparently, without needing to be (JIT-)compiled manually by the user.
6 //===----------------------------------------------------------------------===//
9 #include <Config/dlfcn.h>
10 #include <Config/errno.h>
11 #include <Config/stdlib.h>
16 * This is the expected header for all valid LLVM bytecode files.
17 * The first four characters must be exactly this.
19 static const char llvmHeader[] = "llvm";
22 * The type of the execve() function is long and boring, but required.
24 typedef int(*execveTy)(const char*, char *const[], char *const[]);
27 * This method finds the real `execve' call in the C library and executes the
30 int executeProgram(const char *filename, char *const argv[], char *const envp[])
33 * Find a pointer to the *real* execve() function starting the search in the
34 * next library and forward, to avoid finding the one defined in this file.
37 execveTy execvePtr = (execveTy) dlsym(RTLD_NEXT, "execve");
38 if ((error = dlerror()) != NULL) {
39 fprintf(stderr, "%s\n", error);
43 /* Really execute the program */
44 return execvePtr(filename, argv, envp);
48 * This replacement execve() function first checks the file to be executed
49 * to see if it is a valid LLVM bytecode file, and then either invokes our
50 * execution environment or passes it on to the system execve() call.
52 int execve(const char *filename, char *const argv[], char *const envp[])
54 /* Open the file, test to see if first four characters are "llvm" */
56 FILE *file = fopen(filename, "r");
57 /* Check validity of `file' */
58 if (errno) { return errno; }
59 /* Read the header from the file */
60 size_t headerSize = strlen(llvmHeader) - 1; // ignore the NULL terminator
61 size_t bytesRead = fread(header, sizeof(char), headerSize, file);
63 if (bytesRead != headerSize) {
66 if (!strncmp(llvmHeader, header, headerSize)) {
68 * This is a bytecode file, so execute the JIT with the program and
71 unsigned argvSize, idx;
72 for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
74 char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
75 char *LLIpath = FindExecutable("lli");
77 fprintf(stderr, "Cannot find path to `lli', exiting.\n");
81 for (idx = 0; idx != argvSize; ++idx)
82 LLIargs[idx+1] = argv[idx];
83 LLIargs[argvSize + 1] = '\0';
85 for (idx = 0; idx != argvSize+2; ++idx)
86 printf("LLI args[%d] = \"%s\"\n", idx, LLIargs[idx]);
88 return executeProgram(LLIpath, LLIargs, envp);
90 executeProgram(filename, argv, envp);