AcessNative - Cleanup and slight fixes.
[tpg/acess2.git] / AcessNative / ld-acess_src / elf_load.c
diff --git a/AcessNative/ld-acess_src/elf_load.c b/AcessNative/ld-acess_src/elf_load.c
new file mode 100644 (file)
index 0000000..4929869
--- /dev/null
@@ -0,0 +1,184 @@
+/*\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

UCC git Repository :: git.ucc.asn.au