Initial checkin of the LLEE, the (LL)VM (E)xecution (E)nvironment.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7760 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Misha Brukman 2003-08-11 22:29:36 +00:00
parent 00b40943ab
commit 0abaaf49fd
5 changed files with 223 additions and 0 deletions

View File

@ -0,0 +1,92 @@
//===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===//
//
// This file implements a replacement execve() to spawn off LLVM programs to run
// transparently, without needing to be (JIT-)compiled manually by the user.
//
//===----------------------------------------------------------------------===//
#include "SysUtils.h"
#include <Config/dlfcn.h>
#include <Config/errno.h>
#include <Config/stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* This is the expected header for all valid LLVM bytecode files.
* The first four characters must be exactly this.
*/
static const char llvmHeader[] = "llvm";
/*
* The type of the execve() function is long and boring, but required.
*/
typedef int(*execveTy)(const char*, char *const[], char *const[]);
/*
* This method finds the real `execve' call in the C library and executes the
* given program.
*/
int executeProgram(const char *filename, char *const argv[], char *const envp[])
{
/*
* Find a pointer to the *real* execve() function starting the search in the
* next library and forward, to avoid finding the one defined in this file.
*/
char *error;
execveTy execvePtr = (execveTy) dlsym(RTLD_NEXT, "execve");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return -1;
}
/* Really execute the program */
return execvePtr(filename, argv, envp);
}
/*
* This replacement execve() function first checks the file to be executed
* to see if it is a valid LLVM bytecode file, and then either invokes our
* execution environment or passes it on to the system execve() call.
*/
int execve(const char *filename, char *const argv[], char *const envp[])
{
/* Open the file, test to see if first four characters are "llvm" */
char header[4];
FILE *file = fopen(filename, "r");
/* Check validity of `file' */
if (errno) { return errno; }
/* Read the header from the file */
size_t headerSize = strlen(llvmHeader) - 1; // ignore the NULL terminator
size_t bytesRead = fread(header, sizeof(char), headerSize, file);
fclose(file);
if (bytesRead != headerSize) {
return EIO;
}
if (!strncmp(llvmHeader, header, headerSize)) {
/*
* This is a bytecode file, so execute the JIT with the program and
* parameters.
*/
unsigned argvSize, idx;
for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
++argvSize;
char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
char *LLIpath = FindExecutable("lli");
if (!LLIpath) {
fprintf(stderr, "Cannot find path to `lli', exiting.\n");
return -1;
}
LLIargs[0] = LLIpath;
for (idx = 0; idx != argvSize; ++idx)
LLIargs[idx+1] = argv[idx];
LLIargs[argvSize + 1] = '\0';
/*
for (idx = 0; idx != argvSize+2; ++idx)
printf("LLI args[%d] = \"%s\"\n", idx, LLIargs[idx]);
*/
return executeProgram(LLIpath, LLIargs, envp);
}
executeProgram(filename, argv, envp);
return 0;
}

21
tools/llee/Makefile Normal file
View File

@ -0,0 +1,21 @@
LEVEL = ../..
include $(LEVEL)/Makefile.config
SRCS = ExecveHandler.c SysUtils.c
OBJS = $(SRCS:%.c=%.o)
SO = execve.so
all: $(SO) execve_test
%.o: %.c
gcc -g -I../../include -D_GNU_SOURCE $< -c -o $@
$(SO): $(OBJS)
gcc -g -shared -ldl -rdynamic $(OBJS) -o $@
execve_test: execve_test.c
gcc -g $< -o $@
clean:
rm -f $(OBJS) $(SO)

81
tools/llee/SysUtils.c Normal file
View File

@ -0,0 +1,81 @@
//===- SystemUtils.h - Utilities to do low-level system stuff --*- C++ -*--===//
//
// This file contains functions used to do a variety of low-level, often
// system-specific, tasks.
//
//===----------------------------------------------------------------------===//
#include "SysUtils.h"
#include "Config/sys/types.h"
#include "Config/sys/stat.h"
#include "Config/fcntl.h"
#include "Config/sys/wait.h"
#include "Config/unistd.h"
#include "Config/errno.h"
#include <stdlib.h>
#include <string.h>
/// isExecutableFile - This function returns true if the filename specified
/// exists and is executable.
///
bool isExecutableFile(const char *ExeFileName) {
struct stat Buf;
if (stat(ExeFileName, &Buf))
return false; // Must not be executable!
if (!(Buf.st_mode & S_IFREG))
return false; // Not a regular file?
if (Buf.st_uid == getuid()) // Owner of file?
return Buf.st_mode & S_IXUSR;
else if (Buf.st_gid == getgid()) // In group of file?
return Buf.st_mode & S_IXGRP;
else // Unrelated to file?
return Buf.st_mode & S_IXOTH;
}
/// FindExecutable - Find a named executable in the directories listed in $PATH.
/// If the executable cannot be found, returns NULL.
///
char *FindExecutable(const char *ExeName) {
/* Try to find the executable in the path */
const char *PathStr = getenv("PATH");
if (PathStr == 0) return "";
// Now we have a colon separated list of directories to search... try them...
unsigned PathLen = strlen(PathStr);
while (PathLen) {
/* Find the next colon */
const char *Colon = strchr(PathStr, ':');
/* Check to see if this first directory contains the executable... */
unsigned DirLen = Colon ? (Colon-PathStr) : strlen(PathStr);
char *FilePath = alloca(sizeof(char) * (DirLen+1+strlen(ExeName)+1));
unsigned i, e;
for (i = 0; i != DirLen; ++i)
FilePath[i] = PathStr[i];
FilePath[i] = '/';
for (i = 0, e = strlen(ExeName); i != e; ++i)
FilePath[DirLen + 1 + i] = ExeName[i];
FilePath[DirLen + 1 + i] = '\0';
if (isExecutableFile(FilePath))
return strdup(FilePath); /* Found the executable! */
/* If Colon is NULL, there are no more colon separators and no more dirs */
if (!Colon) break;
/* Nope, it wasn't in this directory, check the next range! */
PathLen -= DirLen;
PathStr = Colon;
while (*PathStr == ':') { /* Advance past colons */
PathStr++;
PathLen--;
}
/* Advance past the colon */
++Colon;
}
// If we fell out, we ran out of directories in PATH to search, return failure
return NULL;
}

28
tools/llee/SysUtils.h Normal file
View File

@ -0,0 +1,28 @@
/*===- sysutils.h - Utilities to do low-level system stuff -------*- C -*--===*\
* *
* This file contains functions used to do a variety of low-level, often *
* system-specific, tasks. *
* *
\*===----------------------------------------------------------------------===*/
#ifndef SYSUTILS_H
#define SYSUTILS_H
typedef unsigned bool;
enum { false = 0, true = 1 };
/*
* isExecutableFile - This function returns true if the filename specified
* exists and is executable.
*/
bool isExecutableFile(const char *ExeFileName);
/*
* FindExecutable - Find a named executable, giving the argv[0] of program
* being executed. This allows us to find another LLVM tool if it is built into
* the same directory, but that directory is neither the current directory, nor
* in the PATH. If the executable cannot be found, return an empty string.
*/
char *FindExecutable(const char *ExeName);
#endif

1
tools/llee/llee Executable file
View File

@ -0,0 +1 @@
exec env LD_PRELOAD=`pwd`/execve.so $*