| 1 | //! The ELF ABI. 🧝 |
| 2 | //! |
| 3 | //! This module is not as comprehensive as bindgened [`elf_uapi`] and provides only types for target |
| 4 | //! pointer width: instead of [`elf32_phdr`] and [`elf64_phdr`] there's only [`Elf_Phdr`]. |
| 5 | //! |
| 6 | //! [`elf_uapi`]: super::elf_uapi |
| 7 | //! [`elf32_phdr`]: super::elf_uapi::elf32_phdr |
| 8 | //! [`elf64_phdr`]: super::elf_uapi::elf64_phdr |
| 9 | |
| 10 | pub const SELFMAG: usize = 4; |
| 11 | pub const ELFMAG: [u8; SELFMAG] = [0x7f, b'E' , b'L' , b'F' ]; |
| 12 | pub const EI_CLASS: usize = 4; |
| 13 | pub const EI_DATA: usize = 5; |
| 14 | pub const EI_VERSION: usize = 6; |
| 15 | pub const EI_OSABI: usize = 7; |
| 16 | pub const EI_ABIVERSION: usize = 8; |
| 17 | pub const EV_CURRENT: u8 = 1; |
| 18 | #[cfg (target_pointer_width = "32" )] |
| 19 | pub const ELFCLASS: u8 = 1; // ELFCLASS32 |
| 20 | #[cfg (target_pointer_width = "64" )] |
| 21 | pub const ELFCLASS: u8 = 2; // ELFCLASS64 |
| 22 | #[cfg (target_endian = "little" )] |
| 23 | pub const ELFDATA: u8 = 1; // ELFDATA2LSB |
| 24 | #[cfg (target_endian = "big" )] |
| 25 | pub const ELFDATA: u8 = 2; // ELFDATA2MSB |
| 26 | pub const ELFOSABI_SYSV: u8 = 0; |
| 27 | pub const ELFOSABI_LINUX: u8 = 3; |
| 28 | // At present all of our supported platforms use 0. |
| 29 | pub const ELFABIVERSION: u8 = 0; |
| 30 | pub const ET_DYN: u16 = 3; |
| 31 | pub const EI_NIDENT: usize = 16; |
| 32 | pub const SHN_UNDEF: u16 = 0; |
| 33 | pub const SHN_ABS: u16 = 0xfff1; |
| 34 | pub const PN_XNUM: u16 = 0xffff; |
| 35 | pub const PT_LOAD: u32 = 1; |
| 36 | pub const PT_DYNAMIC: u32 = 2; |
| 37 | pub const PT_INTERP: u32 = 3; |
| 38 | pub const PT_PHDR: u32 = 6; |
| 39 | pub const PT_TLS: u32 = 7; |
| 40 | pub const PT_GNU_STACK: u32 = 0x6474_e551; |
| 41 | pub const PT_GNU_RELRO: u32 = 0x6474_e552; |
| 42 | pub const PF_X: u32 = 1; |
| 43 | pub const PF_W: u32 = 2; |
| 44 | pub const PF_R: u32 = 4; |
| 45 | pub const DT_NULL: usize = 0; |
| 46 | pub const DT_HASH: usize = 4; |
| 47 | pub const DT_STRTAB: usize = 5; |
| 48 | pub const DT_SYMTAB: usize = 6; |
| 49 | pub const DT_RELA: usize = 7; |
| 50 | pub const DT_RELASZ: usize = 8; |
| 51 | pub const DT_RELAENT: usize = 9; |
| 52 | pub const DT_REL: usize = 17; |
| 53 | pub const DT_RELSZ: usize = 18; |
| 54 | pub const DT_RELENT: usize = 19; |
| 55 | pub const DT_SYMENT: usize = 11; |
| 56 | pub const DT_GNU_HASH: usize = 0x6fff_fef5; |
| 57 | pub const DT_VERSYM: usize = 0x6fff_fff0; |
| 58 | pub const DT_VERDEF: usize = 0x6fff_fffc; |
| 59 | pub const STB_WEAK: u8 = 2; |
| 60 | pub const STB_GLOBAL: u8 = 1; |
| 61 | pub const STT_NOTYPE: u8 = 0; |
| 62 | pub const STT_FUNC: u8 = 2; |
| 63 | pub const STN_UNDEF: u32 = 0; |
| 64 | pub const VER_FLG_BASE: u16 = 0x1; |
| 65 | pub const VER_DEF_CURRENT: u16 = 1; |
| 66 | pub const STV_DEFAULT: u8 = 0; |
| 67 | #[cfg (target_arch = "arm" )] |
| 68 | pub const EM_CURRENT: u16 = 40; // EM_ARM |
| 69 | #[cfg (target_arch = "x86" )] |
| 70 | pub const EM_CURRENT: u16 = 3; // EM_386 |
| 71 | #[cfg (target_arch = "powerpc64" )] |
| 72 | pub const EM_CURRENT: u16 = 21; // EM_PPC64 |
| 73 | #[cfg (any( |
| 74 | target_arch = "mips" , |
| 75 | target_arch = "mips32r6" , |
| 76 | target_arch = "mips64" , |
| 77 | target_arch = "mips64r6" |
| 78 | ))] |
| 79 | pub const EM_CURRENT: u16 = 8; // EM_MIPS |
| 80 | #[cfg (target_arch = "x86_64" )] |
| 81 | pub const EM_CURRENT: u16 = 62; // EM_X86_64 |
| 82 | #[cfg (target_arch = "aarch64" )] |
| 83 | pub const EM_CURRENT: u16 = 183; // EM_AARCH64 |
| 84 | #[cfg (target_arch = "riscv64" )] |
| 85 | pub const EM_CURRENT: u16 = 243; // EM_RISCV |
| 86 | |
| 87 | #[inline ] |
| 88 | pub const fn ELF_ST_VISIBILITY(o: u8) -> u8 { |
| 89 | o & 0x03 |
| 90 | } |
| 91 | |
| 92 | #[inline ] |
| 93 | pub const fn ELF_ST_BIND(val: u8) -> u8 { |
| 94 | val >> 4 |
| 95 | } |
| 96 | |
| 97 | #[inline ] |
| 98 | pub const fn ELF_ST_TYPE(val: u8) -> u8 { |
| 99 | val & 0xf |
| 100 | } |
| 101 | |
| 102 | #[repr (C)] |
| 103 | pub struct Elf_Ehdr { |
| 104 | pub e_ident: [u8; EI_NIDENT], |
| 105 | pub e_type: u16, |
| 106 | pub e_machine: u16, |
| 107 | pub e_version: u32, |
| 108 | pub e_entry: usize, |
| 109 | pub e_phoff: usize, |
| 110 | pub e_shoff: usize, |
| 111 | pub e_flags: u32, |
| 112 | pub e_ehsize: u16, |
| 113 | pub e_phentsize: u16, |
| 114 | pub e_phnum: u16, |
| 115 | pub e_shentsize: u16, |
| 116 | pub e_shnum: u16, |
| 117 | pub e_shstrndx: u16, |
| 118 | } |
| 119 | |
| 120 | #[cfg (target_pointer_width = "32" )] |
| 121 | #[repr (C)] |
| 122 | pub struct Elf_Phdr { |
| 123 | pub p_type: u32, |
| 124 | pub p_offset: usize, |
| 125 | pub p_vaddr: usize, |
| 126 | pub p_paddr: usize, |
| 127 | pub p_filesz: usize, |
| 128 | pub p_memsz: usize, |
| 129 | pub p_flags: u32, |
| 130 | pub p_align: usize, |
| 131 | } |
| 132 | |
| 133 | #[cfg (target_pointer_width = "64" )] |
| 134 | #[repr (C)] |
| 135 | pub struct Elf_Phdr { |
| 136 | pub p_type: u32, |
| 137 | pub p_flags: u32, |
| 138 | pub p_offset: usize, |
| 139 | pub p_vaddr: usize, |
| 140 | pub p_paddr: usize, |
| 141 | pub p_filesz: usize, |
| 142 | pub p_memsz: usize, |
| 143 | pub p_align: usize, |
| 144 | } |
| 145 | |
| 146 | #[cfg (target_pointer_width = "32" )] |
| 147 | #[repr (C)] |
| 148 | pub struct Elf_Sym { |
| 149 | pub st_name: u32, |
| 150 | pub st_value: usize, |
| 151 | pub st_size: usize, |
| 152 | pub st_info: u8, |
| 153 | pub st_other: u8, |
| 154 | pub st_shndx: u16, |
| 155 | } |
| 156 | |
| 157 | #[cfg (target_pointer_width = "64" )] |
| 158 | #[repr (C)] |
| 159 | pub struct Elf_Sym { |
| 160 | pub st_name: u32, |
| 161 | pub st_info: u8, |
| 162 | pub st_other: u8, |
| 163 | pub st_shndx: u16, |
| 164 | pub st_value: usize, |
| 165 | pub st_size: usize, |
| 166 | } |
| 167 | |
| 168 | #[repr (C)] |
| 169 | pub struct Elf_Verdef { |
| 170 | pub vd_version: u16, |
| 171 | pub vd_flags: u16, |
| 172 | pub vd_ndx: u16, |
| 173 | pub vd_cnt: u16, |
| 174 | pub vd_hash: u32, |
| 175 | pub vd_aux: u32, |
| 176 | pub vd_next: u32, |
| 177 | } |
| 178 | |
| 179 | #[repr (C)] |
| 180 | pub struct Elf_Verdaux { |
| 181 | pub vda_name: u32, |
| 182 | pub _vda_next: u32, |
| 183 | } |
| 184 | |
| 185 | #[cfg (target_pointer_width = "32" )] |
| 186 | #[repr (C)] |
| 187 | #[derive (Copy, Clone)] |
| 188 | pub struct Elf_Dyn { |
| 189 | pub d_tag: usize, |
| 190 | pub d_un: Elf_Dyn_Union, |
| 191 | } |
| 192 | |
| 193 | #[cfg (target_pointer_width = "32" )] |
| 194 | #[repr (C)] |
| 195 | #[derive (Copy, Clone)] |
| 196 | pub union Elf_Dyn_Union { |
| 197 | pub d_val: u32, |
| 198 | pub d_ptr: usize, |
| 199 | } |
| 200 | |
| 201 | #[cfg (target_pointer_width = "64" )] |
| 202 | #[repr (C)] |
| 203 | #[derive (Copy, Clone)] |
| 204 | pub struct Elf_Dyn { |
| 205 | pub d_tag: usize, |
| 206 | pub d_un: Elf_Dyn_Union, |
| 207 | } |
| 208 | |
| 209 | #[cfg (target_pointer_width = "64" )] |
| 210 | #[repr (C)] |
| 211 | #[derive (Copy, Clone)] |
| 212 | pub union Elf_Dyn_Union { |
| 213 | pub d_val: u64, |
| 214 | pub d_ptr: usize, |
| 215 | } |
| 216 | |
| 217 | #[cfg (target_pointer_width = "32" )] |
| 218 | #[repr (C)] |
| 219 | pub struct Elf_Rela { |
| 220 | pub r_offset: usize, |
| 221 | pub r_info: u32, |
| 222 | pub r_addend: usize, |
| 223 | } |
| 224 | |
| 225 | #[cfg (target_pointer_width = "64" )] |
| 226 | #[repr (C)] |
| 227 | pub struct Elf_Rela { |
| 228 | pub r_offset: usize, |
| 229 | pub r_info: u64, |
| 230 | pub r_addend: usize, |
| 231 | } |
| 232 | |
| 233 | impl Elf_Rela { |
| 234 | #[inline ] |
| 235 | pub fn type_(&self) -> u32 { |
| 236 | #[cfg (target_pointer_width = "32" )] |
| 237 | { |
| 238 | self.r_info & 0xff |
| 239 | } |
| 240 | #[cfg (target_pointer_width = "64" )] |
| 241 | { |
| 242 | (self.r_info & 0xffff_ffff) as u32 |
| 243 | } |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | #[cfg (target_pointer_width = "32" )] |
| 248 | #[repr (C)] |
| 249 | pub struct Elf_Rel { |
| 250 | pub r_offset: usize, |
| 251 | pub r_info: u32, |
| 252 | } |
| 253 | |
| 254 | #[cfg (target_pointer_width = "64" )] |
| 255 | #[repr (C)] |
| 256 | pub struct Elf_Rel { |
| 257 | pub r_offset: usize, |
| 258 | pub r_info: u64, |
| 259 | } |
| 260 | |
| 261 | impl Elf_Rel { |
| 262 | #[inline ] |
| 263 | pub fn type_(&self) -> u32 { |
| 264 | #[cfg (target_pointer_width = "32" )] |
| 265 | { |
| 266 | self.r_info & 0xff |
| 267 | } |
| 268 | #[cfg (target_pointer_width = "64" )] |
| 269 | { |
| 270 | (self.r_info & 0xffff_ffff) as u32 |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | #[cfg (target_arch = "x86_64" )] |
| 276 | pub const R_RELATIVE: u32 = 8; // `R_X86_64_RELATIVE` |
| 277 | #[cfg (target_arch = "x86" )] |
| 278 | pub const R_RELATIVE: u32 = 8; // `R_386_RELATIVE` |
| 279 | #[cfg (target_arch = "aarch64" )] |
| 280 | pub const R_RELATIVE: u32 = 1027; // `R_AARCH64_RELATIVE` |
| 281 | #[cfg (target_arch = "riscv64" )] |
| 282 | pub const R_RELATIVE: u32 = 3; // `R_RISCV_RELATIVE` |
| 283 | #[cfg (target_arch = "arm" )] |
| 284 | pub const R_RELATIVE: u32 = 23; // `R_ARM_RELATIVE` |
| 285 | |
| 286 | #[repr (C)] |
| 287 | #[derive (Clone)] |
| 288 | pub struct Elf_auxv_t { |
| 289 | pub a_type: usize, |
| 290 | |
| 291 | // Some of the values in the auxv array are pointers, so we make `a_val` a |
| 292 | // pointer, in order to preserve their provenance. For the values which are |
| 293 | // integers, we cast this to `usize`. |
| 294 | pub a_val: *mut crate::ctypes::c_void, |
| 295 | } |
| 296 | |