changeset 2:994ca5c4a51c

Added (untested) 64-bit support.
author Gregor Richards <Richards@codu.org>
date Sat, 25 Jul 2009 16:12:41 -0400
parents cabe9c86a5b5
children 56f873c979c3
files README elfload/Makefile.in elfload/config.h.in elfload/configure elfload/configure.ac elfload/scripts/ac_compile_check_sizeof.ac elfload/src/Makefile.in elfload/src/elfload.c elfload/src/elfload.h elfload/src/elfload_exec.h elfload/src/main.c
diffstat 11 files changed, 177 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/README	Fri Jul 24 21:13:46 2009 -0400
+++ b/README	Sat Jul 25 16:12:41 2009 -0400
@@ -27,7 +27,7 @@
 make all install
 
 
-The ELF binaries can be run with elfload.exe, provided in crosslibc.
+The ELF binaries can be run with elfload.exe.
 
 
 For reference, the GCC configure flags:
--- a/elfload/Makefile.in	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/Makefile.in	Sat Jul 25 16:12:41 2009 -0400
@@ -35,7 +35,9 @@
 	$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
 	scripts/depcomp scripts/install-sh scripts/missing
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__aclocal_m4_deps =  \
+	$(top_srcdir)/scripts/ac_compile_check_sizeof.ac \
+	$(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -402,6 +404,10 @@
 	tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
 	$(am__remove_distdir)
 
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+	$(am__remove_distdir)
+
 dist-tarZ: distdir
 	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
 	$(am__remove_distdir)
@@ -430,6 +436,8 @@
 	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
 	*.tar.lzma*) \
 	  unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
 	*.tar.Z*) \
 	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
 	*.shar.gz*) \
@@ -580,15 +588,15 @@
 .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
 	all all-am am--refresh check check-am clean clean-generic \
 	ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
-	dist-lzma dist-shar dist-tarZ dist-zip distcheck distclean \
-	distclean-generic distclean-hdr distclean-tags distcleancheck \
-	distdir distuninstallcheck dvi dvi-am html html-am info \
-	info-am install install-am install-data install-data-am \
-	install-dvi install-dvi-am install-exec install-exec-am \
-	install-html install-html-am install-info install-info-am \
-	install-man install-pdf install-pdf-am install-ps \
-	install-ps-am install-strip installcheck installcheck-am \
-	installdirs installdirs-am maintainer-clean \
+	dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
+	distclean distclean-generic distclean-hdr distclean-tags \
+	distcleancheck distdir distuninstallcheck dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
 	pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
 
--- a/elfload/config.h.in	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/config.h.in	Sat Jul 25 16:12:41 2009 -0400
@@ -66,6 +66,9 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* The number of bytes in type void * */
+#undef SIZEOF_VOID_P
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
--- a/elfload/configure	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/configure	Sat Jul 25 16:12:41 2009 -0400
@@ -2317,6 +2317,9 @@
 
 
 
+
+
+
 # Checks for programs.
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -5268,6 +5271,75 @@
 ;;
   esac
 
+{ $as_echo "$as_me:$LINENO: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if test "${ac_cv_sizeof_void_p+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+int
+main ()
+{
+switch (0) case 0: case (sizeof (void *) == $ac_size):;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sizeof_void_p=$ac_size
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  if test x$ac_cv_sizeof_void_p != x ; then break; fi
+done
+
+fi
+
+if test x$ac_cv_sizeof_void_p = x ; then
+  { { $as_echo "$as_me:$LINENO: error: cannot determine a size for void *" >&5
+$as_echo "$as_me: error: cannot determine a size for void *" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
 
 # Checks for library functions.
 #AC_FUNC_ALLOCA
@@ -6377,9 +6449,9 @@
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 # Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-config_commands="$ac_config_commands"
+config_files="`echo $ac_config_files`"
+config_headers="`echo $ac_config_headers`"
+config_commands="`echo $ac_config_commands`"
 
 _ACEOF
 
--- a/elfload/configure.ac	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/configure.ac	Sat Jul 25 16:12:41 2009 -0400
@@ -9,6 +9,8 @@
 AC_CONFIG_AUX_DIR([scripts])
 AM_INIT_AUTOMAKE()
 
+m4_include([scripts/ac_compile_check_sizeof.ac])
+
 # Checks for programs.
 AC_PROG_CC
 AC_PROG_RANLIB
@@ -51,6 +53,7 @@
 AC_TYPE_UINT16_T
 AC_TYPE_UINT32_T
 AC_TYPE_UINT64_T
+AC_COMPILE_CHECK_SIZEOF([void *])
 
 # Checks for library functions.
 #AC_FUNC_ALLOCA
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/elfload/scripts/ac_compile_check_sizeof.ac	Sat Jul 25 16:12:41 2009 -0400
@@ -0,0 +1,25 @@
+AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[for ac_size in 4 8 1 2 16 $3 ; do # List sizes in rough order of prevalence.
+  AC_TRY_COMPILE([#include "confdefs.h"
+#include <sys/types.h>
+$2
+], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
+  if test x$AC_CV_NAME != x ; then break; fi
+done
+])
+if test x$AC_CV_NAME = x ; then
+  AC_MSG_ERROR([cannot determine a size for $1])
+fi
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
--- a/elfload/src/Makefile.in	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/src/Makefile.in	Sat Jul 25 16:12:41 2009 -0400
@@ -38,7 +38,9 @@
 DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__aclocal_m4_deps =  \
+	$(top_srcdir)/scripts/ac_compile_check_sizeof.ac \
+	$(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
--- a/elfload/src/elfload.c	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/src/elfload.c	Sat Jul 25 16:12:41 2009 -0400
@@ -39,8 +39,8 @@
     int i, fileNo, phdri;
     struct ELF_File *f;
     void *curphdrl;
-    Elf32_Phdr *curphdr;
-    Elf32_Dyn *curdyn;
+    ElfNative_Phdr *curphdr;
+    ElfNative_Dyn *curdyn;
 
     /* first, make sure it's not already loaded or loading */
     for (i = 0; i < elfFileCount; i++) {
@@ -93,15 +93,16 @@
     readFile(nm, f);
 
     /* make sure it's an ELF file */
-    f->ehdr = (Elf32_Ehdr *) f->prog;
+    f->ehdr = (ElfNative_Ehdr *) f->prog;
     if (memcmp(f->ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
         fprintf(stderr, "%s does not appear to be an ELF file.\n", nm);
         exit(1);
     }
 
-    /* only 32-bit supported for the moment */
-    if (f->ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
-        fprintf(stderr, "%s is not a 32-bit ELF file.\n", nm);
+    /* only native-bit supported for the moment */
+    if ((SIZEOF_VOID_P == 4 && f->ehdr->e_ident[EI_CLASS] != ELFCLASS32) ||
+        (SIZEOF_VOID_P == 8 && f->ehdr->e_ident[EI_CLASS] != ELFCLASS64)) {
+        fprintf(stderr, "%s is not a %d-bit ELF file.\n", SIZEOF_VOID_P * 8, nm);
         exit(1);
     }
 
@@ -121,7 +122,7 @@
 
     for (phdri = 0; phdri < f->ehdr->e_phnum; phdri++) {
         curphdrl += f->ehdr->e_phentsize;
-        curphdr = (Elf32_Phdr *) curphdrl;
+        curphdr = (ElfNative_Phdr *) curphdrl;
 
         /* perhaps check its location */
         if (curphdr->p_type == PT_LOAD) {
@@ -154,7 +155,7 @@
     curphdrl = f->prog + f->ehdr->e_phoff - f->ehdr->e_phentsize;
     for (phdri = 0; phdri < f->ehdr->e_phnum; phdri++) {
         curphdrl += f->ehdr->e_phentsize;
-        curphdr = (Elf32_Phdr *) curphdrl;
+        curphdr = (ElfNative_Phdr *) curphdrl;
 
         /* perhaps load it in */
         if (curphdr->p_type == PT_LOAD) {
@@ -167,7 +168,7 @@
 
         } else if (curphdr->p_type == PT_DYNAMIC) {
             /* we need this to load in dependencies, et cetera */
-            f->dynamic = (Elf32_Dyn *) (f->prog + curphdr->p_offset);
+            f->dynamic = (ElfNative_Dyn *) (f->prog + curphdr->p_offset);
 
         }
     }
@@ -178,19 +179,19 @@
             f->strtab = (char *) (curdyn->d_un.d_ptr + f->offset);
 
         } else if (curdyn->d_tag == DT_SYMTAB) {
-            f->symtab = (Elf32_Sym *) (curdyn->d_un.d_ptr + f->offset);
+            f->symtab = (ElfNative_Sym *) (curdyn->d_un.d_ptr + f->offset);
 
         } else if (curdyn->d_tag == DT_HASH) {
-            f->hashtab = (Elf32_Word *) (curdyn->d_un.d_ptr + f->offset);
+            f->hashtab = (ElfNative_Word *) (curdyn->d_un.d_ptr + f->offset);
 
         } else if (curdyn->d_tag == DT_RELA) {
-            f->rela = (Elf32_Rela *) (curdyn->d_un.d_ptr + f->offset);
+            f->rela = (ElfNative_Rela *) (curdyn->d_un.d_ptr + f->offset);
 
         } else if (curdyn->d_tag == DT_RELASZ) {
             f->relasz = curdyn->d_un.d_val;
 
         } else if (curdyn->d_tag == DT_REL) {
-            f->rel = (Elf32_Rel *) (curdyn->d_un.d_ptr + f->offset);
+            f->rel = (ElfNative_Rel *) (curdyn->d_un.d_ptr + f->offset);
 
         } else if (curdyn->d_tag == DT_RELSZ) {
             f->relsz = curdyn->d_un.d_val;
@@ -212,19 +213,20 @@
     }
 
     /* do processor-specific relocation */
-#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_)
+#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || \
+    defined(__x86_64__) || defined(_M_X64)
 #define REL_P ((ssize_t) (currel->r_offset + f->offset))
 #define REL_S ((ssize_t) (findELFSymbol( \
-                f->strtab + f->symtab[ELF32_R_SYM(currel->r_info)].st_name, \
+                f->strtab + f->symtab[ELFNATIVE_R_SYM(currel->r_info)].st_name, \
                 NULL, fileNo, -1, NULL)))
 #define REL_A (*((ssize_t *) REL_P))
 #define WORD32_REL(to) REL_A = (ssize_t) (to)
 
     /* we ought to have rel and symtab defined */
     if (f->rel && f->symtab) {
-        Elf32_Rel *currel = f->rel;
+        ElfNative_Rel *currel = f->rel;
         for (; (void *) currel < (void *) f->rel + f->relsz; currel++) {
-            switch (ELF32_R_TYPE(currel->r_info)) {
+            switch (ELFNATIVE_R_TYPE(currel->r_info)) {
                 case R_386_32:
                     WORD32_REL(REL_S + REL_A);
                     break;
@@ -236,8 +238,8 @@
                 case R_386_COPY:
                 {
                     /* this is a bit more convoluted, as we need to find it in both places and copy */
-                    Elf32_Sym *localsym, *sosym;
-                    localsym = &(f->symtab[ELF32_R_SYM(currel->r_info)]);
+                    ElfNative_Sym *localsym, *sosym;
+                    localsym = &(f->symtab[ELFNATIVE_R_SYM(currel->r_info)]);
                     void *soptr = findELFSymbol(
                             f->strtab + localsym->st_name,
                             NULL, -1, fileNo, &sosym);
@@ -264,9 +266,9 @@
     }
 
     if (f->jmprel && f->symtab) {
-        Elf32_Rel *currel = (Elf32_Rel *) f->jmprel;
+        ElfNative_Rel *currel = (ElfNative_Rel *) f->jmprel;
         for (; (void *) currel < f->jmprel + f->jmprelsz; currel++) {
-            switch (ELF32_R_TYPE(currel->r_info)) {
+            switch (ELFNATIVE_R_TYPE(currel->r_info)) {
                 case R_386_JMP_SLOT:
                     WORD32_REL(REL_S);
                     break;
@@ -287,7 +289,7 @@
 {
     int i;
     struct ELF_File *f;
-    Elf32_Dyn *dyn;
+    ElfNative_Dyn *dyn;
 
     for (i = elfFileCount - 1; i >= 0; i--) {
         f = &(elfFiles[i]);
@@ -309,13 +311,13 @@
  * localin: The number of the current file, where STB_LOCAL symbols are OK
  * notin: Do not bind to symbols in this file 
  * Either can be -1 */
-void *findELFSymbol(const char *nm, struct ELF_File *onlyin, int localin, int notin, Elf32_Sym **syminto)
+void *findELFSymbol(const char *nm, struct ELF_File *onlyin, int localin, int notin, ElfNative_Sym **syminto)
 {
     int i;
     struct ELF_File *f;
-    Elf32_Word hash = elf_hash((unsigned char *) nm);
-    Elf32_Word bucket, index;
-    Elf32_Sym *sym;
+    ElfNative_Word hash = elf_hash((unsigned char *) nm);
+    ElfNative_Word bucket, index;
+    ElfNative_Sym *sym;
     void *hostsym;
 
     if (nm[0] == '\0') return NULL;
@@ -383,7 +385,7 @@
 
             /* see if it's defined */
             if (strcmp(f->strtab + sym->st_name, nm) == 0 &&
-                (i == localin || ELF32_ST_BIND(sym->st_info) != STB_LOCAL) &&
+                (i == localin || ELFNATIVE_ST_BIND(sym->st_info) != STB_LOCAL) &&
                 sym->st_shndx != SHN_UNDEF) {
                 /* we found our symbol! */
                 if (syminto != NULL) {
@@ -400,9 +402,9 @@
 }
 
 /* The standard ELF hash function */
-Elf32_Word elf_hash(const unsigned char *name)
+ElfNative_Word elf_hash(const unsigned char *name)
 {
-    Elf32_Word h = 0, g;
+    ElfNative_Word h = 0, g;
 
     while (*name) {
         h = (h << 4) + *name++;
--- a/elfload/src/elfload.h	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/src/elfload.h	Sat Jul 25 16:12:41 2009 -0400
@@ -3,7 +3,7 @@
 
 #include <sys/types.h>
 
-#include "elfload_elf.h"
+#include "elfnative.h"
 
 #define HOSTLIB_NOT  0
 #define HOSTLIB_HOST 1
@@ -21,7 +21,7 @@
     size_t proglen;
 
     /* same pointer, actually */
-    Elf32_Ehdr *ehdr;
+    ElfNative_Ehdr *ehdr;
 
     /* the size in memory of this file */
     ssize_t memsz;
@@ -36,25 +36,25 @@
     ssize_t offset;
 
     /* the dynamic entries table */
-    Elf32_Dyn *dynamic;
+    ElfNative_Dyn *dynamic;
 
     /* the string table */
     char *strtab;
 
     /* and symbol table */
-    Elf32_Sym *symtab;
+    ElfNative_Sym *symtab;
 
     /* with its associated hash table */
-    Elf32_Word *hashtab;
+    ElfNative_Word *hashtab;
 #define ELFFILE_NBUCKET(f) ((f)->hashtab[0])
 #define ELFFILE_NCHAIN(f) ((f)->hashtab[1])
 #define ELFFILE_BUCKET(f, i) ((f)->hashtab[(i) + 2])
 #define ELFFILE_CHAIN(f, i) ((f)->hashtab[(i) + ELFFILE_NBUCKET(f) + 2])
 
     /* relocation table(s) */
-    Elf32_Rel *rel;
+    ElfNative_Rel *rel;
     size_t relsz;
-    Elf32_Rela *rela;
+    ElfNative_Rela *rela;
     size_t relasz;
     void *jmprel;
     size_t jmprelsz;
@@ -65,7 +65,7 @@
 void readFile(const char *nm, struct ELF_File *ef);
 void closeFile(struct ELF_File *ef);
 void *findELFSymbol(const char *nm, struct ELF_File *onlyin, int localin, int notin,
-                    Elf32_Sym **syminto);
-Elf32_Word elf_hash(const unsigned char *name);
+                    ElfNative_Sym **syminto);
+ElfNative_Word elf_hash(const unsigned char *name);
 
 #endif
--- a/elfload/src/elfload_exec.h	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/src/elfload_exec.h	Sat Jul 25 16:12:41 2009 -0400
@@ -19,13 +19,20 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef __i386__
+#if defined(__i386__)
 #define WITHSTACK_JMP(newstack, newloc) \
     asm("mov %0, %%esp\n" \
         "jmp *%1\n" \
         : \
         : "r"(newstack), "r"(newloc));
 
+#elif defined(__x86_64__)
+#define WITHSTACK_JMP(newstack, newloc) \
+    asm("mov %0, %%rsp\n" \
+        "jmp *%1\n" \
+        : \
+        : "r"(newstack), "r"(newloc));
+
 #else
 #error No assembly code for subprocess execution known.
 #endif
--- a/elfload/src/main.c	Fri Jul 24 21:13:46 2009 -0400
+++ b/elfload/src/main.c	Sat Jul 25 16:12:41 2009 -0400
@@ -25,7 +25,7 @@
     for (envc = 0; envp[envc]; envc++);
     newstack = (void**)
         alloca((argc + envc + 2) * sizeof(void*));
-    newstack[0] = (void*) (argc - 1);
+    newstack[0] = (void*) (size_t) (argc - 1);
     for (i = 1; i < argc; i++) {
         newstack[i] = (void*) argv[i];
     }