* Acess v0.1\r
* ELF Executable Loader Code\r
*/\r
-#define DEBUG 0\r
+#define DEBUG 1\r
#include <acess.h>\r
#include <binary.h>\r
#include "elf.h"\r
\r
// === PROTOTYPES ===\r
tBinary *Elf_Load(int fp);\r
+tBinary *Elf_Load64(int fp, Elf64_Ehdr *hdr);\r
+tBinary *Elf_Load32(int fp, Elf32_Ehdr *hdr);\r
int Elf_Relocate(void *Base);\r
+ int Elf_Relocate32(void *Base);\r
int Elf_GetSymbol(void *Base, const char *Name, Uint *ret);\r
int Elf_Int_DoRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab, Uint base);\r
Uint Elf_Int_HashString(const char *str);\r
// === CODE ===\r
tBinary *Elf_Load(int fp)\r
{\r
- tBinary *ret;\r
- Elf32_Ehdr hdr;\r
- Elf32_Phdr *phtab;\r
- int i, j;\r
- int iLoadCount;\r
- \r
- ENTER("xfp", fp);\r
+ Elf64_Ehdr hdr;\r
\r
// Read ELF Header\r
VFS_Read(fp, sizeof(hdr), &hdr);\r
\r
// Check the file type\r
- if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') {\r
+ if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
Log_Warning("ELF", "Non-ELF File was passed to the ELF loader");\r
- LEAVE('n');\r
return NULL;\r
}\r
+\r
+ switch(hdr.e_ident[4]) // EI_CLASS\r
+ {\r
+ case ELFCLASS32:\r
+ return Elf_Load32(fp, (Elf32_Ehdr*)&hdr);\r
+ case ELFCLASS64:\r
+ return Elf_Load64(fp, &hdr);\r
+ default:\r
+ Log_Warning("ELF", "Unknown EI_CLASS value %i", hdr.e_ident[4]);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+tBinary *Elf_Load64(int FD, Elf64_Ehdr *Header)\r
+{\r
+ tBinary *ret;\r
+ Elf64_Phdr phtab[Header->e_phnum];\r
+ int nLoadSegments;\r
+ int i, j;\r
\r
+ // Sanity check\r
+ if( Header->e_phoff == 0 )\r
+ {\r
+ Log_Warning("ELF", "No program header, panic!");\r
+ return NULL;\r
+ }\r
+ if( Header->e_shentsize != sizeof(Elf64_Shdr) ) {\r
+ Log_Warning("ELF", "Header gives shentsize as %i, my type is %i",\r
+ Header->e_shentsize, sizeof(Elf64_Shdr) );\r
+ }\r
+ if( Header->e_phentsize != sizeof(Elf64_Phdr) ) {\r
+ Log_Warning("ELF", "Header gives phentsize as %i, my type is %i",\r
+ Header->e_phentsize, sizeof(Elf64_Phdr) );\r
+ }\r
+\r
+ LOG("Header = {");\r
+ LOG(" e_ident = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",\r
+ Header->e_ident[0], Header->e_ident[1], Header->e_ident[2], Header->e_ident[3],\r
+ Header->e_ident[4], Header->e_ident[5], Header->e_ident[6], Header->e_ident[7],\r
+ Header->e_ident[8], Header->e_ident[9], Header->e_ident[10], Header->e_ident[11],\r
+ Header->e_ident[12], Header->e_ident[13], Header->e_ident[14], Header->e_ident[15]\r
+ );\r
+ LOG(" e_type = %i", Header->e_type);\r
+ LOG(" e_machine = %i", Header->e_machine);\r
+ LOG(" e_version = %i", Header->e_version);\r
+ LOG(" e_entry = 0x%llx", Header->e_entry);\r
+ LOG(" e_phoff = 0x%llx", Header->e_phoff);\r
+ LOG(" e_shoff = 0x%llx", Header->e_shoff);\r
+ LOG(" e_flags = 0x%x", Header->e_flags);\r
+ LOG(" e_ehsize = %i", Header->e_ehsize);\r
+ LOG(" e_phentsize = %i", Header->e_phentsize);\r
+ LOG(" e_phnum = %i", Header->e_phnum);\r
+ LOG(" e_shentsize = %i", Header->e_shentsize);\r
+ LOG(" e_shnum = %i", Header->e_shnum);\r
+ LOG(" e_shstrndx = %i", Header->e_shstrndx);\r
+ LOG("}");\r
+\r
+ // Load Program Header table\r
+ VFS_Seek(FD, Header->e_phoff, SEEK_SET);\r
+ VFS_Read(FD, sizeof(Elf64_Phdr)*Header->e_phnum, phtab);\r
+\r
+ // Count load segments\r
+ nLoadSegments = 0;\r
+ for( i = 0; i < Header->e_phnum; i ++ )\r
+ {\r
+ if( phtab[i].p_type != PT_LOAD ) continue ;\r
+ nLoadSegments ++;\r
+ }\r
+ \r
+ // Allocate Information Structure\r
+ ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*nLoadSegments );\r
+ // Fill Info Struct\r
+ ret->Entry = Header->e_entry;\r
+ ret->Base = -1; // Set Base to maximum value\r
+ ret->NumSections = nLoadSegments;\r
+ ret->Interpreter = NULL;\r
+\r
+ j = 0; // LoadSections[] index\r
+ for( i = 0; i < Header->e_phnum; i ++ )\r
+ {\r
+ LOG("phtab[%i] = {", i);\r
+ LOG(" .p_type = %i", phtab[i].p_type);\r
+ LOG(" .p_flags = 0x%x", phtab[i].p_flags);\r
+ LOG(" .p_offset = 0x%llx", phtab[i].p_offset);\r
+ LOG(" .p_vaddr = 0x%llx", phtab[i].p_vaddr);\r
+ LOG(" .p_paddr = 0x%llx", phtab[i].p_paddr);\r
+ LOG(" .p_filesz = 0x%llx", phtab[i].p_filesz);\r
+ LOG(" .p_memsz = 0x%llx", phtab[i].p_memsz);\r
+ LOG(" .p_align = 0x%llx", phtab[i].p_align);\r
+ LOG("}");\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);\r
+ VFS_Seek(FD, phtab[i].p_offset, 1);\r
+ VFS_Read(FD, phtab[i].p_filesz, tmp);\r
+ ret->Interpreter = Binary_RegInterp(tmp);\r
+ LOG("Interpreter '%s'", tmp);\r
+ free(tmp);\r
+ continue;\r
+ }\r
+ \r
+ if( phtab[i].p_type != PT_LOAD ) continue ;\r
+ \r
+ // Find the executable base\r
+ if( phtab[i].p_vaddr < ret->Base ) ret->Base = phtab[i].p_vaddr;\r
+\r
+ ret->LoadSections[j].Offset = phtab[i].p_offset;\r
+ ret->LoadSections[j].Virtual = phtab[i].p_vaddr;\r
+ ret->LoadSections[j].FileSize = phtab[i].p_filesz;\r
+ ret->LoadSections[j].MemSize = phtab[i].p_memsz;\r
+ \r
+ ret->LoadSections[j].Flags = 0;\r
+ if( !(phtab[i].p_flags & PF_W) )\r
+ ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;\r
+ if( phtab[i].p_flags & PF_X )\r
+ ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;\r
+ j ++;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)\r
+{\r
+ tBinary *ret;\r
+ Elf32_Phdr *phtab;\r
+ int i, j;\r
+ int iLoadCount;\r
+\r
+ ENTER("xFD", FD);\r
+\r
+ // Check architecture with current CPU\r
+ // - TODO: Support kernel level emulation\r
+ #if ARCH_IS_x86\r
+ if( Header->machine != EM_386 )\r
+ {\r
+ Log_Warning("ELF", "Unknown architecure on ELF-32");\r
+ LEAVE_RET('n');\r
+ return NULL;\r
+ }\r
+ #endif\r
+\r
// Check for a program header\r
- if(hdr.phoff == 0) {\r
+ if(Header->phoff == 0) {\r
#if DEBUG_WARN\r
Log_Warning("ELF", "File does not contain a program header (phoff == 0)");\r
#endif\r
}\r
\r
// Read Program Header Table\r
- phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount );\r
+ phtab = malloc( sizeof(Elf32_Phdr) * Header->phentcount );\r
if( !phtab ) {\r
LEAVE('n');\r
return NULL;\r
}\r
- LOG("hdr.phoff = 0x%08x", hdr.phoff);\r
- VFS_Seek(fp, hdr.phoff, SEEK_SET);\r
- VFS_Read(fp, sizeof(Elf32_Phdr)*hdr.phentcount, phtab);\r
+ LOG("hdr.phoff = 0x%08x", Header->phoff);\r
+ VFS_Seek(FD, Header->phoff, SEEK_SET);\r
+ VFS_Read(FD, sizeof(Elf32_Phdr)*Header->phentcount, phtab);\r
\r
// Count Pages\r
iLoadCount = 0;\r
- LOG("hdr.phentcount = %i", hdr.phentcount);\r
- for( i = 0; i < hdr.phentcount; i++ )\r
+ LOG("Header->phentcount = %i", Header->phentcount);\r
+ for( i = 0; i < Header->phentcount; i++ )\r
{\r
// Ignore Non-LOAD types\r
if(phtab[i].Type != PT_LOAD)\r
// Allocate Information Structure\r
ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*iLoadCount );\r
// Fill Info Struct\r
- ret->Entry = hdr.entrypoint;\r
+ ret->Entry = Header->entrypoint;\r
ret->Base = -1; // Set Base to maximum value\r
ret->NumSections = iLoadCount;\r
ret->Interpreter = NULL;\r
\r
// Load Pages\r
j = 0;\r
- for( i = 0; i < hdr.phentcount; i++ )\r
+ for( i = 0; i < Header->phentcount; i++ )\r
{\r
//LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
LOG("phtab[%i] = {", i);\r
char *tmp;\r
if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].FileSize);\r
- VFS_Seek(fp, phtab[i].Offset, 1);\r
- VFS_Read(fp, phtab[i].FileSize, tmp);\r
+ VFS_Seek(FD, phtab[i].Offset, 1);\r
+ VFS_Read(FD, phtab[i].FileSize, tmp);\r
ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'", tmp);\r
free(tmp);\r
}\r
\r
// --- ELF RELOCATION ---\r
-// Taken from 'ld-acess.so'\r
-/**\r
- \fn int Elf_Relocate(void *Base)\r
- \brief Relocates a loaded ELF Executable\r
-*/\r
int Elf_Relocate(void *Base)\r
+{\r
+ Elf64_Ehdr *hdr = Base;\r
+ \r
+ switch( hdr->e_ident[EI_CLASS] )\r
+ {\r
+ case ELFCLASS32:\r
+ return Elf_Relocate32(Base);\r
+ case ELFCLASS64:\r
+ return 0;\r
+ default:\r
+ return 1;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Relocates a loaded ELF Executable\r
+ */\r
+int Elf_Relocate32(void *Base)\r
{\r
Elf32_Ehdr *hdr = Base;\r
Elf32_Phdr *phtab;\r
// Check if a PT_DYNAMIC segement was found\r
if(!dynamicTab) {\r
Log_Warning("ELF", "Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
- LEAVE('x', hdr->entrypoint);\r
- return hdr->entrypoint;\r
+ LEAVE('x', 0);\r
+ return 0;\r
}\r
\r
// Page Align real base\r