1use {
2 crate::errors::DisassemblerError,
3 object::{Endianness, read::elf::ElfFile64},
4 serde::{Deserialize, Serialize, Serializer},
5 std::str,
6};
7
8pub const EI_MAGIC: [u8; 4] = *b"\x7fELF"; pub const EI_CLASS: u8 = 0x02; pub const EI_DATA: u8 = 0x01; pub const EI_VERSION: u8 = 0x01; pub const EI_OSABI: u8 = 0x00; pub const EI_OSABI_LINUX: u8 = 0x03; pub const EI_ABIVERSION: u8 = 0x00; pub const EI_PAD: [u8; 7] = [0u8; 7]; pub const E_TYPE: u16 = 0x03; pub const E_MACHINE: u16 = 0xf7; pub const E_MACHINE_SBPF: u16 = 0x0107; pub const E_VERSION: u32 = 0x01; fn elf_magic<S>(magic: &[u8; 4], serializer: S) -> Result<S::Ok, S::Error>
22where
23 S: Serializer,
24{
25 let s = String::from_utf8_lossy(magic);
26 serializer.serialize_str(&s)
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct ELFHeader {
31 #[serde(serialize_with = "elf_magic")]
32 pub ei_magic: [u8; 4],
33 pub ei_class: u8,
34 pub ei_data: u8,
35 pub ei_version: u8,
36 pub ei_osabi: u8,
37 pub ei_abiversion: u8,
38 pub ei_pad: [u8; 7],
39 pub e_type: u16,
40 pub e_machine: u16,
41 pub e_version: u32,
42 pub e_entry: u64,
43 pub e_phoff: u64,
44 pub e_shoff: u64,
45 pub e_flags: u32,
46 pub e_ehsize: u16,
47 pub e_phentsize: u16,
48 pub e_phnum: u16,
49 pub e_shentsize: u16,
50 pub e_shnum: u16,
51 pub e_shstrndx: u16,
52}
53
54impl ELFHeader {
55 pub fn from_elf_file(elf_file: &ElfFile64<Endianness>) -> Result<Self, Vec<DisassemblerError>> {
56 let endian = elf_file.endian();
57 let elf_header = elf_file.elf_header();
58
59 let e_ident = elf_header.e_ident;
61 let e_type = elf_header.e_type.get(endian);
62 let e_machine = elf_header.e_machine.get(endian);
63 let e_version = elf_header.e_version.get(endian);
64 let e_entry = elf_header.e_entry.get(endian);
65 let e_phoff = elf_header.e_phoff.get(endian);
66 let e_shoff = elf_header.e_shoff.get(endian);
67 let e_flags = elf_header.e_flags.get(endian);
68 let e_ehsize = elf_header.e_ehsize.get(endian);
69 let e_phentsize = elf_header.e_phentsize.get(endian);
70 let e_phnum = elf_header.e_phnum.get(endian);
71 let e_shentsize = elf_header.e_shentsize.get(endian);
72 let e_shnum = elf_header.e_shnum.get(endian);
73 let e_shstrndx = elf_header.e_shstrndx.get(endian);
74
75 let mut errors = Vec::new();
76
77 if e_ident.magic != EI_MAGIC {
78 errors.push(DisassemblerError::NonStandardElfHeader {
79 field: "magic",
80 expected: vec![u32::from_be_bytes(EI_MAGIC) as u64],
81 found: u32::from_be_bytes(e_ident.magic) as u64,
82 });
83 }
84
85 if e_ident.class != EI_CLASS {
86 errors.push(DisassemblerError::NonStandardElfHeader {
87 field: "class",
88 expected: vec![EI_CLASS as u64],
89 found: e_ident.class as u64,
90 });
91 }
92
93 if e_ident.data != EI_DATA {
94 errors.push(DisassemblerError::NonStandardElfHeader {
95 field: "data",
96 expected: vec![EI_DATA as u64],
97 found: e_ident.data as u64,
98 });
99 }
100
101 if e_ident.version != EI_VERSION {
102 errors.push(DisassemblerError::NonStandardElfHeader {
103 field: "ident version",
104 expected: vec![EI_VERSION as u64],
105 found: e_ident.version as u64,
106 });
107 }
108
109 if !matches!(e_ident.os_abi, EI_OSABI | EI_OSABI_LINUX) {
110 errors.push(DisassemblerError::NonStandardElfHeader {
111 field: "os abi",
112 expected: vec![EI_OSABI as u64, EI_OSABI_LINUX as u64],
113 found: e_ident.os_abi as u64,
114 });
115 }
116
117 if e_ident.abi_version != EI_ABIVERSION {
118 errors.push(DisassemblerError::NonStandardElfHeader {
119 field: "abi version",
120 expected: vec![EI_ABIVERSION as u64],
121 found: e_ident.abi_version as u64,
122 });
123 }
124
125 if e_ident.padding != EI_PAD {
126 let mut found = [0u8; 8];
129 found[1..].copy_from_slice(&e_ident.padding);
130 errors.push(DisassemblerError::NonStandardElfHeader {
131 field: "padding",
132 expected: vec![0],
133 found: u64::from_be_bytes(found),
134 });
135 }
136
137 if e_machine != E_MACHINE && e_machine != E_MACHINE_SBPF {
138 errors.push(DisassemblerError::NonStandardElfHeader {
139 field: "machine",
140 expected: vec![E_MACHINE as u64, E_MACHINE_SBPF as u64],
141 found: e_machine as u64,
142 });
143 }
144
145 if e_version != E_VERSION {
146 errors.push(DisassemblerError::NonStandardElfHeader {
147 field: "version",
148 expected: vec![E_VERSION as u64],
149 found: e_version as u64,
150 });
151 }
152
153 if errors.is_empty() {
154 Ok(ELFHeader {
155 ei_magic: e_ident.magic,
156 ei_class: e_ident.class,
157 ei_data: e_ident.data,
158 ei_version: e_ident.version,
159 ei_osabi: e_ident.os_abi,
160 ei_abiversion: e_ident.abi_version,
161 ei_pad: e_ident.padding,
162 e_type,
163 e_machine,
164 e_version,
165 e_entry,
166 e_phoff,
167 e_shoff,
168 e_flags,
169 e_ehsize,
170 e_phentsize,
171 e_phnum,
172 e_shentsize,
173 e_shnum,
174 e_shstrndx,
175 })
176 } else {
177 Err(errors)
178 }
179 }
180
181 pub fn to_bytes(&self) -> Vec<u8> {
182 let mut b = self.ei_magic.to_vec();
183 b.extend_from_slice(&[
184 self.ei_class,
185 self.ei_data,
186 self.ei_version,
187 self.ei_osabi,
188 self.ei_abiversion,
189 ]);
190 b.extend_from_slice(&self.ei_pad);
191 b.extend_from_slice(&self.e_type.to_le_bytes());
192 b.extend_from_slice(&self.e_machine.to_le_bytes());
193 b.extend_from_slice(&self.e_version.to_le_bytes());
194 b.extend_from_slice(&self.e_entry.to_le_bytes());
195 b.extend_from_slice(&self.e_phoff.to_le_bytes());
196 b.extend_from_slice(&self.e_shoff.to_le_bytes());
197 b.extend_from_slice(&self.e_flags.to_le_bytes());
198 b.extend_from_slice(&self.e_ehsize.to_le_bytes());
199 b.extend_from_slice(&self.e_phentsize.to_le_bytes());
200 b.extend_from_slice(&self.e_phnum.to_le_bytes());
201 b.extend_from_slice(&self.e_shentsize.to_le_bytes());
202 b.extend_from_slice(&self.e_shnum.to_le_bytes());
203 b.extend_from_slice(&self.e_shstrndx.to_le_bytes());
204 b
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use {
211 super::*,
212 crate::{
213 elf_header::{
214 E_MACHINE, E_MACHINE_SBPF, E_TYPE, E_VERSION, EI_ABIVERSION, EI_CLASS, EI_DATA,
215 EI_MAGIC, EI_OSABI, EI_PAD, EI_VERSION,
216 },
217 errors::DisassemblerError,
218 program::Program,
219 },
220 hex_literal::hex,
221 };
222
223 #[test]
224 fn test_elf_header() {
225 let program = Program::from_bytes(&hex!("7F454C460201010000000000000000000300F700010000002001000000000000400000000000000028020000000000000000000040003800030040000600050001000000050000002001000000000000200100000000000020010000000000003000000000000000300000000000000000100000000000000100000004000000C001000000000000C001000000000000C0010000000000003C000000000000003C000000000000000010000000000000020000000600000050010000000000005001000000000000500100000000000070000000000000007000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007912A000000000007911182900000000B7000000010000002D21010000000000B70000000000000095000000000000001E0000000000000004000000000000000600000000000000C0010000000000000B0000000000000018000000000000000500000000000000F0010000000000000A000000000000000C00000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000120001002001000000000000300000000000000000656E747279706F696E7400002E74657874002E64796E737472002E64796E73796D002E64796E616D6963002E73687374727461620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000600000000000000200100000000000020010000000000003000000000000000000000000000000008000000000000000000000000000000170000000600000003000000000000005001000000000000500100000000000070000000000000000400000000000000080000000000000010000000000000000F0000000B0000000200000000000000C001000000000000C001000000000000300000000000000004000000010000000800000000000000180000000000000007000000030000000200000000000000F001000000000000F0010000000000000C00000000000000000000000000000001000000000000000000000000000000200000000300000000000000000000000000000000000000FC010000000000002A00000000000000000000000000000001000000000000000000000000000000")).unwrap();
226
227 assert_eq!(program.elf_header.ei_magic, EI_MAGIC);
229 assert_eq!(program.elf_header.ei_class, EI_CLASS);
230 assert_eq!(program.elf_header.ei_data, EI_DATA);
231 assert_eq!(program.elf_header.ei_version, EI_VERSION);
232 assert_eq!(program.elf_header.ei_osabi, EI_OSABI);
233 assert_eq!(program.elf_header.ei_abiversion, EI_ABIVERSION);
234 assert_eq!(program.elf_header.ei_pad, EI_PAD);
235 assert_eq!(program.elf_header.e_type, E_TYPE);
236 assert!(
237 program.elf_header.e_machine == E_MACHINE_SBPF
238 || program.elf_header.e_machine == E_MACHINE
239 );
240 assert_eq!(program.elf_header.e_version, E_VERSION);
241 }
242
243 #[test]
244 fn test_elf_header_to_bytes() {
245 let header = ELFHeader {
246 ei_magic: EI_MAGIC,
247 ei_class: EI_CLASS,
248 ei_data: EI_DATA,
249 ei_version: EI_VERSION,
250 ei_osabi: EI_OSABI,
251 ei_abiversion: EI_ABIVERSION,
252 ei_pad: EI_PAD,
253 e_type: 0x03,
254 e_machine: 0xf7,
255 e_version: 0x01,
256 e_entry: 0x120,
257 e_phoff: 64,
258 e_shoff: 552,
259 e_flags: 0,
260 e_ehsize: 64,
261 e_phentsize: 56,
262 e_phnum: 3,
263 e_shentsize: 64,
264 e_shnum: 6,
265 e_shstrndx: 5,
266 };
267
268 let bytes = header.to_bytes();
269 assert_eq!(bytes.len(), 64);
270 assert_eq!(&bytes[0..4], &EI_MAGIC);
271 assert_eq!(bytes[4], EI_CLASS);
272 assert_eq!(bytes[5], EI_DATA);
273 assert_eq!(bytes[6], EI_VERSION);
274 assert_eq!(bytes[7], EI_OSABI);
275 assert_eq!(bytes[8], EI_ABIVERSION);
276 assert_eq!(&bytes[9..16], &EI_PAD);
277 }
278
279 #[test]
280 fn test_elf_header_validation_errors() {
281 let invalid_magic = hex!(
285 "00454C460201010000000000000000000300F700010000000000000000000000400000000000000000000000000000000000000040003800000000000000000000"
286 );
287 let err = Program::from_bytes(&invalid_magic).unwrap_err();
288 assert!(
289 matches!(err.as_slice(), [DisassemblerError::InvalidElfFile { .. }]),
290 "expected InvalidElfFile, got {err:?}"
291 );
292
293 let invalid_class = hex!(
295 "7F454C460101010000000000000000000300F700010000000000000000000000400000000000000000000000000000000000000040003800000000000000000000"
296 );
297 let err = Program::from_bytes(&invalid_class).unwrap_err();
298 assert!(
299 matches!(err.as_slice(), [DisassemblerError::InvalidElfFile { .. }]),
300 "expected InvalidElfFile, got {err:?}"
301 );
302
303 let invalid_endian = hex!(
305 "7F454C460202010000000000000000000300F700010000000000000000000000400000000000000000000000000000000000000040003800000000000000000000"
306 );
307 let errors = Program::from_bytes(&invalid_endian).unwrap_err();
308 match errors.first() {
309 Some(DisassemblerError::NonStandardElfHeader {
310 field,
311 expected,
312 found,
313 }) => {
314 assert_eq!(*field, "data");
315 assert_eq!(*expected, vec![EI_DATA as u64]);
316 assert_eq!(*found, 0x02);
317 }
318 other => panic!("expected NonStandardElfHeader for data, got {other:?}"),
319 }
320 }
321}