X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Fld-acess_src%2Felf_load.c;h=19a8c13fc945255552d3afdc5e93308fd666dbb7;hb=71402d670b1de4f4db7c1768e92ac1f723b51d9a;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..19a8c13f 100644 --- a/AcessNative/ld-acess_src/elf_load.c +++ b/AcessNative/ld-acess_src/elf_load.c @@ -1,14 +1,17 @@ /* - * Acess v0.1 + * Acess2 - AcessNative + * * ELF Executable Loader Code */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include #include +#include // PRIx64 #include "common.h" #include "elf32.h" +#include "elf64.h" #define DEBUG_WARN 1 @@ -20,7 +23,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,14 +34,15 @@ // === 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)); + acess__SysRead(FD, &hdr, sizeof(hdr)); // Check the file type if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') { @@ -49,11 +53,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; @@ -81,8 +89,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) return NULL; } LOG("hdr.phoff = 0x%08x\n", hdr->phoff); - acess_seek(FD, hdr->phoff, ACESS_SEEK_SET); - acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount); + acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET); + acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount); // Count Pages iPageCount = 0; @@ -122,8 +130,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; @@ -138,8 +146,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) char *tmp; //if(ret->Interpreter) continue; tmp = malloc(phtab[i].FileSize); - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, tmp, phtab[i].FileSize); + acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET); + acess__SysRead(FD, tmp, phtab[i].FileSize); //ret->Interpreter = Binary_RegInterp(tmp); LOG("Interpreter '%s'\n", tmp); free(tmp); @@ -160,8 +168,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) return NULL; } - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, PTRMK(void, addr), phtab[i].FileSize); + acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET); + acess__SysRead(FD, PTRMK(void, addr), phtab[i].FileSize); memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize ); } @@ -171,3 +179,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( sizeof(void*) == 4) { + Warning("ELF64 being loaded in 32-bit env, this may not work"); + } + + // 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__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET); + acess__SysRead(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__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); + acess__SysRead(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 %"PRIx64" (0x%"PRIx64" bytes)\n", + (uint64_t)addr, (uint64_t)phtab[i].p_memsz); + free( phtab ); + return NULL; + } + + acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); + acess__SysRead(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); +} +