summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMisha Brukman <brukman+llvm@gmail.com>2003-08-11 22:29:36 +0000
committerMisha Brukman <brukman+llvm@gmail.com>2003-08-11 22:29:36 +0000
commit0abaaf49fd32eb32abc3117a4bff41fe82d9ec3e (patch)
treecba354c6513603091e238dd492f5f96db4136261 /tools
parent00b40943ab839d9fef27a093b91dadef69fd8694 (diff)
downloadllvm-0abaaf49fd32eb32abc3117a4bff41fe82d9ec3e.tar.gz
llvm-0abaaf49fd32eb32abc3117a4bff41fe82d9ec3e.tar.bz2
llvm-0abaaf49fd32eb32abc3117a4bff41fe82d9ec3e.tar.xz
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
Diffstat (limited to 'tools')
-rw-r--r--tools/llee/ExecveHandler.c92
-rw-r--r--tools/llee/Makefile21
-rw-r--r--tools/llee/SysUtils.c81
-rw-r--r--tools/llee/SysUtils.h28
-rwxr-xr-xtools/llee/llee1
5 files changed, 223 insertions, 0 deletions
diff --git a/tools/llee/ExecveHandler.c b/tools/llee/ExecveHandler.c
new file mode 100644
index 0000000000..947b2fcdbd
--- /dev/null
+++ b/tools/llee/ExecveHandler.c
@@ -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;
+}
diff --git a/tools/llee/Makefile b/tools/llee/Makefile
new file mode 100644
index 0000000000..aabbed635b
--- /dev/null
+++ b/tools/llee/Makefile
@@ -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)
diff --git a/tools/llee/SysUtils.c b/tools/llee/SysUtils.c
new file mode 100644
index 0000000000..1c3aa85e5c
--- /dev/null
+++ b/tools/llee/SysUtils.c
@@ -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;
+}
diff --git a/tools/llee/SysUtils.h b/tools/llee/SysUtils.h
new file mode 100644
index 0000000000..89b647970e
--- /dev/null
+++ b/tools/llee/SysUtils.h
@@ -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
diff --git a/tools/llee/llee b/tools/llee/llee
new file mode 100755
index 0000000000..7a3ea959ed
--- /dev/null
+++ b/tools/llee/llee
@@ -0,0 +1 @@
+exec env LD_PRELOAD=`pwd`/execve.so $*