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