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