AcessNative - Little fixes to get it running on 64-bit
[tpg/acess2.git] / AcessNative / ld-acess_src / elf_load.c
index 9e5a032..590da37 100644 (file)
@@ -1,5 +1,6 @@
 /*\r
- * Acess v0.1\r
+ * Acess2 - AcessNative\r
+ *\r
  * ELF Executable Loader Code\r
  */\r
 #define DEBUG  1\r
@@ -9,6 +10,7 @@
 #include <unistd.h>\r
 #include "common.h"\r
 #include "elf32.h"\r
+#include "elf64.h"\r
 \r
 #define DEBUG_WARN     1\r
 \r
@@ -20,7 +22,7 @@
 # define ENTER(...)    printf("%s: ---- ENTER ----\n", __func__);\r
 # define LOG(s, ...)   printf("%s: " s, __func__, __VA_ARGS__)\r
 # define LOGS(s)       printf("%s: " s, __func__)\r
-# define LEAVE(...)\r
+# define LEAVE(...)    printf("%s: ---- LEAVE ----\n", __func__);\r
 #else\r
 # define ENTER(...)\r
 # define LOG(...)\r
 // === PROTOTYPES ===\r
 void   *Elf_Load(int FD);\r
 void   *Elf32Load(int FD, Elf32_Ehdr *hdr);\r
+void   *Elf64Load(int FD, Elf64_Ehdr *hdr);\r
 \r
 // === CODE ===\r
 void *Elf_Load(int FD)\r
 {\r
-       Elf32_Ehdr      hdr;\r
+       Elf64_Ehdr      hdr;\r
        \r
        // Read ELF Header\r
        acess_read(FD, &hdr, sizeof(hdr));\r
@@ -49,11 +52,15 @@ void *Elf_Load(int FD)
        switch(hdr.e_ident[4])\r
        {\r
        case ELFCLASS32:\r
-               return Elf32Load(FD, &hdr);\r
+               return Elf32Load(FD, (void*)&hdr);\r
+       case ELFCLASS64:\r
+               return Elf64Load(FD, &hdr);\r
        default:\r
+               Warning("Unknown ELF class (%i)", hdr.e_ident[4]);\r
                return NULL;\r
        }\r
 }\r
+\r
 void *Elf32Load(int FD, Elf32_Ehdr *hdr)\r
 {\r
        Elf32_Phdr      *phtab;\r
@@ -122,8 +129,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
        LOG("base = %08x, max = %08x\n", base, max);\r
 \r
        if( base == 0 ) {\r
-               // Find a nice space (31 address bits allowed)\r
-               base = FindFreeRange( max, 31 );\r
+               // Find a nice space (47 address bits allowed)\r
+               base = FindFreeRange( max, 47 );\r
                LOG("new base = %08x\n", base);\r
                if( base == 0 ) return NULL;\r
                baseDiff = base;\r
@@ -171,3 +178,131 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
        LEAVE('p', base);\r
        return PTRMK(void, base);\r
 }\r
+\r
+void *Elf64Load(int FD, Elf64_Ehdr *hdr)\r
+{\r
+       Elf64_Phdr      *phtab;\r
+        int    i;\r
+        int    iPageCount;\r
+       uint64_t        max, base;\r
+       uint64_t        addr;\r
+       uint64_t        baseDiff = 0;\r
+       \r
+       ENTER("iFD", FD);\r
+       \r
+       #if BITS <= 32\r
+       Warning("ELF64 being loaded in 32-bit env, this may not work");\r
+       #endif\r
+\r
+       // Check for a program header\r
+       if(hdr->e_phoff == 0) {\r
+               #if DEBUG_WARN\r
+               Warning("ELF File does not contain a program header\n");\r
+               #endif\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Read Program Header Table\r
+       phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );\r
+       if( !phtab ) {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
+       acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+       acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
+       \r
+       // Count Pages\r
+       iPageCount = 0;\r
+       LOG("hdr.phentcount = %i\n", hdr->e_phnum);\r
+       for( i = 0; i < hdr->e_phnum; i++ )\r
+       {\r
+               // Ignore Non-LOAD types\r
+               if(phtab[i].p_type != PT_LOAD)\r
+                       continue;\r
+               iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;\r
+               LOG("phtab[%i] = {VAddr:0x%llx, MemSize:0x%llx}\n",\r
+                       i, (long long)phtab[i].p_vaddr, (long long)phtab[i].p_memsz);\r
+       }\r
+       \r
+       LOG("iPageCount = %i\n", iPageCount);\r
+       \r
+       // Allocate Information Structure\r
+       //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
+       // Fill Info Struct\r
+       //ret->Entry = hdr.entrypoint;\r
+       //ret->Base = -1;               // Set Base to maximum value\r
+       //ret->NumPages = iPageCount;\r
+       //ret->Interpreter = NULL;\r
+\r
+       // Prescan for base and size\r
+       max = 0;\r
+       base = 0xFFFFFFFF;\r
+       for( i = 0; i < hdr->e_phnum; i ++)\r
+       {\r
+               if( phtab[i].p_type != PT_LOAD )\r
+                       continue;\r
+               if( phtab[i].p_vaddr < base )\r
+                       base = phtab[i].p_vaddr;\r
+               if( phtab[i].p_vaddr + phtab[i].p_memsz > max )\r
+                       max = phtab[i].p_vaddr + phtab[i].p_memsz;\r
+       }\r
+\r
+       LOG("base = %08lx, max = %08lx\n", base, max);\r
+\r
+       if( base == 0 ) {\r
+               // Find a nice space (31 address bits allowed)\r
+               base = FindFreeRange( max, 31 );\r
+               LOG("new base = %08lx\n", base);\r
+               if( base == 0 ) return NULL;\r
+               baseDiff = base;\r
+       }\r
+       \r
+       // Load Pages\r
+       for( i = 0; i < hdr->e_phnum; i++ )\r
+       {\r
+               // Get Interpreter Name\r
+               if( phtab[i].p_type == PT_INTERP )\r
+               {\r
+                       char *tmp;\r
+                       //if(ret->Interpreter)  continue;\r
+                       tmp = malloc(phtab[i].p_filesz+1);\r
+                       tmp[ phtab[i].p_filesz ] = 0;\r
+                       acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+                       acess_read(FD, tmp, phtab[i].p_filesz);\r
+                       //ret->Interpreter = Binary_RegInterp(tmp);\r
+                       LOG("Interpreter '%s'\n", tmp);\r
+                       free(tmp);\r
+                       continue;\r
+               }\r
+               // Ignore non-LOAD types\r
+               if(phtab[i].p_type != PT_LOAD)  continue;\r
+               \r
+               LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%llx, Offset:0x%llx, FileSize:0x%llx, MemSize:0x%llx}\n",\r
+                       i,\r
+                       (long long)phtab[i].p_vaddr+baseDiff, (long long)phtab[i].p_offset,\r
+                       (long long)phtab[i].p_filesz, (long long)phtab[i].p_memsz\r
+                       );\r
+               \r
+               addr = phtab[i].p_vaddr + baseDiff;\r
+\r
+               if( AllocateMemory( addr, phtab[i].p_memsz ) ) {\r
+                       fprintf(stderr, "Elf_Load: Unable to map memory at %llx (0x%llx bytes)\n",\r
+                               (long long)addr, (long long)phtab[i].p_memsz);\r
+                       free( phtab );\r
+                       return NULL;\r
+               }\r
+               \r
+               acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+               acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
+               memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );\r
+       }\r
+       \r
+       // Clean Up\r
+       free(phtab);\r
+       // Return\r
+       LEAVE('p', base);\r
+       return PTRMK(void, base);\r
+}\r
+\r

UCC git Repository :: git.ucc.asn.au