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
use crate::{note::NoteIter, Elf, ElfError};
use bit_field::BitField;
use scroll_derive::Pread;
#[derive(PartialEq, Eq, Debug)]
pub enum SegmentType {
Null,
Load,
Dynamic,
Interp,
Note,
Shlib,
Phdr,
Tls,
Os(u32),
Proc(u32),
}
#[derive(Debug, Pread)]
#[repr(C)]
pub struct ProgramHeader {
pub segment_type: u32,
pub flags: u32,
pub offset: u64,
pub virtual_address: u64,
pub physical_address: u64,
pub file_size: u64,
pub mem_size: u64,
pub alignment: u64,
}
impl ProgramHeader {
pub(crate) fn validate(&self) -> Result<(), ElfError> {
match self.segment_type {
0..=7 | 0x60000000..=0x7fffffff => Ok(()),
_ => Err(ElfError::SegmentInvalidType),
}?;
Ok(())
}
pub fn segment_type(&self) -> SegmentType {
match self.segment_type {
0 => SegmentType::Null,
1 => SegmentType::Load,
2 => SegmentType::Dynamic,
3 => SegmentType::Interp,
4 => SegmentType::Note,
5 => SegmentType::Shlib,
6 => SegmentType::Phdr,
7 => SegmentType::Tls,
0x60000000..=0x6fffffff => SegmentType::Os(self.segment_type),
0x70000000..=0x7fffffff => SegmentType::Proc(self.segment_type),
_ => panic!("segment_type called on segment with invalid type. Was validate called?"),
}
}
pub fn data<'a>(&self, elf: &'a Elf) -> &'a [u8] {
&elf.bytes[(self.offset as usize)..((self.offset + self.file_size) as usize)]
}
pub fn is_executable(&self) -> bool {
self.flags.get_bit(0)
}
pub fn is_writable(&self) -> bool {
self.flags.get_bit(1)
}
pub fn is_readable(&self) -> bool {
self.flags.get_bit(2)
}
pub fn iterate_note_entries<'a>(&self, elf: &'a Elf) -> Option<NoteIter<'a>> {
if self.segment_type() != SegmentType::Note {
return None;
}
Some(NoteIter::new(self.data(elf)))
}
}