[lib][elf] elf64 support

This commit is contained in:
Travis Geiselbrecht
2016-02-23 21:06:31 -08:00
parent 2a51111387
commit 79cd8e4969
3 changed files with 132 additions and 12 deletions

View File

@@ -32,6 +32,27 @@
#define LOCAL_TRACE 0
/* conditionally define a 32 or 64 bit version of the data structures
* we care about, based on our bitness.
*/
#if WITH_ELF32
typedef struct Elf32_Ehdr elf_ehdr_t;
typedef struct Elf32_Phdr elf_phdr_t;
#define ELF_OFF_PRINT_U "%u"
#define ELF_OFF_PRINT_X "%x"
#define ELF_ADDR_PRINT_U "%u"
#define ELF_ADDR_PRINT_X "%x"
#else
typedef struct Elf64_Ehdr elf_ehdr_t;
typedef struct Elf64_Phdr elf_phdr_t;
#define ELF_OFF_PRINT_U "%llu"
#define ELF_OFF_PRINT_X "%llx"
#define ELF_ADDR_PRINT_U "%llu"
#define ELF_ADDR_PRINT_X "%llx"
#endif
struct read_hook_memory_args {
const uint8_t *ptr;
size_t len;
@@ -106,13 +127,20 @@ void elf_close_handle(elf_handle_t *handle)
free(handle->pheaders);
}
static int verify_eheader(const struct Elf32_Ehdr *eheader)
static int verify_eheader(const void *header)
{
const elf_ehdr_t *eheader = header;
if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
return ERR_NOT_FOUND;
#if WITH_ELF32
if (eheader->e_ident[EI_CLASS] != ELFCLASS32)
return ERR_NOT_FOUND;
#else
if (eheader->e_ident[EI_CLASS] != ELFCLASS64)
return ERR_NOT_FOUND;
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
if (eheader->e_ident[EI_DATA] != ELFDATA2LSB)
@@ -128,21 +156,21 @@ static int verify_eheader(const struct Elf32_Ehdr *eheader)
if (eheader->e_phoff == 0)
return ERR_NOT_FOUND;
if (eheader->e_phentsize < sizeof(struct Elf32_Phdr))
if (eheader->e_phentsize < sizeof(elf_phdr_t))
return ERR_NOT_FOUND;
#if ARCH_ARM
if (eheader->e_machine != EM_ARM)
return ERR_NOT_FOUND;
#elif ARCH_ARM64
if (eheader->e_machine != EM_AARCH64)
return ERR_NOT_FOUND;
#elif ARCH_X86
if (eheader->e_machine != EM_386)
return ERR_NOT_FOUND;
#elif ARCH_X86_64
if (eheader->e_machine != EM_X86_64)
return ERR_NOT_FOUND;
#elif ARCH_ARM64
if (eheader->e_machine != EM_AARCH64)
return ERR_NOT_FOUND;
#elif ARCH_MICROBLAZE
if (eheader->e_machine != EM_MICROBLAZE)
return ERR_NOT_FOUND;
@@ -174,7 +202,8 @@ status_t elf_load(elf_handle_t *handle)
// sanity check number of program headers
LTRACEF("number of program headers %u, entry size %u\n", handle->eheader.e_phnum, handle->eheader.e_phentsize);
if (handle->eheader.e_phnum > 16 || handle->eheader.e_phentsize != sizeof(struct Elf32_Phdr)) {
if (handle->eheader.e_phnum > 16 ||
handle->eheader.e_phentsize != sizeof(elf_phdr_t)) {
LTRACEF("too many program headers or bad size\n");
return ERR_NO_MEMORY;
}
@@ -196,10 +225,13 @@ status_t elf_load(elf_handle_t *handle)
uint load_count = 0;
for (uint i = 0; i < handle->eheader.e_phnum; i++) {
// parse the program headers
struct Elf32_Phdr *pheader = &handle->pheaders[i];
elf_phdr_t *pheader = &handle->pheaders[i];
LTRACEF("%u: type %u offset 0x%x vaddr 0x%x paddr 0x%x memsiz %u filesize %u\n",
i, pheader->p_type, pheader->p_offset, pheader->p_vaddr, pheader->p_paddr, pheader->p_memsz, pheader->p_filesz);
LTRACEF("%u: type %u offset 0x" ELF_OFF_PRINT_X " vaddr "
ELF_ADDR_PRINT_X " paddr " ELF_ADDR_PRINT_X " memsiz "
ELF_ADDR_PRINT_U " filesize " ELF_ADDR_PRINT_U "\n",
i, pheader->p_type, pheader->p_offset, pheader->p_vaddr,
pheader->p_paddr, pheader->p_memsz, pheader->p_filesz);
// we only care about PT_LOAD segments at the moment
if (pheader->p_type == PT_LOAD) {
@@ -216,7 +248,7 @@ status_t elf_load(elf_handle_t *handle)
}
// read the file portion of the segment into memory at vaddr
LTRACEF("reading segment at offset %u to address %p\n", pheader->p_offset, ptr);
LTRACEF("reading segment at offset " ELF_OFF_PRINT_U " to address %p\n", pheader->p_offset, ptr);
readerr = handle->read_hook(handle, ptr, pheader->p_offset, pheader->p_filesz);
if (readerr < (ssize_t)pheader->p_filesz) {
LTRACEF("error %ld reading program header %u\n", readerr, i);

View File

@@ -26,6 +26,13 @@
#include <sys/types.h>
#include <stdbool.h>
/* based on our bitness, support 32 or 64 bit elf */
#if IS_64BIT
#define WITH_ELF64 1
#else
#define WITH_ELF32 1
#endif
/* api */
struct elf_handle;
typedef ssize_t (*elf_read_hook_t)(struct elf_handle *, void *buf, uint64_t offset, size_t len);
@@ -44,8 +51,13 @@ typedef struct elf_handle {
void *mem_alloc_hook_arg;
// loaded info about the elf file
#if WITH_ELF32
struct Elf32_Ehdr eheader; // a copy of the main elf header
struct Elf32_Phdr *pheaders; // a pointer to a buffer of program headers
#else
struct Elf64_Ehdr eheader; // a copy of the main elf header
struct Elf64_Phdr *pheaders; // a pointer to a buffer of program headers
#endif
addr_t load_address;
addr_t entry;

View File

@@ -423,8 +423,8 @@
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
#define R_ARM_RABS32 253
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
/* elf32 stuff */
typedef uint32_t Elf32_Addr;
@@ -510,3 +510,79 @@ struct Elf32_Dyn {
} d_un;
};
/* elf64 stuff */
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Lword;
typedef uint64_t Elf64_Xword;
struct Elf64_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
};
struct Elf64_Shdr {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
};
struct Elf64_Phdr {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
};
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
struct Elf64_Rel {
Elf64_Addr r_offset;
Elf64_Xword r_info;
};
struct Elf64_Rela {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
};
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56)
#define ELF64_R_TYPE_INFO(data, type) (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))