X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Fld-acess_src%2Felf_load.c;h=76d92519a8b5ddf2f631d5228838e8c3c43fa718;hb=9a9053e91df6e08761e2ce72be350c5c2233153b;hp=49298699c0fe43ed5cb721dfe88048d28c0c564e;hpb=b8b25ae01e13c655608fb6705574e5218b1a519f;p=tpg%2Facess2.git diff --git a/AcessNative/ld-acess_src/elf_load.c b/AcessNative/ld-acess_src/elf_load.c index 49298699..76d92519 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 0 @@ -7,8 +8,10 @@ #include #include #include +#include // PRIx64 #include "common.h" #include "elf32.h" +#include "elf64.h" #define DEBUG_WARN 1 @@ -17,10 +20,10 @@ #define PTR(_val) ((void*)(uintptr_t)(_val)) #if DEBUG -# define ENTER(...) +# 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, sizeof(hdr), &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,24 +53,21 @@ 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; - int i; - int iPageCount; - uint32_t max, base; - uint32_t addr; - uint32_t baseDiff = 0; - ENTER("iFD", FD); // Check for a program header - if(hdr->phoff == 0) { + if(hdr->e_phoff == 0) { #if DEBUG_WARN Warning("ELF File does not contain a program header\n"); #endif @@ -75,25 +76,25 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) } // Read Program Header Table - phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount ); + Elf32_Phdr* phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum ); if( !phtab ) { LEAVE('n'); return NULL; } - LOG("hdr.phoff = 0x%08x\n", hdr->phoff); - acess_seek(FD, hdr->phoff, ACESS_SEEK_SET); - acess_read(FD, sizeof(Elf32_Phdr) * hdr->phentcount, phtab); + LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff); + acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET); + acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum); // Count Pages - iPageCount = 0; - LOG("hdr.phentcount = %i\n", hdr->phentcount); - for( i = 0; i < hdr->phentcount; i++ ) + unsigned int iPageCount = 0; + LOG("hdr.e_phnum = %i\n", hdr->e_phnum); + for( unsigned int i = 0; i < hdr->e_phnum; i++ ) { // Ignore Non-LOAD types - if(phtab[i].Type != PT_LOAD) + if(phtab[i].p_type != PT_LOAD) continue; - iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12; - LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize); + iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12; + LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize); } LOG("iPageCount = %i\n", iPageCount); @@ -107,73 +108,63 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) //ret->Interpreter = NULL; // Prescan for base and size - max = 0; - base = 0xFFFFFFFF; - for( i = 0; i < hdr->phentcount; i ++) + uint32_t max = 0; + uint32_t base = UINT32_MAX; + for( unsigned int i = 0; i < hdr->e_phnum; i ++) { - if( phtab[i].Type != PT_LOAD ) + if( phtab[i].p_type != PT_LOAD ) continue; - if( phtab[i].VAddr < base ) - base = phtab[i].VAddr; - if( phtab[i].VAddr + phtab[i].MemSize > max ) - max = phtab[i].VAddr + phtab[i].MemSize; + 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 = %08x, max = %08x\n", base, max); + uint32_t baseDiff = 0; 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; } // Load Pages - for( i = 0; i < hdr->phentcount; i++ ) + for( unsigned int i = 0; i < hdr->e_phnum; i++ ) { - //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type); - LOG("phtab[%i] = {\n", i); - LOG(" .Type = 0x%08x\n", phtab[i].Type); - LOG(" .Offset = 0x%08x\n", phtab[i].Offset); - LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr); - LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr); - LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize); - LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize); - LOG(" .Flags = 0x%08x\n", phtab[i].Flags); - LOG(" .Align = 0x%08x\n", phtab[i].Align); - LOGS(" }\n"); // Get Interpreter Name - if( phtab[i].Type == PT_INTERP ) + if( phtab[i].p_type == PT_INTERP ) { char *tmp; //if(ret->Interpreter) continue; - tmp = malloc(phtab[i].FileSize); - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, phtab[i].FileSize, tmp); + tmp = malloc(phtab[i].p_filesz); + 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].Type != PT_LOAD) continue; + if(phtab[i].p_type != PT_LOAD) continue; - LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n", - i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize); + LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n", + i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz); - addr = phtab[i].VAddr + baseDiff; + uint64_t addr = phtab[i].p_vaddr + baseDiff; - if( AllocateMemory( addr, phtab[i].MemSize ) ) { - fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n", - addr, phtab[i].MemSize); + if( AllocateMemory( addr, phtab[i].p_memsz ) ) { + fprintf(stderr, "Elf_Load: Unable to map memory at 0x%"PRIx64" (0x%x bytes)\n", + addr, phtab[i].p_memsz); free( phtab ); return NULL; } - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, phtab[i].FileSize, PTRMK(void, addr) ); - memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize ); + 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 @@ -182,3 +173,129 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) LEAVE('p', base); return PTRMK(void, base); } + +void *Elf64Load(int FD, Elf64_Ehdr *hdr) +{ + 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 + Elf64_Phdr* phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum ); + if( !phtab ) { + LEAVE('n'); + return NULL; + } + LOG("hdr.e_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 + unsigned int iPageCount = 0; + LOG("hdr.e_phnum = %i\n", hdr->e_phnum); + for( unsigned int 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] = {p_vaddr:0x%llx, p_memsz: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 + uint64_t max = 0; + uint64_t base = UINT64_MAX; + for( unsigned int 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); + + uint64_t baseDiff = 0; + if( base == 0 ) { + // Find a nice space (31 address bits allowed) + base = FindFreeRange( max, 31 ); + LOG("new base = %08lx\n", base); + if( base == 0 ) + goto _err; + baseDiff = base; + } + + // Load Pages + for( unsigned int 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 p_vaddr:0x%llx, p_offset:0x%llx, p_filesz:0x%llx, p_memsz: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 + ); + + uint64_t 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); + goto _err; + } + + 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); +_err: + free(phtab); + LEAVE('n'); + return NULL; +} +