1use crate::errors;
10use crate::field::Field;
11
12#[derive(Debug, PartialEq, Eq)]
13pub enum ElfType {
14 None,
15 Relocatable,
16 Executable,
17 SharedObject,
18 Core,
19 Other(u16),
20}
21
22impl From<u16> for ElfType {
23 fn from(value: u16) -> Self {
24 match value {
25 0 => Self::None,
26 1 => Self::Relocatable,
27 2 => Self::Executable,
28 3 => Self::SharedObject,
29 4 => Self::Core,
30 _ => Self::Other(value),
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy)]
36pub enum Endianness {
37 Little,
38 Big,
39}
40
41#[derive(Debug)]
42pub struct ElfHeader {
43 pub ident: Vec<u8>,
44 pub endianness: Endianness,
45 pub elf_type: Field<ElfType>,
46 pub machine: Field<u16>,
47 pub version: Field<u32>,
48 pub entry: Field<u64>,
49 pub ph_off: Field<u64>,
50 pub sh_off: Field<u64>,
51 pub flags: Field<u32>,
52 pub eh_size: Field<u16>,
53 pub ph_ent_size: Field<u16>,
54 pub ph_num: Field<u16>,
55 pub sh_ent_size: Field<u16>,
56 pub sh_num: Field<u16>,
57 pub sh_strndx: Field<u16>,
58}
59
60impl ElfHeader {
61 pub fn parse(buffer: &[u8]) -> Result<Self, errors::FileParseError> {
62 if buffer.len() < 64 {
63 return Err(errors::FileParseError::BufferOverflow);
64 }
65
66 if buffer[0..4] != [0x7F, b'E', b'L', b'F'] {
68 return Err(errors::FileParseError::InvalidFileFormat);
69 }
70
71 let ident: Vec<u8> = buffer[0..16].to_vec();
72 let endianness = match buffer[5] {
73 1 => Endianness::Little,
74 2 => Endianness::Big,
75 _ => return Err(errors::FileParseError::InvalidFileFormat),
76 };
77
78 let read_u16 = |offset: usize| -> u16 {
79 let bytes = [buffer[offset], buffer[offset + 1]];
80 match endianness {
81 Endianness::Little => u16::from_le_bytes(bytes),
82 Endianness::Big => u16::from_be_bytes(bytes),
83 }
84 };
85 let read_u32 = |offset: usize| -> u32 {
86 let bytes = [
87 buffer[offset],
88 buffer[offset + 1],
89 buffer[offset + 2],
90 buffer[offset + 3],
91 ];
92 match endianness {
93 Endianness::Little => u32::from_le_bytes(bytes),
94 Endianness::Big => u32::from_be_bytes(bytes),
95 }
96 };
97 let read_u64 = |offset: usize| -> u64 {
98 let bytes = [
99 buffer[offset],
100 buffer[offset + 1],
101 buffer[offset + 2],
102 buffer[offset + 3],
103 buffer[offset + 4],
104 buffer[offset + 5],
105 buffer[offset + 6],
106 buffer[offset + 7],
107 ];
108 match endianness {
109 Endianness::Little => u64::from_le_bytes(bytes),
110 Endianness::Big => u64::from_be_bytes(bytes),
111 }
112 };
113
114 let elf_type: Field<ElfType> = Field::new(ElfType::from(read_u16(16)), 16, 2);
115 let machine: Field<u16> = Field::new(read_u16(18), 18, 2);
116 let version: Field<u32> = Field::new(read_u32(20), 20, 4);
117 let entry: Field<u64> = Field::new(read_u64(24), 24, 8);
118 let ph_off: Field<u64> = Field::new(read_u64(32), 32, 8);
119 let sh_off: Field<u64> = Field::new(read_u64(40), 40, 8);
120 let flags: Field<u32> = Field::new(read_u32(48), 48, 4);
121 let eh_size: Field<u16> = Field::new(read_u16(52), 52, 2);
122 let ph_ent_size: Field<u16> = Field::new(read_u16(54), 54, 2);
123 let ph_num: Field<u16> = Field::new(read_u16(56), 56, 2);
124 let sh_ent_size: Field<u16> = Field::new(read_u16(58), 58, 2);
125 let sh_num: Field<u16> = Field::new(read_u16(60), 60, 2);
126 let sh_strndx: Field<u16> = Field::new(read_u16(62), 62, 2);
127
128 Ok(ElfHeader {
129 ident,
130 endianness,
131 elf_type,
132 machine,
133 version,
134 entry,
135 ph_off,
136 sh_off,
137 flags,
138 eh_size,
139 ph_ent_size,
140 ph_num,
141 sh_ent_size,
142 sh_num,
143 sh_strndx,
144 })
145 }
146}