changeset 4:54ff11eb9191

Now works properly on x86_64 :)
author Gregor Richards <Richards@codu.org>
date Sun, 13 Dec 2009 18:04:50 -0500
parents 56f873c979c3
children 6b8e05507b18
files elfload/src/elfload.c
diffstat 1 files changed, 72 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/elfload/src/elfload.c	Sat Jul 25 22:36:11 2009 -0400
+++ b/elfload/src/elfload.c	Sun Dec 13 18:04:50 2009 -0500
@@ -213,8 +213,8 @@
     }
 
     /* do processor-specific relocation */
-#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || \
-    defined(__x86_64__) || defined(_M_X64)
+#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[ELFNATIVE_R_SYM(currel->r_info)].st_name, \
@@ -261,6 +261,9 @@
                 case R_386_RELATIVE:
                     WORD32_REL(f->loc + REL_A);
                     break;
+
+                default:
+                    fprintf(stderr, "Unsupported relocation %d\n", ELFNATIVE_R_TYPE(currel->r_info));
             }
         }
     }
@@ -277,6 +280,73 @@
     }
 
 
+#elif 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[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 = (int32_t) (to)
+#define WORD64_REL(to) REL_A = (ssize_t) (to)
+
+    /* we ought to have rel and symtab defined */
+    if (f->rela && f->symtab) {
+        ElfNative_Rela *currel = f->rela;
+        for (; (void *) currel < (void *) f->rela + f->relasz; currel++) {
+            switch (ELFNATIVE_R_TYPE(currel->r_info)) {
+                case R_X86_64_64:
+                    WORD64_REL(REL_S + REL_A);
+                    break;
+
+                case R_X86_64_PC32:
+                    WORD32_REL(REL_S + REL_A - REL_P);
+                    break;
+
+                case R_X86_64_COPY:
+                {
+                    /* this is a bit more convoluted, as we need to find it in both places and copy */
+                    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);
+
+                    /* OK, we should have both, so copy it over */
+                    if (localsym && sosym) {
+                        memcpy((void *) (localsym->st_value + f->offset),
+                               soptr, sosym->st_size);
+                    } else {
+                        /* depend on localsym's size */
+                        memcpy((void *) (localsym->st_value + f->offset),
+                               soptr, localsym->st_size);
+
+                    }
+
+                    break;
+                }
+
+                case R_X86_64_RELATIVE:
+                    WORD64_REL(f->loc + REL_A);
+                    break;
+
+                default:
+                    fprintf(stderr, "Unsupported relocation %d\n", ELFNATIVE_R_TYPE(currel->r_info));
+            }
+        }
+    }
+
+    if (f->jmprel && f->symtab) {
+        ElfNative_Rel *currel = (ElfNative_Rel *) f->jmprel;
+        for (; (void *) currel < f->jmprel + f->jmprelsz; currel++) {
+            switch (ELFNATIVE_R_TYPE(currel->r_info)) {
+                case R_X86_64_JUMP_SLOT:
+                    WORD64_REL(REL_S);
+                    break;
+            }
+        }
+    }
+
+
 #else
 #error Unsupported architecture.
 #endif