[llvm-commits] CVS: llvm/tools/llee/OSInterface.h StorageProxy.c ExecveHandler.c Makefile SysUtils.c SysUtils.h llee

Misha Brukman brukman at cs.uiuc.edu
Mon Sep 29 17:38:01 PDT 2003


Changes in directory llvm/tools/llee:

OSInterface.h added (r1.1)
StorageProxy.c added (r1.1)
ExecveHandler.c updated: 1.3 -> 1.4
Makefile updated: 1.2 -> 1.3
SysUtils.c updated: 1.3 -> 1.4
SysUtils.h updated: 1.2 -> 1.3
llee (r1.1) removed

---
Log message:

* 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


---
Diffs of the changes:

Index: llvm/tools/llee/OSInterface.h
diff -c /dev/null llvm/tools/llee/OSInterface.h:1.1
*** /dev/null	Mon Sep 29 17:37:10 2003
--- llvm/tools/llee/OSInterface.h	Mon Sep 29 17:37:00 2003
***************
*** 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


Index: llvm/tools/llee/StorageProxy.c
diff -c /dev/null llvm/tools/llee/StorageProxy.c:1.1
*** /dev/null	Mon Sep 29 17:37:10 2003
--- llvm/tools/llee/StorageProxy.c	Mon Sep 29 17:37:00 2003
***************
*** 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);
+ }


Index: llvm/tools/llee/ExecveHandler.c
diff -u llvm/tools/llee/ExecveHandler.c:1.3 llvm/tools/llee/ExecveHandler.c:1.4
--- llvm/tools/llee/ExecveHandler.c:1.3	Sat Sep 27 17:26:37 2003
+++ llvm/tools/llee/ExecveHandler.c	Mon Sep 29 17:36:59 2003
@@ -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 @@
   /* 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 @@
   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 @@
     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';


Index: llvm/tools/llee/Makefile
diff -u llvm/tools/llee/Makefile:1.2 llvm/tools/llee/Makefile:1.3
--- llvm/tools/llee/Makefile:1.2	Fri Aug 15 18:31:54 2003
+++ llvm/tools/llee/Makefile	Mon Sep 29 17:37:00 2003
@@ -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


Index: llvm/tools/llee/SysUtils.c
diff -u llvm/tools/llee/SysUtils.c:1.3 llvm/tools/llee/SysUtils.c:1.4
--- llvm/tools/llee/SysUtils.c:1.3	Sat Sep 27 17:26:37 2003
+++ llvm/tools/llee/SysUtils.c	Mon Sep 29 17:37:00 2003
@@ -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.
@@ -80,4 +91,30 @@
 
   /* 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);
 }


Index: llvm/tools/llee/SysUtils.h
diff -u llvm/tools/llee/SysUtils.h:1.2 llvm/tools/llee/SysUtils.h:1.3
--- llvm/tools/llee/SysUtils.h:1.2	Fri Aug 15 18:31:16 2003
+++ llvm/tools/llee/SysUtils.h	Mon Sep 29 17:37:00 2003
@@ -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.
@@ -18,5 +26,12 @@
  * FindExecutable - Find a named executable in the path.
  */ 
 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





More information about the llvm-commits mailing list