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