Kernel - Updated ELF loader to support ELF64
authorJohn Hodge <[email protected]>
Thu, 8 Sep 2011 00:20:26 +0000 (08:20 +0800)
committerJohn Hodge <[email protected]>
Thu, 8 Sep 2011 00:20:26 +0000 (08:20 +0800)
Kernel/bin/elf.c
Kernel/bin/elf.h

index 73154c1..1ae1956 100644 (file)
@@ -2,7 +2,7 @@
  * 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
@@ -27,26 +30,164 @@ tBinaryType        gELF_Info = {
 // === 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
@@ -55,19 +196,19 @@ tBinary *Elf_Load(int fp)
        }\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
@@ -81,14 +222,14 @@ tBinary *Elf_Load(int fp)
        // 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
@@ -107,8 +248,8 @@ tBinary *Elf_Load(int fp)
                        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
@@ -143,12 +284,26 @@ tBinary *Elf_Load(int fp)
 }\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
@@ -197,8 +352,8 @@ int Elf_Relocate(void *Base)
        // 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
index b038766..13b5373 100644 (file)
@@ -5,6 +5,30 @@
 #ifndef _BIN_ELF_H\r
 #define _BIN_ELF_H\r
 \r
+typedef Uint16 Elf64_Half;\r
+typedef Uint32 Elf64_Word;\r
+typedef Uint64 Elf64_Addr;\r
+typedef Uint64 Elf64_Off;\r
+typedef Uint64 Elf64_Xword;\r
+\r
+enum e_ident_values\r
+{\r
+       EI_MAG0,\r
+       EI_MAG1,\r
+       EI_MAG2,\r
+       EI_MAG3,\r
+       EI_CLASS,\r
+       EI_DATA,\r
+       EI_VERSION,\r
+       EI_OSABI,\r
+       EI_ABIVERSION,\r
+       EI_PAD,\r
+       EI_NIDENT = 16,\r
+};\r
+\r
+#define ELFCLASS32     1\r
+#define ELFCLASS64     2\r
+\r
 /**\r
  * \brief ELF File Header\r
  */\r
@@ -34,6 +58,24 @@ struct sElf32_Ehdr
        Uint16  shstrindex;     //!< Section Header String Table Index\r
 } __attribute__ ((packed));\r
 \r
+typedef struct\r
+{\r
+       unsigned char   e_ident[16];\r
+       Elf64_Half      e_type;\r
+       Elf64_Half      e_machine;\r
+       Elf64_Word      e_version;\r
+       Elf64_Addr      e_entry;\r
+       Elf64_Off       e_phoff;\r
+       Elf64_Off       e_shoff;\r
+       Elf64_Word      e_flags;\r
+       Elf64_Half      e_ehsize;\r
+       Elf64_Half      e_phentsize;\r
+       Elf64_Half      e_phnum;\r
+       Elf64_Half      e_shentsize;\r
+       Elf64_Half      e_shnum;\r
+       Elf64_Half      e_shstrndx;\r
+} Elf64_Ehdr;\r
+\r
 /**\r
  * \brief Executable Types\r
  */\r
@@ -54,10 +96,10 @@ enum eElf32_ExecTypes
 */\r
 #define SHN_UNDEF              0       //!< Undefined Section\r
 #define SHN_LORESERVE  0xFF00  //!< Low Reserved\r
-#define SHN_LOPROC             0xFF00  //!< Low Impl Defined\r
-#define SHN_HIPROC             0xFF1F  //!< High Impl Defined\r
-#define SHN_ABS                        0xFFF1  //!< Absolute Address (Base: 0, Size: -1)\r
-#define SHN_COMMON             0xFFF2  //!< Common\r
+#define SHN_LOPROC     0xFF00  //!< Low Impl Defined\r
+#define SHN_HIPROC     0xFF1F  //!< High Impl Defined\r
+#define SHN_ABS        0xFFF1  //!< Absolute Address (Base: 0, Size: -1)\r
+#define SHN_COMMON     0xFFF2  //!< Common\r
 #define SHN_HIRESERVE  0xFFFF  //!< High Reserved\r
 //! \}\r
 \r
@@ -103,6 +145,20 @@ struct sElf32_Shent {
        Uint32  entsize;\r
 } __attribute__ ((packed));    //sizeof = 40\r
 \r
+typedef struct\r
+{\r
+       Elf64_Word      sh_name;\r
+       Elf64_Word      sh_type;\r
+       Elf64_Xword     sh_flags;\r
+       Elf64_Addr      sh_addr;\r
+       Elf64_Off       sh_offset;\r
+       Elf64_Xword     sh_size;\r
+       Elf64_Word      sh_link;\r
+       Elf64_Word      sh_info;\r
+       Elf64_Xword     sh_addralign;\r
+       Elf64_Xword     sh_entsize;\r
+} Elf64_Shdr;\r
+\r
 struct elf_sym_s {\r
        union {\r
                Uint32  nameOfs;\r
@@ -139,6 +195,18 @@ struct sElf32_Phdr {
        Uint32  Align;\r
 } __attribute__ ((packed));\r
 \r
+typedef struct\r
+{\r
+       Elf64_Word      p_type;\r
+       Elf64_Word      p_flags;\r
+       Elf64_Off       p_offset;\r
+       Elf64_Addr      p_vaddr;\r
+       Elf64_Addr      p_paddr;\r
+       Elf64_Xword     p_filesz;\r
+       Elf64_Xword     p_memsz;\r
+       Elf64_Xword     p_align;\r
+} Elf64_Phdr;\r
+\r
 #define PF_X   1\r
 #define PF_W   2\r
 #define PF_R   4\r

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