--- /dev/null
+/*\r
+ * Acess v0.1\r
+ * ELF Executable Loader Code\r
+ */\r
+#define DEBUG 0\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include "common.h"\r
+#include "elf32.h"\r
+\r
+#define DEBUG_WARN 1\r
+\r
+#define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val))\r
+#define PTRMK(_type,_val) MKPTR(_type,_val)\r
+#define PTR(_val) ((void*)(uintptr_t)(_val))\r
+\r
+#if DEBUG\r
+# define ENTER(...)\r
+# define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__)\r
+# define LOGS(s) printf("%s: " s, __func__)\r
+# define LEAVE(...)\r
+#else\r
+# define ENTER(...)\r
+# define LOG(...)\r
+# define LOGS(...)\r
+# define LEAVE(...)\r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+void *Elf_Load(int FD);\r
+void *Elf32Load(int FD, Elf32_Ehdr *hdr);\r
+\r
+// === CODE ===\r
+void *Elf_Load(int FD)\r
+{\r
+ Elf32_Ehdr hdr;\r
+ \r
+ // Read ELF Header\r
+ acess_read(FD, sizeof(hdr), &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
+ Warning("Non-ELF File was passed to the ELF loader\n");\r
+ return NULL;\r
+ }\r
+\r
+ switch(hdr.e_ident[4])\r
+ {\r
+ case ELFCLASS32:\r
+ return Elf32Load(FD, &hdr);\r
+ default:\r
+ return NULL;\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 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
+ phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount );\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
+ \r
+ // Count Pages\r
+ iPageCount = 0;\r
+ LOG("hdr.phentcount = %i\n", hdr->phentcount);\r
+ for( i = 0; i < hdr->phentcount; i++ )\r
+ {\r
+ // Ignore Non-LOAD types\r
+ if(phtab[i].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
+ }\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
+ max = 0;\r
+ base = 0xFFFFFFFF;\r
+ for( i = 0; i < hdr->phentcount; i ++)\r
+ {\r
+ if( phtab[i].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
+ }\r
+\r
+ LOG("base = %08x, max = %08x\n", base, max);\r
+\r
+ if( base == 0 ) {\r
+ // Find a nice space (31 address bits allowed)\r
+ base = FindFreeRange( max, 31 );\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
+ {\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
+ {\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
+ //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
+ \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
+ \r
+ addr = phtab[i].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
+ 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
+ }\r
+ \r
+ // Clean Up\r
+ free(phtab);\r
+ // Return\r
+ LEAVE('p', base);\r
+ return PTRMK(void, base);\r
+}\r