1 use alloc::vec::Vec;
2 use core::fmt::Debug;
3 use core::{mem, str};
4 
5 use core::convert::TryInto;
6 
7 use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
8 use crate::read::{
9     self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
10     Object, ObjectComdat, ReadError, ReadRef, Result, SectionIndex, SymbolIndex,
11 };
12 use crate::{
13     pe, ByteString, Bytes, CodeView, LittleEndian as LE, Pod, U16Bytes, U32Bytes, U32, U64,
14 };
15 
16 use super::{PeSection, PeSectionIterator, PeSegment, PeSegmentIterator, SectionTable};
17 
18 /// A PE32 (32-bit) image file.
19 pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>;
20 /// A PE32+ (64-bit) image file.
21 pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>;
22 
23 /// A PE object file.
24 #[derive(Debug)]
25 pub struct PeFile<'data, Pe, R = &'data [u8]>
26 where
27     Pe: ImageNtHeaders,
28     R: ReadRef<'data>,
29 {
30     pub(super) dos_header: &'data pe::ImageDosHeader,
31     pub(super) nt_headers: &'data Pe,
32     pub(super) data_directories: &'data [pe::ImageDataDirectory],
33     pub(super) common: CoffCommon<'data, R>,
34     pub(super) data: R,
35 }
36 
37 impl<'data, Pe, R> PeFile<'data, Pe, R>
38 where
39     Pe: ImageNtHeaders,
40     R: ReadRef<'data>,
41 {
42     /// Parse the raw PE file data.
parse(data: R) -> Result<Self>43     pub fn parse(data: R) -> Result<Self> {
44         let dos_header = pe::ImageDosHeader::parse(data)?;
45         let mut offset = dos_header.nt_headers_offset().into();
46         let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?;
47         let sections = nt_headers.sections(data, offset)?;
48         let symbols = nt_headers.symbols(data)?;
49         let image_base = nt_headers.optional_header().image_base();
50 
51         Ok(PeFile {
52             dos_header,
53             nt_headers,
54             data_directories,
55             common: CoffCommon {
56                 sections,
57                 symbols,
58                 image_base,
59             },
60             data,
61         })
62     }
63 
section_alignment(&self) -> u6464     pub(super) fn section_alignment(&self) -> u64 {
65         u64::from(self.nt_headers.optional_header().section_alignment())
66     }
67 
68     /// Return the DOS header of this file
dos_header(&self) -> &'data pe::ImageDosHeader69     pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
70         self.dos_header
71     }
72 
73     /// Return the NT Headers of this file
nt_headers(&self) -> &'data Pe74     pub fn nt_headers(&self) -> &'data Pe {
75         self.nt_headers
76     }
77 
78     /// Returns the section table of this binary.
section_table(&self) -> SectionTable<'data>79     pub fn section_table(&self) -> SectionTable<'data> {
80         self.common.sections
81     }
82 
83     /// Returns the data directory at the given index.
data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory>84     pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
85         self.data_directories
86             .get(id)
87             .filter(|d| d.size.get(LE) != 0)
88     }
89 
data_at(&self, va: u32) -> Option<Bytes<'data>>90     fn data_at(&self, va: u32) -> Option<Bytes<'data>> {
91         self.common.sections.pe_data_at(self.data, va).map(Bytes)
92     }
93 
94     /// Returns this binary data.
data(&self) -> R95     pub fn data(&self) -> R {
96         self.data
97     }
98 }
99 
100 impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R>
101 where
102     Pe: ImageNtHeaders,
103     R: ReadRef<'data>,
104 {
105 }
106 
107 impl<'data, 'file, Pe, R> Object<'data, 'file> for PeFile<'data, Pe, R>
108 where
109     'data: 'file,
110     Pe: ImageNtHeaders,
111     R: 'file + ReadRef<'data>,
112 {
113     type Segment = PeSegment<'data, 'file, Pe, R>;
114     type SegmentIterator = PeSegmentIterator<'data, 'file, Pe, R>;
115     type Section = PeSection<'data, 'file, Pe, R>;
116     type SectionIterator = PeSectionIterator<'data, 'file, Pe, R>;
117     type Comdat = PeComdat<'data, 'file, Pe, R>;
118     type ComdatIterator = PeComdatIterator<'data, 'file, Pe, R>;
119     type Symbol = CoffSymbol<'data, 'file, R>;
120     type SymbolIterator = CoffSymbolIterator<'data, 'file, R>;
121     type SymbolTable = CoffSymbolTable<'data, 'file, R>;
122     type DynamicRelocationIterator = NoDynamicRelocationIterator;
123 
architecture(&self) -> Architecture124     fn architecture(&self) -> Architecture {
125         match self.nt_headers.file_header().machine.get(LE) {
126             pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm,
127             pe::IMAGE_FILE_MACHINE_ARM64 => Architecture::Aarch64,
128             pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
129             pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
130             _ => Architecture::Unknown,
131         }
132     }
133 
134     #[inline]
is_little_endian(&self) -> bool135     fn is_little_endian(&self) -> bool {
136         // Only little endian is supported.
137         true
138     }
139 
140     #[inline]
is_64(&self) -> bool141     fn is_64(&self) -> bool {
142         self.nt_headers.is_type_64()
143     }
144 
segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R>145     fn segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R> {
146         PeSegmentIterator {
147             file: self,
148             iter: self.common.sections.iter(),
149         }
150     }
151 
section_by_name(&'file self, section_name: &str) -> Option<PeSection<'data, 'file, Pe, R>>152     fn section_by_name(&'file self, section_name: &str) -> Option<PeSection<'data, 'file, Pe, R>> {
153         self.common
154             .sections
155             .section_by_name(self.common.symbols.strings(), section_name.as_bytes())
156             .map(|(index, section)| PeSection {
157                 file: self,
158                 index: SectionIndex(index),
159                 section,
160             })
161     }
162 
section_by_index( &'file self, index: SectionIndex, ) -> Result<PeSection<'data, 'file, Pe, R>>163     fn section_by_index(
164         &'file self,
165         index: SectionIndex,
166     ) -> Result<PeSection<'data, 'file, Pe, R>> {
167         let section = self.common.sections.section(index.0)?;
168         Ok(PeSection {
169             file: self,
170             index,
171             section,
172         })
173     }
174 
sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R>175     fn sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R> {
176         PeSectionIterator {
177             file: self,
178             iter: self.common.sections.iter().enumerate(),
179         }
180     }
181 
comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R>182     fn comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R> {
183         PeComdatIterator { file: self }
184     }
185 
symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file, R>>186     fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file, R>> {
187         let symbol = self.common.symbols.symbol(index.0)?;
188         Ok(CoffSymbol {
189             file: &self.common,
190             index,
191             symbol,
192         })
193     }
194 
symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R>195     fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
196         CoffSymbolIterator {
197             file: &self.common,
198             index: 0,
199         }
200     }
201 
symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>>202     fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
203         Some(CoffSymbolTable { file: &self.common })
204     }
205 
dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R>206     fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
207         CoffSymbolIterator {
208             file: &self.common,
209             // Hack: don't return any.
210             index: self.common.symbols.len(),
211         }
212     }
213 
dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>>214     fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
215         None
216     }
217 
dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator>218     fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> {
219         None
220     }
221 
imports(&self) -> Result<Vec<Import<'data>>>222     fn imports(&self) -> Result<Vec<Import<'data>>> {
223         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_IMPORT) {
224             Some(data_dir) => data_dir,
225             None => return Ok(Vec::new()),
226         };
227         let mut import_descriptors = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
228         let mut imports = Vec::new();
229         loop {
230             let import_desc = import_descriptors
231                 .read::<pe::ImageImportDescriptor>()
232                 .read_error("Missing PE null import descriptor")?;
233             if import_desc.original_first_thunk.get(LE) == 0 {
234                 break;
235             }
236 
237             let library = self
238                 .data_at(import_desc.name.get(LE))
239                 .read_error("Invalid PE import descriptor name")?
240                 .read_string()
241                 .read_error("Invalid PE import descriptor name")?;
242 
243             let thunk_va = import_desc.original_first_thunk.get(LE);
244             let mut thunk_data = self
245                 .data_at(thunk_va)
246                 .read_error("Invalid PE import thunk address")?;
247             loop {
248                 let hint_name = if self.is_64() {
249                     let thunk = thunk_data
250                         .read::<U64<_>>()
251                         .read_error("Missing PE null import thunk")?
252                         .get(LE);
253                     if thunk == 0 {
254                         break;
255                     }
256                     if thunk & pe::IMAGE_ORDINAL_FLAG64 != 0 {
257                         // TODO: handle import by ordinal
258                         continue;
259                     }
260                     thunk as u32
261                 } else {
262                     let thunk = thunk_data
263                         .read::<U32<_>>()
264                         .read_error("Missing PE null import thunk")?
265                         .get(LE);
266                     if thunk == 0 {
267                         break;
268                     }
269                     if thunk & pe::IMAGE_ORDINAL_FLAG32 != 0 {
270                         // TODO: handle import by ordinal
271                         continue;
272                     }
273                     thunk
274                 };
275                 let name = self
276                     .data_at(hint_name)
277                     .read_error("Invalid PE import thunk name")?
278                     .read_string_at(2)
279                     .read_error("Invalid PE import thunk name")?;
280 
281                 imports.push(Import {
282                     name: ByteString(name),
283                     library: ByteString(library),
284                 });
285             }
286         }
287         Ok(imports)
288     }
289 
exports(&self) -> Result<Vec<Export<'data>>>290     fn exports(&self) -> Result<Vec<Export<'data>>> {
291         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) {
292             Some(data_dir) => data_dir,
293             None => return Ok(Vec::new()),
294         };
295         let export_va = data_dir.virtual_address.get(LE);
296         let export_size = data_dir.size.get(LE);
297         let export_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
298         let export_dir = export_data
299             .read_at::<pe::ImageExportDirectory>(0)
300             .read_error("Invalid PE export dir size")?;
301         let addresses = export_data
302             .read_slice_at::<U32Bytes<_>>(
303                 export_dir
304                     .address_of_functions
305                     .get(LE)
306                     .wrapping_sub(export_va) as usize,
307                 export_dir.number_of_functions.get(LE) as usize,
308             )
309             .read_error("Invalid PE export address table")?;
310         let number = export_dir.number_of_names.get(LE) as usize;
311         let names = export_data
312             .read_slice_at::<U32Bytes<_>>(
313                 export_dir.address_of_names.get(LE).wrapping_sub(export_va) as usize,
314                 number,
315             )
316             .read_error("Invalid PE export name table")?;
317         let ordinals = export_data
318             .read_slice_at::<U16Bytes<_>>(
319                 export_dir
320                     .address_of_name_ordinals
321                     .get(LE)
322                     .wrapping_sub(export_va) as usize,
323                 number,
324             )
325             .read_error("Invalid PE export ordinal table")?;
326 
327         let mut exports = Vec::new();
328         for (name, ordinal) in names.iter().zip(ordinals.iter()) {
329             let name = export_data
330                 .read_string_at(name.get(LE).wrapping_sub(export_va) as usize)
331                 .read_error("Invalid PE export name entry")?;
332             let address = addresses
333                 .get(ordinal.get(LE) as usize)
334                 .read_error("Invalid PE export ordinal entry")?
335                 .get(LE);
336             // Check for export address (vs forwarder address).
337             if address < export_va || (address - export_va) >= export_size {
338                 exports.push(Export {
339                     name: ByteString(name),
340                     address: self.common.image_base.wrapping_add(address.into()),
341                 })
342             }
343         }
344         Ok(exports)
345     }
346 
pdb_info(&self) -> Result<Option<CodeView>>347     fn pdb_info(&self) -> Result<Option<CodeView>> {
348         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_DEBUG) {
349             Some(data_dir) => data_dir,
350             None => return Ok(None),
351         };
352         let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
353         let debug_dir = debug_data
354             .read_at::<pe::ImageDebugDirectory>(0)
355             .read_error("Invalid PE debug dir size")?;
356 
357         if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
358             return Ok(None);
359         }
360 
361         let info = self
362             .data
363             .read_slice_at::<u8>(
364                 debug_dir.pointer_to_raw_data.get(LE) as u64,
365                 debug_dir.size_of_data.get(LE) as usize,
366             )
367             .read_error("Invalid CodeView Info address")?;
368 
369         let mut info = Bytes(info);
370 
371         let sig = info
372             .read_bytes(4)
373             .read_error("Invalid CodeView signature")?;
374         if sig.0 != b"RSDS" {
375             return Ok(None);
376         }
377 
378         let guid: [u8; 16] = info
379             .read_bytes(16)
380             .read_error("Invalid CodeView GUID")?
381             .0
382             .try_into()
383             .unwrap();
384 
385         let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
386 
387         let path = info
388             .read_string()
389             .read_error("Invalid CodeView file path")?;
390 
391         Ok(Some(CodeView {
392             path: ByteString(path),
393             guid,
394             age: age.get(LE),
395         }))
396     }
397 
has_debug_symbols(&self) -> bool398     fn has_debug_symbols(&self) -> bool {
399         self.section_by_name(".debug_info").is_some()
400     }
401 
relative_address_base(&self) -> u64402     fn relative_address_base(&self) -> u64 {
403         self.common.image_base
404     }
405 
entry(&self) -> u64406     fn entry(&self) -> u64 {
407         u64::from(self.nt_headers.optional_header().address_of_entry_point())
408             .wrapping_add(self.common.image_base)
409     }
410 
flags(&self) -> FileFlags411     fn flags(&self) -> FileFlags {
412         FileFlags::Coff {
413             characteristics: self.nt_headers.file_header().characteristics.get(LE),
414         }
415     }
416 }
417 
418 /// An iterator over the COMDAT section groups of a `PeFile32`.
419 pub type PeComdatIterator32<'data, 'file, R = &'data [u8]> =
420     PeComdatIterator<'data, 'file, pe::ImageNtHeaders32, R>;
421 /// An iterator over the COMDAT section groups of a `PeFile64`.
422 pub type PeComdatIterator64<'data, 'file, R = &'data [u8]> =
423     PeComdatIterator<'data, 'file, pe::ImageNtHeaders64, R>;
424 
425 /// An iterator over the COMDAT section groups of a `PeFile`.
426 #[derive(Debug)]
427 pub struct PeComdatIterator<'data, 'file, Pe, R = &'data [u8]>
428 where
429     Pe: ImageNtHeaders,
430     R: ReadRef<'data>,
431 {
432     file: &'file PeFile<'data, Pe, R>,
433 }
434 
435 impl<'data, 'file, Pe, R> Iterator for PeComdatIterator<'data, 'file, Pe, R>
436 where
437     Pe: ImageNtHeaders,
438     R: ReadRef<'data>,
439 {
440     type Item = PeComdat<'data, 'file, Pe, R>;
441 
442     #[inline]
next(&mut self) -> Option<Self::Item>443     fn next(&mut self) -> Option<Self::Item> {
444         None
445     }
446 }
447 
448 /// A COMDAT section group of a `PeFile32`.
449 pub type PeComdat32<'data, 'file, R = &'data [u8]> =
450     PeComdat<'data, 'file, pe::ImageNtHeaders32, R>;
451 /// A COMDAT section group of a `PeFile64`.
452 pub type PeComdat64<'data, 'file, R = &'data [u8]> =
453     PeComdat<'data, 'file, pe::ImageNtHeaders64, R>;
454 
455 /// A COMDAT section group of a `PeFile`.
456 #[derive(Debug)]
457 pub struct PeComdat<'data, 'file, Pe, R = &'data [u8]>
458 where
459     Pe: ImageNtHeaders,
460     R: ReadRef<'data>,
461 {
462     file: &'file PeFile<'data, Pe, R>,
463 }
464 
465 impl<'data, 'file, Pe, R> read::private::Sealed for PeComdat<'data, 'file, Pe, R>
466 where
467     Pe: ImageNtHeaders,
468     R: ReadRef<'data>,
469 {
470 }
471 
472 impl<'data, 'file, Pe, R> ObjectComdat<'data> for PeComdat<'data, 'file, Pe, R>
473 where
474     Pe: ImageNtHeaders,
475     R: ReadRef<'data>,
476 {
477     type SectionIterator = PeComdatSectionIterator<'data, 'file, Pe, R>;
478 
479     #[inline]
kind(&self) -> ComdatKind480     fn kind(&self) -> ComdatKind {
481         unreachable!();
482     }
483 
484     #[inline]
symbol(&self) -> SymbolIndex485     fn symbol(&self) -> SymbolIndex {
486         unreachable!();
487     }
488 
489     #[inline]
name(&self) -> Result<&str>490     fn name(&self) -> Result<&str> {
491         unreachable!();
492     }
493 
494     #[inline]
sections(&self) -> Self::SectionIterator495     fn sections(&self) -> Self::SectionIterator {
496         unreachable!();
497     }
498 }
499 
500 /// An iterator over the sections in a COMDAT section group of a `PeFile32`.
501 pub type PeComdatSectionIterator32<'data, 'file, R = &'data [u8]> =
502     PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
503 /// An iterator over the sections in a COMDAT section group of a `PeFile64`.
504 pub type PeComdatSectionIterator64<'data, 'file, R = &'data [u8]> =
505     PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
506 
507 /// An iterator over the sections in a COMDAT section group of a `PeFile`.
508 #[derive(Debug)]
509 pub struct PeComdatSectionIterator<'data, 'file, Pe, R = &'data [u8]>
510 where
511     Pe: ImageNtHeaders,
512     R: ReadRef<'data>,
513 {
514     file: &'file PeFile<'data, Pe, R>,
515 }
516 
517 impl<'data, 'file, Pe, R> Iterator for PeComdatSectionIterator<'data, 'file, Pe, R>
518 where
519     Pe: ImageNtHeaders,
520     R: ReadRef<'data>,
521 {
522     type Item = SectionIndex;
523 
next(&mut self) -> Option<Self::Item>524     fn next(&mut self) -> Option<Self::Item> {
525         None
526     }
527 }
528 
529 impl pe::ImageDosHeader {
530     /// Read the DOS header.
531     ///
532     /// Also checks that the `e_magic` field in the header is valid.
parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self>533     pub fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
534         // DOS header comes first.
535         let dos_header = data
536             .read_at::<pe::ImageDosHeader>(0)
537             .read_error("Invalid DOS header size or alignment")?;
538         if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE {
539             return Err(Error("Invalid DOS magic"));
540         }
541         Ok(dos_header)
542     }
543 
544     /// Return the file offset of the nt_headers.
545     #[inline]
nt_headers_offset(&self) -> u32546     pub fn nt_headers_offset(&self) -> u32 {
547         self.e_lfanew.get(LE)
548     }
549 }
550 
551 /// Find the optional header and read the `optional_header.magic`.
552 ///
553 /// It can be useful to know this magic value before trying to
554 /// fully parse the NT headers.
optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16>555 pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16> {
556     let dos_header = pe::ImageDosHeader::parse(data)?;
557     // NT headers are at an offset specified in the DOS header.
558     let offset = dos_header.nt_headers_offset().into();
559     // It doesn't matter which NT header type is used for the purpose
560     // of reading the optional header magic.
561     let nt_headers = data
562         .read_at::<pe::ImageNtHeaders32>(offset)
563         .read_error("Invalid NT headers offset, size, or alignment")?;
564     if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
565         return Err(Error("Invalid PE magic"));
566     }
567     Ok(nt_headers.optional_header().magic())
568 }
569 
570 /// A trait for generic access to `ImageNtHeaders32` and `ImageNtHeaders64`.
571 #[allow(missing_docs)]
572 pub trait ImageNtHeaders: Debug + Pod {
573     type ImageOptionalHeader: ImageOptionalHeader;
574 
575     /// Return true if this type is a 64-bit header.
576     ///
577     /// This is a property of the type, not a value in the header data.
is_type_64(&self) -> bool578     fn is_type_64(&self) -> bool;
579 
580     /// Return true if the magic field in the optional header is valid.
is_valid_optional_magic(&self) -> bool581     fn is_valid_optional_magic(&self) -> bool;
582 
583     /// Return the signature
signature(&self) -> u32584     fn signature(&self) -> u32;
585 
586     /// Return the file header.
file_header(&self) -> &pe::ImageFileHeader587     fn file_header(&self) -> &pe::ImageFileHeader;
588 
589     /// Return the optional header.
optional_header(&self) -> &Self::ImageOptionalHeader590     fn optional_header(&self) -> &Self::ImageOptionalHeader;
591 
592     // Provided methods.
593 
594     /// Read the NT headers, including the data directories.
595     ///
596     /// `data` must be for the entire file.
597     ///
598     /// `offset` must be headers offset, which can be obtained from `ImageDosHeader::nt_headers_offset`.
599     /// It is updated to point after the optional header, which is where the section headers are located.
600     ///
601     /// Also checks that the `signature` and `magic` fields in the headers are valid.
parse<'data, R: ReadRef<'data>>( data: R, offset: &mut u64, ) -> read::Result<(&'data Self, &'data [pe::ImageDataDirectory])>602     fn parse<'data, R: ReadRef<'data>>(
603         data: R,
604         offset: &mut u64,
605     ) -> read::Result<(&'data Self, &'data [pe::ImageDataDirectory])> {
606         // Note that this does not include the data directories in the optional header.
607         let nt_headers = data
608             .read::<Self>(offset)
609             .read_error("Invalid PE headers offset or size")?;
610         if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
611             return Err(Error("Invalid PE magic"));
612         }
613         if !nt_headers.is_valid_optional_magic() {
614             return Err(Error("Invalid PE optional header magic"));
615         }
616 
617         // Read the rest of the optional header, and then read the data directories from that.
618         let optional_data_size =
619             u64::from(nt_headers.file_header().size_of_optional_header.get(LE))
620                 .checked_sub(mem::size_of::<Self::ImageOptionalHeader>() as u64)
621                 .read_error("PE optional header size is too small")?;
622         let mut optional_data = data
623             .read_bytes(offset, optional_data_size)
624             .read_error("Invalid PE optional header size")
625             .map(Bytes)?;
626         let data_directories = optional_data
627             .read_slice(nt_headers.optional_header().number_of_rva_and_sizes() as usize)
628             .read_error("Invalid PE number of RVA and sizes")?;
629 
630         Ok((nt_headers, data_directories))
631     }
632 
633     /// Read the section table.
634     ///
635     /// `data` must be for the entire file.
636     /// `offset` must be after the optional file header.
637     #[inline]
sections<'data, R: ReadRef<'data>>( &self, data: R, offset: u64, ) -> read::Result<SectionTable<'data>>638     fn sections<'data, R: ReadRef<'data>>(
639         &self,
640         data: R,
641         offset: u64,
642     ) -> read::Result<SectionTable<'data>> {
643         SectionTable::parse(self.file_header(), data, offset)
644     }
645 
646     /// Read the symbol table and string table.
647     ///
648     /// `data` must be the entire file data.
649     #[inline]
symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data, R>>650     fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data, R>> {
651         SymbolTable::parse(self.file_header(), data)
652     }
653 }
654 
655 /// A trait for generic access to `ImageOptionalHeader32` and `ImageOptionalHeader64`.
656 #[allow(missing_docs)]
657 pub trait ImageOptionalHeader: Debug + Pod {
658     // Standard fields.
magic(&self) -> u16659     fn magic(&self) -> u16;
major_linker_version(&self) -> u8660     fn major_linker_version(&self) -> u8;
minor_linker_version(&self) -> u8661     fn minor_linker_version(&self) -> u8;
size_of_code(&self) -> u32662     fn size_of_code(&self) -> u32;
size_of_initialized_data(&self) -> u32663     fn size_of_initialized_data(&self) -> u32;
size_of_uninitialized_data(&self) -> u32664     fn size_of_uninitialized_data(&self) -> u32;
address_of_entry_point(&self) -> u32665     fn address_of_entry_point(&self) -> u32;
base_of_code(&self) -> u32666     fn base_of_code(&self) -> u32;
667 
668     // NT additional fields.
image_base(&self) -> u64669     fn image_base(&self) -> u64;
section_alignment(&self) -> u32670     fn section_alignment(&self) -> u32;
file_alignment(&self) -> u32671     fn file_alignment(&self) -> u32;
major_operating_system_version(&self) -> u16672     fn major_operating_system_version(&self) -> u16;
minor_operating_system_version(&self) -> u16673     fn minor_operating_system_version(&self) -> u16;
major_image_version(&self) -> u16674     fn major_image_version(&self) -> u16;
minor_image_version(&self) -> u16675     fn minor_image_version(&self) -> u16;
major_subsystem_version(&self) -> u16676     fn major_subsystem_version(&self) -> u16;
minor_subsystem_version(&self) -> u16677     fn minor_subsystem_version(&self) -> u16;
win32_version_value(&self) -> u32678     fn win32_version_value(&self) -> u32;
size_of_image(&self) -> u32679     fn size_of_image(&self) -> u32;
size_of_headers(&self) -> u32680     fn size_of_headers(&self) -> u32;
check_sum(&self) -> u32681     fn check_sum(&self) -> u32;
subsystem(&self) -> u16682     fn subsystem(&self) -> u16;
dll_characteristics(&self) -> u16683     fn dll_characteristics(&self) -> u16;
size_of_stack_reserve(&self) -> u64684     fn size_of_stack_reserve(&self) -> u64;
size_of_stack_commit(&self) -> u64685     fn size_of_stack_commit(&self) -> u64;
size_of_heap_reserve(&self) -> u64686     fn size_of_heap_reserve(&self) -> u64;
size_of_heap_commit(&self) -> u64687     fn size_of_heap_commit(&self) -> u64;
loader_flags(&self) -> u32688     fn loader_flags(&self) -> u32;
number_of_rva_and_sizes(&self) -> u32689     fn number_of_rva_and_sizes(&self) -> u32;
690 }
691 
692 impl ImageNtHeaders for pe::ImageNtHeaders32 {
693     type ImageOptionalHeader = pe::ImageOptionalHeader32;
694 
695     #[inline]
is_type_64(&self) -> bool696     fn is_type_64(&self) -> bool {
697         false
698     }
699 
700     #[inline]
is_valid_optional_magic(&self) -> bool701     fn is_valid_optional_magic(&self) -> bool {
702         self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC
703     }
704 
705     #[inline]
signature(&self) -> u32706     fn signature(&self) -> u32 {
707         self.signature.get(LE)
708     }
709 
710     #[inline]
file_header(&self) -> &pe::ImageFileHeader711     fn file_header(&self) -> &pe::ImageFileHeader {
712         &self.file_header
713     }
714 
715     #[inline]
optional_header(&self) -> &Self::ImageOptionalHeader716     fn optional_header(&self) -> &Self::ImageOptionalHeader {
717         &self.optional_header
718     }
719 }
720 
721 impl ImageOptionalHeader for pe::ImageOptionalHeader32 {
722     #[inline]
magic(&self) -> u16723     fn magic(&self) -> u16 {
724         self.magic.get(LE)
725     }
726 
727     #[inline]
major_linker_version(&self) -> u8728     fn major_linker_version(&self) -> u8 {
729         self.major_linker_version
730     }
731 
732     #[inline]
minor_linker_version(&self) -> u8733     fn minor_linker_version(&self) -> u8 {
734         self.minor_linker_version
735     }
736 
737     #[inline]
size_of_code(&self) -> u32738     fn size_of_code(&self) -> u32 {
739         self.size_of_code.get(LE)
740     }
741 
742     #[inline]
size_of_initialized_data(&self) -> u32743     fn size_of_initialized_data(&self) -> u32 {
744         self.size_of_initialized_data.get(LE)
745     }
746 
747     #[inline]
size_of_uninitialized_data(&self) -> u32748     fn size_of_uninitialized_data(&self) -> u32 {
749         self.size_of_uninitialized_data.get(LE)
750     }
751 
752     #[inline]
address_of_entry_point(&self) -> u32753     fn address_of_entry_point(&self) -> u32 {
754         self.address_of_entry_point.get(LE)
755     }
756 
757     #[inline]
base_of_code(&self) -> u32758     fn base_of_code(&self) -> u32 {
759         self.base_of_code.get(LE)
760     }
761 
762     #[inline]
image_base(&self) -> u64763     fn image_base(&self) -> u64 {
764         self.image_base.get(LE).into()
765     }
766 
767     #[inline]
section_alignment(&self) -> u32768     fn section_alignment(&self) -> u32 {
769         self.section_alignment.get(LE)
770     }
771 
772     #[inline]
file_alignment(&self) -> u32773     fn file_alignment(&self) -> u32 {
774         self.file_alignment.get(LE)
775     }
776 
777     #[inline]
major_operating_system_version(&self) -> u16778     fn major_operating_system_version(&self) -> u16 {
779         self.major_operating_system_version.get(LE)
780     }
781 
782     #[inline]
minor_operating_system_version(&self) -> u16783     fn minor_operating_system_version(&self) -> u16 {
784         self.minor_operating_system_version.get(LE)
785     }
786 
787     #[inline]
major_image_version(&self) -> u16788     fn major_image_version(&self) -> u16 {
789         self.major_image_version.get(LE)
790     }
791 
792     #[inline]
minor_image_version(&self) -> u16793     fn minor_image_version(&self) -> u16 {
794         self.minor_image_version.get(LE)
795     }
796 
797     #[inline]
major_subsystem_version(&self) -> u16798     fn major_subsystem_version(&self) -> u16 {
799         self.major_subsystem_version.get(LE)
800     }
801 
802     #[inline]
minor_subsystem_version(&self) -> u16803     fn minor_subsystem_version(&self) -> u16 {
804         self.minor_subsystem_version.get(LE)
805     }
806 
807     #[inline]
win32_version_value(&self) -> u32808     fn win32_version_value(&self) -> u32 {
809         self.win32_version_value.get(LE)
810     }
811 
812     #[inline]
size_of_image(&self) -> u32813     fn size_of_image(&self) -> u32 {
814         self.size_of_image.get(LE)
815     }
816 
817     #[inline]
size_of_headers(&self) -> u32818     fn size_of_headers(&self) -> u32 {
819         self.size_of_headers.get(LE)
820     }
821 
822     #[inline]
check_sum(&self) -> u32823     fn check_sum(&self) -> u32 {
824         self.check_sum.get(LE)
825     }
826 
827     #[inline]
subsystem(&self) -> u16828     fn subsystem(&self) -> u16 {
829         self.subsystem.get(LE)
830     }
831 
832     #[inline]
dll_characteristics(&self) -> u16833     fn dll_characteristics(&self) -> u16 {
834         self.dll_characteristics.get(LE)
835     }
836 
837     #[inline]
size_of_stack_reserve(&self) -> u64838     fn size_of_stack_reserve(&self) -> u64 {
839         self.size_of_stack_reserve.get(LE).into()
840     }
841 
842     #[inline]
size_of_stack_commit(&self) -> u64843     fn size_of_stack_commit(&self) -> u64 {
844         self.size_of_stack_commit.get(LE).into()
845     }
846 
847     #[inline]
size_of_heap_reserve(&self) -> u64848     fn size_of_heap_reserve(&self) -> u64 {
849         self.size_of_heap_reserve.get(LE).into()
850     }
851 
852     #[inline]
size_of_heap_commit(&self) -> u64853     fn size_of_heap_commit(&self) -> u64 {
854         self.size_of_heap_commit.get(LE).into()
855     }
856 
857     #[inline]
loader_flags(&self) -> u32858     fn loader_flags(&self) -> u32 {
859         self.loader_flags.get(LE)
860     }
861 
862     #[inline]
number_of_rva_and_sizes(&self) -> u32863     fn number_of_rva_and_sizes(&self) -> u32 {
864         self.number_of_rva_and_sizes.get(LE)
865     }
866 }
867 
868 impl ImageNtHeaders for pe::ImageNtHeaders64 {
869     type ImageOptionalHeader = pe::ImageOptionalHeader64;
870 
871     #[inline]
is_type_64(&self) -> bool872     fn is_type_64(&self) -> bool {
873         true
874     }
875 
876     #[inline]
is_valid_optional_magic(&self) -> bool877     fn is_valid_optional_magic(&self) -> bool {
878         self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC
879     }
880 
881     #[inline]
signature(&self) -> u32882     fn signature(&self) -> u32 {
883         self.signature.get(LE)
884     }
885 
886     #[inline]
file_header(&self) -> &pe::ImageFileHeader887     fn file_header(&self) -> &pe::ImageFileHeader {
888         &self.file_header
889     }
890 
891     #[inline]
optional_header(&self) -> &Self::ImageOptionalHeader892     fn optional_header(&self) -> &Self::ImageOptionalHeader {
893         &self.optional_header
894     }
895 }
896 
897 impl ImageOptionalHeader for pe::ImageOptionalHeader64 {
898     #[inline]
magic(&self) -> u16899     fn magic(&self) -> u16 {
900         self.magic.get(LE)
901     }
902 
903     #[inline]
major_linker_version(&self) -> u8904     fn major_linker_version(&self) -> u8 {
905         self.major_linker_version
906     }
907 
908     #[inline]
minor_linker_version(&self) -> u8909     fn minor_linker_version(&self) -> u8 {
910         self.minor_linker_version
911     }
912 
913     #[inline]
size_of_code(&self) -> u32914     fn size_of_code(&self) -> u32 {
915         self.size_of_code.get(LE)
916     }
917 
918     #[inline]
size_of_initialized_data(&self) -> u32919     fn size_of_initialized_data(&self) -> u32 {
920         self.size_of_initialized_data.get(LE)
921     }
922 
923     #[inline]
size_of_uninitialized_data(&self) -> u32924     fn size_of_uninitialized_data(&self) -> u32 {
925         self.size_of_uninitialized_data.get(LE)
926     }
927 
928     #[inline]
address_of_entry_point(&self) -> u32929     fn address_of_entry_point(&self) -> u32 {
930         self.address_of_entry_point.get(LE)
931     }
932 
933     #[inline]
base_of_code(&self) -> u32934     fn base_of_code(&self) -> u32 {
935         self.base_of_code.get(LE)
936     }
937 
938     #[inline]
image_base(&self) -> u64939     fn image_base(&self) -> u64 {
940         self.image_base.get(LE)
941     }
942 
943     #[inline]
section_alignment(&self) -> u32944     fn section_alignment(&self) -> u32 {
945         self.section_alignment.get(LE)
946     }
947 
948     #[inline]
file_alignment(&self) -> u32949     fn file_alignment(&self) -> u32 {
950         self.file_alignment.get(LE)
951     }
952 
953     #[inline]
major_operating_system_version(&self) -> u16954     fn major_operating_system_version(&self) -> u16 {
955         self.major_operating_system_version.get(LE)
956     }
957 
958     #[inline]
minor_operating_system_version(&self) -> u16959     fn minor_operating_system_version(&self) -> u16 {
960         self.minor_operating_system_version.get(LE)
961     }
962 
963     #[inline]
major_image_version(&self) -> u16964     fn major_image_version(&self) -> u16 {
965         self.major_image_version.get(LE)
966     }
967 
968     #[inline]
minor_image_version(&self) -> u16969     fn minor_image_version(&self) -> u16 {
970         self.minor_image_version.get(LE)
971     }
972 
973     #[inline]
major_subsystem_version(&self) -> u16974     fn major_subsystem_version(&self) -> u16 {
975         self.major_subsystem_version.get(LE)
976     }
977 
978     #[inline]
minor_subsystem_version(&self) -> u16979     fn minor_subsystem_version(&self) -> u16 {
980         self.minor_subsystem_version.get(LE)
981     }
982 
983     #[inline]
win32_version_value(&self) -> u32984     fn win32_version_value(&self) -> u32 {
985         self.win32_version_value.get(LE)
986     }
987 
988     #[inline]
size_of_image(&self) -> u32989     fn size_of_image(&self) -> u32 {
990         self.size_of_image.get(LE)
991     }
992 
993     #[inline]
size_of_headers(&self) -> u32994     fn size_of_headers(&self) -> u32 {
995         self.size_of_headers.get(LE)
996     }
997 
998     #[inline]
check_sum(&self) -> u32999     fn check_sum(&self) -> u32 {
1000         self.check_sum.get(LE)
1001     }
1002 
1003     #[inline]
subsystem(&self) -> u161004     fn subsystem(&self) -> u16 {
1005         self.subsystem.get(LE)
1006     }
1007 
1008     #[inline]
dll_characteristics(&self) -> u161009     fn dll_characteristics(&self) -> u16 {
1010         self.dll_characteristics.get(LE)
1011     }
1012 
1013     #[inline]
size_of_stack_reserve(&self) -> u641014     fn size_of_stack_reserve(&self) -> u64 {
1015         self.size_of_stack_reserve.get(LE)
1016     }
1017 
1018     #[inline]
size_of_stack_commit(&self) -> u641019     fn size_of_stack_commit(&self) -> u64 {
1020         self.size_of_stack_commit.get(LE)
1021     }
1022 
1023     #[inline]
size_of_heap_reserve(&self) -> u641024     fn size_of_heap_reserve(&self) -> u64 {
1025         self.size_of_heap_reserve.get(LE)
1026     }
1027 
1028     #[inline]
size_of_heap_commit(&self) -> u641029     fn size_of_heap_commit(&self) -> u64 {
1030         self.size_of_heap_commit.get(LE)
1031     }
1032 
1033     #[inline]
loader_flags(&self) -> u321034     fn loader_flags(&self) -> u32 {
1035         self.loader_flags.get(LE)
1036     }
1037 
1038     #[inline]
number_of_rva_and_sizes(&self) -> u321039     fn number_of_rva_and_sizes(&self) -> u32 {
1040         self.number_of_rva_and_sizes.get(LE)
1041     }
1042 }
1043 
1044 impl pe::ImageDataDirectory {
1045     /// Get the data referenced by this directory entry.
data<'data, R: ReadRef<'data>>( &self, data: R, sections: &SectionTable<'data>, ) -> Result<&'data [u8]>1046     pub fn data<'data, R: ReadRef<'data>>(
1047         &self,
1048         data: R,
1049         sections: &SectionTable<'data>,
1050     ) -> Result<&'data [u8]> {
1051         sections
1052             .pe_data_at(data, self.virtual_address.get(LE))
1053             .read_error("Invalid data dir virtual address or size")?
1054             .get(..self.size.get(LE) as usize)
1055             .read_error("Invalid data dir size")
1056     }
1057 }
1058