Make sure llee can deal with compressed bytecode too.
[oota-llvm.git] / tools / llee / ExecveHandler.c
1 /*===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===*\
2  *                                                                            
3  *                     The LLVM Compiler Infrastructure                       
4  *
5  * This file was developed by the LLVM research group and is distributed under
6  * the University of Illinois Open Source License. See LICENSE.TXT for details.
7  * 
8  *===----------------------------------------------------------------------===
9  *
10  * This file implements a replacement execve() to spawn off LLVM programs to run
11  * transparently, without needing to be (JIT-)compiled manually by the user.
12  *
13 \*===----------------------------------------------------------------------===*/
14
15 #include "SysUtils.h"
16 #include "llvm/Config/unistd.h"
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 /*
24  * These are the expected headers for all valid LLVM bytecode files.
25  * The first four characters must be one of these.
26  */
27 static const char llvmHeaderUncompressed[] = "llvm";
28 static const char llvmHeaderCompressed[] = "llvc";
29
30 /*
31  * This replacement execve() function first checks the file to be executed
32  * to see if it is a valid LLVM bytecode file, and then either invokes our
33  * execution environment or passes it on to the system execve() call.
34  */
35 int execve(const char *filename, char *const argv[], char *const envp[])
36 {
37   /* Open the file, test to see if first four characters are "llvm" */
38   size_t headerSize = strlen(llvmHeaderCompressed);
39   char header[headerSize];
40   char* realFilename = 0;
41   /* 
42    * If the program is specified with a relative or absolute path, 
43    * then just use the path and filename as is, otherwise search for it.
44    */
45   if (filename[0] != '.' && filename[0] != '/')
46     realFilename = FindExecutable(filename);
47   else
48     realFilename = (char*) filename;
49   if (!realFilename) {
50     fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
51     return -1;
52   }
53   errno = 0;
54   int file = open(realFilename, O_RDONLY);
55   /* Check validity of `file' */
56   if (errno) return EIO;
57   /* Read the header from the file */
58   ssize_t bytesRead = read(file, header, headerSize);
59   close(file);
60   if (bytesRead != (ssize_t)headerSize) return EIO;
61   if (!memcmp(llvmHeaderCompressed, header, headerSize) || 
62       !memcmp(llvmHeaderUncompressed, header, headerSize)) {
63     /* 
64      * This is a bytecode file, so execute the JIT with the program and
65      * parameters.
66      */
67     unsigned argvSize, idx;
68     for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
69       ++argvSize;
70     char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
71     char *LLIpath = FindExecutable("lli");
72     if (!LLIpath) {
73       fprintf(stderr, "Cannot find path to `lli', exiting.\n");
74       return -1;
75     }
76     LLIargs[0] = LLIpath;
77     LLIargs[1] = realFilename;
78     for (idx = 1; idx != argvSize; ++idx)
79       LLIargs[idx+1] = argv[idx];
80     LLIargs[argvSize + 1] = '\0';
81     return executeProgram(LLIpath, LLIargs, envp);
82   }
83   return executeProgram(filename, argv, envp); 
84 }