summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMisha Brukman <brukman+llvm@gmail.com>2003-09-29 22:37:00 +0000
committerMisha Brukman <brukman+llvm@gmail.com>2003-09-29 22:37:00 +0000
commit2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d (patch)
treeeb3df0aeb13232e8d0a3d9be88aacd047e013a3c
parente676313966c3ede37644dbf2e49aa06f0c8b242a (diff)
downloadllvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.tar.gz
llvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.tar.bz2
llvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.tar.xz
* Added an interface for how LLEE would communicate with the OS
* Implemented the interface in StorageProxy.c * Removed the script `llee' as it is now created by the Makefile * Makefile now compiles a shared object version of the library, but only if using gcc-3.3, linking fails under gcc-3.2 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8751 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--tools/llee/ExecveHandler.c79
-rw-r--r--tools/llee/Makefile26
-rw-r--r--tools/llee/OSInterface.h48
-rw-r--r--tools/llee/StorageProxy.c101
-rw-r--r--tools/llee/SysUtils.c67
-rw-r--r--tools/llee/SysUtils.h15
-rwxr-xr-xtools/llee/llee1
7 files changed, 263 insertions, 74 deletions
diff --git a/tools/llee/ExecveHandler.c b/tools/llee/ExecveHandler.c
index dba419cfa3..4b740147ad 100644
--- a/tools/llee/ExecveHandler.c
+++ b/tools/llee/ExecveHandler.c
@@ -5,8 +5,8 @@
//
//===----------------------------------------------------------------------===//
+#include "OSInterface.h"
#include "SysUtils.h"
-#include "Config/dlfcn.h"
#include "Config/errno.h"
#include "Config/stdlib.h"
#include "Config/unistd.h"
@@ -21,32 +21,6 @@
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.
@@ -56,8 +30,21 @@ int execve(const char *filename, char *const argv[], char *const envp[])
/* Open the file, test to see if first four characters are "llvm" */
size_t headerSize = strlen(llvmHeader);
char header[headerSize];
+ char* realFilename = 0;
+ /*
+ * If the program is specified with a relative or absolute path,
+ * then just use the path and filename as is, otherwise search for it.
+ */
+ if (filename[0] != '.' && filename[0] != '/')
+ realFilename = FindExecutable(filename);
+ else
+ realFilename = (char*) filename;
+ if (!realFilename) {
+ fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
+ return -1;
+ }
errno = 0;
- int file = open(filename, O_RDONLY);
+ int file = open(realFilename, O_RDONLY);
/* Check validity of `file' */
if (errno) return EIO;
/* Read the header from the file */
@@ -65,6 +52,27 @@ int execve(const char *filename, char *const argv[], char *const envp[])
close(file);
if (bytesRead != (ssize_t)headerSize) return EIO;
if (!memcmp(llvmHeader, header, headerSize)) {
+ /*
+ * Check if we have a cached translation on disk
+ */
+ struct stat buf;
+ llvmStat(realFilename, &buf);
+ if (isExecutable(&buf)) {
+ size_t size;
+ void *fileAddr = llvmReadFile(realFilename, &size);
+ fprintf(stderr, "Found in cache: '%s'\n", realFilename);
+ if (fileAddr) {
+ free(fileAddr);
+ }
+ llvmExecve(realFilename, argv, envp);
+ } else {
+ /*
+ * Not in cache: save translation
+ */
+ //llvmSaveFile(realFilename, addr, len);
+ //fprintf(stderr, "Cached: '%s'\n", realFilename);
+ }
+
/*
* This is a bytecode file, so execute the JIT with the program and
* parameters.
@@ -73,26 +81,13 @@ int execve(const char *filename, char *const argv[], char *const envp[])
for (argvSize = 0, idx = 0; argv[idx] && argv[idx][0]; ++idx)
++argvSize;
char **LLIargs = (char**) malloc(sizeof(char*) * (argvSize+2));
- char *BCpath;
- /*
- * If the program is specified with a relative or absolute path,
- * then just use the path and filename as is, otherwise search for it.
- */
- if (filename[0] != '.' && filename[0] != '/')
- BCpath = FindExecutable(filename);
- else
- BCpath = (char*) filename;
- if (!BCpath) {
- fprintf(stderr, "Cannot find path to `%s', exiting.\n", filename);
- return -1;
- }
char *LLIpath = FindExecutable("lli");
if (!LLIpath) {
fprintf(stderr, "Cannot find path to `lli', exiting.\n");
return -1;
}
LLIargs[0] = LLIpath;
- LLIargs[1] = BCpath;
+ LLIargs[1] = realFilename;
for (idx = 1; idx != argvSize; ++idx)
LLIargs[idx+1] = argv[idx];
LLIargs[argvSize + 1] = '\0';
diff --git a/tools/llee/Makefile b/tools/llee/Makefile
index b39129829d..cbaf896f6a 100644
--- a/tools/llee/Makefile
+++ b/tools/llee/Makefile
@@ -1,21 +1,15 @@
LEVEL = ../..
-include $(LEVEL)/Makefile.config
+LIBRARYNAME = execve
+SHARED_LIBRARY = 1
+include $(LEVEL)/Makefile.common
-SRCS = ExecveHandler.c SysUtils.c
+all:: llee
-OBJS = $(SRCS:%.c=%.o)
-SO = execve.so
+llee: $(DESTTOOLCURRENT)/llee
-all: $(SO)
-
-%.o: %.c
- gcc -g -I../../include -D_GNU_SOURCE $< -c -o $@
+$(DESTTOOLCURRENT)/llee: Makefile
+ echo exec env LD_PRELOAD=$(DESTLIBCURRENT)/execve.so $$\* > $@
+ chmod u+x $@
-$(SO): $(OBJS)
- gcc -g -shared -ldl -rdynamic $(OBJS) -o $@
-
-execve_test: execve_test.c
- gcc -g $< -o $@
-
-clean:
- rm -f $(OBJS) $(SO)
+clean::
+ rm -f $(DESTTOOLCURRENT)/llee
diff --git a/tools/llee/OSInterface.h b/tools/llee/OSInterface.h
new file mode 100644
index 0000000000..18fe0da13a
--- /dev/null
+++ b/tools/llee/OSInterface.h
@@ -0,0 +1,48 @@
+/*===- OSInterface.h - Interface to query OS for functionality ---*- C -*--===*\
+ * *
+ * This file defines the prototype interface that we will expect operating *
+ * systems to implement if they wish to support offline cachine. *
+ * *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef OS_INTERFACE_H
+#define OS_INTERFACE_H
+
+#include "Config/sys/types.h"
+
+struct stat;
+
+/*
+ * llvmStat - equivalent to stat(3), except the key may not necessarily
+ * correspond to a file by that name, implementation is up to the OS.
+ * Values returned in buf are similar as they are in Unix.
+ */
+void llvmStat(const char *key, struct stat *buf);
+
+/*
+ * llvmWriteFile - implements a 'save' of a file in the OS. 'key' may not
+ * necessarily map to a file of the same name.
+ * Returns:
+ * 0 - success
+ * non-zero - error
+ */
+int llvmWriteFile(const char *key, const void *data, size_t len);
+
+/*
+ * llvmLoadFile - tells the OS to load data corresponding to a particular key
+ * somewhere into memory.
+ * Returns:
+ * 0 - failure
+ * non-zero - address of loaded file
+ *
+ * Value of size is the length of data loaded into memory.
+ */
+void* llvmReadFile(const char *key, size_t *size);
+
+/*
+ * llvmExecve - execute a file from cache. This is a temporary proof-of-concept
+ * because we do not relocate what we can read from disk.
+ */
+int llvmExecve(const char *filename, char *const argv[], char *const envp[]);
+
+#endif
diff --git a/tools/llee/StorageProxy.c b/tools/llee/StorageProxy.c
new file mode 100644
index 0000000000..0562796ec2
--- /dev/null
+++ b/tools/llee/StorageProxy.c
@@ -0,0 +1,101 @@
+/*===- StorageProxy.c - OS implementation of the caching interface --------===*\
+ * *
+ * This file implements the interface that we will expect operating *
+ * systems to implement if they wish to support offline cachine. *
+ * *
+\*===----------------------------------------------------------------------===*/
+
+#include "OSInterface.h"
+#include "SysUtils.h"
+#include "Config/fcntl.h"
+#include "Config/stdlib.h"
+#include "Config/unistd.h"
+#include "Config/sys/types.h"
+#include "Config/sys/stat.h"
+#include <stdio.h>
+#include <string.h>
+
+static const char CacheRoot[] = "/tmp/LLVMCache";
+static const char ExeSuffix[] = ".exe";
+
+char* computeCachedFile(const char *key) {
+ /* CacheRoot + "/" + std::string(key) + ExeSuffix; */
+ char *cacheFile = (char*) malloc(strlen(CacheRoot) + 1 + strlen(key) +
+ strlen(ExeSuffix) + 1);
+ char *pCacheFile = cacheFile;
+ if (!cacheFile) return 0;
+ memcpy(cacheFile, CacheRoot, strlen(CacheRoot));
+ pCacheFile += strlen(CacheRoot);
+ *pCacheFile++ = '/';
+ memcpy(pCacheFile, key, strlen(key));
+ pCacheFile += strlen(key);
+ memcpy(pCacheFile, ExeSuffix, strlen(ExeSuffix));
+ pCacheFile += strlen(ExeSuffix);
+ *pCacheFile = 0; // Null-terminate
+ return cacheFile;
+}
+
+/*
+ * llvmStat - equivalent to stat(3), except the key may not necessarily
+ * correspond to a file by that name, implementation is up to the OS.
+ * Values returned in buf are similar as they are in Unix.
+ */
+void llvmStat(const char *key, struct stat *buf) {
+ char* cacheFile = computeCachedFile(key);
+ fprintf(stderr, "llvmStat(%s)\n", cacheFile);
+ stat(cacheFile, buf);
+ free(cacheFile);
+}
+
+/*
+ * llvmWriteFile - implements a 'save' of a file in the OS. 'key' may not
+ * necessarily map to a file of the same name.
+ * Returns:
+ * 0 - success
+ * non-zero - error
+ */
+int llvmWriteFile(const char *key, const void *data, size_t len)
+{
+ char* cacheFile = computeCachedFile(key);
+ int fd = open(cacheFile, O_CREAT|O_WRONLY|O_TRUNC);
+ free(cacheFile);
+ if (fd < 0) return -1; // encountered an error
+ if (write(fd, data, len)) return -1;
+ if (fsync(fd)) return -1;
+ if (close(fd)) return -1;
+ return 0;
+}
+
+/*
+ * llvmReadFile - tells the OS to load data corresponding to a particular key
+ * somewhere into memory.
+ * Returns:
+ * 0 - failure
+ * non-zero - address of loaded file
+ *
+ * Value of size is the length of data loaded into memory.
+ */
+void* llvmReadFile(const char *key, size_t *size) {
+ char* cacheFile = computeCachedFile(key);
+ if (!cacheFile) return 0;
+ struct stat buf;
+ stat(cacheFile, &buf);
+ int fd = open(cacheFile, O_RDONLY);
+ if (fd < 0) return 0; // encountered an error
+ void* data = malloc(buf.st_size);
+ if (read(fd, data, buf.st_size)) {
+ free(data);
+ return 0;
+ }
+ *size = buf.st_size;
+ return data;
+}
+
+/*
+ * llvmExecve - execute a file from cache. This is a temporary proof-of-concept
+ * because we do not relocate what we can read from disk.
+ */
+int llvmExecve(const char *filename, char *const argv[], char *const envp[]) {
+ char* cacheFile = computeCachedFile(filename);
+ executeProgram(cacheFile, argv, envp);
+}
diff --git a/tools/llee/SysUtils.c b/tools/llee/SysUtils.c
index 8399612446..6d6dc50a6a 100644
--- a/tools/llee/SysUtils.c
+++ b/tools/llee/SysUtils.c
@@ -6,35 +6,46 @@
//===----------------------------------------------------------------------===//
#include "SysUtils.h"
-#include "Config/sys/types.h"
-#include "Config/sys/stat.h"
+#include "Config/dlfcn.h"
+#include "Config/errno.h"
#include "Config/fcntl.h"
-#include "Config/sys/wait.h"
#include "Config/unistd.h"
-#include "Config/errno.h"
+#include "Config/sys/stat.h"
+#include "Config/sys/types.h"
+#include "Config/sys/wait.h"
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
+ * isExecutable - This function returns true if given struct stat describes the
+ * file as being executable.
+ */
+unsigned isExecutable(const struct stat *buf) {
+ if (!(buf->st_mode & S_IFREG))
+ return 0; // 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;
+}
+
+/*
* isExecutableFile - This function returns true if the filename specified
* exists and is executable.
*/
unsigned isExecutableFile(const char *ExeFileName) {
- struct stat Buf;
- if (stat(ExeFileName, &Buf))
+ struct stat buf;
+ if (stat(ExeFileName, &buf))
return 0; // Must not be executable!
- if (!(Buf.st_mode & S_IFREG))
- return 0; // 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;
+ return isExecutable(&buf);
}
+
/*
* FindExecutable - Find a named executable in the directories listed in $PATH.
* If the executable cannot be found, returns NULL.
@@ -81,3 +92,29 @@ char *FindExecutable(const char *ExeName) {
/* If we fell out, we ran out of directories to search, return failure. */
return NULL;
}
+
+/*
+ * 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);
+}
diff --git a/tools/llee/SysUtils.h b/tools/llee/SysUtils.h
index 84e7f9d6b2..2e498a80e8 100644
--- a/tools/llee/SysUtils.h
+++ b/tools/llee/SysUtils.h
@@ -8,6 +8,14 @@
#ifndef SYSUTILS_H
#define SYSUTILS_H
+struct stat;
+
+/*
+ * isExecutable - This function returns true if given struct stat describes the
+ * file as being executable.
+ */
+unsigned isExecutable(const struct stat *buf);
+
/*
* isExecutableFile - This function returns true if the filename specified
* exists and is executable.
@@ -19,4 +27,11 @@ unsigned isExecutableFile(const char *ExeFileName);
*/
char *FindExecutable(const char *ExeName);
+/*
+ * 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[]);
+
#endif
diff --git a/tools/llee/llee b/tools/llee/llee
deleted file mode 100755
index 7a3ea959ed..0000000000
--- a/tools/llee/llee
+++ /dev/null
@@ -1 +0,0 @@
-exec env LD_PRELOAD=`pwd`/execve.so $*