// Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_ELF_H #define RDI_ELF_H // https://refspecs.linuxfoundation.org/elf/elf.pdf //////////////////////////////// //~ Elf Format Types // elf header #define ELF_NIDENT 16 typedef struct ELF_Ehdr32{ U8 e_ident[ELF_NIDENT]; U16 e_type; U16 e_machine; U32 e_version; U32 e_entry; U32 e_phoff; U32 e_shoff; U32 e_flags; U16 e_ehsize; U16 e_phentsize; U16 e_phnum; U16 e_shentsize; U16 e_shnum; U16 e_shstrndx; } ELF_Ehdr32; typedef struct ELF_Ehdr64{ U8 e_ident[ELF_NIDENT]; U16 e_type; U16 e_machine; U32 e_version; U64 e_entry; U64 e_phoff; U64 e_shoff; U32 e_flags; U16 e_ehsize; U16 e_phentsize; U16 e_phnum; U16 e_shentsize; U16 e_shnum; U16 e_shstrndx; } ELF_Ehdr64; typedef enum ELF_Type{ ELF_Type_NONE = 0, ELF_Type_REL = 1, ELF_Type_EXEC = 2, ELF_Type_DYN = 3, ELF_Type_CORE = 4, ELF_Type_LOOS = 0xfe00, ELF_Type_HIOS = 0xfeff, ELF_Type_LOPROC = 0xff00, ELF_Type_HIPROC = 0xffff, } ELF_Type; typedef enum ELF_Machine{ ELF_Machine_NONE = 0, ELF_Machine_M32 = 1, ELF_Machine_SPARC = 2, ELF_Machine_386 = 3, ELF_Machine_68K = 4, ELF_Machine_88K = 5, ELF_Machine_860 = 7, ELF_Machine_MIPS = 8, ELF_Machine_S370 = 9, ELF_Machine_MIPS_RS3_LE = 10, ELF_Machine_PARISC = 15, ELF_Machine_VPP500 = 17, ELF_Machine_SPARC32PLUS = 18, ELF_Machine_960 = 19, ELF_Machine_PPC = 20, ELF_Machine_PPC64 = 21, ELF_Machine_S390 = 22, ELF_Machine_V800 = 36, ELF_Machine_FR20 = 37, ELF_Machine_RH32 = 38, ELF_Machine_RCE = 39, ELF_Machine_ARM = 40, ELF_Machine_ALPHA = 41, ELF_Machine_SH = 42, ELF_Machine_SPARCV9 = 43, ELF_Machine_TRICORE = 44, ELF_Machine_ARC = 45, ELF_Machine_H8_300 = 46, ELF_Machine_H8_300H = 47, ELF_Machine_H8S = 48, ELF_Machine_H8_500 = 49, ELF_Machine_IA_64 = 50, ELF_Machine_MIPS_X = 51, ELF_Machine_COLDFIRE = 52, ELF_Machine_68HC12 = 53, ELF_Machine_MMA = 54, ELF_Machine_PCP = 55, ELF_Machine_NCPU = 56, ELF_Machine_NDR1 = 57, ELF_Machine_STARCORE = 58, ELF_Machine_ME16 = 59, ELF_Machine_ST100 = 60, ELF_Machine_TINYJ = 61, ELF_Machine_X86_64 = 62, ELF_Machine_PDSP = 63, ELF_Machine_PDP10 = 64, ELF_Machine_PDP11 = 65, ELF_Machine_FX66 = 66, ELF_Machine_ST9PLUS = 67, ELF_Machine_ST7 = 68, ELF_Machine_68HC16 = 69, ELF_Machine_68HC11 = 70, ELF_Machine_68HC08 = 71, ELF_Machine_68HC05 = 72, ELF_Machine_SVX = 73, ELF_Machine_ST19 = 74, ELF_Machine_VAX = 75, ELF_Machine_CRIS = 76, ELF_Machine_JAVELIN = 77, ELF_Machine_FIREPATH = 78, ELF_Machine_ZSP = 79, ELF_Machine_MMIX = 80, ELF_Machine_HUANY = 81, ELF_Machine_PRISM = 82, ELF_Machine_AVR = 83, ELF_Machine_FR30 = 84, ELF_Machine_D10V = 85, ELF_Machine_D30V = 86, ELF_Machine_V850 = 87, ELF_Machine_M32R = 88, ELF_Machine_MN10300 = 89, ELF_Machine_MN10200 = 90, ELF_Machine_PJ = 91, ELF_Machine_OPENRISC = 92, ELF_Machine_ARC_A5 = 93, ELF_Machine_XTENSA = 94, ELF_Machine_VIDEOCORE = 95, ELF_Machine_TMM_GPP = 96, ELF_Machine_NS32K = 97, ELF_Machine_TPC = 98, ELF_Machine_SNP1K = 99, ELF_Machine_ST200 = 100, } ELF_Machine; typedef enum ELF_Version{ ELF_Version_NONE = 0, ELF_Version_CURRENT = 1, } ELF_Version; typedef enum ELF_Identification{ ELF_Identification_MAG0 = 0, ELF_Identification_MAG1 = 1, ELF_Identification_MAG2 = 2, ELF_Identification_MAG3 = 3, ELF_Identification_CLASS = 4, ELF_Identification_DATA = 5, ELF_Identification_VERSION = 6, ELF_Identification_OSABI = 7, ELF_Identification_ABIVERSION = 8, ELF_Identification_PAD = 9, } ELF_Identification; read_only global U8 elf_magic[] = {0x7F, 'E', 'L', 'F'}; typedef enum ELF_Class{ ELF_Class_NONE = 0, ELF_Class_32 = 1, ELF_Class_64 = 2, } ELF_Class; typedef enum ELF_DataEncoding{ ELF_DataEncoding_NONE = 0, ELF_DataEncoding_2LSB = 1, ELF_DataEncoding_2MSB = 2, } ELF_DataEncoding; typedef enum ELF_OsAbi{ ELF_OsAbi_NONE = 0, ELF_OsAbi_HPUX = 1, ELF_OsAbi_NETBSD = 2, ELF_OsAbi_LINUX = 3, ELF_OsAbi_SOLARIS = 6, ELF_OsAbi_AIX = 7, ELF_OsAbi_IRIX = 8, ELF_OsAbi_FREEBSD = 9, ELF_OsAbi_TRU64 = 10, ELF_OsAbi_MODESTO = 11, ELF_OsAbi_OPENBSD = 12, ELF_OsAbi_OPENVMS = 13, ELF_OsAbi_NSK = 14, } ELF_OsAbi; // sections typedef enum ELF_ReservedSectionIndex{ ELF_ReservedSectionIndex_UNDEF = 0, ELF_ReservedSectionIndex_LORESERVE = 0xFF00, ELF_ReservedSectionIndex_LOPROC = 0xFF00, ELF_ReservedSectionIndex_HIPROC = 0xFF1F, ELF_ReservedSectionIndex_LOOS = 0xFF20, ELF_ReservedSectionIndex_HIOS = 0xFF3F, ELF_ReservedSectionIndex_ABS = 0xFFF1, ELF_ReservedSectionIndex_COMMON = 0xFFF2, ELF_ReservedSectionIndex_XINDEX = 0xFFFF, ELF_ReservedSectionIndex_HIRESERVE = 0xFFFF, } ELF_ReservedSectionIndex; typedef struct ELF_Shdr32{ U32 sh_name; U32 sh_type; U32 sh_flags; U32 sh_addr; U32 sh_offset; U32 sh_size; U32 sh_link; U32 sh_info; U32 sh_addralign; U32 sh_entsize; } ELF_Shdr32; typedef struct ELF_Shdr64{ U32 sh_name; U32 sh_type; U64 sh_flags; U64 sh_addr; U64 sh_offset; U64 sh_size; U32 sh_link; U32 sh_info; U64 sh_addralign; U64 sh_entsize; } ELF_Shdr64; // X(name, code) #define ELF_SectionTypeXList(X)\ X(NULL, 0)\ X(PROGBITS, 1)\ X(SYMTAB, 2)\ X(STRTAB, 3)\ X(RELA, 4)\ X(HASH, 5)\ X(DYNAMIC, 6)\ X(NOTE, 7)\ X(NOBITS, 8)\ X(REL, 9)\ X(SHLIB, 10)\ X(DYNSYM, 11)\ X(INIT_ARRAY, 14)\ X(FINI_ARRAY, 15)\ X(PREINIT_ARRAY, 16)\ X(GROUP, 17)\ X(SYMTAB_SHNDX, 18)\ X(LOOS, 0x60000000)\ X(HIOS, 0x6FFFFFFF)\ X(LOPROC, 0x70000000)\ X(HIPROC, 0x7FFFFFFF)\ X(LOUSER, 0x80000000)\ X(HIUSER, 0x8FFFFFFF) typedef enum ELF_SectionType{ #define X(N,C) ELF_SectionType_##N = C, ELF_SectionTypeXList(X) #undef X } ELF_SectionType; typedef enum ELF_SectionAttributeFlags{ ELF_SectionAttributeFlag_WRITE = 0x001, ELF_SectionAttributeFlag_ALLOC = 0x002, ELF_SectionAttributeFlag_EXECINSTR = 0x004, ELF_SectionAttributeFlag_MERGE = 0x010, ELF_SectionAttributeFlag_STRINGS = 0x020, ELF_SectionAttributeFlag_INFO_LINK = 0x040, ELF_SectionAttributeFlag_LINK_ORDER = 0x080, ELF_SectionAttributeFlag_OS_NONCONFORMING = 0x100, ELF_SectionAttributeFlag_GROUP = 0x200, ELF_SectionAttributeFlag_TLS = 0x400, ELF_SectionAttributeFlag_MASKOS = 0x0FF00000, ELF_SectionAttributeFlag_MASKPROC = 0xF0000000, } ELF_SectionAttributeFlags; typedef enum ELF_SectionGroupFlags{ ELF_SectionGroupFlag_COMDAT = 0x1, ELF_SectionGroupFlag_MASKOS = 0x0FF00000, ELF_SectionGroupFlag_MASKPROC = 0xF0000000, } ELF_SectionGroupFlags; typedef enum ELF_ReservedSymbolTableIndex{ ELF_ReservedSymbolTableIndex_UNDEF = 0, } ELF_ReservedSymbolTableIndex; // symbol table typedef struct ELF_Sym32{ U32 st_name; U32 st_value; U32 st_size; U8 st_info; U8 st_other; U16 st_shndx; } ELF_Sym32; typedef struct ELF_Sym64{ U32 st_name; U8 st_info; U8 st_other; U16 st_shndx; U64 st_value; U64 st_size; } ELF_Sym64; #define ELF_SymBindingFromInfo(x) (ELF_SymbolBinding)((x)>>4) #define ELF_SymTypeFromInfo(x) (ELF_SymbolType)((x)&0xF) #define ELF_SymInfoFromBindingType(b,t) ((((b)<<4)&0xF)|((t)&0xF)) #define ELF_SymVisibilityFromOther(x) ((x)&0x3) #define ELF_SymOtherFromVisibility(x) ((x)&0x3) #define ELF_SymbolBindingXList(X)\ X(LOCAL, 0)\ X(GLOBAL, 1)\ X(WEAK, 2)\ X(LOOS, 10)\ X(HIOS, 12)\ X(LOPROC, 13)\ X(HIPROC, 15)\ typedef enum ELF_SymbolBinding{ #define X(N,C) ELF_SymbolBinding_##N = C, ELF_SymbolBindingXList(X) #undef X } ELF_SymbolBinding; #define ELF_SymbolTypeXList(X)\ X(NOTYPE, 0)\ X(OBJECT, 1)\ X(FUNC, 2)\ X(SECTION, 3)\ X(FILE, 4)\ X(COMMON, 5)\ X(TLS, 6)\ X(LOOS, 10)\ X(HIOS, 12)\ X(LOPROC, 13)\ X(HIPROC, 15) typedef enum ELF_SymbolType{ #define X(N,C) ELF_SymbolType_##N = C, ELF_SymbolTypeXList(X) #undef X } ELF_SymbolType; #define ELF_SymbolVisibilityXList(X)\ X(DEFAULT, 0)\ X(INTERNAL, 1)\ X(HIDDEN, 2)\ X(PROTECTED, 3) typedef enum ELF_SymbolVisibility{ #define X(N,C) ELF_SymbolVisibility_##N = C, ELF_SymbolVisibilityXList(X) #undef X } ELF_SymbolVisibility; // relocation typedef struct ELF_Rel32{ U32 r_offset; U32 r_info; } ELF_Rel32; typedef struct ELF_Rela32{ U32 r_offset; U32 r_info; S32 r_addend; } ELF_Rela32; typedef struct ELF_Rel64{ U64 r_offset; U64 r_info; } ELF_Rel64; typedef struct ELF_Rela64{ U64 r_offset; U64 r_info; S64 r_addend; } ELF_Rela64; #define ELF_RelSymIndexFromInfo32(x) ((x)>>8) #define ELF_RelTypeFromInfo32(x) ((x)&0xF) #define ELF_RelInfoFromSymIndexType32(n,t) (((n)<<8)|((t)&0xF)) #define ELF_RelSymIndexFromInfo64(x) ((x)>>32) #define ELF_RelTypeFromInfo64(x) ((x)&0xFFFFFFFFL) #define ELF_RelInfoFromSymIndexType64(n,t) (((n)<<8)|((t)&0xFFFFFFFFL)) // program header typedef struct ELF_Phdr32{ U32 p_type; U32 p_offset; U32 p_vaddr; U32 p_paddr; U32 p_filesz; U32 p_memsz; U32 p_flags; U32 p_align; } ELF_Phdr32; typedef struct ELF_Phdr64{ U32 p_type; U32 p_flags; U64 p_offset; U64 p_vaddr; U64 p_paddr; U64 p_filesz; U64 p_memsz; U64 p_align; } ELF_Phdr64; typedef enum ELF_SegmentType{ ELF_SegmentType_NULL = 0, ELF_SegmentType_LOAD = 1, ELF_SegmentType_DYNAMIC = 2, ELF_SegmentType_INTERP = 3, ELF_SegmentType_NOTE = 4, ELF_SegmentType_SHLIB = 5, ELF_SegmentType_PHDR = 6, ELF_SegmentType_TLS = 7, ELF_SegmentType_LOOS = 0x60000000, ELF_SegmentType_HIOS = 0x6fffffff, ELF_SegmentType_LOPROC = 0x70000000, ELF_SegmentType_HIPROC = 0x7fffffff, } ELF_SegmentType; typedef enum ELF_SegmentFlags{ ELF_SegmentFlag_X = 0x1, ELF_SegmentFlag_W = 0x2, ELF_SegmentFlag_R = 0x4, ELF_SegmentFlag_MASKOS = 0x0FF00000, ELF_SegmentFlag_MASKPROC = 0xF0000000, } ELF_SegmentFlags; //////////////////////////////// //~ ELF Parser Types // elf top level typedef struct ELF_SectionArray{ ELF_Shdr64 *sections; U64 count; } ELF_SectionArray; typedef struct ELF_SegmentArray{ ELF_Phdr64 *segments; U64 count; } ELF_SegmentArray; typedef struct ELF_Parsed{ String8 data; ELF_Class elf_class; Architecture arch; ELF_Shdr64 *sections; String8 *section_names; U64 section_foff; U64 section_count; ELF_Phdr64 *segments; U64 segment_foff; U64 segment_count; U64 vbase; U64 entry_vaddr; U64 section_name_table_foff; U64 section_name_table_opl; U64 strtab_idx; U64 symtab_idx; U64 dynsym_idx; } ELF_Parsed; // elf symtab typedef struct ELF_SymArray{ ELF_Sym64 *symbols; U64 count; } ELF_SymArray; //////////////////////////////// //~ ELF Parser Functions static ELF_Parsed* elf_parsed_from_data(Arena *arena, String8 elf_data); static ELF_SectionArray elf_section_array_from_elf(ELF_Parsed *elf); static String8Array elf_section_name_array_from_elf(ELF_Parsed *elf); static ELF_SegmentArray elf_segment_array_from_elf(ELF_Parsed *elf); static String8 elf_section_name_from_name_offset(ELF_Parsed *elf, U64 offset); static String8 elf_section_name_from_idx(ELF_Parsed *elf, U32 idx); static U32 elf_section_idx_from_name(ELF_Parsed *elf, String8 name); static String8 elf_section_data_from_idx(ELF_Parsed *elf, U32 idx); static ELF_SymArray elf_sym_array_from_data(Arena *arena, ELF_Class elf_class, String8 data); // string functions static String8 elf_string_from_section_type(ELF_SectionType section_type); static String8 elf_string_from_symbol_binding(ELF_SymbolBinding binding); static String8 elf_string_from_symbol_type(ELF_SymbolType type); static String8 elf_string_from_symbol_visibility(ELF_SymbolVisibility visibility); #endif //RDI_ELF_H