// Copyright (c) 2025 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ELF_H #define ELF_H typedef U8 ELF_Class; enum { ELF_Class_None = 0, ELF_Class_32 = 1, ELF_Class_64 = 2, ELF_Class_Count = 3 }; typedef U8 ELF_OsAbi; enum { ELF_OsAbi_None, ELF_OsAbi_SYSV, ELF_OsAbi_HPUX, ELF_OsAbi_NETBSD, ELF_OsAbi_GNU, ELF_OsAbi_LINUX, ELF_OsAbi_SOLARIS, ELF_OsAbi_IRIX, ELF_OsAbi_FREEBSD, ELF_OsAbi_TRU64, ELF_OsAbi_ARM = 97, ELF_OsAbi_STANDALONE = 255, }; typedef U8 ELF_Version; enum { ELF_Version_None, ELF_Version_Current, }; typedef U16 ELF_MachineKind; enum { ELF_MachineKind_None = 0, ELF_MachineKind_M32 = 1, ELF_MachineKind_SPARC = 2, ELF_MachineKind_386 = 3, ELF_MachineKind_68K = 4, ELF_MachineKind_88K = 5, ELF_MachineKind_IAMCU = 6, ELF_MachineKind_860 = 7, ELF_MachineKind_MIPS = 8, ELF_MachineKind_S370 = 9, ELF_MachineKind_MIPS_RS3_LE = 10, // 11-14 reserved ELF_MachineKind_PARISC = 15, // 16 reserved ELF_MachineKind_VPP500 = 17, ELF_MachineKind_SPARC32PLUS = 18, // nick: Sun's "v8plus" ELF_MachineKind_INTEL960 = 19, ELF_MachineKind_PPC = 20, ELF_MachineKind_PPC64 = 21, ELF_MachineKind_S390 = 22, ELF_MachineKind_SPU = 23, // 24-35 reserved ELF_MachineKind_V800 = 36, ELF_MachineKind_FR20 = 37, ELF_MachineKind_RH32 = 38, ELF_MachineKind_MCORE = 39, ELF_MachineKind_ARM = 40, ELF_MachineKind_SH = 42, ELF_MachineKind_ALPHA = 41, ELF_MachineKind_SPARCV9 = 43, ELF_MachineKind_TRICORE = 44, ELF_MachineKind_ARC = 45, ELF_MachineKind_H8_300 = 46, ELF_MachineKind_H8_300H = 47, ELF_MachineKind_H8S = 48, ELF_MachineKind_H8_500 = 49, ELF_MachineKind_IA_64 = 50, ELF_MachineKind_MIPS_X = 51, ELF_MachineKind_COLDFILE = 52, ELF_MachineKind_68HC12 = 53, ELF_MachineKind_MMA = 54, ELF_MachineKind_PCP = 55, ELF_MachineKind_NCPU = 56, ELF_MachineKind_NDR1 = 57, ELF_MachineKind_STARCORE = 58, ELF_MachineKind_ME16 = 59, ELF_MachineKind_ST100 = 60, ELF_MachineKind_TINYJ = 61, ELF_MachineKind_X86_64 = 62, ELF_MachineKind_AARCH64 = 183, ELF_MachineKind_TI_C6000 = 140, ELF_MachineKind_L1OM = 180, ELF_MachineKind_K1OM = 181, ELF_MachineKind_RISCV = 243, ELF_MachineKind_S390_OLD = 0xA390, }; typedef U8 ELF_Data; enum { ELF_Data_None = 0, ELF_Data_2LSB = 1, ELF_Data_2MSB = 2, }; typedef U32 ELF_PType; enum { ELF_PType_Null = 0, ELF_PType_Load = 1, ELF_PType_Dynamic = 2, ELF_PType_Interp = 3, ELF_PType_Note = 4, ELF_PType_ShLib = 5, ELF_PType_PHdr = 6, ELF_PType_Tls = 7, ELF_PType_LoOs = 0x60000000, ELF_PType_HiOs = 0x6fffffff, ELF_PType_LowProc = 0x70000000, ELF_PType_HighProc = 0x7fffffff, // specific to Sun ELF_PType_LowSunW = 0x6ffffffa, ELF_PType_SunWBSS = 0x6ffffffb, ELF_PType_GnuEHFrame = 0x6474E550, ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e550, // frame unwind information ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e551, // stack flags ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e552, // read-only after relocations ELF_PType_SunEHFrame = ELF_PType_GnuEHFrame, }; typedef U32 ELF_PFlag; enum { ELF_PFlag_Exec = (1 << 0), ELF_PFlag_Write = (1 << 1), ELF_PFlag_Read = (1 << 2), }; typedef U32 ELF_SectionCode; enum { ELF_SectionCode_Null = 0, ELF_SectionCode_ProgBits = 1, ELF_SectionCode_Symtab = 2, ELF_SectionCode_Strtab = 3, ELF_SectionCode_Rela = 4, ELF_SectionCode_Hash = 5, ELF_SectionCode_Dynamic = 6, ELF_SectionCode_Note = 7, ELF_SectionCode_NoBits = 8, ELF_SectionCode_Rel = 9, ELF_SectionCode_Shlib = 10, ELF_SectionCode_Dynsym = 11, ELF_SectionCode_InitArray = 14, ELF_SectionCode_FiniArray = 15, // Array of ptrs to init functions ELF_SectionCode_PreinitArray = 16, // Array of ptrs to finish functions ELF_SectionCode_Group = 17, // Array of ptrs to pre-init funcs ELF_SectionCode_SymtabShndx = 18, // Section contains a section group ELF_SectionCode_GNU_IncrementalInputs = 0x6fff4700, // Indices for SHN_XINDEX entries ELF_SectionCode_GNU_Attributes = 0x6ffffff5, // Incremental build data ELF_SectionCode_GNU_Hash = 0x6ffffff6, // Object attributes ELF_SectionCode_GNU_LibList = 0x6ffffff7, // GNU style symbol hash table ELF_SectionCode_SUNW_verdef = 0x6ffffffd, ELF_SectionCode_SUNW_verneed = 0x6ffffffe, // Versions defined by file ELF_SectionCode_SUNW_versym = 0x6fffffff, // Versions needed by file // Symbol versions ELF_SectionCode_GNU_verdef = ELF_SectionCode_SUNW_verdef, ELF_SectionCode_GNU_verneed = ELF_SectionCode_SUNW_verneed, ELF_SectionCode_GNU_versym = ELF_SectionCode_SUNW_versym, ELF_SectionCode_Proc, ELF_SectionCode_User, }; typedef U32 ELF_SectionIndex; enum { ELF_SectionIndex_Undef = 0, // Symbol with section index is undefined and must be resolved by the link editor ELF_SectionIndex_Abs = 0xfff1, // Symbol has absolute value and wont change after relocations ELF_SectionIndex_Common = 0xfff2, // This symbol indicates to linker to allocate the storage at address multiple of st_value ELF_SectionIndex_LoReserve = 0xff00, ELF_SectionIndex_HiReserve = 0xffff, // Processor specific ELF_SectionIndex_LoProc = ELF_SectionIndex_LoReserve, ELF_SectionIndex_HiProc = 0xff1f, // Reserved for OS ELF_SectionIndex_LoOs = 0xff20, ELF_SectionIndex_HiOs = 0xff3f, ELF_SectionIndex_IA64_ASNI_Common = ELF_SectionIndex_LoProc, ELF_SectionIndex_X8664_LCommon = 0xff02, ELF_SectionIndex_MIPS_SCommon = 0xff03, ELF_SectionIndex_TIC6X_Common = ELF_SectionIndex_LoReserve, ELF_SectionIndex_MIPS_SUndefined = 0xff04, }; typedef U32 ELF_SectionFlag; enum { ELF_Shf_Write = (1 << 0), ELF_Shf_Alloc = (1 << 1), ELF_Shf_ExecInstr = (1 << 2), ELF_Shf_Merge = (1 << 4), ELF_Shf_Strings = (1 << 5), ELF_Shf_InfoLink = (1 << 6), ELF_Shf_LinkOrder = (1 << 7), ELF_Shf_OsNonConforming = (1 << 8), ELF_Shf_Group = (1 << 9), ELF_Shf_Tls = (1 << 10), ELF_Shf_Compressed = (1 << 11), ELF_Shf_MaskOs_Shift = 16, ELF_Shf_MaskOs_Mask = 0xff, ELF_Shf_AMD64Large = (1 << 28), ELF_Shf_Ordered = (1 << 30), ELF_Shf_Exclude = (1 << 31), ELF_Shf_MaskProc_Shift = 28, ELF_Shf_MaskProc_Mask = 0xf, }; #define ELF_SectionFlag_Extract_MaskOs(f) (U8)(((f) >> ELF_SectionFlag_MaskOs_Shift) & ELF_SectionFlag_MaskOs_Mask) #define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask) typedef U32 ELF_AuxType; enum { ELF_AuxType_Null = 0, ELF_AuxType_Phdr = 3, // program headers ELF_AuxType_Phent = 4, // size of a program header ELF_AuxType_Phnum = 5, // number of program headers ELF_AuxType_Pagesz = 6, // system page size ELF_AuxType_Base = 7, // interpreter base address ELF_AuxType_Flags = 8, ELF_AuxType_Entry = 9, // program entry point ELF_AuxType_Uid = 11, ELF_AuxType_Euid = 12, ELF_AuxType_Gid = 13, ELF_AuxType_Egid = 14, ELF_AuxType_Platform = 15, ELF_AuxType_Hwcap = 16, ELF_AuxType_Clktck = 17, ELF_AuxType_DCacheBSize = 19, ELF_AuxType_ICacheBSize = 20, ELF_AuxType_UCacheBSize = 21, ELF_AuxType_IgnorePPC = 22, ELF_AuxType_Secure = 23, ELF_AuxType_BasePlatform = 24, ELF_AuxType_Random = 25, ELF_AuxType_Hwcap2 = 26, // addres to 16 random bytes ELF_AuxType_ExecFn = 31, ELF_AuxType_SysInfo = 32, // file name of executable ELF_AuxType_SysInfoEhdr = 33, ELF_AuxType_L1I_CacheSize = 40, ELF_AuxType_L1I_CacheGeometry = 41, ELF_AuxType_L1D_CacheSize = 42, ELF_AuxType_L1D_CacheGeometry = 43, ELF_AuxType_L2_CacheSize = 44, ELF_AuxType_L2_CacheGeometry = 45, ELF_AuxType_L3_CacheSize = 46, ELF_AuxType_L3_CacheGeometry = 47, }; typedef U32 ELF_DynTag; enum { ELF_DynTag_Null = 0, ELF_DynTag_Needed = 1, ELF_DynTag_PltRelsz = 2, ELF_DynTag_PltGot = 3, ELF_DynTag_Hash = 4, ELF_DynTag_Strtab = 5, ELF_DynTag_Symtab = 6, ELF_DynTag_Rela = 7, ELF_DynTag_Relasz = 8, ELF_DynTag_Relaent = 9, ELF_DynTag_Strsz = 10, ELF_DynTag_Syment = 11, ELF_DynTag_Init = 12, ELF_DynTag_Fini = 13, ELF_DynTag_SoName = 14, ELF_DynTag_RPath = 15, ELF_DynTag_Symbolic = 16, ELF_DynTag_Rel = 17, ELF_DynTag_Relsz = 18, ELF_DynTag_Relent = 19, ELF_DynTag_Pltrel = 20, ELF_DynTag_Debug = 21, ELF_DynTag_TextRel = 22, ELF_DynTag_JmpRel = 23, ELF_DynTag_BindNow = 24, ELF_DynTag_InitArray = 25, ELF_DynTag_FiniArray = 26, ELF_DynTag_InitArraysz = 27, ELF_DynTag_FIniArraysz = 28, ELF_DynTag_RunPath = 29, ELF_DynTag_Flags = 30, ELF_DynTag_PreInitArray = 32, ELF_DynTag_PreInitArraysz = 33, ELF_DynTag_SymtabShndx = 34, ELF_DynTag_LoOs = 0x6000000D, ELF_DynTag_HiOs = 0x6ffff000, ELF_DynTag_ValRngLo = 0x6ffffd00, ELF_DynTag_GNU_PreLinked = 0x6ffffdf5, ELF_DynTag_GNU_Conflictsz = 0x6ffffdf6, ELF_DynTag_GNU_LibListsz = 0x6ffffdf7, ELF_DynTag_Checksum = 0x6ffffdf8, ELF_DynTag_Pltpadsz = 0x6ffffdf9, ELF_DynTag_Moveent = 0x6ffffdfa, ELF_DynTag_Movesz = 0x6ffffdfb, ELF_DynTag_Feature = 0x6ffffdfc, ELF_DynTag_PosFlag_1 = 0x6ffffdfd, ELF_DynTag_SymInSz = 0x6ffffdfe, ELF_DynTag_SymInEnt = 0x6ffffdff, ELF_DynTag_ValRngHi = ELF_DynTag_SymInEnt, ELF_DynTag_AddrRngLo = 0x6ffffe00, ELF_DynTag_GNU_Hash = 0x6ffffef5, ELF_DynTag_TlsDescPlt = 0x6ffffef6, ELF_DynTag_TlsDescGot = 0x6ffffef7, ELF_DynTag_GNU_Conflict = 0x6ffffef8, ELF_DynTag_GNU_LibList = 0x6ffffef9, ELF_DynTag_Config = 0x6ffffefa, ELF_DynTag_DepAudit = 0x6ffffefb, ELF_DynTag_Audit = 0x6ffffefc, ELF_DynTag_PltPad = 0x6ffffefd, ELF_DynTag_MoveTab = 0x6ffffefe, ELF_DynTag_SymInfo = 0x6ffffeff, ELF_DynTag_AddrRngHi = ELF_DynTag_SymInfo, ELF_DynTag_RelaCount = 0x6ffffff9, ELF_DynTag_RelCount = 0x6ffffffa, ELF_DynTag_Flags_1 = 0x6ffffffb, ELF_DynTag_VerDef = 0x6ffffffc, ELF_DynTag_VerDefNum = 0x6ffffffd, ELF_DynTag_VerNeed = 0x6ffffffe, ELF_DynTag_VerNeedNum = 0x6fffffff, ELF_DynTag_VerSym = 0x6ffffff0, ELF_DynTag_LoProc = 0x70000000, ELF_DynTag_HiProc = 0x7fffffff, }; typedef U32 ELF_DynFlag; enum { ELF_DynFlag_Origin = (1 << 0), ELF_DynFlag_Symbolic = (1 << 1), ELF_DynFlag_TextTel = (1 << 2), ELF_DynFlag_BindNow = (1 << 3), ELF_DynFlag_StaticTls = (1 << 4), }; typedef U32 ELF_DynFeatureFlag; enum { ELF_DynFeatureFlag_ParInit = (1 << 0), ELF_DynFeatureFlag_ConfExp = (1 << 1), }; typedef U8 ELF_SymBind; enum { // the same name may exists in multiple files without interfering with each other. ELF_SymBind_Local = 0, // Visible to all objects that are linked together. ELF_SymBind_Global = 1, // If there is a global symbol with identical name linker doesn't issue an error. ELF_SymBind_Weak = 2, ELF_SymBind_LoProc = 13, ELF_SymBind_HiProc = 15, }; typedef U8 ELF_SymType; enum { ELF_SymType_NoType = 0, // Type is not specified. ELF_SymType_Object = 1, // Symbol is associated with data object, such as a variable, an array, etc. ELF_SymType_Func = 2, // Symbol is associated with a function. ELF_SymType_Section = 3, // Symbol is used to relocate sections and normally have LOCAL binding. ELF_SymType_File = 4, // Gives name of the source file associated with object. ELF_SymType_Common = 5, ELF_SymType_Tls = 6, ELF_SymType_LoProc = 13, ELF_SymType_HiProc = 15, }; typedef U8 ELF_SymVisibility; enum { ELF_SymVisibility_Default = 0, ELF_SymVisibility_Internal = 1, ELF_SymVisibility_Hidden = 2, ELF_SymVisibility_Protected = 3, }; typedef U32 ELF_RelocI386; enum { ELF_RelocI386_None = 0, ELF_RelocI386_32 = 1, ELF_RelocI386_PC32 = 2, ELF_RelocI386_GOT32 = 3, ELF_RelocI386_PLT32 = 4, ELF_RelocI386_Copy = 5, ELF_RelocI386_GlobDat = 6, ELF_RelocI386_JumpSlot = 7, ELF_RelocI386_Relative = 8, ELF_RelocI386_GotOff = 9, ELF_RelocI386_GotPc = 10, ELF_RelocI386_32Plt = 11, ELF_RelocI386_Tls_tpoff = 14, ELF_RelocI386_Tls_ie = 15, ELF_RelocI386_Tls_gotie = 16, ELF_RelocI386_Tls_le = 17, ELF_RelocI386_Tls_gd = 18, ELF_RelocI386_Tls_ldm = 19, ELF_RelocI386_16 = 20, ELF_RelocI386_PC16 = 21, ELF_RelocI386_8 = 22, ELF_RelocI386_Pc8 = 23, ELF_RelocI386_TlsGd32 = 24, ELF_RelocI386_TlsGdPush = 25, ELF_RelocI386_TlsGdCall = 26, ELF_RelocI386_TlsGdPop = 27, ELF_RelocI386_TlsLdm32 = 28, ELF_RelocI386_TlsLdmPush = 29, ELF_RelocI386_TlsLdmCall = 30, ELF_RelocI386_TlsLdmPop = 31, ELF_RelocI386_TlsLdo32 = 32, ELF_RelocI386_TlsIe32 = 33, ELF_RelocI386_TlsLe32 = 34, ELF_RelocI386_TlsDtpmod32 = 35, ELF_RelocI386_TlsDtpoff32 = 36, ELF_RelocI386_TlsTpoff32 = 37, // 38 is not taken ELF_RelocI386_TlsGotDesc = 39, ELF_RelocI386_TlsDescCall = 40, ELF_RelocI386_TlsDesc = 41, ELF_RelocI386_IRelative = 42, ELF_RelocI386_Gotx32x = 43, ELF_RelocI386_UsedByIntel200 = 200, ELF_RelocI386_GNU_VTInherit = 250, ELF_RelocI386_GNU_VTEntry = 251, }; typedef U32 ELF_RelocX8664; enum { ELF_RelocX8664_None = 0, ELF_RelocX8664_64 = 1, ELF_RelocX8664_Pc32 = 2, ELF_RelocX8664_Got32 = 3, ELF_RelocX8664_Plt32 = 4, ELF_RelocX8664_Copy = 5, ELF_RelocX8664_GlobDat = 6, ELF_RelocX8664_JumpSlot = 7, ELF_RelocX8664_Relative = 8, ELF_RelocX8664_GotPcRel = 9, ELF_RelocX8664_32 = 10, ELF_RelocX8664_32S = 11, ELF_RelocX8664_16 = 12, ELF_RelocX8664_Pc16 = 13, ELF_RelocX8664_8 = 14, ELF_RelocX8664_Pc8 = 15, ELF_RelocX8664_DtpMod64 = 16, ELF_RelocX8664_DtpOff64 = 17, ELF_RelocX8664_TpOff64 = 18, ELF_RelocX8664_TlsGd = 19, ELF_RelocX8664_TlsLd = 20, ELF_RelocX8664_DtpOff32 = 21, ELF_RelocX8664_GotTpOff = 22, ELF_RelocX8664_TpOff32 = 23, ELF_RelocX8664_Pc64 = 24, ELF_RelocX8664_GotOff64 = 25, ELF_RelocX8664_GotPc32 = 26, ELF_RelocX8664_Got64 = 27, ELF_RelocX8664_GotPcRel64 = 28, ELF_RelocX8664_GotPc64 = 29, ELF_RelocX8664_GotPlt64 = 30, ELF_RelocX8664_PltOff64 = 31, ELF_RelocX8664_Size32 = 32, ELF_RelocX8664_Size64 = 33, ELF_RelocX8664_GotPc32TlsDesc = 34, ELF_RelocX8664_TlsDescCall = 35, ELF_RelocX8664_TlsDesc = 36, ELF_RelocX8664_IRelative = 37, ELF_RelocX8664_Relative64 = 38, ELF_RelocX8664_Pc32Bnd = 39, ELF_RelocX8664_Plt32Bnd = 40, ELF_RelocX8664_GotPcRelx = 41, ELF_RelocX8664_RexGotPcRelx = 42, ELF_RelocX8664_GNU_VTInherit = 250, ELF_RelocX8664_GNU_VTEntry = 251, }; typedef U32 ELF_ExternalVerFlag; enum { ELF_ExternalVerFlag_Base = (1 << 0), ELF_ExternalVerFlag_Weak = (1 << 1), ELF_ExternalVerFlag_Info = (1 << 2), }; typedef U32 ELF_NoteType; enum { ELF_NoteType_GNU_Abi = 1, ELF_NoteType_GNU_HwCap = 2, ELF_NoteType_GNU_BuildId = 3, ELF_NoteType_GNU_GoldVersion = 4, ELF_NoteType_GNU_PropertyType0 = 5, }; typedef U32 ELF_GnuABITag; enum { ELF_GnuABITag_Linux = 0, ELF_GnuABITag_Hurd = 1, ELF_GnuABITag_Solaris = 2, ELF_GnuABITag_FreeBsd = 3, ELF_GnuABITag_NetBsd = 4, ELF_GnuABITag_Syllable = 5, ELF_GnuABITag_Nacl = 6, }; typedef S32 ELF_GnuProperty; enum { ELF_GnuProperty_LoProc = 0xc0000000, // processor-specific range ELF_GnuProperty_HiProc = 0xdfffffff, ELF_GnuProperty_LoUser = 0xe0000000, // application-specific range ELF_GnuProperty_HiUser = 0xffffffff, ELF_GnuProperty_StackSize = 1, ELF_GnuProperty_NoCopyOnProtected = 2, }; typedef U32 ELF_GnuPropertyX86Isa1; enum { ELF_GnuPropertyX86Isa1_BaseLine = (1 << 0), ELF_GnuPropertyX86Isa1_V2 = (1 << 1), ELF_GnuPropertyX86Isa1_V3 = (1 << 2), ELF_GnuPropertyX86Isa1_V4 = (1 << 3), }; typedef U32 ELF_GnuPropertyX86Compat1Isa1; enum { ELF_GnuPropertyX86Compat1Isa1_486 = (1 << 0), ELF_GnuPropertyX86Compat1Isa1_586 = (1 << 1), ELF_GnuPropertyX86Compat1Isa1_686 = (1 << 2), ELF_GnuPropertyX86Compat1Isa1_SSE = (1 << 3), ELF_GnuPropertyX86Compat1Isa1_SSE2 = (1 << 4), ELF_GnuPropertyX86Compat1Isa1_SSE3 = (1 << 5), ELF_GnuPropertyX86Compat1Isa1_SSSE3 = (1 << 6), ELF_GnuPropertyX86Compat1Isa1_SSE4_1 = (1 << 7), ELF_GnuPropertyX86Compat1Isa1_SSE4_2 = (1 << 8), ELF_GnuPropertyX86Compat1Isa1_AVX = (1 << 9), ELF_GnuPropertyX86Compat1Isa1_AVX2 = (1 << 10), ELF_GnuPropertyX86Compat1Isa1_AVX512F = (1 << 11), ELF_GnuPropertyX86Compat1Isa1_AVX512ER = (1 << 12), ELF_GnuPropertyX86Compat1Isa1_AVX512PF = (1 << 13), ELF_GnuPropertyX86Compat1Isa1_AVX512VL = (1 << 14), ELF_GnuPropertyX86Compat1Isa1_AVX512DQ = (1 << 15), ELF_GnuPropertyX86Compat1Isa1_AVX512BW = (1 << 16), }; typedef U32 ELF_GnuPropertyX86Compat2Isa1; enum { ELF_GnuPropertyX86Compat2Isa1_CMOVE = (1 << 0), ELF_GnuPropertyX86Compat2Isa1_SSE = (1 << 1), ELF_GnuPropertyX86Compat2Isa1_SSE2 = (1 << 2), ELF_GnuPropertyX86Compat2Isa1_SSE3 = (1 << 3), ELF_GnuPropertyX86Compat2Isa1_SSE4_1 = (1 << 4), ELF_GnuPropertyX86Compat2Isa1_SSE4_2 = (1 << 5), ELF_GnuPropertyX86Compat2Isa1_AVX = (1 << 6), ELF_GnuPropertyX86Compat2Isa1_AVX2 = (1 << 7), ELF_GnuPropertyX86Compat2Isa1_FMA = (1 << 8), ELF_GnuPropertyX86Compat2Isa1_AVX512F = (1 << 9), ELF_GnuPropertyX86Compat2Isa1_AVX512CD = (1 << 10), ELF_GnuPropertyX86Compat2Isa1_AVX512ER = (1 << 11), ELF_GnuPropertyX86Compat2Isa1_AVX512PF = (1 << 12), ELF_GnuPropertyX86Compat2Isa1_AVX512VL = (1 << 13), ELF_GnuPropertyX86Compat2Isa1_AVX512DQ = (1 << 14), ELF_GnuPropertyX86Compat2Isa1_AVX512BW = (1 << 15), ELF_GnuPropertyX86Compat2Isa1_AVX512_4FMAPS = (1 << 16), ELF_GnuPropertyX86Compat2Isa1_AVX512_4VNNIW = (1 << 17), ELF_GnuPropertyX86Compat2Isa1_AVX512_BITALG = (1 << 18), ELF_GnuPropertyX86Compat2Isa1_AVX512_IFMA = (1 << 19), ELF_GnuPropertyX86Compat2Isa1_AVX512_VBMI = (1 << 20), ELF_GnuPropertyX86Compat2Isa1_AVX512_VBMI2 = (1 << 21), ELF_GnuPropertyX86Compat2Isa1_AVX512_VNNI = (1 << 22), ELF_GnuPropertyX86Compat2Isa1_AVX512_BF16 = (1 << 23), }; typedef S32 ELF_GnuPropertyX86; enum { ELF_GnuPropertyX86_Feature1And = 0xc0000002, ELF_GnuPropertyX86_Feature2Used = 0xc0010001, ELF_GnuPropertyX86_Isa1needed = 0xc0008002, ELF_GnuPropertyX86_Isa2Needed = 0xc0008001, ELF_GnuPropertyX86_Isa1Used = 0xc0010002, ELF_GnuPropertyX86_Compat_isa_1_used = 0xc0000000, ELF_GnuPropertyX86_Compat_isa_1_needed = 0xc0000001, ELF_GnuPropertyX86_UInt32AndLo = ELF_GnuPropertyX86_Feature1And, ELF_GnuPropertyX86_UInt32AndHi = 0xc0007fff, ELF_GnuPropertyX86_UInt32OrLo = 0xc0008000, ELF_GnuPropertyX86_UInt32OrHi = 0xc000ffff, ELF_GnuPropertyX86_UInt32OrAndLo = 0xc0010000, ELF_GnuPropertyX86_UInt32OrAndHi = 0xc0017fff, }; typedef U32 ELF_GnuPropertyX86Feature1; enum { ELF_GnuPropertyX86Feature1_Ibt = (1 << 0), ELF_GnuPropertyX86Feature1_Shstk = (1 << 1), ELF_GnuPropertyX86Feature1_LamU48 = (1 << 2), ELF_GnuPropertyX86Feature1_LamU57 = (1 << 3), }; typedef U32 ELF_GnuPropertyX86Feature2; enum { ELF_GnuPropertyX86Feature2_X86 = (1 << 0), ELF_GnuPropertyX86Feature2_X87 = (1 << 1), ELF_GnuPropertyX86Feature2_MMX = (1 << 2), ELF_GnuPropertyX86Feature2_XMM = (1 << 3), ELF_GnuPropertyX86Feature2_YMM = (1 << 4), ELF_GnuPropertyX86Feature2_ZMM = (1 << 5), ELF_GnuPropertyX86Feature2_FXSR = (1 << 6), ELF_GnuPropertyX86Feature2_XSAVE = (1 << 7), ELF_GnuPropertyX86Feature2_XSAVEOPT = (1 << 8), ELF_GnuPropertyX86Feature2_XSAVEC = (1 << 9), ELF_GnuPropertyX86Feature2_TMM = (1 << 10), ELF_GnuPropertyX86Feature2_MASK = (1 << 11), }; #define ELF_HdrIs64Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_64) #define ELF_HdrIs32Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_32) typedef enum ELF_Identifier { ELF_Identifier_Mag0 = 0, ELF_Identifier_Mag1 = 1, ELF_Identifier_Mag2 = 2, ELF_Identifier_Mag3 = 3, ELF_Identifier_Class = 4, ELF_Identifier_Data = 5, ELF_Identifier_Version = 6, ELF_Identifier_OsAbi = 7, ELF_Identfiier_AbiBersion = 8, ELF_Identifier_Max = 16, } ELF_Identifier; typedef U16 ELF_Type; typedef enum ELF_TypeEnum { 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_TypeEnum; typedef struct ELF_Hdr64 { U8 e_ident[ELF_Identifier_Max]; ELF_Type e_type; ELF_MachineKind 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_Hdr64; typedef struct ELF_Hdr32 { U8 e_ident[ELF_Identifier_Max]; ELF_Type e_type; ELF_MachineKind 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_Hdr32; 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; 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_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 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; //////////////////////////////// // Auxiliary Vectors // these appear in /proc//auxv of a process, they are not in elf files typedef struct ELF_Auxv32 { U32 a_type; U32 a_val; } ELF_Auxv32; typedef struct ELF_Auxv64 { U64 a_type; U64 a_val; } ELF_Auxv64; //////////////////////////////// // Dynamic Structures // these appear in the virtual address space of a process, they are not in elf files typedef struct ELF_Dyn32 { U32 tag; U32 val; } ELF_Dyn32; typedef struct ELF_Dyn64 { U64 tag; U64 val; } ELF_Dyn64; typedef struct ELF_LinkMap32 { U32 base; U32 name; U32 ld; U32 next; } ELF_LinkMap32; typedef struct ELF_LinkMap64 { U64 base; U64 name; U64 ld; U64 next; } ELF_LinkMap64; //////////////////////////////// // Imports and Exports typedef struct { U32 st_name; // Holds index into files string table. U32 st_value; // Depending on the context, this may be address, size, etc. U32 st_size; // Data size in bytes. Zero when size is unknown. U8 st_info; // Contains symbols type and binding. U8 st_other; // Reserved for future use, currenly zero. U16 st_shndx; // Section index to which symbol is relevant. } ELF_Sym32; typedef struct { U32 st_name; U8 st_info; U8 st_other; U16 st_shndx; U64 st_value; U64 st_size; } ELF_Sym64; #define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF)) #define ELF_ST_BIND(x) ((x) >> 4) #define ELF_ST_TYPE(x) ((x) & 0xF) #define ELF_ST_VISIBILITY(v) ((v) & 0x3) typedef struct { U32 r_offset; U32 r_info; } ELF_Rel32; typedef struct { U32 r_offset; U32 r_info; S32 r_addend; } ELF_Rela32; typedef struct { U64 r_offset; U64 r_info; } ELF_Rel64; typedef struct { U64 r_offset; U64 r_info; S64 r_addend; } ELF_Rela64; #define ELF32_R_SYM(x) ((x) >> 8) #define ELF32_R_TYPE(x) ((x) & 0xFF) #define ELF64_R_INFO(s,t) (((U64)(s) << 32) | (U64)t) #define ELF64_R_SYM(x) ((x) >> 32) #define ELF64_R_TYPE(x) ((x) & 0xffffffff) // This flag is set to indicate that symbol is not available outside shared object #define ELF_EXTERNAL_VERSYM_HIDDEN 0x8000 #define ELF_EXTERNAL_VERSYM_MASK 0x7FFF // Appears in .gnu.verdef (SHT_GNU_verdef) typedef struct { U16 vd_version; U16 vd_flags; U16 vd_ndx; U16 vd_cnt; U32 vd_hash; U32 vd_aux; U32 vd_next; } ELF_ExternalVerdef; // Appears in .gnu.verdef (SHT_GNU_verdef) typedef struct { U32 vda_name; U32 vda_next; } ELF_ExternalVerdaux; // Appears in .gnu.verneed (SHT_GNU_verneed) typedef struct { U16 vn_version; U16 vn_cnt; U32 vn_file; U32 vn_aux; U32 vn_next; } ELF_ExternalVerneed; // Appears in .gnu.verneed (SHT_GNU_verneed) typedef struct { U32 vna_hash; U16 vna_flags; U16 vna_other; U32 vna_name; U32 vna_next; } ELF_ExternalVernaux; // Appears in .gnu.version (SHT_GNU_versym) typedef struct { U16 vs_vers; } ELF_ExternalVersym; typedef struct { U32 name_size; U32 desc_size; U32 type; // name + desc // U8 data[1]; } ELF_Note; //////////////////////////////// // Extensions typedef U8 ELF_CompressType; enum ELF_CompressTypeEnum { ELF_CompressType_None = 0, ELF_CompressType_ZLib = 1, ELF_CompressType_ZStd = 2, ELF_CompressType_LoOs = 0x60000000, ELF_CompressType_HiOs = 0x6fffffff, ELF_CompressType_LoProc = 0x70000000, ELF_CompressType_HiProc = 0x7fffffff, }; typedef struct ELF_Chdr32 { U32 ch_type; U32 ch_size; U32 ch_addr_align; } ELF_Chdr32; typedef struct ELF_Chdr64 { U64 ch_type; U64 ch_size; U64 ch_addr_align; } ELF_Chdr64; //////////////////////////////// internal ELF_Hdr64 elf_hdr64_from_ehdr32(ELF_Hdr32 h32); internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32); internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32); internal ELF_Dyn64 elf_dyn64_from_dyn32 (ELF_Dyn32 h32); internal ELF_Sym64 elf_sym64_from_sym32 (ELF_Sym32 sym32); internal ELF_Rel64 elf_rel64_from_rel32 (ELF_Rel32 rel32); internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32); internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32); //////////////////////////////// internal String8 elf_string_from_class(Arena *arena, ELF_Class v); //////////////////////////////// internal Arch arch_from_elf_machine(ELF_MachineKind machine); #endif // ELF_H