/*\r
- * Acess v0.1\r
+ * Acess2 - AcessNative\r
+ *\r
* ELF Executable Loader Code\r
*/\r
#define DEBUG 0\r
#include <stdio.h>\r
#include <string.h>\r
#include <unistd.h>\r
+#include <inttypes.h> // PRIx64\r
#include "common.h"\r
#include "elf32.h"\r
+#include "elf64.h"\r
\r
#define DEBUG_WARN 1\r
\r
#define PTR(_val) ((void*)(uintptr_t)(_val))\r
\r
#if DEBUG\r
-# define ENTER(...)\r
+# 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, sizeof(hdr), &hdr);\r
+ acess__SysRead(FD, &hdr, sizeof(hdr));\r
\r
// Check the file type\r
if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
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
- int i;\r
- int iPageCount;\r
- uint32_t max, base;\r
- uint32_t addr;\r
- uint32_t baseDiff = 0;\r
- \r
ENTER("iFD", FD);\r
\r
// Check for a program header\r
- if(hdr->phoff == 0) {\r
+ if(hdr->e_phoff == 0) {\r
#if DEBUG_WARN\r
Warning("ELF File does not contain a program header\n");\r
#endif\r
}\r
\r
// Read Program Header Table\r
- phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount );\r
+ Elf32_Phdr* phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum );\r
if( !phtab ) {\r
LEAVE('n');\r
return NULL;\r
}\r
- LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
- acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);\r
- acess_read(FD, sizeof(Elf32_Phdr) * hdr->phentcount, phtab);\r
+ LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff);\r
+ acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum);\r
\r
// Count Pages\r
- iPageCount = 0;\r
- LOG("hdr.phentcount = %i\n", hdr->phentcount);\r
- for( i = 0; i < hdr->phentcount; i++ )\r
+ unsigned int iPageCount = 0;\r
+ LOG("hdr.e_phnum = %i\n", hdr->e_phnum);\r
+ for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
{\r
// Ignore Non-LOAD types\r
- if(phtab[i].Type != PT_LOAD)\r
+ if(phtab[i].p_type != PT_LOAD)\r
continue;\r
- iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
- LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);\r
+ iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;\r
+ LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize);\r
}\r
\r
LOG("iPageCount = %i\n", iPageCount);\r
//ret->Interpreter = NULL;\r
\r
// Prescan for base and size\r
- max = 0;\r
- base = 0xFFFFFFFF;\r
- for( i = 0; i < hdr->phentcount; i ++)\r
+ uint32_t max = 0;\r
+ uint32_t base = UINT32_MAX;\r
+ for( unsigned int i = 0; i < hdr->e_phnum; i ++)\r
{\r
- if( phtab[i].Type != PT_LOAD )\r
+ if( phtab[i].p_type != PT_LOAD )\r
continue;\r
- if( phtab[i].VAddr < base )\r
- base = phtab[i].VAddr;\r
- if( phtab[i].VAddr + phtab[i].MemSize > max )\r
- max = phtab[i].VAddr + phtab[i].MemSize;\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 = %08x, max = %08x\n", base, max);\r
\r
+ uint32_t baseDiff = 0;\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
}\r
\r
// Load Pages\r
- for( i = 0; i < hdr->phentcount; i++ )\r
+ for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
{\r
- //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
- LOG("phtab[%i] = {\n", i);\r
- LOG(" .Type = 0x%08x\n", phtab[i].Type);\r
- LOG(" .Offset = 0x%08x\n", phtab[i].Offset);\r
- LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr);\r
- LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr);\r
- LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize);\r
- LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize);\r
- LOG(" .Flags = 0x%08x\n", phtab[i].Flags);\r
- LOG(" .Align = 0x%08x\n", phtab[i].Align);\r
- LOGS(" }\n");\r
// Get Interpreter Name\r
- if( phtab[i].Type == PT_INTERP )\r
+ if( phtab[i].p_type == PT_INTERP )\r
{\r
char *tmp;\r
//if(ret->Interpreter) continue;\r
- tmp = malloc(phtab[i].FileSize);\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, phtab[i].FileSize, tmp);\r
+ tmp = malloc(phtab[i].p_filesz);\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(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].Type != PT_LOAD) continue;\r
+ if(phtab[i].p_type != PT_LOAD) continue;\r
\r
- LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n",\r
- i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize);\r
+ LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n",\r
+ i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz);\r
\r
- addr = phtab[i].VAddr + baseDiff;\r
+ uint64_t addr = phtab[i].p_vaddr + baseDiff;\r
\r
- if( AllocateMemory( addr, phtab[i].MemSize ) ) {\r
- fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n",\r
- addr, phtab[i].MemSize);\r
+ if( AllocateMemory( addr, phtab[i].p_memsz ) ) {\r
+ fprintf(stderr, "Elf_Load: Unable to map memory at 0x%"PRIx64" (0x%x bytes)\n",\r
+ addr, phtab[i].p_memsz);\r
free( phtab );\r
return NULL;\r
}\r
\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, phtab[i].FileSize, PTRMK(void, addr) );\r
- memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(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
LEAVE('p', base);\r
return PTRMK(void, base);\r
}\r
+\r
+void *Elf64Load(int FD, Elf64_Ehdr *hdr)\r
+{\r
+ ENTER("iFD", FD);\r
+ \r
+ if( sizeof(void*) == 4) {\r
+ Warning("ELF64 being loaded in 32-bit env, this may not work");\r
+ }\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
+ Elf64_Phdr* phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );\r
+ if( !phtab ) {\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ LOG("hdr.e_phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
+ acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
+ \r
+ // Count Pages\r
+ unsigned int iPageCount = 0;\r
+ LOG("hdr.e_phnum = %i\n", hdr->e_phnum);\r
+ for( unsigned int 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] = {p_vaddr:0x%llx, p_memsz: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
+ uint64_t max = 0;\r
+ uint64_t base = UINT64_MAX;\r
+ for( unsigned int 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
+ uint64_t baseDiff = 0;\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 )\r
+ goto _err;\r
+ baseDiff = base;\r
+ }\r
+ \r
+ // Load Pages\r
+ for( unsigned int 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__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(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 p_vaddr:0x%llx, p_offset:0x%llx, p_filesz:0x%llx, p_memsz: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
+ uint64_t 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 %"PRIx64" (0x%"PRIx64" bytes)\n",\r
+ (uint64_t)addr, (uint64_t)phtab[i].p_memsz);\r
+ goto _err;\r
+ }\r
+ \r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(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
+_err:\r
+ free(phtab);\r
+ LEAVE('n');\r
+ return NULL;\r
+}\r
+\r