object/read/pe/
file.rs

1use alloc::vec::Vec;
2use core::fmt::Debug;
3use core::{mem, str};
4
5use core::convert::TryInto;
6
7use crate::endian::{LittleEndian as LE, U32};
8use crate::pe;
9use crate::pod::{self, Pod};
10use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
11use crate::read::{
12    self, Architecture, ByteString, Bytes, CodeView, ComdatKind, Error, Export, FileFlags, Import,
13    NoDynamicRelocationIterator, Object, ObjectComdat, ObjectKind, ReadError, ReadRef, Result,
14    SectionIndex, SubArchitecture, SymbolIndex,
15};
16
17use super::{
18    DataDirectories, ExportTable, ImageThunkData, ImportTable, PeSection, PeSectionIterator,
19    PeSegment, PeSegmentIterator, RichHeaderInfo, SectionTable,
20};
21
22/// A PE32 (32-bit) image file.
23///
24/// This is a file that starts with [`pe::ImageNtHeaders32`], and corresponds
25/// to [`crate::FileKind::Pe32`].
26pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>;
27/// A PE32+ (64-bit) image file.
28///
29/// This is a file that starts with [`pe::ImageNtHeaders64`], and corresponds
30/// to [`crate::FileKind::Pe64`].
31pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>;
32
33/// A PE image file.
34///
35/// Most functionality is provided by the [`Object`] trait implementation.
36#[derive(Debug)]
37pub struct PeFile<'data, Pe, R = &'data [u8]>
38where
39    Pe: ImageNtHeaders,
40    R: ReadRef<'data>,
41{
42    pub(super) dos_header: &'data pe::ImageDosHeader,
43    pub(super) nt_headers: &'data Pe,
44    pub(super) data_directories: DataDirectories<'data>,
45    pub(super) common: CoffCommon<'data, R>,
46    pub(super) data: R,
47}
48
49impl<'data, Pe, R> PeFile<'data, Pe, R>
50where
51    Pe: ImageNtHeaders,
52    R: ReadRef<'data>,
53{
54    /// Parse the raw PE file data.
55    pub fn parse(data: R) -> Result<Self> {
56        let dos_header = pe::ImageDosHeader::parse(data)?;
57        let mut offset = dos_header.nt_headers_offset().into();
58        let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?;
59        let sections = nt_headers.sections(data, offset)?;
60        let coff_symbols = nt_headers.symbols(data);
61        let image_base = nt_headers.optional_header().image_base();
62
63        Ok(PeFile {
64            dos_header,
65            nt_headers,
66            data_directories,
67            common: CoffCommon {
68                sections,
69                // The PE file format deprecates the COFF symbol table (https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image)
70                // We do not want to prevent parsing the rest of the PE file for a corrupt COFF header, but rather return an empty symbol table
71                symbols: coff_symbols.unwrap_or_default(),
72                image_base,
73            },
74            data,
75        })
76    }
77
78    /// Returns this binary data.
79    pub fn data(&self) -> R {
80        self.data
81    }
82
83    /// Return the DOS header of this file.
84    pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
85        self.dos_header
86    }
87
88    /// Return the NT Headers of this file.
89    pub fn nt_headers(&self) -> &'data Pe {
90        self.nt_headers
91    }
92
93    /// Returns information about the rich header of this file (if any).
94    pub fn rich_header_info(&self) -> Option<RichHeaderInfo<'_>> {
95        RichHeaderInfo::parse(self.data, self.dos_header.nt_headers_offset().into())
96    }
97
98    /// Returns the section table of this binary.
99    pub fn section_table(&self) -> SectionTable<'data> {
100        self.common.sections
101    }
102
103    /// Returns the data directories of this file.
104    pub fn data_directories(&self) -> DataDirectories<'data> {
105        self.data_directories
106    }
107
108    /// Returns the data directory at the given index.
109    pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
110        self.data_directories.get(id)
111    }
112
113    /// Returns the export table of this file.
114    ///
115    /// The export table is located using the data directory.
116    pub fn export_table(&self) -> Result<Option<ExportTable<'data>>> {
117        self.data_directories
118            .export_table(self.data, &self.common.sections)
119    }
120
121    /// Returns the import table of this file.
122    ///
123    /// The import table is located using the data directory.
124    pub fn import_table(&self) -> Result<Option<ImportTable<'data>>> {
125        self.data_directories
126            .import_table(self.data, &self.common.sections)
127    }
128
129    pub(super) fn section_alignment(&self) -> u64 {
130        u64::from(self.nt_headers.optional_header().section_alignment())
131    }
132}
133
134impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R>
135where
136    Pe: ImageNtHeaders,
137    R: ReadRef<'data>,
138{
139}
140
141impl<'data, Pe, R> Object<'data> for PeFile<'data, Pe, R>
142where
143    Pe: ImageNtHeaders,
144    R: ReadRef<'data>,
145{
146    type Segment<'file> = PeSegment<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
147    type SegmentIterator<'file> = PeSegmentIterator<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
148    type Section<'file> = PeSection<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
149    type SectionIterator<'file> = PeSectionIterator<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
150    type Comdat<'file> = PeComdat<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
151    type ComdatIterator<'file> = PeComdatIterator<'data, 'file, Pe, R> where Self: 'file, 'data: 'file;
152    type Symbol<'file> = CoffSymbol<'data, 'file, R> where Self: 'file, 'data: 'file;
153    type SymbolIterator<'file> = CoffSymbolIterator<'data, 'file, R> where Self: 'file, 'data: 'file;
154    type SymbolTable<'file> = CoffSymbolTable<'data, 'file, R> where Self: 'file, 'data: 'file;
155    type DynamicRelocationIterator<'file> = NoDynamicRelocationIterator where Self: 'file, 'data: 'file;
156
157    fn architecture(&self) -> Architecture {
158        match self.nt_headers.file_header().machine.get(LE) {
159            pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm,
160            pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => Architecture::Aarch64,
161            pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
162            pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
163            _ => Architecture::Unknown,
164        }
165    }
166
167    fn sub_architecture(&self) -> Option<SubArchitecture> {
168        match self.nt_headers.file_header().machine.get(LE) {
169            pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC),
170            _ => None,
171        }
172    }
173
174    #[inline]
175    fn is_little_endian(&self) -> bool {
176        // Only little endian is supported.
177        true
178    }
179
180    #[inline]
181    fn is_64(&self) -> bool {
182        self.nt_headers.is_type_64()
183    }
184
185    fn kind(&self) -> ObjectKind {
186        let characteristics = self.nt_headers.file_header().characteristics.get(LE);
187        if characteristics & pe::IMAGE_FILE_DLL != 0 {
188            ObjectKind::Dynamic
189        } else if characteristics & pe::IMAGE_FILE_SYSTEM != 0 {
190            ObjectKind::Unknown
191        } else {
192            ObjectKind::Executable
193        }
194    }
195
196    fn segments(&self) -> PeSegmentIterator<'data, '_, Pe, R> {
197        PeSegmentIterator {
198            file: self,
199            iter: self.common.sections.iter(),
200        }
201    }
202
203    fn section_by_name_bytes<'file>(
204        &'file self,
205        section_name: &[u8],
206    ) -> Option<PeSection<'data, 'file, Pe, R>> {
207        self.common
208            .sections
209            .section_by_name(self.common.symbols.strings(), section_name)
210            .map(|(index, section)| PeSection {
211                file: self,
212                index,
213                section,
214            })
215    }
216
217    fn section_by_index(&self, index: SectionIndex) -> Result<PeSection<'data, '_, Pe, R>> {
218        let section = self.common.sections.section(index)?;
219        Ok(PeSection {
220            file: self,
221            index,
222            section,
223        })
224    }
225
226    fn sections(&self) -> PeSectionIterator<'data, '_, Pe, R> {
227        PeSectionIterator {
228            file: self,
229            iter: self.common.sections.iter().enumerate(),
230        }
231    }
232
233    fn comdats(&self) -> PeComdatIterator<'data, '_, Pe, R> {
234        PeComdatIterator { file: self }
235    }
236
237    fn symbol_by_index(&self, index: SymbolIndex) -> Result<CoffSymbol<'data, '_, R>> {
238        let symbol = self.common.symbols.symbol(index)?;
239        Ok(CoffSymbol {
240            file: &self.common,
241            index,
242            symbol,
243        })
244    }
245
246    fn symbols(&self) -> CoffSymbolIterator<'data, '_, R> {
247        CoffSymbolIterator::new(&self.common)
248    }
249
250    fn symbol_table(&self) -> Option<CoffSymbolTable<'data, '_, R>> {
251        Some(CoffSymbolTable { file: &self.common })
252    }
253
254    fn dynamic_symbols(&self) -> CoffSymbolIterator<'data, '_, R> {
255        CoffSymbolIterator::empty(&self.common)
256    }
257
258    fn dynamic_symbol_table(&self) -> Option<CoffSymbolTable<'data, '_, R>> {
259        None
260    }
261
262    fn dynamic_relocations(&self) -> Option<NoDynamicRelocationIterator> {
263        None
264    }
265
266    fn imports(&self) -> Result<Vec<Import<'data>>> {
267        let mut imports = Vec::new();
268        if let Some(import_table) = self.import_table()? {
269            let mut import_descs = import_table.descriptors()?;
270            while let Some(import_desc) = import_descs.next()? {
271                let library = import_table.name(import_desc.name.get(LE))?;
272                let mut first_thunk = import_desc.original_first_thunk.get(LE);
273                if first_thunk == 0 {
274                    first_thunk = import_desc.first_thunk.get(LE);
275                }
276                let mut thunks = import_table.thunks(first_thunk)?;
277                while let Some(thunk) = thunks.next::<Pe>()? {
278                    if !thunk.is_ordinal() {
279                        let (_hint, name) = import_table.hint_name(thunk.address())?;
280                        imports.push(Import {
281                            library: ByteString(library),
282                            name: ByteString(name),
283                        });
284                    }
285                }
286            }
287        }
288        Ok(imports)
289    }
290
291    fn exports(&self) -> Result<Vec<Export<'data>>> {
292        let mut exports = Vec::new();
293        if let Some(export_table) = self.export_table()? {
294            for (name_pointer, address_index) in export_table.name_iter() {
295                let name = export_table.name_from_pointer(name_pointer)?;
296                let address = export_table.address_by_index(address_index.into())?;
297                if !export_table.is_forward(address) {
298                    exports.push(Export {
299                        name: ByteString(name),
300                        address: self.common.image_base.wrapping_add(address.into()),
301                    })
302                }
303            }
304        }
305        Ok(exports)
306    }
307
308    fn pdb_info(&self) -> Result<Option<CodeView<'_>>> {
309        let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_DEBUG) {
310            Some(data_dir) => data_dir,
311            None => return Ok(None),
312        };
313        let debug_data = data_dir.data(self.data, &self.common.sections)?;
314        let debug_dirs = pod::slice_from_all_bytes::<pe::ImageDebugDirectory>(debug_data)
315            .read_error("Invalid PE debug dir size")?;
316
317        for debug_dir in debug_dirs {
318            if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
319                continue;
320            }
321
322            let info = self
323                .data
324                .read_slice_at::<u8>(
325                    debug_dir.pointer_to_raw_data.get(LE) as u64,
326                    debug_dir.size_of_data.get(LE) as usize,
327                )
328                .read_error("Invalid CodeView Info address")?;
329
330            let mut info = Bytes(info);
331
332            let sig = info
333                .read_bytes(4)
334                .read_error("Invalid CodeView signature")?;
335            if sig.0 != b"RSDS" {
336                continue;
337            }
338
339            let guid: [u8; 16] = info
340                .read_bytes(16)
341                .read_error("Invalid CodeView GUID")?
342                .0
343                .try_into()
344                .unwrap();
345
346            let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
347
348            let path = info
349                .read_string()
350                .read_error("Invalid CodeView file path")?;
351
352            return Ok(Some(CodeView {
353                path: ByteString(path),
354                guid,
355                age: age.get(LE),
356            }));
357        }
358        Ok(None)
359    }
360
361    fn has_debug_symbols(&self) -> bool {
362        self.section_by_name(".debug_info").is_some()
363    }
364
365    fn relative_address_base(&self) -> u64 {
366        self.common.image_base
367    }
368
369    fn entry(&self) -> u64 {
370        u64::from(self.nt_headers.optional_header().address_of_entry_point())
371            .wrapping_add(self.common.image_base)
372    }
373
374    fn flags(&self) -> FileFlags {
375        FileFlags::Coff {
376            characteristics: self.nt_headers.file_header().characteristics.get(LE),
377        }
378    }
379}
380
381/// An iterator for the COMDAT section groups in a [`PeFile32`].
382pub type PeComdatIterator32<'data, 'file, R = &'data [u8]> =
383    PeComdatIterator<'data, 'file, pe::ImageNtHeaders32, R>;
384/// An iterator for the COMDAT section groups in a [`PeFile64`].
385pub type PeComdatIterator64<'data, 'file, R = &'data [u8]> =
386    PeComdatIterator<'data, 'file, pe::ImageNtHeaders64, R>;
387
388/// An iterator for the COMDAT section groups in a [`PeFile`].
389///
390/// This is a stub that doesn't implement any functionality.
391#[derive(Debug)]
392pub struct PeComdatIterator<'data, 'file, Pe, R = &'data [u8]>
393where
394    Pe: ImageNtHeaders,
395    R: ReadRef<'data>,
396{
397    #[allow(unused)]
398    file: &'file PeFile<'data, Pe, R>,
399}
400
401impl<'data, 'file, Pe, R> Iterator for PeComdatIterator<'data, 'file, Pe, R>
402where
403    Pe: ImageNtHeaders,
404    R: ReadRef<'data>,
405{
406    type Item = PeComdat<'data, 'file, Pe, R>;
407
408    #[inline]
409    fn next(&mut self) -> Option<Self::Item> {
410        None
411    }
412}
413
414/// A COMDAT section group in a [`PeFile32`].
415pub type PeComdat32<'data, 'file, R = &'data [u8]> =
416    PeComdat<'data, 'file, pe::ImageNtHeaders32, R>;
417/// A COMDAT section group in a [`PeFile64`].
418pub type PeComdat64<'data, 'file, R = &'data [u8]> =
419    PeComdat<'data, 'file, pe::ImageNtHeaders64, R>;
420
421/// A COMDAT section group in a [`PeFile`].
422///
423/// This is a stub that doesn't implement any functionality.
424#[derive(Debug)]
425pub struct PeComdat<'data, 'file, Pe, R = &'data [u8]>
426where
427    Pe: ImageNtHeaders,
428    R: ReadRef<'data>,
429{
430    #[allow(unused)]
431    file: &'file PeFile<'data, Pe, R>,
432}
433
434impl<'data, 'file, Pe, R> read::private::Sealed for PeComdat<'data, 'file, Pe, R>
435where
436    Pe: ImageNtHeaders,
437    R: ReadRef<'data>,
438{
439}
440
441impl<'data, 'file, Pe, R> ObjectComdat<'data> for PeComdat<'data, 'file, Pe, R>
442where
443    Pe: ImageNtHeaders,
444    R: ReadRef<'data>,
445{
446    type SectionIterator = PeComdatSectionIterator<'data, 'file, Pe, R>;
447
448    #[inline]
449    fn kind(&self) -> ComdatKind {
450        unreachable!();
451    }
452
453    #[inline]
454    fn symbol(&self) -> SymbolIndex {
455        unreachable!();
456    }
457
458    #[inline]
459    fn name_bytes(&self) -> Result<&'data [u8]> {
460        unreachable!();
461    }
462
463    #[inline]
464    fn name(&self) -> Result<&'data str> {
465        unreachable!();
466    }
467
468    #[inline]
469    fn sections(&self) -> Self::SectionIterator {
470        unreachable!();
471    }
472}
473
474/// An iterator for the sections in a COMDAT section group in a [`PeFile32`].
475pub type PeComdatSectionIterator32<'data, 'file, R = &'data [u8]> =
476    PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
477/// An iterator for the sections in a COMDAT section group in a [`PeFile64`].
478pub type PeComdatSectionIterator64<'data, 'file, R = &'data [u8]> =
479    PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
480
481/// An iterator for the sections in a COMDAT section group in a [`PeFile`].
482///
483/// This is a stub that doesn't implement any functionality.
484#[derive(Debug)]
485pub struct PeComdatSectionIterator<'data, 'file, Pe, R = &'data [u8]>
486where
487    Pe: ImageNtHeaders,
488    R: ReadRef<'data>,
489{
490    #[allow(unused)]
491    file: &'file PeFile<'data, Pe, R>,
492}
493
494impl<'data, 'file, Pe, R> Iterator for PeComdatSectionIterator<'data, 'file, Pe, R>
495where
496    Pe: ImageNtHeaders,
497    R: ReadRef<'data>,
498{
499    type Item = SectionIndex;
500
501    fn next(&mut self) -> Option<Self::Item> {
502        None
503    }
504}
505
506impl pe::ImageDosHeader {
507    /// Read the DOS header.
508    ///
509    /// Also checks that the `e_magic` field in the header is valid.
510    pub fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
511        // DOS header comes first.
512        let dos_header = data
513            .read_at::<pe::ImageDosHeader>(0)
514            .read_error("Invalid DOS header size or alignment")?;
515        if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE {
516            return Err(Error("Invalid DOS magic"));
517        }
518        Ok(dos_header)
519    }
520
521    /// Return the file offset of the nt_headers.
522    #[inline]
523    pub fn nt_headers_offset(&self) -> u32 {
524        self.e_lfanew.get(LE)
525    }
526}
527
528/// Find the optional header and read its `magic` field.
529///
530/// It can be useful to know this magic value before trying to
531/// fully parse the NT headers.
532pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16> {
533    let dos_header = pe::ImageDosHeader::parse(data)?;
534    // NT headers are at an offset specified in the DOS header.
535    let offset = dos_header.nt_headers_offset().into();
536    // It doesn't matter which NT header type is used for the purpose
537    // of reading the optional header magic.
538    let nt_headers = data
539        .read_at::<pe::ImageNtHeaders32>(offset)
540        .read_error("Invalid NT headers offset, size, or alignment")?;
541    if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
542        return Err(Error("Invalid PE magic"));
543    }
544    Ok(nt_headers.optional_header().magic())
545}
546
547/// A trait for generic access to [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`].
548#[allow(missing_docs)]
549pub trait ImageNtHeaders: Debug + Pod {
550    type ImageOptionalHeader: ImageOptionalHeader;
551    type ImageThunkData: ImageThunkData;
552
553    /// Return true if this type is a 64-bit header.
554    ///
555    /// This is a property of the type, not a value in the header data.
556    fn is_type_64(&self) -> bool;
557
558    /// Return true if the magic field in the optional header is valid.
559    fn is_valid_optional_magic(&self) -> bool;
560
561    /// Return the signature
562    fn signature(&self) -> u32;
563
564    /// Return the file header.
565    fn file_header(&self) -> &pe::ImageFileHeader;
566
567    /// Return the optional header.
568    fn optional_header(&self) -> &Self::ImageOptionalHeader;
569
570    // Provided methods.
571
572    /// Read the NT headers, including the data directories.
573    ///
574    /// `data` must be for the entire file.
575    ///
576    /// `offset` must be headers offset, which can be obtained from [`pe::ImageDosHeader::nt_headers_offset`].
577    /// It is updated to point after the optional header, which is where the section headers are located.
578    ///
579    /// Also checks that the `signature` and `magic` fields in the headers are valid.
580    fn parse<'data, R: ReadRef<'data>>(
581        data: R,
582        offset: &mut u64,
583    ) -> read::Result<(&'data Self, DataDirectories<'data>)> {
584        // Note that this does not include the data directories in the optional header.
585        let nt_headers = data
586            .read::<Self>(offset)
587            .read_error("Invalid PE headers offset or size")?;
588        if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
589            return Err(Error("Invalid PE magic"));
590        }
591        if !nt_headers.is_valid_optional_magic() {
592            return Err(Error("Invalid PE optional header magic"));
593        }
594
595        // Read the rest of the optional header, and then read the data directories from that.
596        let optional_data_size =
597            u64::from(nt_headers.file_header().size_of_optional_header.get(LE))
598                .checked_sub(mem::size_of::<Self::ImageOptionalHeader>() as u64)
599                .read_error("PE optional header size is too small")?;
600        let optional_data = data
601            .read_bytes(offset, optional_data_size)
602            .read_error("Invalid PE optional header size")?;
603        let data_directories = DataDirectories::parse(
604            optional_data,
605            nt_headers.optional_header().number_of_rva_and_sizes(),
606        )?;
607
608        Ok((nt_headers, data_directories))
609    }
610
611    /// Read the section table.
612    ///
613    /// `data` must be for the entire file.
614    /// `offset` must be after the optional file header.
615    #[inline]
616    fn sections<'data, R: ReadRef<'data>>(
617        &self,
618        data: R,
619        offset: u64,
620    ) -> read::Result<SectionTable<'data>> {
621        SectionTable::parse(self.file_header(), data, offset)
622    }
623
624    /// Read the COFF symbol table and string table.
625    ///
626    /// `data` must be the entire file data.
627    #[inline]
628    fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data, R>> {
629        SymbolTable::parse(self.file_header(), data)
630    }
631}
632
633/// A trait for generic access to [`pe::ImageOptionalHeader32`] and [`pe::ImageOptionalHeader64`].
634#[allow(missing_docs)]
635pub trait ImageOptionalHeader: Debug + Pod {
636    // Standard fields.
637    fn magic(&self) -> u16;
638    fn major_linker_version(&self) -> u8;
639    fn minor_linker_version(&self) -> u8;
640    fn size_of_code(&self) -> u32;
641    fn size_of_initialized_data(&self) -> u32;
642    fn size_of_uninitialized_data(&self) -> u32;
643    fn address_of_entry_point(&self) -> u32;
644    fn base_of_code(&self) -> u32;
645    fn base_of_data(&self) -> Option<u32>;
646
647    // NT additional fields.
648    fn image_base(&self) -> u64;
649    fn section_alignment(&self) -> u32;
650    fn file_alignment(&self) -> u32;
651    fn major_operating_system_version(&self) -> u16;
652    fn minor_operating_system_version(&self) -> u16;
653    fn major_image_version(&self) -> u16;
654    fn minor_image_version(&self) -> u16;
655    fn major_subsystem_version(&self) -> u16;
656    fn minor_subsystem_version(&self) -> u16;
657    fn win32_version_value(&self) -> u32;
658    fn size_of_image(&self) -> u32;
659    fn size_of_headers(&self) -> u32;
660    fn check_sum(&self) -> u32;
661    fn subsystem(&self) -> u16;
662    fn dll_characteristics(&self) -> u16;
663    fn size_of_stack_reserve(&self) -> u64;
664    fn size_of_stack_commit(&self) -> u64;
665    fn size_of_heap_reserve(&self) -> u64;
666    fn size_of_heap_commit(&self) -> u64;
667    fn loader_flags(&self) -> u32;
668    fn number_of_rva_and_sizes(&self) -> u32;
669}
670
671impl ImageNtHeaders for pe::ImageNtHeaders32 {
672    type ImageOptionalHeader = pe::ImageOptionalHeader32;
673    type ImageThunkData = pe::ImageThunkData32;
674
675    #[inline]
676    fn is_type_64(&self) -> bool {
677        false
678    }
679
680    #[inline]
681    fn is_valid_optional_magic(&self) -> bool {
682        self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC
683    }
684
685    #[inline]
686    fn signature(&self) -> u32 {
687        self.signature.get(LE)
688    }
689
690    #[inline]
691    fn file_header(&self) -> &pe::ImageFileHeader {
692        &self.file_header
693    }
694
695    #[inline]
696    fn optional_header(&self) -> &Self::ImageOptionalHeader {
697        &self.optional_header
698    }
699}
700
701impl ImageOptionalHeader for pe::ImageOptionalHeader32 {
702    #[inline]
703    fn magic(&self) -> u16 {
704        self.magic.get(LE)
705    }
706
707    #[inline]
708    fn major_linker_version(&self) -> u8 {
709        self.major_linker_version
710    }
711
712    #[inline]
713    fn minor_linker_version(&self) -> u8 {
714        self.minor_linker_version
715    }
716
717    #[inline]
718    fn size_of_code(&self) -> u32 {
719        self.size_of_code.get(LE)
720    }
721
722    #[inline]
723    fn size_of_initialized_data(&self) -> u32 {
724        self.size_of_initialized_data.get(LE)
725    }
726
727    #[inline]
728    fn size_of_uninitialized_data(&self) -> u32 {
729        self.size_of_uninitialized_data.get(LE)
730    }
731
732    #[inline]
733    fn address_of_entry_point(&self) -> u32 {
734        self.address_of_entry_point.get(LE)
735    }
736
737    #[inline]
738    fn base_of_code(&self) -> u32 {
739        self.base_of_code.get(LE)
740    }
741
742    #[inline]
743    fn base_of_data(&self) -> Option<u32> {
744        Some(self.base_of_data.get(LE))
745    }
746
747    #[inline]
748    fn image_base(&self) -> u64 {
749        self.image_base.get(LE).into()
750    }
751
752    #[inline]
753    fn section_alignment(&self) -> u32 {
754        self.section_alignment.get(LE)
755    }
756
757    #[inline]
758    fn file_alignment(&self) -> u32 {
759        self.file_alignment.get(LE)
760    }
761
762    #[inline]
763    fn major_operating_system_version(&self) -> u16 {
764        self.major_operating_system_version.get(LE)
765    }
766
767    #[inline]
768    fn minor_operating_system_version(&self) -> u16 {
769        self.minor_operating_system_version.get(LE)
770    }
771
772    #[inline]
773    fn major_image_version(&self) -> u16 {
774        self.major_image_version.get(LE)
775    }
776
777    #[inline]
778    fn minor_image_version(&self) -> u16 {
779        self.minor_image_version.get(LE)
780    }
781
782    #[inline]
783    fn major_subsystem_version(&self) -> u16 {
784        self.major_subsystem_version.get(LE)
785    }
786
787    #[inline]
788    fn minor_subsystem_version(&self) -> u16 {
789        self.minor_subsystem_version.get(LE)
790    }
791
792    #[inline]
793    fn win32_version_value(&self) -> u32 {
794        self.win32_version_value.get(LE)
795    }
796
797    #[inline]
798    fn size_of_image(&self) -> u32 {
799        self.size_of_image.get(LE)
800    }
801
802    #[inline]
803    fn size_of_headers(&self) -> u32 {
804        self.size_of_headers.get(LE)
805    }
806
807    #[inline]
808    fn check_sum(&self) -> u32 {
809        self.check_sum.get(LE)
810    }
811
812    #[inline]
813    fn subsystem(&self) -> u16 {
814        self.subsystem.get(LE)
815    }
816
817    #[inline]
818    fn dll_characteristics(&self) -> u16 {
819        self.dll_characteristics.get(LE)
820    }
821
822    #[inline]
823    fn size_of_stack_reserve(&self) -> u64 {
824        self.size_of_stack_reserve.get(LE).into()
825    }
826
827    #[inline]
828    fn size_of_stack_commit(&self) -> u64 {
829        self.size_of_stack_commit.get(LE).into()
830    }
831
832    #[inline]
833    fn size_of_heap_reserve(&self) -> u64 {
834        self.size_of_heap_reserve.get(LE).into()
835    }
836
837    #[inline]
838    fn size_of_heap_commit(&self) -> u64 {
839        self.size_of_heap_commit.get(LE).into()
840    }
841
842    #[inline]
843    fn loader_flags(&self) -> u32 {
844        self.loader_flags.get(LE)
845    }
846
847    #[inline]
848    fn number_of_rva_and_sizes(&self) -> u32 {
849        self.number_of_rva_and_sizes.get(LE)
850    }
851}
852
853impl ImageNtHeaders for pe::ImageNtHeaders64 {
854    type ImageOptionalHeader = pe::ImageOptionalHeader64;
855    type ImageThunkData = pe::ImageThunkData64;
856
857    #[inline]
858    fn is_type_64(&self) -> bool {
859        true
860    }
861
862    #[inline]
863    fn is_valid_optional_magic(&self) -> bool {
864        self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC
865    }
866
867    #[inline]
868    fn signature(&self) -> u32 {
869        self.signature.get(LE)
870    }
871
872    #[inline]
873    fn file_header(&self) -> &pe::ImageFileHeader {
874        &self.file_header
875    }
876
877    #[inline]
878    fn optional_header(&self) -> &Self::ImageOptionalHeader {
879        &self.optional_header
880    }
881}
882
883impl ImageOptionalHeader for pe::ImageOptionalHeader64 {
884    #[inline]
885    fn magic(&self) -> u16 {
886        self.magic.get(LE)
887    }
888
889    #[inline]
890    fn major_linker_version(&self) -> u8 {
891        self.major_linker_version
892    }
893
894    #[inline]
895    fn minor_linker_version(&self) -> u8 {
896        self.minor_linker_version
897    }
898
899    #[inline]
900    fn size_of_code(&self) -> u32 {
901        self.size_of_code.get(LE)
902    }
903
904    #[inline]
905    fn size_of_initialized_data(&self) -> u32 {
906        self.size_of_initialized_data.get(LE)
907    }
908
909    #[inline]
910    fn size_of_uninitialized_data(&self) -> u32 {
911        self.size_of_uninitialized_data.get(LE)
912    }
913
914    #[inline]
915    fn address_of_entry_point(&self) -> u32 {
916        self.address_of_entry_point.get(LE)
917    }
918
919    #[inline]
920    fn base_of_code(&self) -> u32 {
921        self.base_of_code.get(LE)
922    }
923
924    #[inline]
925    fn base_of_data(&self) -> Option<u32> {
926        None
927    }
928
929    #[inline]
930    fn image_base(&self) -> u64 {
931        self.image_base.get(LE)
932    }
933
934    #[inline]
935    fn section_alignment(&self) -> u32 {
936        self.section_alignment.get(LE)
937    }
938
939    #[inline]
940    fn file_alignment(&self) -> u32 {
941        self.file_alignment.get(LE)
942    }
943
944    #[inline]
945    fn major_operating_system_version(&self) -> u16 {
946        self.major_operating_system_version.get(LE)
947    }
948
949    #[inline]
950    fn minor_operating_system_version(&self) -> u16 {
951        self.minor_operating_system_version.get(LE)
952    }
953
954    #[inline]
955    fn major_image_version(&self) -> u16 {
956        self.major_image_version.get(LE)
957    }
958
959    #[inline]
960    fn minor_image_version(&self) -> u16 {
961        self.minor_image_version.get(LE)
962    }
963
964    #[inline]
965    fn major_subsystem_version(&self) -> u16 {
966        self.major_subsystem_version.get(LE)
967    }
968
969    #[inline]
970    fn minor_subsystem_version(&self) -> u16 {
971        self.minor_subsystem_version.get(LE)
972    }
973
974    #[inline]
975    fn win32_version_value(&self) -> u32 {
976        self.win32_version_value.get(LE)
977    }
978
979    #[inline]
980    fn size_of_image(&self) -> u32 {
981        self.size_of_image.get(LE)
982    }
983
984    #[inline]
985    fn size_of_headers(&self) -> u32 {
986        self.size_of_headers.get(LE)
987    }
988
989    #[inline]
990    fn check_sum(&self) -> u32 {
991        self.check_sum.get(LE)
992    }
993
994    #[inline]
995    fn subsystem(&self) -> u16 {
996        self.subsystem.get(LE)
997    }
998
999    #[inline]
1000    fn dll_characteristics(&self) -> u16 {
1001        self.dll_characteristics.get(LE)
1002    }
1003
1004    #[inline]
1005    fn size_of_stack_reserve(&self) -> u64 {
1006        self.size_of_stack_reserve.get(LE)
1007    }
1008
1009    #[inline]
1010    fn size_of_stack_commit(&self) -> u64 {
1011        self.size_of_stack_commit.get(LE)
1012    }
1013
1014    #[inline]
1015    fn size_of_heap_reserve(&self) -> u64 {
1016        self.size_of_heap_reserve.get(LE)
1017    }
1018
1019    #[inline]
1020    fn size_of_heap_commit(&self) -> u64 {
1021        self.size_of_heap_commit.get(LE)
1022    }
1023
1024    #[inline]
1025    fn loader_flags(&self) -> u32 {
1026        self.loader_flags.get(LE)
1027    }
1028
1029    #[inline]
1030    fn number_of_rva_and_sizes(&self) -> u32 {
1031        self.number_of_rva_and_sizes.get(LE)
1032    }
1033}