1use {
2 crate::{errors::DisassemblerError, section_header_entry::SectionHeaderEntry},
3 object::{Endianness, read::elf::ElfFile64},
4 serde::{Deserialize, Serialize},
5 std::fmt::{Debug, Display},
6};
7
8#[allow(non_camel_case_types)]
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[repr(u32)]
11pub enum SectionHeaderType {
12 SHT_NULL = 0x00, SHT_PROGBITS = 0x01, SHT_SYMTAB = 0x02, SHT_STRTAB = 0x03, SHT_RELA = 0x04, SHT_HASH = 0x05, SHT_DYNAMIC = 0x06, SHT_NOTE = 0x07, SHT_NOBITS = 0x08, SHT_REL = 0x09, SHT_SHLIB = 0x0A, SHT_DYNSYM = 0x0B, SHT_INIT_ARRAY = 0x0E, SHT_FINI_ARRAY = 0x0F, SHT_PREINIT_ARRAY = 0x10, SHT_GROUP = 0x11, SHT_SYMTAB_SHNDX = 0x12, SHT_NUM = 0x13, SHT_GNU_HASH = 0x6ffffff6, }
32
33impl TryFrom<u32> for SectionHeaderType {
34 type Error = DisassemblerError;
35
36 fn try_from(value: u32) -> Result<Self, Self::Error> {
37 Ok(match value {
38 0x00 => Self::SHT_NULL,
39 0x01 => Self::SHT_PROGBITS,
40 0x02 => Self::SHT_SYMTAB,
41 0x03 => Self::SHT_STRTAB,
42 0x04 => Self::SHT_RELA,
43 0x05 => Self::SHT_HASH,
44 0x06 => Self::SHT_DYNAMIC,
45 0x07 => Self::SHT_NOTE,
46 0x08 => Self::SHT_NOBITS,
47 0x09 => Self::SHT_REL,
48 0x0A => Self::SHT_SHLIB,
49 0x0B => Self::SHT_DYNSYM,
50 0x0E => Self::SHT_INIT_ARRAY,
51 0x0F => Self::SHT_FINI_ARRAY,
52 0x10 => Self::SHT_PREINIT_ARRAY,
53 0x11 => Self::SHT_GROUP,
54 0x12 => Self::SHT_SYMTAB_SHNDX,
55 0x13 => Self::SHT_NUM,
56 0x6ffffff6 => Self::SHT_GNU_HASH,
57 _ => return Err(DisassemblerError::InvalidSectionHeaderType),
58 })
59 }
60}
61
62impl Display for SectionHeaderType {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 f.write_str(Into::<&str>::into(self.clone()))
65 }
66}
67
68impl From<SectionHeaderType> for &str {
69 fn from(val: SectionHeaderType) -> Self {
70 match val {
71 SectionHeaderType::SHT_NULL => "SHT_NULL",
72 SectionHeaderType::SHT_PROGBITS => "SHT_PROGBITS",
73 SectionHeaderType::SHT_SYMTAB => "SHT_SYMTAB",
74 SectionHeaderType::SHT_STRTAB => "SHT_STRTAB",
75 SectionHeaderType::SHT_RELA => "SHT_RELA",
76 SectionHeaderType::SHT_HASH => "SHT_HASH",
77 SectionHeaderType::SHT_DYNAMIC => "SHT_DYNAMIC",
78 SectionHeaderType::SHT_NOTE => "SHT_NOTE",
79 SectionHeaderType::SHT_NOBITS => "SHT_NOBITS",
80 SectionHeaderType::SHT_REL => "SHT_REL",
81 SectionHeaderType::SHT_SHLIB => "SHT_SHLIB",
82 SectionHeaderType::SHT_DYNSYM => "SHT_DYNSYM",
83 SectionHeaderType::SHT_INIT_ARRAY => "SHT_INIT_ARRAY",
84 SectionHeaderType::SHT_FINI_ARRAY => "SHT_FINI_ARRAY",
85 SectionHeaderType::SHT_PREINIT_ARRAY => "SHT_PREINIT_ARRAY",
86 SectionHeaderType::SHT_GROUP => "SHT_GROUP",
87 SectionHeaderType::SHT_SYMTAB_SHNDX => "SHT_SYMTAB_SHNDX",
88 SectionHeaderType::SHT_NUM => "SHT_NUM",
89 SectionHeaderType::SHT_GNU_HASH => "SHT_GNU_HASH",
90 }
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct SectionHeader {
96 pub sh_name: u32, pub sh_type: SectionHeaderType, pub sh_flags: u64, pub sh_addr: u64, pub sh_offset: u64, pub sh_size: u64, pub sh_link: u32, pub sh_info: u32, pub sh_addralign: u64, pub sh_entsize: u64, }
107
108impl SectionHeader {
109 pub fn from_elf_file(
110 elf_file: &ElfFile64<Endianness>,
111 ) -> Result<(Vec<Self>, Vec<SectionHeaderEntry>), DisassemblerError> {
112 let endian = elf_file.endian();
113 let section_headers_data: Vec<_> = elf_file.elf_section_table().iter().collect();
114
115 let mut section_headers = Vec::new();
116 for sh in section_headers_data.iter() {
117 let sh_name = sh.sh_name.get(endian);
118 let sh_type = SectionHeaderType::try_from(sh.sh_type.get(endian))?;
119 let sh_flags = sh.sh_flags.get(endian);
120 let sh_addr = sh.sh_addr.get(endian);
121 let sh_offset = sh.sh_offset.get(endian);
122 let sh_size = sh.sh_size.get(endian);
123 let sh_link = sh.sh_link.get(endian);
124 let sh_info = sh.sh_info.get(endian);
125 let sh_addralign = sh.sh_addralign.get(endian);
126 let sh_entsize = sh.sh_entsize.get(endian);
127
128 section_headers.push(SectionHeader {
129 sh_name,
130 sh_type,
131 sh_flags,
132 sh_addr,
133 sh_offset,
134 sh_size,
135 sh_link,
136 sh_info,
137 sh_addralign,
138 sh_entsize,
139 });
140 }
141
142 let elf_header = elf_file.elf_header();
143 let e_shstrndx = elf_header.e_shstrndx.get(endian);
144 let shstrndx = §ion_headers[e_shstrndx as usize];
145 let shstrndx_value = elf_file.data()
146 [shstrndx.sh_offset as usize..shstrndx.sh_offset as usize + shstrndx.sh_size as usize]
147 .to_vec();
148
149 let mut indices: Vec<u32> = section_headers.iter().map(|h| h.sh_name).collect();
150 indices.push(shstrndx.sh_size as u32);
151 indices.sort_unstable();
152
153 let section_header_entries = section_headers
154 .iter()
155 .map(|s| {
156 let current_offset = s.sh_name as usize;
157
158 let label_bytes = &shstrndx_value[current_offset..];
160 let null_pos = label_bytes
161 .iter()
162 .position(|&b| b == 0)
163 .unwrap_or(label_bytes.len());
164 let label = String::from_utf8(
165 label_bytes[..=null_pos.min(label_bytes.len().saturating_sub(1))].to_vec(),
166 )
167 .unwrap_or("default".to_string());
168
169 let data = elf_file.data()
170 [s.sh_offset as usize..s.sh_offset as usize + s.sh_size as usize]
171 .to_vec();
172
173 SectionHeaderEntry::new(label, s.sh_offset as usize, data)
174 })
175 .collect::<Result<Vec<_>, _>>()?;
176
177 Ok((section_headers, section_header_entries))
178 }
179
180 pub fn to_bytes(&self) -> Vec<u8> {
181 let mut b = self.sh_name.to_le_bytes().to_vec();
182 b.extend_from_slice(&(self.sh_type.clone() as u32).to_le_bytes());
183 b.extend_from_slice(&self.sh_flags.to_le_bytes());
184 b.extend_from_slice(&self.sh_addr.to_le_bytes());
185 b.extend_from_slice(&self.sh_offset.to_le_bytes());
186 b.extend_from_slice(&self.sh_size.to_le_bytes());
187 b.extend_from_slice(&self.sh_link.to_le_bytes());
188 b.extend_from_slice(&self.sh_info.to_le_bytes());
189 b.extend_from_slice(&self.sh_addralign.to_le_bytes());
190 b.extend_from_slice(&self.sh_entsize.to_le_bytes());
191 b
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use {super::*, crate::program::Program, hex_literal::hex};
198
199 #[test]
200 fn test_section_headers() {
201 let program = Program::from_bytes(&hex!("7F454C460201010000000000000000000300F700010000002001000000000000400000000000000028020000000000000000000040003800030040000600050001000000050000002001000000000000200100000000000020010000000000003000000000000000300000000000000000100000000000000100000004000000C001000000000000C001000000000000C0010000000000003C000000000000003C000000000000000010000000000000020000000600000050010000000000005001000000000000500100000000000070000000000000007000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007912A000000000007911182900000000B7000000010000002D21010000000000B70000000000000095000000000000001E0000000000000004000000000000000600000000000000C0010000000000000B0000000000000018000000000000000500000000000000F0010000000000000A000000000000000C00000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000120001002001000000000000300000000000000000656E747279706F696E7400002E74657874002E64796E737472002E64796E73796D002E64796E616D6963002E73687374727461620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000600000000000000200100000000000020010000000000003000000000000000000000000000000008000000000000000000000000000000170000000600000003000000000000005001000000000000500100000000000070000000000000000400000000000000080000000000000010000000000000000F0000000B0000000200000000000000C001000000000000C001000000000000300000000000000004000000010000000800000000000000180000000000000007000000030000000200000000000000F001000000000000F0010000000000000C00000000000000000000000000000001000000000000000000000000000000200000000300000000000000000000000000000000000000FC010000000000002A00000000000000000000000000000001000000000000000000000000000000")).unwrap();
202
203 assert_eq!(program.section_headers.len(), 6);
205 assert_eq!(program.section_header_entries.len(), 6);
206 }
207
208 #[test]
209 fn test_section_header_type_conversions() {
210 assert!(matches!(
212 SectionHeaderType::try_from(0x00),
213 Ok(SectionHeaderType::SHT_NULL)
214 ));
215 assert!(matches!(
216 SectionHeaderType::try_from(0x01),
217 Ok(SectionHeaderType::SHT_PROGBITS)
218 ));
219 assert!(matches!(
220 SectionHeaderType::try_from(0x02),
221 Ok(SectionHeaderType::SHT_SYMTAB)
222 ));
223 assert!(matches!(
224 SectionHeaderType::try_from(0x03),
225 Ok(SectionHeaderType::SHT_STRTAB)
226 ));
227 assert!(matches!(
228 SectionHeaderType::try_from(0x04),
229 Ok(SectionHeaderType::SHT_RELA)
230 ));
231 assert!(matches!(
232 SectionHeaderType::try_from(0x05),
233 Ok(SectionHeaderType::SHT_HASH)
234 ));
235 assert!(matches!(
236 SectionHeaderType::try_from(0x06),
237 Ok(SectionHeaderType::SHT_DYNAMIC)
238 ));
239 assert!(matches!(
240 SectionHeaderType::try_from(0x07),
241 Ok(SectionHeaderType::SHT_NOTE)
242 ));
243 assert!(matches!(
244 SectionHeaderType::try_from(0x08),
245 Ok(SectionHeaderType::SHT_NOBITS)
246 ));
247 assert!(matches!(
248 SectionHeaderType::try_from(0x09),
249 Ok(SectionHeaderType::SHT_REL)
250 ));
251 assert!(matches!(
252 SectionHeaderType::try_from(0x0A),
253 Ok(SectionHeaderType::SHT_SHLIB)
254 ));
255 assert!(matches!(
256 SectionHeaderType::try_from(0x0B),
257 Ok(SectionHeaderType::SHT_DYNSYM)
258 ));
259 assert!(matches!(
260 SectionHeaderType::try_from(0x0E),
261 Ok(SectionHeaderType::SHT_INIT_ARRAY)
262 ));
263 assert!(matches!(
264 SectionHeaderType::try_from(0x0F),
265 Ok(SectionHeaderType::SHT_FINI_ARRAY)
266 ));
267 assert!(matches!(
268 SectionHeaderType::try_from(0x10),
269 Ok(SectionHeaderType::SHT_PREINIT_ARRAY)
270 ));
271 assert!(matches!(
272 SectionHeaderType::try_from(0x11),
273 Ok(SectionHeaderType::SHT_GROUP)
274 ));
275 assert!(matches!(
276 SectionHeaderType::try_from(0x12),
277 Ok(SectionHeaderType::SHT_SYMTAB_SHNDX)
278 ));
279 assert!(matches!(
280 SectionHeaderType::try_from(0x13),
281 Ok(SectionHeaderType::SHT_NUM)
282 ));
283 assert!(matches!(
284 SectionHeaderType::try_from(0x6ffffff6),
285 Ok(SectionHeaderType::SHT_GNU_HASH)
286 ));
287
288 assert!(SectionHeaderType::try_from(0xFF).is_err());
290 }
291
292 #[test]
293 fn test_section_header_type_to_str() {
294 assert_eq!(<&str>::from(SectionHeaderType::SHT_NULL), "SHT_NULL");
296 assert_eq!(
297 <&str>::from(SectionHeaderType::SHT_PROGBITS),
298 "SHT_PROGBITS"
299 );
300 assert_eq!(<&str>::from(SectionHeaderType::SHT_SYMTAB), "SHT_SYMTAB");
301 assert_eq!(<&str>::from(SectionHeaderType::SHT_STRTAB), "SHT_STRTAB");
302 assert_eq!(<&str>::from(SectionHeaderType::SHT_RELA), "SHT_RELA");
303 assert_eq!(<&str>::from(SectionHeaderType::SHT_HASH), "SHT_HASH");
304 assert_eq!(<&str>::from(SectionHeaderType::SHT_DYNAMIC), "SHT_DYNAMIC");
305 assert_eq!(<&str>::from(SectionHeaderType::SHT_NOTE), "SHT_NOTE");
306 assert_eq!(<&str>::from(SectionHeaderType::SHT_NOBITS), "SHT_NOBITS");
307 assert_eq!(<&str>::from(SectionHeaderType::SHT_REL), "SHT_REL");
308 assert_eq!(<&str>::from(SectionHeaderType::SHT_SHLIB), "SHT_SHLIB");
309 assert_eq!(<&str>::from(SectionHeaderType::SHT_DYNSYM), "SHT_DYNSYM");
310 assert_eq!(
311 <&str>::from(SectionHeaderType::SHT_INIT_ARRAY),
312 "SHT_INIT_ARRAY"
313 );
314 assert_eq!(
315 <&str>::from(SectionHeaderType::SHT_FINI_ARRAY),
316 "SHT_FINI_ARRAY"
317 );
318 assert_eq!(
319 <&str>::from(SectionHeaderType::SHT_PREINIT_ARRAY),
320 "SHT_PREINIT_ARRAY"
321 );
322 assert_eq!(<&str>::from(SectionHeaderType::SHT_GROUP), "SHT_GROUP");
323 assert_eq!(
324 <&str>::from(SectionHeaderType::SHT_SYMTAB_SHNDX),
325 "SHT_SYMTAB_SHNDX"
326 );
327 assert_eq!(<&str>::from(SectionHeaderType::SHT_NUM), "SHT_NUM");
328 assert_eq!(
329 <&str>::from(SectionHeaderType::SHT_GNU_HASH),
330 "SHT_GNU_HASH"
331 );
332 }
333
334 #[test]
335 fn test_section_header_type_display() {
336 assert_eq!(SectionHeaderType::SHT_PROGBITS.to_string(), "SHT_PROGBITS");
337 assert_eq!(SectionHeaderType::SHT_DYNAMIC.to_string(), "SHT_DYNAMIC");
338 }
339
340 #[test]
341 fn test_section_header_to_bytes() {
342 let header = SectionHeader {
343 sh_name: 1,
344 sh_type: SectionHeaderType::SHT_PROGBITS,
345 sh_flags: 6,
346 sh_addr: 0x120,
347 sh_offset: 0x120,
348 sh_size: 48,
349 sh_link: 0,
350 sh_info: 0,
351 sh_addralign: 8,
352 sh_entsize: 0,
353 };
354
355 let bytes = header.to_bytes();
356 assert_eq!(bytes.len(), 64);
357
358 assert_eq!(
360 u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
361 1
362 );
363 assert_eq!(
364 u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
365 1
366 );
367 }
368}