1 use core
::marker
::PhantomData
;
2 use core
::{cmp, iter, result, slice, str}
;
4 use crate::endian
::LittleEndian
as LE
;
7 self, CompressedData
, CompressedFileRange
, ObjectSection
, ObjectSegment
, ReadError
, ReadRef
,
8 Relocation
, Result
, SectionFlags
, SectionIndex
, SectionKind
,
11 use super::{ImageNtHeaders, PeFile, SectionTable}
;
13 /// An iterator over the loadable sections of a `PeFile32`.
14 pub type PeSegmentIterator32
<'data
, 'file
, R
= &'data
[u8]> =
15 PeSegmentIterator
<'data
, 'file
, pe
::ImageNtHeaders32
, R
>;
16 /// An iterator over the loadable sections of a `PeFile64`.
17 pub type PeSegmentIterator64
<'data
, 'file
, R
= &'data
[u8]> =
18 PeSegmentIterator
<'data
, 'file
, pe
::ImageNtHeaders64
, R
>;
20 /// An iterator over the loadable sections of a `PeFile`.
22 pub struct PeSegmentIterator
<'data
, 'file
, Pe
, R
= &'data
[u8]>
27 pub(super) file
: &'file PeFile
<'data
, Pe
, R
>,
28 pub(super) iter
: slice
::Iter
<'data
, pe
::ImageSectionHeader
>,
31 impl<'data
, 'file
, Pe
, R
> Iterator
for PeSegmentIterator
<'data
, 'file
, Pe
, R
>
36 type Item
= PeSegment
<'data
, 'file
, Pe
, R
>;
38 fn next(&mut self) -> Option
<Self::Item
> {
39 self.iter
.next().map(|section
| PeSegment
{
46 /// A loadable section of a `PeFile32`.
47 pub type PeSegment32
<'data
, 'file
, R
= &'data
[u8]> =
48 PeSegment
<'data
, 'file
, pe
::ImageNtHeaders32
, R
>;
49 /// A loadable section of a `PeFile64`.
50 pub type PeSegment64
<'data
, 'file
, R
= &'data
[u8]> =
51 PeSegment
<'data
, 'file
, pe
::ImageNtHeaders64
, R
>;
53 /// A loadable section of a `PeFile`.
55 pub struct PeSegment
<'data
, 'file
, Pe
, R
= &'data
[u8]>
60 file
: &'file PeFile
<'data
, Pe
, R
>,
61 section
: &'data pe
::ImageSectionHeader
,
64 impl<'data
, 'file
, Pe
, R
> PeSegment
<'data
, 'file
, Pe
, R
>
69 fn bytes(&self) -> Result
<&'data
[u8]> {
71 .pe_data(self.file
.data
)
72 .read_error("Invalid PE section offset or size")
76 impl<'data
, 'file
, Pe
, R
> read
::private
::Sealed
for PeSegment
<'data
, 'file
, Pe
, R
>
83 impl<'data
, 'file
, Pe
, R
> ObjectSegment
<'data
> for PeSegment
<'data
, 'file
, Pe
, R
>
89 fn address(&self) -> u64 {
90 u64::from(self.section
.virtual_address
.get(LE
)).wrapping_add(self.file
.common
.image_base
)
94 fn size(&self) -> u64 {
95 u64::from(self.section
.virtual_size
.get(LE
))
99 fn align(&self) -> u64 {
100 self.file
.section_alignment()
104 fn file_range(&self) -> (u64, u64) {
105 let (offset
, size
) = self.section
.pe_file_range();
106 (u64::from(offset
), u64::from(size
))
109 fn data(&self) -> Result
<&'data
[u8]> {
113 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>> {
114 Ok(read
::util
::data_range(
123 fn name(&self) -> Result
<Option
<&str>> {
124 let name
= self.section
.name(self.file
.common
.symbols
.strings())?
;
128 .read_error("Non UTF-8 PE section name")?
,
133 /// An iterator over the sections of a `PeFile32`.
134 pub type PeSectionIterator32
<'data
, 'file
, R
= &'data
[u8]> =
135 PeSectionIterator
<'data
, 'file
, pe
::ImageNtHeaders32
, R
>;
136 /// An iterator over the sections of a `PeFile64`.
137 pub type PeSectionIterator64
<'data
, 'file
, R
= &'data
[u8]> =
138 PeSectionIterator
<'data
, 'file
, pe
::ImageNtHeaders64
, R
>;
140 /// An iterator over the sections of a `PeFile`.
142 pub struct PeSectionIterator
<'data
, 'file
, Pe
, R
= &'data
[u8]>
148 pub(super) file
: &'file PeFile
<'data
, Pe
, R
>,
149 pub(super) iter
: iter
::Enumerate
<slice
::Iter
<'data
, pe
::ImageSectionHeader
>>,
152 impl<'data
, 'file
, Pe
, R
> Iterator
for PeSectionIterator
<'data
, 'file
, Pe
, R
>
157 type Item
= PeSection
<'data
, 'file
, Pe
, R
>;
159 fn next(&mut self) -> Option
<Self::Item
> {
160 self.iter
.next().map(|(index
, section
)| PeSection
{
162 index
: SectionIndex(index
+ 1),
168 /// A section of a `PeFile32`.
169 pub type PeSection32
<'data
, 'file
, R
= &'data
[u8]> =
170 PeSection
<'data
, 'file
, pe
::ImageNtHeaders32
, R
>;
171 /// A section of a `PeFile64`.
172 pub type PeSection64
<'data
, 'file
, R
= &'data
[u8]> =
173 PeSection
<'data
, 'file
, pe
::ImageNtHeaders64
, R
>;
175 /// A section of a `PeFile`.
177 pub struct PeSection
<'data
, 'file
, Pe
, R
= &'data
[u8]>
183 pub(super) file
: &'file PeFile
<'data
, Pe
, R
>,
184 pub(super) index
: SectionIndex
,
185 pub(super) section
: &'data pe
::ImageSectionHeader
,
188 impl<'data
, 'file
, Pe
, R
> PeSection
<'data
, 'file
, Pe
, R
>
193 fn bytes(&self) -> Result
<&'data
[u8]> {
195 .pe_data(self.file
.data
)
196 .read_error("Invalid PE section offset or size")
200 impl<'data
, 'file
, Pe
, R
> read
::private
::Sealed
for PeSection
<'data
, 'file
, Pe
, R
>
207 impl<'data
, 'file
, Pe
, R
> ObjectSection
<'data
> for PeSection
<'data
, 'file
, Pe
, R
>
212 type RelocationIterator
= PeRelocationIterator
<'data
, 'file
, R
>;
215 fn index(&self) -> SectionIndex
{
220 fn address(&self) -> u64 {
221 u64::from(self.section
.virtual_address
.get(LE
)).wrapping_add(self.file
.common
.image_base
)
225 fn size(&self) -> u64 {
226 u64::from(self.section
.virtual_size
.get(LE
))
230 fn align(&self) -> u64 {
231 self.file
.section_alignment()
235 fn file_range(&self) -> Option
<(u64, u64)> {
236 let (offset
, size
) = self.section
.pe_file_range();
240 Some((u64::from(offset
), u64::from(size
)))
244 fn data(&self) -> Result
<&'data
[u8]> {
248 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>> {
249 Ok(read
::util
::data_range(
258 fn compressed_file_range(&self) -> Result
<CompressedFileRange
> {
259 Ok(CompressedFileRange
::none(self.file_range()))
263 fn compressed_data(&self) -> Result
<CompressedData
<'data
>> {
264 self.data().map(CompressedData
::none
)
268 fn name(&self) -> Result
<&str> {
269 let name
= self.section
.name(self.file
.common
.symbols
.strings())?
;
272 .read_error("Non UTF-8 PE section name")
276 fn segment_name(&self) -> Result
<Option
<&str>> {
281 fn kind(&self) -> SectionKind
{
285 fn relocations(&self) -> PeRelocationIterator
<'data
, 'file
, R
> {
286 PeRelocationIterator(PhantomData
)
289 fn flags(&self) -> SectionFlags
{
291 characteristics
: self.section
.characteristics
.get(LE
),
296 impl<'data
> SectionTable
<'data
> {
297 /// Return the data at the given virtual address in a PE file.
298 pub fn pe_data_at
<R
: ReadRef
<'data
>>(&self, data
: R
, va
: u32) -> Option
<&'data
[u8]> {
300 .filter_map(|section
| section
.pe_data_at(data
, va
))
305 impl pe
::ImageSectionHeader
{
306 /// Return the offset and size of the section in a PE file.
308 /// Returns `None` for sections that have no data in the file.
309 pub fn pe_file_range(&self) -> (u32, u32) {
310 // Pointer and size will be zero for uninitialized data; we don't need to validate this.
311 let offset
= self.pointer_to_raw_data
.get(LE
);
312 let size
= cmp
::min(self.virtual_size
.get(LE
), self.size_of_raw_data
.get(LE
));
316 /// Return the section data in a PE file.
317 pub fn pe_data
<'data
, R
: ReadRef
<'data
>>(&self, data
: R
) -> result
::Result
<&'data
[u8], ()> {
318 let (offset
, size
) = self.pe_file_range();
319 data
.read_bytes_at(offset
.into(), size
.into())
322 /// Return the data at the given virtual address if this section contains it.
323 pub fn pe_data_at
<'data
, R
: ReadRef
<'data
>>(&self, data
: R
, va
: u32) -> Option
<&'data
[u8]> {
324 let section_va
= self.virtual_address
.get(LE
);
325 let offset
= va
.checked_sub(section_va
)?
;
326 let section_data
= self.pe_data(data
).ok()?
;
327 section_data
.get(offset
as usize..)
331 /// An iterator over the relocations in an `PeSection`.
333 pub struct PeRelocationIterator
<'data
, 'file
, R
= &'data
[u8]>(
334 PhantomData
<(&'
data (), &'
file (), R
)>,
337 impl<'data
, 'file
, R
> Iterator
for PeRelocationIterator
<'data
, 'file
, R
> {
338 type Item
= (u64, Relocation
);
340 fn next(&mut self) -> Option
<Self::Item
> {