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 | |