[lib][elf] elf64 support
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user