| //! The ELF ABI. 🧝 |
| |
| pub const SELFMAG: usize = 4; |
| pub const ELFMAG: [u8; SELFMAG] = [0x7f, b'E', b'L', b'F']; |
| pub const EI_CLASS: usize = 4; |
| pub const EI_DATA: usize = 5; |
| pub const EI_VERSION: usize = 6; |
| pub const EI_OSABI: usize = 7; |
| pub const EI_ABIVERSION: usize = 8; |
| pub const EV_CURRENT: u8 = 1; |
| #[cfg(target_pointer_width = "32")] |
| pub const ELFCLASS: u8 = 1; // ELFCLASS32 |
| #[cfg(target_pointer_width = "64")] |
| pub const ELFCLASS: u8 = 2; // ELFCLASS64 |
| #[cfg(target_endian = "little")] |
| pub const ELFDATA: u8 = 1; // ELFDATA2LSB |
| #[cfg(target_endian = "big")] |
| pub const ELFDATA: u8 = 2; // ELFDATA2MSB |
| pub const ELFOSABI_SYSV: u8 = 0; |
| pub const ELFOSABI_LINUX: u8 = 3; |
| // At present all of our supported platforms use 0. |
| pub const ELFABIVERSION: u8 = 0; |
| pub const ET_DYN: u16 = 3; |
| pub const EI_NIDENT: usize = 16; |
| pub const SHN_UNDEF: u16 = 0; |
| pub const SHN_ABS: u16 = 0xfff1; |
| pub const PN_XNUM: u16 = 0xffff; |
| pub const PT_LOAD: u32 = 1; |
| pub const PT_DYNAMIC: u32 = 2; |
| pub const PT_INTERP: u32 = 3; |
| pub const PT_PHDR: u32 = 6; |
| pub const PT_TLS: u32 = 7; |
| pub const PT_GNU_STACK: u32 = 0x6474_e551; |
| pub const PT_GNU_RELRO: u32 = 0x6474_e552; |
| pub const PF_X: u32 = 1; |
| pub const PF_W: u32 = 2; |
| pub const PF_R: u32 = 4; |
| pub const DT_NULL: usize = 0; |
| pub const DT_HASH: usize = 4; |
| pub const DT_STRTAB: usize = 5; |
| pub const DT_SYMTAB: usize = 6; |
| pub const DT_RELA: usize = 7; |
| pub const DT_RELASZ: usize = 8; |
| pub const DT_RELAENT: usize = 9; |
| pub const DT_REL: usize = 17; |
| pub const DT_RELSZ: usize = 18; |
| pub const DT_RELENT: usize = 19; |
| pub const DT_SYMENT: usize = 11; |
| pub const DT_VERSYM: usize = 0x6fff_fff0; |
| pub const DT_VERDEF: usize = 0x6fff_fffc; |
| pub const STB_WEAK: u8 = 2; |
| pub const STB_GLOBAL: u8 = 1; |
| pub const STT_NOTYPE: u8 = 0; |
| pub const STT_FUNC: u8 = 2; |
| pub const STN_UNDEF: u32 = 0; |
| pub const VER_FLG_BASE: u16 = 0x1; |
| pub const VER_DEF_CURRENT: u16 = 1; |
| pub const STV_DEFAULT: u8 = 0; |
| #[cfg(target_arch = "arm")] |
| pub const EM_CURRENT: u16 = 40; // EM_ARM |
| #[cfg(target_arch = "x86")] |
| pub const EM_CURRENT: u16 = 3; // EM_386 |
| #[cfg(target_arch = "powerpc64")] |
| pub const EM_CURRENT: u16 = 21; // EM_PPC64 |
| #[cfg(any( |
| target_arch = "mips", |
| target_arch = "mips32r6", |
| target_arch = "mips64", |
| target_arch = "mips64r6" |
| ))] |
| pub const EM_CURRENT: u16 = 8; // EM_MIPS |
| #[cfg(target_arch = "x86_64")] |
| pub const EM_CURRENT: u16 = 62; // EM_X86_64 |
| #[cfg(target_arch = "aarch64")] |
| pub const EM_CURRENT: u16 = 183; // EM_AARCH64 |
| #[cfg(target_arch = "riscv64")] |
| pub const EM_CURRENT: u16 = 243; // EM_RISCV |
| |
| #[inline] |
| pub const fn ELF_ST_VISIBILITY(o: u8) -> u8 { |
| o & 0x03 |
| } |
| |
| #[inline] |
| pub const fn ELF_ST_BIND(val: u8) -> u8 { |
| val >> 4 |
| } |
| |
| #[inline] |
| pub const fn ELF_ST_TYPE(val: u8) -> u8 { |
| val & 0xf |
| } |
| |
| #[repr(C)] |
| pub struct Elf_Ehdr { |
| pub e_ident: [u8; EI_NIDENT], |
| pub e_type: u16, |
| pub e_machine: u16, |
| pub e_version: u32, |
| pub e_entry: usize, |
| pub e_phoff: usize, |
| pub e_shoff: usize, |
| pub e_flags: u32, |
| pub e_ehsize: u16, |
| pub e_phentsize: u16, |
| pub e_phnum: u16, |
| pub e_shentsize: u16, |
| pub e_shnum: u16, |
| pub e_shstrndx: u16, |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| pub struct Elf_Phdr { |
| pub p_type: u32, |
| pub p_offset: usize, |
| pub p_vaddr: usize, |
| pub p_paddr: usize, |
| pub p_filesz: usize, |
| pub p_memsz: usize, |
| pub p_flags: u32, |
| pub p_align: usize, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| pub struct Elf_Phdr { |
| pub p_type: u32, |
| pub p_flags: u32, |
| pub p_offset: usize, |
| pub p_vaddr: usize, |
| pub p_paddr: usize, |
| pub p_filesz: usize, |
| pub p_memsz: usize, |
| pub p_align: usize, |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| pub struct Elf_Sym { |
| pub st_name: u32, |
| pub st_value: usize, |
| pub st_size: usize, |
| pub st_info: u8, |
| pub st_other: u8, |
| pub st_shndx: u16, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| pub struct Elf_Sym { |
| pub st_name: u32, |
| pub st_info: u8, |
| pub st_other: u8, |
| pub st_shndx: u16, |
| pub st_value: usize, |
| pub st_size: usize, |
| } |
| |
| #[repr(C)] |
| pub struct Elf_Verdef { |
| pub vd_version: u16, |
| pub vd_flags: u16, |
| pub vd_ndx: u16, |
| pub vd_cnt: u16, |
| pub vd_hash: u32, |
| pub vd_aux: u32, |
| pub vd_next: u32, |
| } |
| |
| #[repr(C)] |
| pub struct Elf_Verdaux { |
| pub vda_name: u32, |
| pub _vda_next: u32, |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub struct Elf_Dyn { |
| pub d_tag: usize, |
| pub d_un: Elf_Dyn_Union, |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub union Elf_Dyn_Union { |
| pub d_val: u32, |
| pub d_ptr: usize, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub struct Elf_Dyn { |
| pub d_tag: usize, |
| pub d_un: Elf_Dyn_Union, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| #[derive(Copy, Clone)] |
| pub union Elf_Dyn_Union { |
| pub d_val: u64, |
| pub d_ptr: usize, |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| pub struct Elf_Rela { |
| pub r_offset: usize, |
| pub r_info: u32, |
| pub r_addend: usize, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| pub struct Elf_Rela { |
| pub r_offset: usize, |
| pub r_info: u64, |
| pub r_addend: usize, |
| } |
| |
| impl Elf_Rela { |
| #[inline] |
| pub fn type_(&self) -> u32 { |
| #[cfg(target_pointer_width = "32")] |
| { |
| self.r_info & 0xff |
| } |
| #[cfg(target_pointer_width = "64")] |
| { |
| (self.r_info & 0xffff_ffff) as u32 |
| } |
| } |
| } |
| |
| #[cfg(target_pointer_width = "32")] |
| #[repr(C)] |
| pub struct Elf_Rel { |
| pub r_offset: usize, |
| pub r_info: u32, |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| #[repr(C)] |
| pub struct Elf_Rel { |
| pub r_offset: usize, |
| pub r_info: u64, |
| } |
| |
| impl Elf_Rel { |
| #[inline] |
| pub fn type_(&self) -> u32 { |
| #[cfg(target_pointer_width = "32")] |
| { |
| self.r_info & 0xff |
| } |
| #[cfg(target_pointer_width = "64")] |
| { |
| (self.r_info & 0xffff_ffff) as u32 |
| } |
| } |
| } |
| |
| #[cfg(target_arch = "x86_64")] |
| pub const R_RELATIVE: u32 = 8; // `R_X86_64_RELATIVE` |
| #[cfg(target_arch = "x86")] |
| pub const R_RELATIVE: u32 = 8; // `R_386_RELATIVE` |
| #[cfg(target_arch = "aarch64")] |
| pub const R_RELATIVE: u32 = 1027; // `R_AARCH64_RELATIVE` |
| #[cfg(target_arch = "riscv64")] |
| pub const R_RELATIVE: u32 = 3; // `R_RISCV_RELATIVE` |
| #[cfg(target_arch = "arm")] |
| pub const R_RELATIVE: u32 = 23; // `R_ARM_RELATIVE` |
| |
| #[repr(C)] |
| #[derive(Clone)] |
| pub struct Elf_auxv_t { |
| pub a_type: usize, |
| |
| // Some of the values in the auxv array are pointers, so we make `a_val` a |
| // pointer, in order to preserve their provenance. For the values which are |
| // integers, we cast this to `usize`. |
| pub a_val: *mut crate::ctypes::c_void, |
| } |