From 7f7dd4585f7b112af7ff6eb808c9d2079fd80fd9 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 22 Jul 2012 20:12:24 +0200 Subject: [PATCH] add the support of ELF64 --- arch/x86/include/asm/elf.h | 172 ++++++++++++++++++++++++++++--------- kernel/tasks.c | 21 +++-- 2 files changed, 147 insertions(+), 46 deletions(-) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index b21c4774..3dce1e70 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -40,6 +40,23 @@ extern "C" { #endif +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + #define ELF_MAGIC 0x464C457F #define ELF_ET_NONE 0x0000 // no type @@ -58,6 +75,8 @@ extern "C" { #define ELF_EM_88K 0x0005 // Motorola 88000 #define ELF_EM_860 0x0007 // Intel 80860 #define ELF_EM_MIPS 0x0008 // MIPS RS3000 +#define ELF_EM_ARM 0x0032 // ARM +#define ELF_EM_X86_64 0x003E // AMD/Intel x86_64 #define ELF_CLASS_NONE 0x0000 #define ELF_CLASS_32 0x0001 // 32bit file @@ -111,60 +130,135 @@ typedef struct { /** @brief Information about the executable * - * ELF header\n + * ELF32 header\n * This structure keeps information about the format of the executable itself. */ typedef struct { elf_ident_t ident; - uint16_t type; - uint16_t machine; - uint32_t version; - uint32_t entry; - uint32_t ph_offset; - uint32_t sh_offset; - uint32_t flags; - uint16_t header_size; - uint16_t ph_entry_size; - uint16_t ph_entry_count; - uint16_t sh_entry_size; - uint16_t sh_entry_count; - uint16_t sh_str_table_index; -} __attribute__ ((packed)) elf_header_t; + Elf32_Half type; + Elf32_Half machine; + Elf32_Word version; + Elf32_Addr entry; + Elf32_Off ph_offset; + Elf32_Off sh_offset; + Elf32_Word flags; + Elf32_Half header_size; + Elf32_Half ph_entry_size; + Elf32_Half ph_entry_count; + Elf32_Half sh_entry_size; + Elf32_Half sh_entry_count; + Elf32_Half sh_str_table_index; +} __attribute__ ((packed)) elf32_header_t; -/** @brief program header information +/** @brief Information about the executable * - * program header table\n + * ELF64 header\n + * This structure keeps information about the format of the executable itself. + */ +typedef struct { + elf_ident_t ident; + Elf64_Half type; + Elf64_Half machine; + Elf64_Word version; + Elf64_Addr entry; + Elf64_Off ph_offset; + Elf64_Off sh_offset; + Elf64_Word flags; + Elf64_Half header_size; + Elf64_Half ph_entry_size; + Elf64_Half ph_entry_count; + Elf64_Half sh_entry_size; + Elf64_Half sh_entry_count; + Elf64_Half sh_str_table_index; +} __attribute__ ((packed)) elf64_header_t; + +#ifdef CONFIG_X86_32 +typedef elf32_header_t elf_header_t; +#else +typedef elf64_header_t elf_header_t; +#endif + +/** @brief ELF32 program header information + * + * ELF32 program header table\n * This structure keeps information about the program header. */ typedef struct { - uint32_t type; - uint32_t offset; - uint32_t virt_addr; - uint32_t phys_addr; - uint32_t file_size; - uint32_t mem_size; - uint32_t flags; - uint32_t alignment; -} __attribute__ ((packed)) elf_program_header_t; + Elf32_Word type; + Elf32_Off offset; + Elf32_Addr virt_addr; + Elf32_Addr phys_addr; + Elf32_Word file_size; + Elf32_Word mem_size; + Elf32_Word flags; + Elf32_Word alignment; +} __attribute__ ((packed)) elf32_program_header_t; -/** @brief Information about ELF section +/** @brief ELF64 program header information * - * ELF section\n + * ELF64 program header table\n + * This structure keeps information about the program header. + */ +typedef struct +{ + Elf64_Word type; + Elf64_Word flags; + Elf64_Off offset; + Elf64_Addr virt_addr; + Elf64_Addr phys_addr; + Elf64_Xword file_size; + Elf64_Xword mem_size; + Elf64_Xword alignment; +} __attribute__ ((packed)) elf64_program_header_t; + +#ifdef CONFIG_X86_32 +typedef elf32_program_header_t elf_program_header_t; +#else +typedef elf64_program_header_t elf_program_header_t; +#endif + +/** @brief Information about ELF32 section + * + * ELF32 section\n * This structure keeps information about a specific ELF section */ typedef struct { -uint32_t name; - uint32_t type; - uint32_t flags; - uint32_t addr; - uint32_t offset; - uint32_t size; - uint32_t link; - uint32_t info; - uint32_t align; - uint32_t enttry_size; -} __attribute__ ((packed)) elf_section_header_t; + Elf32_Word name; + Elf32_Word type; + Elf32_Word flags; + Elf32_Addr addr; + Elf32_Off offset; + Elf32_Word size; + Elf32_Word link; + Elf32_Word info; + Elf32_Word align; + Elf32_Word enttry_size; +} __attribute__ ((packed)) elf32_section_header_t; +/** @brief Information about ELF64 section + * + * ELF32 section\n + * This structure keeps information about a specific ELF section + */ +typedef struct { + Elf64_Word name; + Elf64_Word type; + Elf64_Xword flags; + Elf64_Addr addr; + Elf64_Off offset; + Elf64_Xword size; + Elf64_Word link; + Elf64_Word info; + Elf64_Xword align; + Elf64_Xword enttry_size; +} __attribute__ ((packed)) elf64_section_header_t; + +#ifdef CONFIG_X86_32 +typedef elf32_section_header_t elf_section_header_t; +#else +typedef elf64_section_header_t elf_section_header_t; +#endif + #ifdef __cplusplus } #endif diff --git a/kernel/tasks.c b/kernel/tasks.c index a671bfe0..7405509c 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -537,9 +537,9 @@ typedef struct { */ static int load_task(load_args_t* largs) { -#ifdef CONFIG_X86_32 uint32_t i, offset, idx, fd_i; - uint32_t addr, npages, flags, stack = 0; + uint32_t addr, npages, flags; + size_t stack = 0; elf_header_t header; elf_program_header_t prog_header; //elf_section_header_t sec_header; @@ -589,11 +589,19 @@ static int load_task(load_args_t* largs) if (BUILTIN_EXPECT(header.type != ELF_ET_EXEC, 0)) goto invalid; +#ifdef CONFIG_X86_32 if (BUILTIN_EXPECT(header.machine != ELF_EM_386, 0)) goto invalid; if (BUILTIN_EXPECT(header.ident._class != ELF_CLASS_32, 0)) goto invalid; +#else + if (BUILTIN_EXPECT(header.machine != ELF_EM_X86_64, 0)) + goto invalid; + + if (BUILTIN_EXPECT(header.ident._class != ELF_CLASS_64, 0)) + goto invalid; +#endif if (BUILTIN_EXPECT(header.ident.data != ELF_DATA_2LSB, 0)) goto invalid; @@ -626,8 +634,10 @@ static int load_task(load_args_t* largs) flags |= MAP_CODE; // map page frames in the address space of the current task - if (!map_region(prog_header.virt_addr, addr, npages, flags)) - kprintf("Could not map 0x%x at 0x%x\n", addr, prog_header.virt_addr); + if (!map_region(prog_header.virt_addr, addr, npages, flags)) { + kprintf("Could not map 0x%x at 0x%x (%u pages)\n", addr, prog_header.virt_addr, npages); + return -ENOMEM; + } // clear pages memset((void*) prog_header.virt_addr, 0x00, npages*PAGE_SIZE); @@ -761,9 +771,6 @@ invalid: kprintf("program entry point 0x%x\n", (size_t) header.entry); return -EINVAL; -#else - return -EINVAL; -#endif } /** @brief This call is used to adapt create_task calls