Skip to main content

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