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