diff options
author | Misha Brukman <brukman+llvm@gmail.com> | 2003-09-29 22:37:00 +0000 |
---|---|---|
committer | Misha Brukman <brukman+llvm@gmail.com> | 2003-09-29 22:37:00 +0000 |
commit | 2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d (patch) | |
tree | eb3df0aeb13232e8d0a3d9be88aacd047e013a3c /tools/llee | |
parent | e676313966c3ede37644dbf2e49aa06f0c8b242a (diff) | |
download | external_llvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.zip external_llvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.tar.gz external_llvm-2e1fbdd267b5b7f2cfc1c04e7bef1e8a98f7813d.tar.bz2 |
* 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
Diffstat (limited to 'tools/llee')
-rw-r--r-- | tools/llee/ExecveHandler.c | 79 | ||||
-rw-r--r-- | tools/llee/Makefile | 26 | ||||
-rw-r--r-- | tools/llee/OSInterface.h | 48 | ||||
-rw-r--r-- | tools/llee/StorageProxy.c | 101 | ||||
-rw-r--r-- | tools/llee/SysUtils.c | 67 | ||||
-rw-r--r-- | tools/llee/SysUtils.h | 15 | ||||
-rwxr-xr-x | tools/llee/llee | 1 |
7 files changed, 263 insertions, 74 deletions
diff --git a/tools/llee/ExecveHandler.c b/tools/llee/ExecveHandler.c index dba419c..4b74014 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 b391298..cbaf896 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 0000000..18fe0da --- /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 0000000..0562796 --- /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 8399612..6d6dc50 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 84e7f9d..2e498a8 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 7a3ea95..0000000 --- a/tools/llee/llee +++ /dev/null @@ -1 +0,0 @@ -exec env LD_PRELOAD=`pwd`/execve.so $* |