1 use core
::marker
::PhantomData
;
2 use core
::{cmp, iter, result, slice, str}
;
4 use crate::endian
::LittleEndian
as LE
;
8 self, CompressedData
, ObjectSection
, ObjectSegment
, ReadError
, Relocation
, Result
,
9 SectionFlags
, SectionIndex
, SectionKind
,
12 use super::{ImageNtHeaders, PeFile}
;
14 /// An iterator over the loadable sections of a `PeFile32`.
15 pub type PeSegmentIterator32
<'data
, 'file
> = PeSegmentIterator
<'data
, 'file
, pe
::ImageNtHeaders32
>;
16 /// An iterator over the loadable sections of a `PeFile64`.
17 pub type PeSegmentIterator64
<'data
, 'file
> = PeSegmentIterator
<'data
, 'file
, pe
::ImageNtHeaders64
>;
19 /// An iterator over the loadable sections of a `PeFile`.
21 pub struct PeSegmentIterator
<'data
, 'file
, Pe
>
26 pub(super) file
: &'file PeFile
<'data
, Pe
>,
27 pub(super) iter
: slice
::Iter
<'file
, pe
::ImageSectionHeader
>,
30 impl<'data
, 'file
, Pe
: ImageNtHeaders
> Iterator
for PeSegmentIterator
<'data
, 'file
, Pe
> {
31 type Item
= PeSegment
<'data
, 'file
, Pe
>;
33 fn next(&mut self) -> Option
<Self::Item
> {
34 self.iter
.next().map(|section
| PeSegment
{
41 /// A loadable section of a `PeFile32`.
42 pub type PeSegment32
<'data
, 'file
> = PeSegment
<'data
, 'file
, pe
::ImageNtHeaders32
>;
43 /// A loadable section of a `PeFile64`.
44 pub type PeSegment64
<'data
, 'file
> = PeSegment
<'data
, 'file
, pe
::ImageNtHeaders64
>;
46 /// A loadable section of a `PeFile`.
48 pub struct PeSegment
<'data
, 'file
, Pe
>
53 file
: &'file PeFile
<'data
, Pe
>,
54 section
: &'file pe
::ImageSectionHeader
,
57 impl<'data
, 'file
, Pe
: ImageNtHeaders
> PeSegment
<'data
, 'file
, Pe
> {
58 fn bytes(&self) -> Result
<Bytes
<'data
>> {
60 .pe_data(self.file
.data
)
61 .read_error("Invalid PE section offset or size")
65 impl<'data
, 'file
, Pe
: ImageNtHeaders
> read
::private
::Sealed
for PeSegment
<'data
, 'file
, Pe
> {}
67 impl<'data
, 'file
, Pe
: ImageNtHeaders
> ObjectSegment
<'data
> for PeSegment
<'data
, 'file
, Pe
> {
69 fn address(&self) -> u64 {
70 u64::from(self.section
.virtual_address
.get(LE
))
74 fn size(&self) -> u64 {
75 u64::from(self.section
.virtual_size
.get(LE
))
79 fn align(&self) -> u64 {
80 self.file
.section_alignment()
84 fn file_range(&self) -> (u64, u64) {
85 let (offset
, size
) = self.section
.pe_file_range();
86 (u64::from(offset
), u64::from(size
))
89 fn data(&self) -> Result
<&'data
[u8]> {
93 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>> {
103 fn name(&self) -> Result
<Option
<&str>> {
104 let name
= self.section
.name(self.file
.symbols
.strings())?
;
108 .read_error("Non UTF-8 PE section name")?
,
113 /// An iterator over the sections of a `PeFile32`.
114 pub type PeSectionIterator32
<'data
, 'file
> = PeSectionIterator
<'data
, 'file
, pe
::ImageNtHeaders32
>;
115 /// An iterator over the sections of a `PeFile64`.
116 pub type PeSectionIterator64
<'data
, 'file
> = PeSectionIterator
<'data
, 'file
, pe
::ImageNtHeaders64
>;
118 /// An iterator over the sections of a `PeFile`.
120 pub struct PeSectionIterator
<'data
, 'file
, Pe
>
125 pub(super) file
: &'file PeFile
<'data
, Pe
>,
126 pub(super) iter
: iter
::Enumerate
<slice
::Iter
<'file
, pe
::ImageSectionHeader
>>,
129 impl<'data
, 'file
, Pe
: ImageNtHeaders
> Iterator
for PeSectionIterator
<'data
, 'file
, Pe
> {
130 type Item
= PeSection
<'data
, 'file
, Pe
>;
132 fn next(&mut self) -> Option
<Self::Item
> {
133 self.iter
.next().map(|(index
, section
)| PeSection
{
135 index
: SectionIndex(index
+ 1),
141 /// A section of a `PeFile32`.
142 pub type PeSection32
<'data
, 'file
> = PeSection
<'data
, 'file
, pe
::ImageNtHeaders32
>;
143 /// A section of a `PeFile64`.
144 pub type PeSection64
<'data
, 'file
> = PeSection
<'data
, 'file
, pe
::ImageNtHeaders64
>;
146 /// A section of a `PeFile`.
148 pub struct PeSection
<'data
, 'file
, Pe
>
153 pub(super) file
: &'file PeFile
<'data
, Pe
>,
154 pub(super) index
: SectionIndex
,
155 pub(super) section
: &'file pe
::ImageSectionHeader
,
158 impl<'data
, 'file
, Pe
: ImageNtHeaders
> PeSection
<'data
, 'file
, Pe
> {
159 fn bytes(&self) -> Result
<Bytes
<'data
>> {
161 .pe_data(self.file
.data
)
162 .read_error("Invalid PE section offset or size")
166 impl<'data
, 'file
, Pe
: ImageNtHeaders
> read
::private
::Sealed
for PeSection
<'data
, 'file
, Pe
> {}
168 impl<'data
, 'file
, Pe
: ImageNtHeaders
> ObjectSection
<'data
> for PeSection
<'data
, 'file
, Pe
> {
169 type RelocationIterator
= PeRelocationIterator
<'data
, 'file
>;
172 fn index(&self) -> SectionIndex
{
177 fn address(&self) -> u64 {
178 u64::from(self.section
.virtual_address
.get(LE
))
182 fn size(&self) -> u64 {
183 u64::from(self.section
.virtual_size
.get(LE
))
187 fn align(&self) -> u64 {
188 self.file
.section_alignment()
192 fn file_range(&self) -> Option
<(u64, u64)> {
193 let (offset
, size
) = self.section
.pe_file_range();
197 Some((u64::from(offset
), u64::from(size
)))
201 fn data(&self) -> Result
<&'data
[u8]> {
205 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>> {
215 fn compressed_data(&self) -> Result
<CompressedData
<'data
>> {
216 self.data().map(CompressedData
::none
)
220 fn name(&self) -> Result
<&str> {
221 let name
= self.section
.name(self.file
.symbols
.strings())?
;
224 .read_error("Non UTF-8 PE section name")
228 fn segment_name(&self) -> Result
<Option
<&str>> {
233 fn kind(&self) -> SectionKind
{
237 fn relocations(&self) -> PeRelocationIterator
<'data
, 'file
> {
238 PeRelocationIterator
::default()
241 fn flags(&self) -> SectionFlags
{
243 characteristics
: self.section
.characteristics
.get(LE
),
248 impl pe
::ImageSectionHeader
{
249 fn pe_file_range(&self) -> (u32, u32) {
250 // Pointer and size will be zero for uninitialized data; we don't need to validate this.
251 let offset
= self.pointer_to_raw_data
.get(LE
);
252 let size
= cmp
::min(self.virtual_size
.get(LE
), self.size_of_raw_data
.get(LE
));
256 /// Return the data for a PE section.
257 pub fn pe_data
<'data
>(&self, data
: Bytes
<'data
>) -> result
::Result
<Bytes
<'data
>, ()> {
258 let (offset
, size
) = self.pe_file_range();
259 data
.read_bytes_at(offset
as usize, size
as usize)
263 /// An iterator over the relocations in an `PeSection`.
264 #[derive(Debug, Default)]
265 pub struct PeRelocationIterator
<'data
, 'file
>(PhantomData
<(&'
data (), &'
file ())>);
267 impl<'data
, 'file
> Iterator
for PeRelocationIterator
<'data
, 'file
> {
268 type Item
= (u64, Relocation
);
270 fn next(&mut self) -> Option
<Self::Item
> {