struct elf { struct { u8 ei_magic[4] | matches('\x7fELF') str; enum { CLASS_32 = 1, CLASS_64 } u8 ei_class; enum { ENDIANESS_LE = 1, ENDIANESS_BE } u8 ei_data; u8 ei_version; enum { OSABI_SYSTEM_V, OSABI_HP_UX, OSABI_NETBSD, OSABI_LINUX, OSABI_GNU_HURD, OSABI_SOLARIS, OSABI_AIX, OSABI_IRIX, OSABI_FREEBSD, OSABI_TRU64, OSABI_NOVELL_MODESTO, OSABI_OPENBSD, OSABI_OPENVMS, OSABI_NONSTOP_KERNEL, OSABI_AROS, OSABI_FENIX_OS, OSABI_CLOUD_ABI } u8 ei_osabi; u8 ei_abi_version; u8 ei_pad[7] nul; } e_ident; struct program_header { enum { PT_NULL, PT_LOAD, PT_DYNAMIC, PT_INTERP, PT_NOTE, PT_SHLIB, PT_PHDR, PT_LOOS, PT_HIOS, PT_LOPROC, PT_HIPROC } u32 p_type; select (e_ident.ei_class) { header.CLASS_32) struct { u32 p_offset hex; u32 p_vaddr hex; u32 p_paddr hex; u32 p_filesz; u32 p_memsz; u32 p_flags hex; u32 p_align; } elf32; header.CLASS_64) struct { u32 p_flags hex; u64 p_offset hex; u64 p_vaddr hex; u64 p_paddr hex; u64 p_filesz; u64 p_memsz; u64 p_align; } elf64; } arch; }; struct section_header { enum sh_flags { SHF_WRITE = 0x1, SHF_ALLOC = 0x2, SHF_EXECINSTR = 0x4, SHF_MERGE = 0x10, SHF_STRINGS = 0x20, SHF_INFO_LINK = 0x40, SHF_LINK_ORDER = 0x80, SHF_OS_NONCONFORMING = 0x100, SHF_GROUP = 0x200, SHF_TLS = 0x400, SHF_MASKOS = 0x0ff00000, SHF_MASKPROC = 0xf0000000, SHF_ORDERED = 0x40000000, SHF_EXCLUDE = 0x80000000 }; select (e_ident.ei_class) { header.CLASS_32) struct { u32 sh_name hex; enum sh_type { SHT_NULL, SHT_PROGBITS, SHT_SYMTAB, SHT_STRTAB, SHT_RELA, SHT_HASH, SHT_DYNAMIC, SHT_NOTE, SHT_NOBITS, SHT_REL, SHT_SHLIB, SHT_DYNSYM, SHT_INIT_ARRAY, SHT_FINI_ARRAY, SHT_PREINIT_ARRAY, SHT_GROUP, SHT_SYMTAB_INDEX, SHT_NUM, SHT_LOOS = 0x60000000 } u32 sh_type; enum sh_flags u32 sh_flags; u32 sh_addr hex; u32 sh_offset hex; u32 sh_size; u32 sh_link; u32 sh_info; u32 sh_addralign; u32 sh_entsize; } elf32; header.CLASS_64) struct { enum sh_flags u64 sh_flags; u64 sh_addr hex; u64 sh_offset hex; u64 sh_size; u64 sh_addralign; u64 sh_entsize; } elf64; } arch; }; struct body { enum { ET_NONE, ET_REL, ET_EXEC, ET_DYN, ET_CORE, ET_LOOS = 0xfe00, ET_HIOS = 0xfeff, ET_LOPROC = 0xff00, ET_HIPROC = 0xffff } u16 e_type hex; enum { MACHINE_NONE, MACHINE_SPARC = 0x02, MACHINE_X86 = 0x03, MACHINE_MIPS = 0x08, MACHINE_POWERPC = 0x14, MACHINE_S390 = 0x16, MACHINE_ARM = 0x28, MACHINE_SUPERH = 0x2A, MACHINE_IA_64 = 0x32, MACHINE_X86_64 = 0x3E, MACHINE_AARCH64 = 0xB7, MACHINE_RISCV = 0xF3 } u16 e_machine hex; u32 e_version; select (e_ident.ei_class) { header.CLASS_32) struct { u32 e_entry hex; u32 e_phoff; u32 e_shoff; } elf32; header.CLASS_64) struct { u64 e_entry hex; u64 e_phoff; u64 e_shoff; } elf64; } arch; u32 e_flags hex; u16 e_ehsz; u16 e_phentsize; u16 e_phnum; u16 e_shentsize; u16 e_shnum; u16 e_shstrndx; // TODO: need to handle offsets struct program_header e_ph[e_phnum:e_phentsize]; struct section_header e_sh[e_shnum:e_shentsize]; }; select (e_ident.ei_class) { e_ident.ENDIANESS_LE) struct body le | endianess('le'); e_ident.ENDIANESS_BE) struct body be | endianess('be'); } body; };