]> git.proxmox.com Git - rustc.git/blob - vendor/object-0.26.2/src/read/pe/file.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / object-0.26.2 / src / read / pe / file.rs
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.
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
64 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
69 pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
70 self.dos_header
71 }
72
73 /// Return the NT Headers of this file
74 pub fn nt_headers(&self) -> &'data Pe {
75 self.nt_headers
76 }
77
78 /// Returns the section table of this binary.
79 pub fn section_table(&self) -> SectionTable<'data> {
80 self.common.sections
81 }
82
83 /// Returns the data directory at the given index.
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
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.
95 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
124 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]
135 fn is_little_endian(&self) -> bool {
136 // Only little endian is supported.
137 true
138 }
139
140 #[inline]
141 fn is_64(&self) -> bool {
142 self.nt_headers.is_type_64()
143 }
144
145 fn segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R> {
146 PeSegmentIterator {
147 file: self,
148 iter: self.common.sections.iter(),
149 }
150 }
151
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
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
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
182 fn comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R> {
183 PeComdatIterator { file: self }
184 }
185
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
195 fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
196 CoffSymbolIterator {
197 file: &self.common,
198 index: 0,
199 }
200 }
201
202 fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
203 Some(CoffSymbolTable { file: &self.common })
204 }
205
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
214 fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
215 None
216 }
217
218 fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> {
219 None
220 }
221
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
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
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
398 fn has_debug_symbols(&self) -> bool {
399 self.section_by_name(".debug_info").is_some()
400 }
401
402 fn relative_address_base(&self) -> u64 {
403 self.common.image_base
404 }
405
406 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
411 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]
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]
480 fn kind(&self) -> ComdatKind {
481 unreachable!();
482 }
483
484 #[inline]
485 fn symbol(&self) -> SymbolIndex {
486 unreachable!();
487 }
488
489 #[inline]
490 fn name(&self) -> Result<&str> {
491 unreachable!();
492 }
493
494 #[inline]
495 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
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.
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]
546 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.
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.
578 fn is_type_64(&self) -> bool;
579
580 /// Return true if the magic field in the optional header is valid.
581 fn is_valid_optional_magic(&self) -> bool;
582
583 /// Return the signature
584 fn signature(&self) -> u32;
585
586 /// Return the file header.
587 fn file_header(&self) -> &pe::ImageFileHeader;
588
589 /// Return the optional header.
590 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.
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]
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]
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.
659 fn magic(&self) -> u16;
660 fn major_linker_version(&self) -> u8;
661 fn minor_linker_version(&self) -> u8;
662 fn size_of_code(&self) -> u32;
663 fn size_of_initialized_data(&self) -> u32;
664 fn size_of_uninitialized_data(&self) -> u32;
665 fn address_of_entry_point(&self) -> u32;
666 fn base_of_code(&self) -> u32;
667
668 // NT additional fields.
669 fn image_base(&self) -> u64;
670 fn section_alignment(&self) -> u32;
671 fn file_alignment(&self) -> u32;
672 fn major_operating_system_version(&self) -> u16;
673 fn minor_operating_system_version(&self) -> u16;
674 fn major_image_version(&self) -> u16;
675 fn minor_image_version(&self) -> u16;
676 fn major_subsystem_version(&self) -> u16;
677 fn minor_subsystem_version(&self) -> u16;
678 fn win32_version_value(&self) -> u32;
679 fn size_of_image(&self) -> u32;
680 fn size_of_headers(&self) -> u32;
681 fn check_sum(&self) -> u32;
682 fn subsystem(&self) -> u16;
683 fn dll_characteristics(&self) -> u16;
684 fn size_of_stack_reserve(&self) -> u64;
685 fn size_of_stack_commit(&self) -> u64;
686 fn size_of_heap_reserve(&self) -> u64;
687 fn size_of_heap_commit(&self) -> u64;
688 fn loader_flags(&self) -> u32;
689 fn number_of_rva_and_sizes(&self) -> u32;
690 }
691
692 impl ImageNtHeaders for pe::ImageNtHeaders32 {
693 type ImageOptionalHeader = pe::ImageOptionalHeader32;
694
695 #[inline]
696 fn is_type_64(&self) -> bool {
697 false
698 }
699
700 #[inline]
701 fn is_valid_optional_magic(&self) -> bool {
702 self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC
703 }
704
705 #[inline]
706 fn signature(&self) -> u32 {
707 self.signature.get(LE)
708 }
709
710 #[inline]
711 fn file_header(&self) -> &pe::ImageFileHeader {
712 &self.file_header
713 }
714
715 #[inline]
716 fn optional_header(&self) -> &Self::ImageOptionalHeader {
717 &self.optional_header
718 }
719 }
720
721 impl ImageOptionalHeader for pe::ImageOptionalHeader32 {
722 #[inline]
723 fn magic(&self) -> u16 {
724 self.magic.get(LE)
725 }
726
727 #[inline]
728 fn major_linker_version(&self) -> u8 {
729 self.major_linker_version
730 }
731
732 #[inline]
733 fn minor_linker_version(&self) -> u8 {
734 self.minor_linker_version
735 }
736
737 #[inline]
738 fn size_of_code(&self) -> u32 {
739 self.size_of_code.get(LE)
740 }
741
742 #[inline]
743 fn size_of_initialized_data(&self) -> u32 {
744 self.size_of_initialized_data.get(LE)
745 }
746
747 #[inline]
748 fn size_of_uninitialized_data(&self) -> u32 {
749 self.size_of_uninitialized_data.get(LE)
750 }
751
752 #[inline]
753 fn address_of_entry_point(&self) -> u32 {
754 self.address_of_entry_point.get(LE)
755 }
756
757 #[inline]
758 fn base_of_code(&self) -> u32 {
759 self.base_of_code.get(LE)
760 }
761
762 #[inline]
763 fn image_base(&self) -> u64 {
764 self.image_base.get(LE).into()
765 }
766
767 #[inline]
768 fn section_alignment(&self) -> u32 {
769 self.section_alignment.get(LE)
770 }
771
772 #[inline]
773 fn file_alignment(&self) -> u32 {
774 self.file_alignment.get(LE)
775 }
776
777 #[inline]
778 fn major_operating_system_version(&self) -> u16 {
779 self.major_operating_system_version.get(LE)
780 }
781
782 #[inline]
783 fn minor_operating_system_version(&self) -> u16 {
784 self.minor_operating_system_version.get(LE)
785 }
786
787 #[inline]
788 fn major_image_version(&self) -> u16 {
789 self.major_image_version.get(LE)
790 }
791
792 #[inline]
793 fn minor_image_version(&self) -> u16 {
794 self.minor_image_version.get(LE)
795 }
796
797 #[inline]
798 fn major_subsystem_version(&self) -> u16 {
799 self.major_subsystem_version.get(LE)
800 }
801
802 #[inline]
803 fn minor_subsystem_version(&self) -> u16 {
804 self.minor_subsystem_version.get(LE)
805 }
806
807 #[inline]
808 fn win32_version_value(&self) -> u32 {
809 self.win32_version_value.get(LE)
810 }
811
812 #[inline]
813 fn size_of_image(&self) -> u32 {
814 self.size_of_image.get(LE)
815 }
816
817 #[inline]
818 fn size_of_headers(&self) -> u32 {
819 self.size_of_headers.get(LE)
820 }
821
822 #[inline]
823 fn check_sum(&self) -> u32 {
824 self.check_sum.get(LE)
825 }
826
827 #[inline]
828 fn subsystem(&self) -> u16 {
829 self.subsystem.get(LE)
830 }
831
832 #[inline]
833 fn dll_characteristics(&self) -> u16 {
834 self.dll_characteristics.get(LE)
835 }
836
837 #[inline]
838 fn size_of_stack_reserve(&self) -> u64 {
839 self.size_of_stack_reserve.get(LE).into()
840 }
841
842 #[inline]
843 fn size_of_stack_commit(&self) -> u64 {
844 self.size_of_stack_commit.get(LE).into()
845 }
846
847 #[inline]
848 fn size_of_heap_reserve(&self) -> u64 {
849 self.size_of_heap_reserve.get(LE).into()
850 }
851
852 #[inline]
853 fn size_of_heap_commit(&self) -> u64 {
854 self.size_of_heap_commit.get(LE).into()
855 }
856
857 #[inline]
858 fn loader_flags(&self) -> u32 {
859 self.loader_flags.get(LE)
860 }
861
862 #[inline]
863 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]
872 fn is_type_64(&self) -> bool {
873 true
874 }
875
876 #[inline]
877 fn is_valid_optional_magic(&self) -> bool {
878 self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC
879 }
880
881 #[inline]
882 fn signature(&self) -> u32 {
883 self.signature.get(LE)
884 }
885
886 #[inline]
887 fn file_header(&self) -> &pe::ImageFileHeader {
888 &self.file_header
889 }
890
891 #[inline]
892 fn optional_header(&self) -> &Self::ImageOptionalHeader {
893 &self.optional_header
894 }
895 }
896
897 impl ImageOptionalHeader for pe::ImageOptionalHeader64 {
898 #[inline]
899 fn magic(&self) -> u16 {
900 self.magic.get(LE)
901 }
902
903 #[inline]
904 fn major_linker_version(&self) -> u8 {
905 self.major_linker_version
906 }
907
908 #[inline]
909 fn minor_linker_version(&self) -> u8 {
910 self.minor_linker_version
911 }
912
913 #[inline]
914 fn size_of_code(&self) -> u32 {
915 self.size_of_code.get(LE)
916 }
917
918 #[inline]
919 fn size_of_initialized_data(&self) -> u32 {
920 self.size_of_initialized_data.get(LE)
921 }
922
923 #[inline]
924 fn size_of_uninitialized_data(&self) -> u32 {
925 self.size_of_uninitialized_data.get(LE)
926 }
927
928 #[inline]
929 fn address_of_entry_point(&self) -> u32 {
930 self.address_of_entry_point.get(LE)
931 }
932
933 #[inline]
934 fn base_of_code(&self) -> u32 {
935 self.base_of_code.get(LE)
936 }
937
938 #[inline]
939 fn image_base(&self) -> u64 {
940 self.image_base.get(LE)
941 }
942
943 #[inline]
944 fn section_alignment(&self) -> u32 {
945 self.section_alignment.get(LE)
946 }
947
948 #[inline]
949 fn file_alignment(&self) -> u32 {
950 self.file_alignment.get(LE)
951 }
952
953 #[inline]
954 fn major_operating_system_version(&self) -> u16 {
955 self.major_operating_system_version.get(LE)
956 }
957
958 #[inline]
959 fn minor_operating_system_version(&self) -> u16 {
960 self.minor_operating_system_version.get(LE)
961 }
962
963 #[inline]
964 fn major_image_version(&self) -> u16 {
965 self.major_image_version.get(LE)
966 }
967
968 #[inline]
969 fn minor_image_version(&self) -> u16 {
970 self.minor_image_version.get(LE)
971 }
972
973 #[inline]
974 fn major_subsystem_version(&self) -> u16 {
975 self.major_subsystem_version.get(LE)
976 }
977
978 #[inline]
979 fn minor_subsystem_version(&self) -> u16 {
980 self.minor_subsystem_version.get(LE)
981 }
982
983 #[inline]
984 fn win32_version_value(&self) -> u32 {
985 self.win32_version_value.get(LE)
986 }
987
988 #[inline]
989 fn size_of_image(&self) -> u32 {
990 self.size_of_image.get(LE)
991 }
992
993 #[inline]
994 fn size_of_headers(&self) -> u32 {
995 self.size_of_headers.get(LE)
996 }
997
998 #[inline]
999 fn check_sum(&self) -> u32 {
1000 self.check_sum.get(LE)
1001 }
1002
1003 #[inline]
1004 fn subsystem(&self) -> u16 {
1005 self.subsystem.get(LE)
1006 }
1007
1008 #[inline]
1009 fn dll_characteristics(&self) -> u16 {
1010 self.dll_characteristics.get(LE)
1011 }
1012
1013 #[inline]
1014 fn size_of_stack_reserve(&self) -> u64 {
1015 self.size_of_stack_reserve.get(LE)
1016 }
1017
1018 #[inline]
1019 fn size_of_stack_commit(&self) -> u64 {
1020 self.size_of_stack_commit.get(LE)
1021 }
1022
1023 #[inline]
1024 fn size_of_heap_reserve(&self) -> u64 {
1025 self.size_of_heap_reserve.get(LE)
1026 }
1027
1028 #[inline]
1029 fn size_of_heap_commit(&self) -> u64 {
1030 self.size_of_heap_commit.get(LE)
1031 }
1032
1033 #[inline]
1034 fn loader_flags(&self) -> u32 {
1035 self.loader_flags.get(LE)
1036 }
1037
1038 #[inline]
1039 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.
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 }