blob: b65d227960214ab811c644b6a30626986c1b152e [file] [log] [blame] [edit]
/*
* Copyright (c) 1999-2004 University of New South Wales
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#pragma once
#include <types.h>
#define R_AARCH64_NONE 0 /* No relocation. */
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
/*
* File header
*/
struct Elf64_Header {
unsigned char e_ident[16];
uint16_t e_type; /* Relocatable=1, Executable=2 (+ some more ..) */
uint16_t e_machine; /* Target architecture: MIPS=8 */
uint32_t e_version; /* Elf version (should be 1) */
uint64_t e_entry; /* Code entry point */
uint64_t e_phoff; /* Program header table */
uint64_t e_shoff; /* Section header table */
uint32_t e_flags; /* Flags */
uint16_t e_ehsize; /* ELF header size */
uint16_t e_phentsize;/* Size of one program segment header */
uint16_t e_phnum; /* Number of program segment headers */
uint16_t e_shentsize;/* Size of one section header */
uint16_t e_shnum; /* Number of section headers */
uint16_t e_shstrndx; /* Section header index of the string table for
* section header names
*/
};
/*
* Section header
*/
struct Elf64_Shdr {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
};
/*
* Program header
*/
struct Elf64_Phdr {
uint32_t p_type; /* Segment type: Loadable segment = 1 */
uint32_t p_flags; /* Flags: logical "or" of PF_constants below */
uint64_t p_offset; /* Offset of segment in file */
uint64_t p_vaddr; /* Reqd virtual address of segment when loading */
uint64_t p_paddr; /* Reqd physical address of segment */
uint64_t p_filesz; /* How many bytes this segment occupies in file */
uint64_t p_memsz; /* How many bytes this segment should occupy in
* memory (when loading, expand the segment by
* concatenating enough zero bytes to it)
*/
uint64_t p_align; /* Reqd alignment of segment in memory */
};
/*
* Dynamic section
*/
struct Elf64_Dyn {
uint64_t d_tag;
union {
uint64_t d_val;
uint64_t d_ptr;
} d_un;
};
struct Elf64_Rela {
uint64_t r_offset; /* Address */
uint64_t r_info; /* Relocation type and symbol index */
uint64_t r_addend; /* Addend */
};
int elf64_checkFile(
void const *elfFile);
struct Elf64_Phdr const *elf64_getProgramSegmentTable(
void const *elfFile);
unsigned elf64_getNumSections(
void const *elfFile);
char const *elf64_getStringTable(
void const *elfFile,
unsigned int string_segment);
char const *elf64_getSegmentStringTable(
void const *elfFile);
/* Assume the field is at least 4-byte aligned and little-endian */
static uint64_t elf64_read64(
void const *addr)
{
uint64_t ret;
if (((uintptr_t)addr) % 8 == 0) {
ret = *((uint64_t *)addr);
} else {
ret = *((uint32_t *)(((uintptr_t)addr) + 4));
ret = ret << 32;
ret |= *((uint32_t *)addr);
}
return ret;
}
static inline struct Elf64_Shdr const *elf64_getSectionTable(
struct Elf64_Header const *file)
{
/* Cast heaven! */
return (struct Elf64_Shdr *)(uintptr_t)(((uintptr_t) file) + file->e_shoff);
}
/* accessor functions */
static inline uint32_t elf64_getSectionType(
struct Elf64_Header const *file,
uint16_t s)
{
return elf64_getSectionTable(file)[s].sh_type;
}
static inline uint32_t elf64_getSectionFlags(
struct Elf64_Header const *file,
uint16_t s)
{
return elf64_getSectionTable(file)[s].sh_flags;
}
char const *elf64_getSectionName(
void const *elfFile,
unsigned int i);
uint64_t elf64_getSectionSize(
void const *elfFile,
unsigned int i);
uint64_t elf64_getSectionAddr(
struct Elf64_Header const *elfFile,
unsigned int i);
void const *elf64_getSection(
void const *elfFile,
unsigned int i);
void const *elf64_getSectionNamed(
void const *elfFile,
char const *str);
uint32_t elf64_getSegmentType(
void const *elfFile,
unsigned int segment);
void elf64_getSegmentInfo(
void const *elfFile,
unsigned int segment,
uint64_t *p_vaddr,
uint64_t *p_paddr,
uint64_t *p_filesz,
uint64_t *p_offset,
uint64_t *p_memsz);
void elf64_showDetails(
void const *elfFile,
int size,
char const *name);
uint64_t elf64_getEntryPoint(
struct Elf64_Header const *elfFile);
/* Program Headers functions */
/* Program header functions */
uint16_t elf64_getNumProgramHeaders(
struct Elf64_Header const *file);
static inline struct Elf64_Phdr const *elf64_getProgramHeaderTable(
struct Elf64_Header const *file)
{
/* Cast hell! */
uint64_t e_phoff = elf64_read64(&file->e_phoff);
return (struct Elf64_Phdr *)(uintptr_t)(((uintptr_t) file) + e_phoff);
}
/* accessor functions */
static inline uint32_t elf64_getProgramHeaderFlags(
struct Elf64_Header const *file,
uint16_t ph)
{
return elf64_getProgramHeaderTable(file)[ph].p_flags;
}
static inline uint32_t elf64_getProgramHeaderType(
struct Elf64_Header const *file,
uint16_t ph)
{
return elf64_getProgramHeaderTable(file)[ph].p_type;
}
static inline uint64_t elf64_getProgramHeaderFileSize(
struct Elf64_Header const *file,
uint16_t ph)
{
struct Elf64_Phdr const *phdr = &elf64_getProgramHeaderTable(file)[ph];
return elf64_read64(&phdr->p_filesz);
}
static inline uint64_t elf64_getProgramHeaderMemorySize(
struct Elf64_Header const *file,
uint16_t ph)
{
struct Elf64_Phdr const *phdr = &elf64_getProgramHeaderTable(file)[ph];
return elf64_read64(&phdr->p_memsz);
}
static inline uint64_t elf64_getProgramHeaderVaddr(
struct Elf64_Header const *file,
uint16_t ph)
{
struct Elf64_Phdr const *phdr = &elf64_getProgramHeaderTable(file)[ph];
return elf64_read64(&phdr->p_vaddr);
}
static inline uint64_t elf64_getProgramHeaderPaddr(
struct Elf64_Header const *file,
uint16_t ph)
{
struct Elf64_Phdr const *phdr = &elf64_getProgramHeaderTable(file)[ph];
return elf64_read64(&phdr->p_paddr);
}
static inline uint64_t elf64_getProgramHeaderOffset(
struct Elf64_Header const *file,
uint16_t ph)
{
struct Elf64_Phdr const *phdr = &elf64_getProgramHeaderTable(file)[ph];
return elf64_read64(&phdr->p_offset);
}