blob: 922a154864b5720720bad4fc2db2381dd83389e7 [file] [log] [blame]
Misha Brukman0abaaf42003-08-11 22:29:36 +00001//===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===//
2//
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.
5//
6//===----------------------------------------------------------------------===//
7
8#include "SysUtils.h"
Misha Brukman593ece02003-08-15 23:31:16 +00009#include "Config/errno.h"
10#include "Config/stdlib.h"
11#include "Config/unistd.h"
12#include <fcntl.h>
Misha Brukman0abaaf42003-08-11 22:29:36 +000013#include <stdio.h>
14#include <string.h>
15
16/*
17 * This is the expected header for all valid LLVM bytecode files.
18 * The first four characters must be exactly this.
19 */
20static const char llvmHeader[] = "llvm";
21
22/*
Misha Brukman0abaaf42003-08-11 22:29:36 +000023 * This replacement execve() function first checks the file to be executed
24 * to see if it is a valid LLVM bytecode file, and then either invokes our
25 * execution environment or passes it on to the system execve() call.
26 */
27int execve(const char *filename, char *const argv[], char *const envp[])
28{
29 /* Open the file, test to see if first four characters are "llvm" */
Misha Brukman593ece02003-08-15 23:31:16 +000030 size_t headerSize = strlen(llvmHeader);
31 char header[headerSize];
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000032 char* realFilename = 0;
33 /*
34 * If the program is specified with a relative or absolute path,
35 * then just use the path and filename as is, otherwise search for it.
36 */
37 if (filename[0] != '.' && filename[0] != '/')
38 realFilename = FindExecutable(filename);
39 else
40 realFilename = (char*) filename;
41 if (!realFilename) {
42 fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
43 return -1;
44 }
Misha Brukman593ece02003-08-15 23:31:16 +000045 errno = 0;
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000046 int file = open(realFilename, O_RDONLY);
Misha Brukman0abaaf42003-08-11 22:29:36 +000047 /* Check validity of `file' */
Misha Brukman593ece02003-08-15 23:31:16 +000048 if (errno) return EIO;
Misha Brukman0abaaf42003-08-11 22:29:36 +000049 /* Read the header from the file */
Misha Brukman593ece02003-08-15 23:31:16 +000050 ssize_t bytesRead = read(file, header, headerSize);
51 close(file);
Misha Brukman00ce8402003-09-27 22:26:37 +000052 if (bytesRead != (ssize_t)headerSize) return EIO;
Misha Brukman593ece02003-08-15 23:31:16 +000053 if (!memcmp(llvmHeader, header, headerSize)) {
Misha Brukman0abaaf42003-08-11 22:29:36 +000054 /*
55 * This is a bytecode file, so execute the JIT with the program and
56 * parameters.
57 */
58 unsigned argvSize, idx;
59 for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
60 ++argvSize;
61 char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
62 char *LLIpath = FindExecutable("lli");
63 if (!LLIpath) {
64 fprintf(stderr, "Cannot find path to `lli', exiting.\n");
65 return -1;
66 }
67 LLIargs[0] = LLIpath;
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000068 LLIargs[1] = realFilename;
Misha Brukman593ece02003-08-15 23:31:16 +000069 for (idx = 1; idx != argvSize; ++idx)
Misha Brukman0abaaf42003-08-11 22:29:36 +000070 LLIargs[idx+1] = argv[idx];
71 LLIargs[argvSize + 1] = '\0';
Misha Brukman0abaaf42003-08-11 22:29:36 +000072 return executeProgram(LLIpath, LLIargs, envp);
73 }
Misha Brukman593ece02003-08-15 23:31:16 +000074 return executeProgram(filename, argv, envp);
Misha Brukman0abaaf42003-08-11 22:29:36 +000075}