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
use crate::{error::*, header::*, mem::ByteReader};
use core::str;
/// Section of a PE32+ file
pub struct Section<'a> {
header: &'a SectionHeader,
data: Option<ByteReader<'a>>,
}
impl<'a> Section<'a> {
/// Creates the [`Section`] of a PE32+ which is represented by the specified header
///
/// # Errors
///
/// This function will return an error if the byte buffer does not hold
/// a valid and complete section
pub fn parse(bytes: &'a [u8], header: &'a SectionHeader) -> Result<Self> {
// Check if section contains any raw data
let data = if header.raw_data_size > 0 {
// Get a slice of the PE32+ bytes which holds the sections raw data
let bytes = bytes
.get(
header.raw_data_address as _
..(header.raw_data_address + header.raw_data_size) as _,
)
.ok_or(Error::InsufficientBuffer)?;
Some(ByteReader::new_with_rel(bytes, header.virtual_address as _))
} else {
None
};
Ok(Self { header, data })
}
/// Returns a reference to the header of this [`Section`].
pub fn header(&self) -> &SectionHeader {
self.header
}
/// Returns a reference to the data of this [`Section`].
pub fn data(&self) -> &Option<ByteReader<'a>> {
&self.data
}
/// Returns a reference to the name of this [`Section`].
///
/// # Panics
///
/// Panics if the raw bytes in the sections header are not a valid UTF-8 string.
///
/// This can be ensured by calling [`SectionHeader::validate`] before
/// passing the header to [`Section::parse`].
///
/// The above is automatically done by [`crate::file::PeView::parse`].
pub fn name(&self) -> &str {
str::from_utf8(self.header.name.as_slice()).unwrap()
}
/// Checks if specified flag is contained in the headers characteristics.
pub fn has_flag(&self, flag: SectionFlags) -> bool {
self.header.characteristics & flag as u32 == 1
}
/// Checks if the section has no raw data.
pub fn empty(&self) -> bool {
self.data.is_none()
}
/// Checks if the specified RVA is contained within the sections raw data.
pub fn contains_rva(&self, rva: u32) -> bool {
(self.header.virtual_address
..self.header.virtual_address + self.header.virtual_size)
.contains(&rva)
}
}