mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-01 09:26:22 +00:00
For PR351:
llee was a nice hack, but it wasn't portable so its gone, with Misha's approval. Operating systems have facilities available for making bytecode directly executable without this utility. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18916 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
395fd5949b
commit
90484fb9a2
@ -10,7 +10,7 @@
|
||||
LEVEL := ..
|
||||
PARALLEL_DIRS := llvm-as llvm-dis opt gccas llc llvm-link lli gccld llvm-stub \
|
||||
analyze extract bugpoint llvm-nm llvm-prof llvm-db \
|
||||
llvm-ar llvm-ranlib llvm-bcanalyzer llee llvmc llvm-ld
|
||||
llvm-ar llvm-ranlib llvm-bcanalyzer llvmc llvm-ld
|
||||
|
||||
EXTRA_DIST := Makefile.JIT
|
||||
|
||||
|
@ -1,84 +0,0 @@
|
||||
/*===-- ExecveHandler.c - Replaces execve() to run LLVM files -------------===*\
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file was developed by the LLVM research group and is distributed under
|
||||
* the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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 "llvm/Config/unistd.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* These are the expected headers for all valid LLVM bytecode files.
|
||||
* The first four characters must be one of these.
|
||||
*/
|
||||
static const char llvmHeaderUncompressed[] = "llvm";
|
||||
static const char llvmHeaderCompressed[] = "llvc";
|
||||
|
||||
/*
|
||||
* 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" */
|
||||
size_t headerSize = strlen(llvmHeaderCompressed);
|
||||
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(realFilename, O_RDONLY);
|
||||
/* Check validity of `file' */
|
||||
if (errno) return EIO;
|
||||
/* Read the header from the file */
|
||||
ssize_t bytesRead = read(file, header, headerSize);
|
||||
close(file);
|
||||
if (bytesRead != (ssize_t)headerSize) return EIO;
|
||||
if (!memcmp(llvmHeaderCompressed, header, headerSize) ||
|
||||
!memcmp(llvmHeaderUncompressed, 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;
|
||||
LLIargs[1] = realFilename;
|
||||
for (idx = 1; idx != argvSize; ++idx)
|
||||
LLIargs[idx+1] = argv[idx];
|
||||
LLIargs[argvSize + 1] = '\0';
|
||||
return executeProgram(LLIpath, LLIargs, envp);
|
||||
}
|
||||
return executeProgram(filename, argv, envp);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
##===- tools/llee/Makefile ---------------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file was developed by the LLVM research group and is distributed under
|
||||
# the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../..
|
||||
LIBRARYNAME = LLVMexecve
|
||||
SHARED_LIBRARY = 1
|
||||
DONT_BUILD_RELINKED = 1
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
all:: llee
|
||||
|
||||
llee: $(LLVMToolDir)/llee
|
||||
|
||||
$(LLVMToolDir)/llee: Makefile
|
||||
$(Echo) Constructing llee shell script
|
||||
$(Verb) echo exec env LD_PRELOAD=$(LibDir)/libLLVMexecve$(SHLIBEXT) $$\* > $@
|
||||
$(Verb) chmod u+x $@
|
||||
|
||||
clean::
|
||||
$(Verb) rm -f $(LLVMToolDir)/llee
|
@ -1,56 +0,0 @@
|
||||
/*===- OSInterface.h - Interface to query OS for functionality ---*- C -*--===*\
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file was developed by the LLVM research group and is distributed under
|
||||
* the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
*
|
||||
* 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 "llvm/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
|
@ -1,12 +0,0 @@
|
||||
LLEE: (LL)VM (E)xecution (E)nvironment
|
||||
|
||||
This tool presents a virtual execution environment for LLVM programs. By
|
||||
preloading a shared object which defines a custom execve() function, we can
|
||||
execute bytecode files with the JIT directly, without the user ever thinking
|
||||
about it.
|
||||
|
||||
Thus, a user can freely run any program, native or LLVM bytecode, transparently,
|
||||
and without even being aware of it.
|
||||
|
||||
To use LLEE, run `llee <native_program>'; a good choice is a shell. Anything
|
||||
started within that program will be affected by the execve() replacement.
|
@ -1,101 +0,0 @@
|
||||
/*===- 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 "llvm/Config/fcntl.h"
|
||||
#include "llvm/Config/unistd.h"
|
||||
#include "llvm/Config/sys/types.h"
|
||||
#include "llvm/Config/sys/stat.h"
|
||||
#include <stdlib.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);
|
||||
return executeProgram(cacheFile, argv, envp);
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/*===- SystemUtils.h - Utilities to do low-level system stuff -------------===*\
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file was developed by the LLVM research group and is distributed under
|
||||
* the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file contains functions used to do a variety of low-level, often
|
||||
* system-specific, tasks.
|
||||
*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "SysUtils.h"
|
||||
#include "llvm/Config/dlfcn.h"
|
||||
#include "llvm/Config/fcntl.h"
|
||||
#include "llvm/Config/unistd.h"
|
||||
#include "llvm/Config/sys/stat.h"
|
||||
#include "llvm/Config/sys/types.h"
|
||||
#include "llvm/Config/sys/wait.h"
|
||||
#include <errno.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))
|
||||
return 0; // Must not be executable!
|
||||
|
||||
return isExecutable(&buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 0;
|
||||
|
||||
/* 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 ? (unsigned)(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 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.
|
||||
*/
|
||||
const 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);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*===- SysUtils.h - Utilities to do low-level system stuff ----------------===*\
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file was developed by the LLVM research group and is distributed under
|
||||
* the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
*
|
||||
* This file contains functions used to do a variety of low-level, often
|
||||
* system-specific, tasks.
|
||||
*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#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.
|
||||
*/
|
||||
unsigned isExecutableFile(const char *ExeFileName);
|
||||
|
||||
/*
|
||||
* 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
|
Loading…
x
Reference in New Issue
Block a user