mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
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
This commit is contained in:
parent
00b40943ab
commit
0abaaf49fd
92
tools/llee/ExecveHandler.c
Normal file
92
tools/llee/ExecveHandler.c
Normal file
@ -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;
|
||||
}
|
21
tools/llee/Makefile
Normal file
21
tools/llee/Makefile
Normal file
@ -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)
|
81
tools/llee/SysUtils.c
Normal file
81
tools/llee/SysUtils.c
Normal file
@ -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;
|
||||
}
|
28
tools/llee/SysUtils.h
Normal file
28
tools/llee/SysUtils.h
Normal file
@ -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
|
1
tools/llee/llee
Executable file
1
tools/llee/llee
Executable file
@ -0,0 +1 @@
|
||||
exec env LD_PRELOAD=`pwd`/execve.so $*
|
Loading…
Reference in New Issue
Block a user