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