linux_raw_sys/
elf.rs

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