1use crate::{Elf, ElfError};
2use bit_field::BitField;
3use core::str;
4use scroll::Pread;
5
6#[derive(PartialEq, Eq)]
7pub enum SectionType {
8 Null,
11
12 ProgBits,
14
15 SymTab,
17
18 StrTab,
20
21 Rela,
23
24 Hash,
26
27 Dynamic,
29
30 Note,
32
33 NoBits,
36
37 Rel,
39
40 ShLib,
42
43 DynSym,
45
46 Os(u32),
49
50 Proc(u32),
53}
54
55#[derive(Debug, Pread)]
56#[repr(C)]
57pub struct SectionHeader {
58 pub name: u32,
59 pub section_type: u32,
60 pub flags: u64,
61 pub address: u64,
62 pub offset: u64,
63 pub size: u64,
64
65 pub link: u32,
68
69 pub info: u32,
71 pub alignment: u64,
72
73 pub entry_size: u64,
75}
76
77impl SectionHeader {
78 pub(crate) fn validate(&self) -> Result<(), ElfError> {
79 match self.section_type {
80 0..=11 | 0x60000000..=0x7fffffff => Ok(()),
81 _ => Err(ElfError::SectionInvalidType),
82 }?;
83
84 Ok(())
85 }
86
87 pub fn section_type(&self) -> SectionType {
88 match self.section_type {
89 0 => SectionType::Null,
90 1 => SectionType::ProgBits,
91 2 => SectionType::SymTab,
92 3 => SectionType::StrTab,
93 4 => SectionType::Rela,
94 5 => SectionType::Hash,
95 6 => SectionType::Dynamic,
96 7 => SectionType::Note,
97 8 => SectionType::NoBits,
98 9 => SectionType::Rel,
99 10 => SectionType::ShLib,
100 11 => SectionType::DynSym,
101 0x60000000..=0x6fffffff => SectionType::Os(self.section_type),
102 0x70000000..=0x7fffffff => SectionType::Proc(self.section_type),
103
104 _ => panic!("section_type called on section with invalid type. Was validate called?"),
105 }
106 }
107
108 pub fn name<'a>(&self, elf: &'a Elf) -> Option<&'a str> {
109 if self.name == 0 {
110 return None;
111 }
112
113 let string_table = elf.sections().nth(elf.header.string_table_index as usize)?;
114 crate::from_utf8_null_terminated(&string_table.data(elf)?[(self.name as usize)..]).ok()
115 }
116
117 pub fn data<'a>(&self, elf: &'a Elf) -> Option<&'a [u8]> {
120 match self.section_type() {
121 SectionType::Null | SectionType::NoBits => return None,
122 _ => (),
123 }
124
125 Some(&elf.bytes[(self.offset as usize)..((self.offset + self.size) as usize)])
126 }
127
128 pub fn is_writable(&self) -> bool {
130 self.flags.get_bit(0)
131 }
132
133 pub fn is_allocated(&self) -> bool {
135 self.flags.get_bit(1)
136 }
137
138 pub fn is_executable(&self) -> bool {
140 self.flags.get_bit(2)
141 }
142}