1/* 2 * Copyright (c) 1999-2004 University of New South Wales 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#pragma once 8 9#include <types.h> 10 11#define R_AARCH64_NONE 0 /* No relocation. */ 12#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ 13#define ELF64_R_TYPE(i) ((i) & 0xffffffff) 14/* 15 * File header 16 */ 17struct Elf64_Header { 18 unsigned char e_ident[16]; 19 uint16_t e_type; /* Relocatable=1, Executable=2 (+ some 20 * more ..) */ 21 uint16_t e_machine; /* Target architecture: MIPS=8 */ 22 uint32_t e_version; /* Elf version (should be 1) */ 23 uint64_t e_entry; /* Code entry point */ 24 uint64_t e_phoff; /* Program header table */ 25 uint64_t e_shoff; /* Section header table */ 26 uint32_t e_flags; /* Flags */ 27 uint16_t e_ehsize; /* ELF header size */ 28 uint16_t e_phentsize; /* Size of one program segment 29 * header */ 30 uint16_t e_phnum; /* Number of program segment 31 * headers */ 32 uint16_t e_shentsize; /* Size of one section header */ 33 uint16_t e_shnum; /* Number of section headers */ 34 uint16_t e_shstrndx; /* Section header index of the 35 * string table for section header 36 * * names */ 37}; 38 39/* 40 * Section header 41*/ 42struct Elf64_Shdr { 43 uint32_t sh_name; 44 uint32_t sh_type; 45 uint64_t sh_flags; 46 uint64_t sh_addr; 47 uint64_t sh_offset; 48 uint64_t sh_size; 49 uint32_t sh_link; 50 uint32_t sh_info; 51 uint64_t sh_addralign; 52 uint64_t sh_entsize; 53}; 54 55/* 56 * Program header 57 */ 58struct Elf64_Phdr { 59 uint32_t p_type; /* Segment type: Loadable segment = 1 */ 60 uint32_t p_flags; /* Flags: logical "or" of PF_ 61 * constants below */ 62 uint64_t p_offset; /* Offset of segment in file */ 63 uint64_t p_vaddr; /* Reqd virtual address of segment 64 * when loading */ 65 uint64_t p_paddr; /* Reqd physical address of 66 * segment */ 67 uint64_t p_filesz; /* How many bytes this segment 68 * occupies in file */ 69 uint64_t p_memsz; /* How many bytes this segment 70 * should occupy in * memory (when 71 * * loading, expand the segment 72 * by * concatenating enough zero 73 * bytes to it) */ 74 uint64_t p_align; /* Reqd alignment of segment in 75 * memory */ 76}; 77 78/* 79 * Dynamic section 80 */ 81struct Elf64_Dyn { 82 uint64_t d_tag; 83 union { 84 uint64_t d_val; 85 uint64_t d_ptr; 86 } d_un; 87}; 88 89struct Elf64_Rela { 90 uint64_t r_offset; /* Address */ 91 uint64_t r_info; /* Relocation type and symbol index */ 92 uint64_t r_addend; /* Addend */ 93}; 94 95int elf64_checkFile(void *elfFile); 96struct Elf64_Phdr * elf64_getProgramSegmentTable(void *elfFile); 97unsigned elf64_getNumSections(void *elfFile); 98char * elf64_getStringTable(void *elfFile, int string_segment); 99char * elf64_getSegmentStringTable(void *elfFile); 100 101/* Assume the field is at least 4-byte aligned and little-endian */ 102static uint64_t elf64_read64(void *addr) 103{ 104 uint64_t ret; 105 if (((uintptr_t)addr) % 8 == 0) { 106 ret = *((uint64_t *)addr); 107 } else { 108 ret = *((uint32_t *)(((uintptr_t)addr) + 4)); 109 ret = ret << 32; 110 ret |= *((uint32_t *)addr); 111 } 112 return ret; 113} 114 115static inline struct Elf64_Shdr * 116elf64_getSectionTable(struct Elf64_Header *file) { 117 /* Cast heaven! */ 118 return (struct Elf64_Shdr*) (uintptr_t) (((uintptr_t) file) + file->e_shoff); 119} 120 121/* accessor functions */ 122static inline uint32_t 123elf64_getSectionType(struct Elf64_Header *file, uint16_t s) 124{ 125 return elf64_getSectionTable(file)[s].sh_type; 126} 127 128static inline uint32_t 129elf64_getSectionFlags(struct Elf64_Header *file, uint16_t s) 130{ 131 return elf64_getSectionTable(file)[s].sh_flags; 132} 133 134char * elf64_getSectionName(void *elfFile, int i); 135uint64_t elf64_getSectionSize(void *elfFile, int i); 136uint64_t elf64_getSectionAddr(struct Elf64_Header *elfFile, int i); 137void * elf64_getSection(void *elfFile, int i); 138void * elf64_getSectionNamed(void *elfFile, char *str); 139int elf64_getSegmentType (void *elfFile, int segment); 140void elf64_getSegmentInfo(void *elfFile, int segment, uint64_t *p_vaddr, 141 uint64_t *p_paddr, uint64_t *p_filesz, 142 uint64_t *p_offset, uint64_t *p_memsz); 143void elf64_showDetails(void *elfFile, int size, char *name); 144uint64_t elf64_getEntryPoint (struct Elf64_Header *elfFile); 145 146/* Program Headers functions */ 147/* Program header functions */ 148uint16_t elf64_getNumProgramHeaders(struct Elf64_Header *file); 149 150static inline struct Elf64_Phdr * 151elf64_getProgramHeaderTable(struct Elf64_Header *file) { 152 /* Cast hell! */ 153 uint64_t e_phoff = elf64_read64(&file->e_phoff); 154 return (struct Elf64_Phdr*) (uintptr_t) (((uintptr_t) file) + e_phoff); 155} 156 157/* accessor functions */ 158static inline uint32_t 159elf64_getProgramHeaderFlags(struct Elf64_Header *file, uint16_t ph) 160{ 161 return elf64_getProgramHeaderTable(file)[ph].p_flags; 162} 163 164static inline uint32_t 165elf64_getProgramHeaderType(struct Elf64_Header *file, uint16_t ph) 166{ 167 return elf64_getProgramHeaderTable(file)[ph].p_type; 168} 169 170static inline uint64_t 171elf64_getProgramHeaderFileSize(struct Elf64_Header *file, uint16_t ph) 172{ 173 struct Elf64_Phdr *phdr = &elf64_getProgramHeaderTable(file)[ph]; 174 return elf64_read64(&phdr->p_filesz); 175} 176 177static inline uint64_t 178elf64_getProgramHeaderMemorySize(struct Elf64_Header *file, uint16_t ph) 179{ 180 struct Elf64_Phdr *phdr = &elf64_getProgramHeaderTable(file)[ph]; 181 return elf64_read64(&phdr->p_memsz); 182} 183 184static inline uint64_t 185elf64_getProgramHeaderVaddr(struct Elf64_Header *file, uint16_t ph) 186{ 187 struct Elf64_Phdr *phdr = &elf64_getProgramHeaderTable(file)[ph]; 188 return elf64_read64(&phdr->p_vaddr); 189} 190 191static inline uint64_t 192elf64_getProgramHeaderPaddr(struct Elf64_Header *file, uint16_t ph) 193{ 194 struct Elf64_Phdr *phdr = &elf64_getProgramHeaderTable(file)[ph]; 195 return elf64_read64(&phdr->p_paddr); 196} 197 198static inline uint64_t 199elf64_getProgramHeaderOffset(struct Elf64_Header *file, uint16_t ph) 200{ 201 struct Elf64_Phdr *phdr = &elf64_getProgramHeaderTable(file)[ph]; 202 return elf64_read64(&phdr->p_offset); 203} 204 205