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>,
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 
data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory>78     fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
79         self.data_directories
80             .get(id)
81             .filter(|d| d.size.get(LE) != 0)
82     }
83 
data_at(&self, va: u32) -> Option<Bytes<'data>>84     fn data_at(&self, va: u32) -> Option<Bytes<'data>> {
85         self.common.sections.pe_data_at(self.data, va).map(Bytes)
86     }
87 }
88 
89 impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R>
90 where
91     Pe: ImageNtHeaders,
92     R: ReadRef<'data>,
93 {
94 }
95 
96 impl<'data, 'file, Pe, R> Object<'data, 'file> for PeFile<'data, Pe, R>
97 where
98     'data: 'file,
99     Pe: ImageNtHeaders,
100     R: 'file + ReadRef<'data>,
101 {
102     type Segment = PeSegment<'data, 'file, Pe, R>;
103     type SegmentIterator = PeSegmentIterator<'data, 'file, Pe, R>;
104     type Section = PeSection<'data, 'file, Pe, R>;
105     type SectionIterator = PeSectionIterator<'data, 'file, Pe, R>;
106     type Comdat = PeComdat<'data, 'file, Pe, R>;
107     type ComdatIterator = PeComdatIterator<'data, 'file, Pe, R>;
108     type Symbol = CoffSymbol<'data, 'file>;
109     type SymbolIterator = CoffSymbolIterator<'data, 'file>;
110     type SymbolTable = CoffSymbolTable<'data, 'file>;
111     type DynamicRelocationIterator = NoDynamicRelocationIterator;
112 
architecture(&self) -> Architecture113     fn architecture(&self) -> Architecture {
114         match self.nt_headers.file_header().machine.get(LE) {
115             pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm,
116             pe::IMAGE_FILE_MACHINE_ARM64 => Architecture::Aarch64,
117             pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
118             pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
119             _ => Architecture::Unknown,
120         }
121     }
122 
123     #[inline]
is_little_endian(&self) -> bool124     fn is_little_endian(&self) -> bool {
125         // Only little endian is supported.
126         true
127     }
128 
129     #[inline]
is_64(&self) -> bool130     fn is_64(&self) -> bool {
131         self.nt_headers.is_type_64()
132     }
133 
segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R>134     fn segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R> {
135         PeSegmentIterator {
136             file: self,
137             iter: self.common.sections.iter(),
138         }
139     }
140 
section_by_name(&'file self, section_name: &str) -> Option<PeSection<'data, 'file, Pe, R>>141     fn section_by_name(&'file self, section_name: &str) -> Option<PeSection<'data, 'file, Pe, R>> {
142         self.common
143             .sections
144             .section_by_name(self.common.symbols.strings(), section_name.as_bytes())
145             .map(|(index, section)| PeSection {
146                 file: self,
147                 index: SectionIndex(index),
148                 section,
149             })
150     }
151 
section_by_index( &'file self, index: SectionIndex, ) -> Result<PeSection<'data, 'file, Pe, R>>152     fn section_by_index(
153         &'file self,
154         index: SectionIndex,
155     ) -> Result<PeSection<'data, 'file, Pe, R>> {
156         let section = self.common.sections.section(index.0)?;
157         Ok(PeSection {
158             file: self,
159             index,
160             section,
161         })
162     }
163 
sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R>164     fn sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R> {
165         PeSectionIterator {
166             file: self,
167             iter: self.common.sections.iter().enumerate(),
168         }
169     }
170 
comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R>171     fn comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R> {
172         PeComdatIterator { file: self }
173     }
174 
symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file>>175     fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file>> {
176         let symbol = self.common.symbols.symbol(index.0)?;
177         Ok(CoffSymbol {
178             file: &self.common,
179             index,
180             symbol,
181         })
182     }
183 
symbols(&'file self) -> CoffSymbolIterator<'data, 'file>184     fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
185         CoffSymbolIterator {
186             file: &self.common,
187             index: 0,
188         }
189     }
190 
symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>>191     fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
192         Some(CoffSymbolTable { file: &self.common })
193     }
194 
dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file>195     fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
196         CoffSymbolIterator {
197             file: &self.common,
198             // Hack: don't return any.
199             index: self.common.symbols.len(),
200         }
201     }
202 
dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>>203     fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file>> {
204         None
205     }
206 
dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator>207     fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> {
208         None
209     }
210 
imports(&self) -> Result<Vec<Import<'data>>>211     fn imports(&self) -> Result<Vec<Import<'data>>> {
212         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_IMPORT) {
213             Some(data_dir) => data_dir,
214             None => return Ok(Vec::new()),
215         };
216         let mut import_descriptors = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
217         let mut imports = Vec::new();
218         loop {
219             let import_desc = import_descriptors
220                 .read::<pe::ImageImportDescriptor>()
221                 .read_error("Missing PE null import descriptor")?;
222             if import_desc.original_first_thunk.get(LE) == 0 {
223                 break;
224             }
225 
226             let library = self
227                 .data_at(import_desc.name.get(LE))
228                 .read_error("Invalid PE import descriptor name")?
229                 .read_string()
230                 .read_error("Invalid PE import descriptor name")?;
231 
232             let thunk_va = import_desc.original_first_thunk.get(LE);
233             let mut thunk_data = self
234                 .data_at(thunk_va)
235                 .read_error("Invalid PE import thunk address")?;
236             loop {
237                 let hint_name = if self.is_64() {
238                     let thunk = thunk_data
239                         .read::<U64<_>>()
240                         .read_error("Missing PE null import thunk")?
241                         .get(LE);
242                     if thunk == 0 {
243                         break;
244                     }
245                     if thunk & pe::IMAGE_ORDINAL_FLAG64 != 0 {
246                         // TODO: handle import by ordinal
247                         continue;
248                     }
249                     thunk as u32
250                 } else {
251                     let thunk = thunk_data
252                         .read::<U32<_>>()
253                         .read_error("Missing PE null import thunk")?
254                         .get(LE);
255                     if thunk == 0 {
256                         break;
257                     }
258                     if thunk & pe::IMAGE_ORDINAL_FLAG32 != 0 {
259                         // TODO: handle import by ordinal
260                         continue;
261                     }
262                     thunk
263                 };
264                 let name = self
265                     .data_at(hint_name)
266                     .read_error("Invalid PE import thunk name")?
267                     .read_string_at(2)
268                     .read_error("Invalid PE import thunk name")?;
269 
270                 imports.push(Import {
271                     name: ByteString(name),
272                     library: ByteString(library),
273                 });
274             }
275         }
276         Ok(imports)
277     }
278 
exports(&self) -> Result<Vec<Export<'data>>>279     fn exports(&self) -> Result<Vec<Export<'data>>> {
280         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) {
281             Some(data_dir) => data_dir,
282             None => return Ok(Vec::new()),
283         };
284         let export_va = data_dir.virtual_address.get(LE);
285         let export_size = data_dir.size.get(LE);
286         let export_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
287         let export_dir = export_data
288             .read_at::<pe::ImageExportDirectory>(0)
289             .read_error("Invalid PE export dir size")?;
290         let addresses = export_data
291             .read_slice_at::<U32Bytes<_>>(
292                 export_dir
293                     .address_of_functions
294                     .get(LE)
295                     .wrapping_sub(export_va) as usize,
296                 export_dir.number_of_functions.get(LE) as usize,
297             )
298             .read_error("Invalid PE export address table")?;
299         let number = export_dir.number_of_names.get(LE) as usize;
300         let names = export_data
301             .read_slice_at::<U32Bytes<_>>(
302                 export_dir.address_of_names.get(LE).wrapping_sub(export_va) as usize,
303                 number,
304             )
305             .read_error("Invalid PE export name table")?;
306         let ordinals = export_data
307             .read_slice_at::<U16Bytes<_>>(
308                 export_dir
309                     .address_of_name_ordinals
310                     .get(LE)
311                     .wrapping_sub(export_va) as usize,
312                 number,
313             )
314             .read_error("Invalid PE export ordinal table")?;
315 
316         let mut exports = Vec::new();
317         for (name, ordinal) in names.iter().zip(ordinals.iter()) {
318             let name = export_data
319                 .read_string_at(name.get(LE).wrapping_sub(export_va) as usize)
320                 .read_error("Invalid PE export name entry")?;
321             let address = addresses
322                 .get(ordinal.get(LE) as usize)
323                 .read_error("Invalid PE export ordinal entry")?
324                 .get(LE);
325             // Check for export address (vs forwarder address).
326             if address < export_va || (address - export_va) >= export_size {
327                 exports.push(Export {
328                     name: ByteString(name),
329                     address: self.common.image_base.wrapping_add(address.into()),
330                 })
331             }
332         }
333         Ok(exports)
334     }
335 
pdb_info(&self) -> Result<Option<CodeView>>336     fn pdb_info(&self) -> Result<Option<CodeView>> {
337         let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_DEBUG) {
338             Some(data_dir) => data_dir,
339             None => return Ok(None),
340         };
341         let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
342         let debug_dir = debug_data
343             .read_at::<pe::ImageDebugDirectory>(0)
344             .read_error("Invalid PE debug dir size")?;
345 
346         if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
347             return Ok(None);
348         }
349 
350         let info = self
351             .data
352             .read_slice_at::<u8>(
353                 debug_dir.pointer_to_raw_data.get(LE) as u64,
354                 debug_dir.size_of_data.get(LE) as usize,
355             )
356             .read_error("Invalid CodeView Info address")?;
357 
358         let mut info = Bytes(info);
359 
360         let sig = info
361             .read_bytes(4)
362             .read_error("Invalid CodeView signature")?;
363         if sig.0 != b"RSDS" {
364             return Ok(None);
365         }
366 
367         let guid: [u8; 16] = info
368             .read_bytes(16)
369             .read_error("Invalid CodeView GUID")?
370             .0
371             .try_into()
372             .unwrap();
373 
374         let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
375 
376         let path = info
377             .read_string()
378             .read_error("Invalid CodeView file path")?;
379 
380         Ok(Some(CodeView {
381             path: ByteString(path),
382             guid,
383             age: age.get(LE),
384         }))
385     }
386 
has_debug_symbols(&self) -> bool387     fn has_debug_symbols(&self) -> bool {
388         self.section_by_name(".debug_info").is_some()
389     }
390 
relative_address_base(&self) -> u64391     fn relative_address_base(&self) -> u64 {
392         self.common.image_base
393     }
394 
entry(&self) -> u64395     fn entry(&self) -> u64 {
396         u64::from(self.nt_headers.optional_header().address_of_entry_point())
397             .wrapping_add(self.common.image_base)
398     }
399 
flags(&self) -> FileFlags400     fn flags(&self) -> FileFlags {
401         FileFlags::Coff {
402             characteristics: self.nt_headers.file_header().characteristics.get(LE),
403         }
404     }
405 }
406 
407 /// An iterator over the COMDAT section groups of a `PeFile32`.
408 pub type PeComdatIterator32<'data, 'file, R = &'data [u8]> =
409     PeComdatIterator<'data, 'file, pe::ImageNtHeaders32, R>;
410 /// An iterator over the COMDAT section groups of a `PeFile64`.
411 pub type PeComdatIterator64<'data, 'file, R = &'data [u8]> =
412     PeComdatIterator<'data, 'file, pe::ImageNtHeaders64, R>;
413 
414 /// An iterator over the COMDAT section groups of a `PeFile`.
415 #[derive(Debug)]
416 pub struct PeComdatIterator<'data, 'file, Pe, R = &'data [u8]>
417 where
418     Pe: ImageNtHeaders,
419     R: ReadRef<'data>,
420 {
421     file: &'file PeFile<'data, Pe, R>,
422 }
423 
424 impl<'data, 'file, Pe, R> Iterator for PeComdatIterator<'data, 'file, Pe, R>
425 where
426     Pe: ImageNtHeaders,
427     R: ReadRef<'data>,
428 {
429     type Item = PeComdat<'data, 'file, Pe, R>;
430 
431     #[inline]
next(&mut self) -> Option<Self::Item>432     fn next(&mut self) -> Option<Self::Item> {
433         None
434     }
435 }
436 
437 /// A COMDAT section group of a `PeFile32`.
438 pub type PeComdat32<'data, 'file, R = &'data [u8]> =
439     PeComdat<'data, 'file, pe::ImageNtHeaders32, R>;
440 /// A COMDAT section group of a `PeFile64`.
441 pub type PeComdat64<'data, 'file, R = &'data [u8]> =
442     PeComdat<'data, 'file, pe::ImageNtHeaders64, R>;
443 
444 /// A COMDAT section group of a `PeFile`.
445 #[derive(Debug)]
446 pub struct PeComdat<'data, 'file, Pe, R = &'data [u8]>
447 where
448     Pe: ImageNtHeaders,
449     R: ReadRef<'data>,
450 {
451     file: &'file PeFile<'data, Pe, R>,
452 }
453 
454 impl<'data, 'file, Pe, R> read::private::Sealed for PeComdat<'data, 'file, Pe, R>
455 where
456     Pe: ImageNtHeaders,
457     R: ReadRef<'data>,
458 {
459 }
460 
461 impl<'data, 'file, Pe, R> ObjectComdat<'data> for PeComdat<'data, 'file, Pe, R>
462 where
463     Pe: ImageNtHeaders,
464     R: ReadRef<'data>,
465 {
466     type SectionIterator = PeComdatSectionIterator<'data, 'file, Pe, R>;
467 
468     #[inline]
kind(&self) -> ComdatKind469     fn kind(&self) -> ComdatKind {
470         unreachable!();
471     }
472 
473     #[inline]
symbol(&self) -> SymbolIndex474     fn symbol(&self) -> SymbolIndex {
475         unreachable!();
476     }
477 
478     #[inline]
name(&self) -> Result<&str>479     fn name(&self) -> Result<&str> {
480         unreachable!();
481     }
482 
483     #[inline]
sections(&self) -> Self::SectionIterator484     fn sections(&self) -> Self::SectionIterator {
485         unreachable!();
486     }
487 }
488 
489 /// An iterator over the sections in a COMDAT section group of a `PeFile32`.
490 pub type PeComdatSectionIterator32<'data, 'file, R = &'data [u8]> =
491     PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
492 /// An iterator over the sections in a COMDAT section group of a `PeFile64`.
493 pub type PeComdatSectionIterator64<'data, 'file, R = &'data [u8]> =
494     PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
495 
496 /// An iterator over the sections in a COMDAT section group of a `PeFile`.
497 #[derive(Debug)]
498 pub struct PeComdatSectionIterator<'data, 'file, Pe, R = &'data [u8]>
499 where
500     Pe: ImageNtHeaders,
501     R: ReadRef<'data>,
502 {
503     file: &'file PeFile<'data, Pe, R>,
504 }
505 
506 impl<'data, 'file, Pe, R> Iterator for PeComdatSectionIterator<'data, 'file, Pe, R>
507 where
508     Pe: ImageNtHeaders,
509     R: ReadRef<'data>,
510 {
511     type Item = SectionIndex;
512 
next(&mut self) -> Option<Self::Item>513     fn next(&mut self) -> Option<Self::Item> {
514         None
515     }
516 }
517 
518 impl pe::ImageDosHeader {
519     /// Read the DOS header.
520     ///
521     /// Also checks that the `e_magic` field in the header is valid.
parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self>522     pub fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
523         // DOS header comes first.
524         let dos_header = data
525             .read_at::<pe::ImageDosHeader>(0)
526             .read_error("Invalid DOS header size or alignment")?;
527         if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE {
528             return Err(Error("Invalid DOS magic"));
529         }
530         Ok(dos_header)
531     }
532 
533     /// Return the file offset of the nt_headers.
534     #[inline]
nt_headers_offset(&self) -> u32535     pub fn nt_headers_offset(&self) -> u32 {
536         self.e_lfanew.get(LE)
537     }
538 }
539 
540 /// Find the optional header and read the `optional_header.magic`.
541 ///
542 /// It can be useful to know this magic value before trying to
543 /// fully parse the NT headers.
optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16>544 pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16> {
545     let dos_header = pe::ImageDosHeader::parse(data)?;
546     // NT headers are at an offset specified in the DOS header.
547     let offset = dos_header.nt_headers_offset().into();
548     // It doesn't matter which NT header type is used for the purpose
549     // of reading the optional header magic.
550     let nt_headers = data
551         .read_at::<pe::ImageNtHeaders32>(offset)
552         .read_error("Invalid NT headers offset, size, or alignment")?;
553     if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
554         return Err(Error("Invalid PE magic"));
555     }
556     Ok(nt_headers.optional_header().magic())
557 }
558 
559 /// A trait for generic access to `ImageNtHeaders32` and `ImageNtHeaders64`.
560 #[allow(missing_docs)]
561 pub trait ImageNtHeaders: Debug + Pod {
562     type ImageOptionalHeader: ImageOptionalHeader;
563 
564     /// Return true if this type is a 64-bit header.
565     ///
566     /// This is a property of the type, not a value in the header data.
is_type_64(&self) -> bool567     fn is_type_64(&self) -> bool;
568 
569     /// Return true if the magic field in the optional header is valid.
is_valid_optional_magic(&self) -> bool570     fn is_valid_optional_magic(&self) -> bool;
571 
572     /// Return the signature
signature(&self) -> u32573     fn signature(&self) -> u32;
574 
575     /// Return the file header.
file_header(&self) -> &pe::ImageFileHeader576     fn file_header(&self) -> &pe::ImageFileHeader;
577 
578     /// Return the optional header.
optional_header(&self) -> &Self::ImageOptionalHeader579     fn optional_header(&self) -> &Self::ImageOptionalHeader;
580 
581     // Provided methods.
582 
583     /// Read the NT headers, including the data directories.
584     ///
585     /// `data` must be for the entire file.
586     ///
587     /// `offset` must be headers offset, which can be obtained from `ImageDosHeader::nt_headers_offset`.
588     /// It is updated to point after the optional header, which is where the section headers are located.
589     ///
590     /// 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])>591     fn parse<'data, R: ReadRef<'data>>(
592         data: R,
593         offset: &mut u64,
594     ) -> read::Result<(&'data Self, &'data [pe::ImageDataDirectory])> {
595         // Note that this does not include the data directories in the optional header.
596         let nt_headers = data
597             .read::<Self>(offset)
598             .read_error("Invalid PE headers offset or size")?;
599         if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
600             return Err(Error("Invalid PE magic"));
601         }
602         if !nt_headers.is_valid_optional_magic() {
603             return Err(Error("Invalid PE optional header magic"));
604         }
605 
606         // Read the rest of the optional header, and then read the data directories from that.
607         let optional_data_size =
608             u64::from(nt_headers.file_header().size_of_optional_header.get(LE))
609                 .checked_sub(mem::size_of::<Self::ImageOptionalHeader>() as u64)
610                 .read_error("PE optional header size is too small")?;
611         let mut optional_data = data
612             .read_bytes(offset, optional_data_size)
613             .read_error("Invalid PE optional header size")
614             .map(Bytes)?;
615         let data_directories = optional_data
616             .read_slice(nt_headers.optional_header().number_of_rva_and_sizes() as usize)
617             .read_error("Invalid PE number of RVA and sizes")?;
618 
619         Ok((nt_headers, data_directories))
620     }
621 
622     /// Read the section table.
623     ///
624     /// `data` must be for the entire file.
625     /// `offset` must be after the optional file header.
626     #[inline]
sections<'data, R: ReadRef<'data>>( &self, data: R, offset: u64, ) -> read::Result<SectionTable<'data>>627     fn sections<'data, R: ReadRef<'data>>(
628         &self,
629         data: R,
630         offset: u64,
631     ) -> read::Result<SectionTable<'data>> {
632         SectionTable::parse(self.file_header(), data, offset)
633     }
634 
635     /// Read the symbol table and string table.
636     ///
637     /// `data` must be the entire file data.
638     #[inline]
symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data>>639     fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data>> {
640         SymbolTable::parse(self.file_header(), data)
641     }
642 }
643 
644 /// A trait for generic access to `ImageOptionalHeader32` and `ImageOptionalHeader64`.
645 #[allow(missing_docs)]
646 pub trait ImageOptionalHeader: Debug + Pod {
647     // Standard fields.
magic(&self) -> u16648     fn magic(&self) -> u16;
major_linker_version(&self) -> u8649     fn major_linker_version(&self) -> u8;
minor_linker_version(&self) -> u8650     fn minor_linker_version(&self) -> u8;
size_of_code(&self) -> u32651     fn size_of_code(&self) -> u32;
size_of_initialized_data(&self) -> u32652     fn size_of_initialized_data(&self) -> u32;
size_of_uninitialized_data(&self) -> u32653     fn size_of_uninitialized_data(&self) -> u32;
address_of_entry_point(&self) -> u32654     fn address_of_entry_point(&self) -> u32;
base_of_code(&self) -> u32655     fn base_of_code(&self) -> u32;
656 
657     // NT additional fields.
image_base(&self) -> u64658     fn image_base(&self) -> u64;
section_alignment(&self) -> u32659     fn section_alignment(&self) -> u32;
file_alignment(&self) -> u32660     fn file_alignment(&self) -> u32;
major_operating_system_version(&self) -> u16661     fn major_operating_system_version(&self) -> u16;
minor_operating_system_version(&self) -> u16662     fn minor_operating_system_version(&self) -> u16;
major_image_version(&self) -> u16663     fn major_image_version(&self) -> u16;
minor_image_version(&self) -> u16664     fn minor_image_version(&self) -> u16;
major_subsystem_version(&self) -> u16665     fn major_subsystem_version(&self) -> u16;
minor_subsystem_version(&self) -> u16666     fn minor_subsystem_version(&self) -> u16;
win32_version_value(&self) -> u32667     fn win32_version_value(&self) -> u32;
size_of_image(&self) -> u32668     fn size_of_image(&self) -> u32;
size_of_headers(&self) -> u32669     fn size_of_headers(&self) -> u32;
check_sum(&self) -> u32670     fn check_sum(&self) -> u32;
subsystem(&self) -> u16671     fn subsystem(&self) -> u16;
dll_characteristics(&self) -> u16672     fn dll_characteristics(&self) -> u16;
size_of_stack_reserve(&self) -> u64673     fn size_of_stack_reserve(&self) -> u64;
size_of_stack_commit(&self) -> u64674     fn size_of_stack_commit(&self) -> u64;
size_of_heap_reserve(&self) -> u64675     fn size_of_heap_reserve(&self) -> u64;
size_of_heap_commit(&self) -> u64676     fn size_of_heap_commit(&self) -> u64;
loader_flags(&self) -> u32677     fn loader_flags(&self) -> u32;
number_of_rva_and_sizes(&self) -> u32678     fn number_of_rva_and_sizes(&self) -> u32;
679 }
680 
681 impl ImageNtHeaders for pe::ImageNtHeaders32 {
682     type ImageOptionalHeader = pe::ImageOptionalHeader32;
683 
684     #[inline]
is_type_64(&self) -> bool685     fn is_type_64(&self) -> bool {
686         false
687     }
688 
689     #[inline]
is_valid_optional_magic(&self) -> bool690     fn is_valid_optional_magic(&self) -> bool {
691         self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC
692     }
693 
694     #[inline]
signature(&self) -> u32695     fn signature(&self) -> u32 {
696         self.signature.get(LE)
697     }
698 
699     #[inline]
file_header(&self) -> &pe::ImageFileHeader700     fn file_header(&self) -> &pe::ImageFileHeader {
701         &self.file_header
702     }
703 
704     #[inline]
optional_header(&self) -> &Self::ImageOptionalHeader705     fn optional_header(&self) -> &Self::ImageOptionalHeader {
706         &self.optional_header
707     }
708 }
709 
710 impl ImageOptionalHeader for pe::ImageOptionalHeader32 {
711     #[inline]
magic(&self) -> u16712     fn magic(&self) -> u16 {
713         self.magic.get(LE)
714     }
715 
716     #[inline]
major_linker_version(&self) -> u8717     fn major_linker_version(&self) -> u8 {
718         self.major_linker_version
719     }
720 
721     #[inline]
minor_linker_version(&self) -> u8722     fn minor_linker_version(&self) -> u8 {
723         self.minor_linker_version
724     }
725 
726     #[inline]
size_of_code(&self) -> u32727     fn size_of_code(&self) -> u32 {
728         self.size_of_code.get(LE)
729     }
730 
731     #[inline]
size_of_initialized_data(&self) -> u32732     fn size_of_initialized_data(&self) -> u32 {
733         self.size_of_initialized_data.get(LE)
734     }
735 
736     #[inline]
size_of_uninitialized_data(&self) -> u32737     fn size_of_uninitialized_data(&self) -> u32 {
738         self.size_of_uninitialized_data.get(LE)
739     }
740 
741     #[inline]
address_of_entry_point(&self) -> u32742     fn address_of_entry_point(&self) -> u32 {
743         self.address_of_entry_point.get(LE)
744     }
745 
746     #[inline]
base_of_code(&self) -> u32747     fn base_of_code(&self) -> u32 {
748         self.base_of_code.get(LE)
749     }
750 
751     #[inline]
image_base(&self) -> u64752     fn image_base(&self) -> u64 {
753         self.image_base.get(LE).into()
754     }
755 
756     #[inline]
section_alignment(&self) -> u32757     fn section_alignment(&self) -> u32 {
758         self.section_alignment.get(LE)
759     }
760 
761     #[inline]
file_alignment(&self) -> u32762     fn file_alignment(&self) -> u32 {
763         self.file_alignment.get(LE)
764     }
765 
766     #[inline]
major_operating_system_version(&self) -> u16767     fn major_operating_system_version(&self) -> u16 {
768         self.major_operating_system_version.get(LE)
769     }
770 
771     #[inline]
minor_operating_system_version(&self) -> u16772     fn minor_operating_system_version(&self) -> u16 {
773         self.minor_operating_system_version.get(LE)
774     }
775 
776     #[inline]
major_image_version(&self) -> u16777     fn major_image_version(&self) -> u16 {
778         self.major_image_version.get(LE)
779     }
780 
781     #[inline]
minor_image_version(&self) -> u16782     fn minor_image_version(&self) -> u16 {
783         self.minor_image_version.get(LE)
784     }
785 
786     #[inline]
major_subsystem_version(&self) -> u16787     fn major_subsystem_version(&self) -> u16 {
788         self.major_subsystem_version.get(LE)
789     }
790 
791     #[inline]
minor_subsystem_version(&self) -> u16792     fn minor_subsystem_version(&self) -> u16 {
793         self.minor_subsystem_version.get(LE)
794     }
795 
796     #[inline]
win32_version_value(&self) -> u32797     fn win32_version_value(&self) -> u32 {
798         self.win32_version_value.get(LE)
799     }
800 
801     #[inline]
size_of_image(&self) -> u32802     fn size_of_image(&self) -> u32 {
803         self.size_of_image.get(LE)
804     }
805 
806     #[inline]
size_of_headers(&self) -> u32807     fn size_of_headers(&self) -> u32 {
808         self.size_of_headers.get(LE)
809     }
810 
811     #[inline]
check_sum(&self) -> u32812     fn check_sum(&self) -> u32 {
813         self.check_sum.get(LE)
814     }
815 
816     #[inline]
subsystem(&self) -> u16817     fn subsystem(&self) -> u16 {
818         self.subsystem.get(LE)
819     }
820 
821     #[inline]
dll_characteristics(&self) -> u16822     fn dll_characteristics(&self) -> u16 {
823         self.dll_characteristics.get(LE)
824     }
825 
826     #[inline]
size_of_stack_reserve(&self) -> u64827     fn size_of_stack_reserve(&self) -> u64 {
828         self.size_of_stack_reserve.get(LE).into()
829     }
830 
831     #[inline]
size_of_stack_commit(&self) -> u64832     fn size_of_stack_commit(&self) -> u64 {
833         self.size_of_stack_commit.get(LE).into()
834     }
835 
836     #[inline]
size_of_heap_reserve(&self) -> u64837     fn size_of_heap_reserve(&self) -> u64 {
838         self.size_of_heap_reserve.get(LE).into()
839     }
840 
841     #[inline]
size_of_heap_commit(&self) -> u64842     fn size_of_heap_commit(&self) -> u64 {
843         self.size_of_heap_commit.get(LE).into()
844     }
845 
846     #[inline]
loader_flags(&self) -> u32847     fn loader_flags(&self) -> u32 {
848         self.loader_flags.get(LE)
849     }
850 
851     #[inline]
number_of_rva_and_sizes(&self) -> u32852     fn number_of_rva_and_sizes(&self) -> u32 {
853         self.number_of_rva_and_sizes.get(LE)
854     }
855 }
856 
857 impl ImageNtHeaders for pe::ImageNtHeaders64 {
858     type ImageOptionalHeader = pe::ImageOptionalHeader64;
859 
860     #[inline]
is_type_64(&self) -> bool861     fn is_type_64(&self) -> bool {
862         true
863     }
864 
865     #[inline]
is_valid_optional_magic(&self) -> bool866     fn is_valid_optional_magic(&self) -> bool {
867         self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC
868     }
869 
870     #[inline]
signature(&self) -> u32871     fn signature(&self) -> u32 {
872         self.signature.get(LE)
873     }
874 
875     #[inline]
file_header(&self) -> &pe::ImageFileHeader876     fn file_header(&self) -> &pe::ImageFileHeader {
877         &self.file_header
878     }
879 
880     #[inline]
optional_header(&self) -> &Self::ImageOptionalHeader881     fn optional_header(&self) -> &Self::ImageOptionalHeader {
882         &self.optional_header
883     }
884 }
885 
886 impl ImageOptionalHeader for pe::ImageOptionalHeader64 {
887     #[inline]
magic(&self) -> u16888     fn magic(&self) -> u16 {
889         self.magic.get(LE)
890     }
891 
892     #[inline]
major_linker_version(&self) -> u8893     fn major_linker_version(&self) -> u8 {
894         self.major_linker_version
895     }
896 
897     #[inline]
minor_linker_version(&self) -> u8898     fn minor_linker_version(&self) -> u8 {
899         self.minor_linker_version
900     }
901 
902     #[inline]
size_of_code(&self) -> u32903     fn size_of_code(&self) -> u32 {
904         self.size_of_code.get(LE)
905     }
906 
907     #[inline]
size_of_initialized_data(&self) -> u32908     fn size_of_initialized_data(&self) -> u32 {
909         self.size_of_initialized_data.get(LE)
910     }
911 
912     #[inline]
size_of_uninitialized_data(&self) -> u32913     fn size_of_uninitialized_data(&self) -> u32 {
914         self.size_of_uninitialized_data.get(LE)
915     }
916 
917     #[inline]
address_of_entry_point(&self) -> u32918     fn address_of_entry_point(&self) -> u32 {
919         self.address_of_entry_point.get(LE)
920     }
921 
922     #[inline]
base_of_code(&self) -> u32923     fn base_of_code(&self) -> u32 {
924         self.base_of_code.get(LE)
925     }
926 
927     #[inline]
image_base(&self) -> u64928     fn image_base(&self) -> u64 {
929         self.image_base.get(LE)
930     }
931 
932     #[inline]
section_alignment(&self) -> u32933     fn section_alignment(&self) -> u32 {
934         self.section_alignment.get(LE)
935     }
936 
937     #[inline]
file_alignment(&self) -> u32938     fn file_alignment(&self) -> u32 {
939         self.file_alignment.get(LE)
940     }
941 
942     #[inline]
major_operating_system_version(&self) -> u16943     fn major_operating_system_version(&self) -> u16 {
944         self.major_operating_system_version.get(LE)
945     }
946 
947     #[inline]
minor_operating_system_version(&self) -> u16948     fn minor_operating_system_version(&self) -> u16 {
949         self.minor_operating_system_version.get(LE)
950     }
951 
952     #[inline]
major_image_version(&self) -> u16953     fn major_image_version(&self) -> u16 {
954         self.major_image_version.get(LE)
955     }
956 
957     #[inline]
minor_image_version(&self) -> u16958     fn minor_image_version(&self) -> u16 {
959         self.minor_image_version.get(LE)
960     }
961 
962     #[inline]
major_subsystem_version(&self) -> u16963     fn major_subsystem_version(&self) -> u16 {
964         self.major_subsystem_version.get(LE)
965     }
966 
967     #[inline]
minor_subsystem_version(&self) -> u16968     fn minor_subsystem_version(&self) -> u16 {
969         self.minor_subsystem_version.get(LE)
970     }
971 
972     #[inline]
win32_version_value(&self) -> u32973     fn win32_version_value(&self) -> u32 {
974         self.win32_version_value.get(LE)
975     }
976 
977     #[inline]
size_of_image(&self) -> u32978     fn size_of_image(&self) -> u32 {
979         self.size_of_image.get(LE)
980     }
981 
982     #[inline]
size_of_headers(&self) -> u32983     fn size_of_headers(&self) -> u32 {
984         self.size_of_headers.get(LE)
985     }
986 
987     #[inline]
check_sum(&self) -> u32988     fn check_sum(&self) -> u32 {
989         self.check_sum.get(LE)
990     }
991 
992     #[inline]
subsystem(&self) -> u16993     fn subsystem(&self) -> u16 {
994         self.subsystem.get(LE)
995     }
996 
997     #[inline]
dll_characteristics(&self) -> u16998     fn dll_characteristics(&self) -> u16 {
999         self.dll_characteristics.get(LE)
1000     }
1001 
1002     #[inline]
size_of_stack_reserve(&self) -> u641003     fn size_of_stack_reserve(&self) -> u64 {
1004         self.size_of_stack_reserve.get(LE)
1005     }
1006 
1007     #[inline]
size_of_stack_commit(&self) -> u641008     fn size_of_stack_commit(&self) -> u64 {
1009         self.size_of_stack_commit.get(LE)
1010     }
1011 
1012     #[inline]
size_of_heap_reserve(&self) -> u641013     fn size_of_heap_reserve(&self) -> u64 {
1014         self.size_of_heap_reserve.get(LE)
1015     }
1016 
1017     #[inline]
size_of_heap_commit(&self) -> u641018     fn size_of_heap_commit(&self) -> u64 {
1019         self.size_of_heap_commit.get(LE)
1020     }
1021 
1022     #[inline]
loader_flags(&self) -> u321023     fn loader_flags(&self) -> u32 {
1024         self.loader_flags.get(LE)
1025     }
1026 
1027     #[inline]
number_of_rva_and_sizes(&self) -> u321028     fn number_of_rva_and_sizes(&self) -> u32 {
1029         self.number_of_rva_and_sizes.get(LE)
1030     }
1031 }
1032 
1033 impl pe::ImageDataDirectory {
1034     /// Get the data referenced by this directory entry.
data<'data, R: ReadRef<'data>>( &self, data: R, sections: &SectionTable<'data>, ) -> Result<&'data [u8]>1035     pub fn data<'data, R: ReadRef<'data>>(
1036         &self,
1037         data: R,
1038         sections: &SectionTable<'data>,
1039     ) -> Result<&'data [u8]> {
1040         sections
1041             .pe_data_at(data, self.virtual_address.get(LE))
1042             .read_error("Invalid data dir virtual address or size")?
1043             .get(..self.size.get(LE) as usize)
1044             .read_error("Invalid data dir size")
1045     }
1046 }
1047