add the support of ELF64

This commit is contained in:
Stefan Lankes 2012-07-22 20:12:24 +02:00
parent 8b91ff3fff
commit 7f7dd4585f
2 changed files with 147 additions and 46 deletions

View file

@ -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

View file

@ -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