blob: c15c1465f7018603479dd6fa67b60816904a485d [file] [log] [blame]
Misha Brukman3b87f212004-08-04 21:19:49 +00001/*===-- 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\*===----------------------------------------------------------------------===*/
Misha Brukman0abaaf42003-08-11 22:29:36 +000014
15#include "SysUtils.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000016#include "llvm/Config/unistd.h"
Chris Lattner335eb9d2004-01-10 19:12:09 +000017#include <errno.h>
18#include <stdlib.h>
Misha Brukman593ece02003-08-15 23:31:16 +000019#include <fcntl.h>
Misha Brukman0abaaf42003-08-11 22:29:36 +000020#include <stdio.h>
21#include <string.h>
22
23/*
Reid Spencer31391b62004-11-09 20:21:25 +000024 * These are the expected headers for all valid LLVM bytecode files.
25 * The first four characters must be one of these.
Misha Brukman0abaaf42003-08-11 22:29:36 +000026 */
Reid Spencer31391b62004-11-09 20:21:25 +000027static const char llvmHeaderUncompressed[] = "llvm";
28static const char llvmHeaderCompressed[] = "llvc";
Misha Brukman0abaaf42003-08-11 22:29:36 +000029
30/*
Misha Brukman0abaaf42003-08-11 22:29:36 +000031 * 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 */
35int execve(const char *filename, char *const argv[], char *const envp[])
36{
37 /* Open the file, test to see if first four characters are "llvm" */
Reid Spencer31391b62004-11-09 20:21:25 +000038 size_t headerSize = strlen(llvmHeaderCompressed);
Misha Brukman593ece02003-08-15 23:31:16 +000039 char header[headerSize];
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000040 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 }
Misha Brukman593ece02003-08-15 23:31:16 +000053 errno = 0;
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000054 int file = open(realFilename, O_RDONLY);
Misha Brukman0abaaf42003-08-11 22:29:36 +000055 /* Check validity of `file' */
Misha Brukman593ece02003-08-15 23:31:16 +000056 if (errno) return EIO;
Misha Brukman0abaaf42003-08-11 22:29:36 +000057 /* Read the header from the file */
Misha Brukman593ece02003-08-15 23:31:16 +000058 ssize_t bytesRead = read(file, header, headerSize);
59 close(file);
Misha Brukman00ce8402003-09-27 22:26:37 +000060 if (bytesRead != (ssize_t)headerSize) return EIO;
Reid Spencer31391b62004-11-09 20:21:25 +000061 if (!memcmp(llvmHeaderCompressed, header, headerSize) ||
62 !memcmp(llvmHeaderUncompressed, header, headerSize)) {
Misha Brukman0abaaf42003-08-11 22:29:36 +000063 /*
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;
Misha Brukman2e1fbdd2003-09-29 22:37:00 +000077 LLIargs[1] = realFilename;
Misha Brukman593ece02003-08-15 23:31:16 +000078 for (idx = 1; idx != argvSize; ++idx)
Misha Brukman0abaaf42003-08-11 22:29:36 +000079 LLIargs[idx+1] = argv[idx];
80 LLIargs[argvSize + 1] = '\0';
Misha Brukman0abaaf42003-08-11 22:29:36 +000081 return executeProgram(LLIpath, LLIargs, envp);
82 }
Misha Brukman593ece02003-08-15 23:31:16 +000083 return executeProgram(filename, argv, envp);
Misha Brukman0abaaf42003-08-11 22:29:36 +000084}