aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/read/pe
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/object/src/read/pe')
-rw-r--r--vendor/object/src/read/pe/data_directory.rs213
-rw-r--r--vendor/object/src/read/pe/export.rs333
-rw-r--r--vendor/object/src/read/pe/file.rs1050
-rw-r--r--vendor/object/src/read/pe/import.rs337
-rw-r--r--vendor/object/src/read/pe/mod.rs68
-rw-r--r--vendor/object/src/read/pe/relocation.rs92
-rw-r--r--vendor/object/src/read/pe/resource.rs209
-rw-r--r--vendor/object/src/read/pe/rich.rs91
-rw-r--r--vendor/object/src/read/pe/section.rs440
9 files changed, 0 insertions, 2833 deletions
diff --git a/vendor/object/src/read/pe/data_directory.rs b/vendor/object/src/read/pe/data_directory.rs
deleted file mode 100644
index a17179f..0000000
--- a/vendor/object/src/read/pe/data_directory.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-use core::slice;
-
-use crate::read::{Error, ReadError, ReadRef, Result};
-use crate::{pe, LittleEndian as LE};
-
-use super::{
- DelayLoadImportTable, ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory,
- SectionTable,
-};
-
-/// The table of data directories in a PE file.
-///
-/// Returned by [`ImageNtHeaders::parse`](super::ImageNtHeaders::parse).
-#[derive(Debug, Clone, Copy)]
-pub struct DataDirectories<'data> {
- entries: &'data [pe::ImageDataDirectory],
-}
-
-impl<'data> DataDirectories<'data> {
- /// Parse the data directory table.
- ///
- /// `data` must be the remaining optional data following the
- /// [optional header](pe::ImageOptionalHeader64). `number` must be from the
- /// [`number_of_rva_and_sizes`](pe::ImageOptionalHeader64::number_of_rva_and_sizes)
- /// field of the optional header.
- pub fn parse(data: &'data [u8], number: u32) -> Result<Self> {
- let entries = data
- .read_slice_at(0, number as usize)
- .read_error("Invalid PE number of RVA and sizes")?;
- Ok(DataDirectories { entries })
- }
-
- /// The number of data directories.
- #[allow(clippy::len_without_is_empty)]
- pub fn len(&self) -> usize {
- self.entries.len()
- }
-
- /// Iterator over the data directories.
- pub fn iter(&self) -> slice::Iter<'data, pe::ImageDataDirectory> {
- self.entries.iter()
- }
-
- /// Iterator which gives the directories as well as their index (one of the IMAGE_DIRECTORY_ENTRY_* constants).
- pub fn enumerate(&self) -> core::iter::Enumerate<slice::Iter<'data, pe::ImageDataDirectory>> {
- self.entries.iter().enumerate()
- }
-
- /// Returns the data directory at the given index.
- ///
- /// Index should be one of the `IMAGE_DIRECTORY_ENTRY_*` constants.
- ///
- /// Returns `None` if the index is larger than the table size,
- /// or if the entry at the index has a zero virtual address.
- pub fn get(&self, index: usize) -> Option<&'data pe::ImageDataDirectory> {
- self.entries
- .get(index)
- .filter(|d| d.virtual_address.get(LE) != 0)
- }
-
- /// Returns the unparsed export directory.
- ///
- /// `data` must be the entire file data.
- pub fn export_directory<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<&'data pe::ImageExportDirectory>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let export_data = data_dir.data(data, sections)?;
- ExportTable::parse_directory(export_data).map(Some)
- }
-
- /// Returns the partially parsed export directory.
- ///
- /// `data` must be the entire file data.
- pub fn export_table<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<ExportTable<'data>>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let export_va = data_dir.virtual_address.get(LE);
- let export_data = data_dir.data(data, sections)?;
- ExportTable::parse(export_data, export_va).map(Some)
- }
-
- /// Returns the partially parsed import directory.
- ///
- /// `data` must be the entire file data.
- pub fn import_table<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<ImportTable<'data>>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_IMPORT) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let import_va = data_dir.virtual_address.get(LE);
- let (section_data, section_va) = sections
- .pe_data_containing(data, import_va)
- .read_error("Invalid import data dir virtual address")?;
- Ok(Some(ImportTable::new(section_data, section_va, import_va)))
- }
-
- /// Returns the partially parsed delay-load import directory.
- ///
- /// `data` must be the entire file data.
- pub fn delay_load_import_table<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<DelayLoadImportTable<'data>>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let import_va = data_dir.virtual_address.get(LE);
- let (section_data, section_va) = sections
- .pe_data_containing(data, import_va)
- .read_error("Invalid import data dir virtual address")?;
- Ok(Some(DelayLoadImportTable::new(
- section_data,
- section_va,
- import_va,
- )))
- }
-
- /// Returns the blocks in the base relocation directory.
- ///
- /// `data` must be the entire file data.
- pub fn relocation_blocks<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<RelocationBlockIterator<'data>>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_BASERELOC) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let reloc_data = data_dir.data(data, sections)?;
- Ok(Some(RelocationBlockIterator::new(reloc_data)))
- }
-
- /// Returns the resource directory.
- ///
- /// `data` must be the entire file data.
- pub fn resource_directory<R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<Option<ResourceDirectory<'data>>> {
- let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let rsrc_data = data_dir.data(data, sections)?;
- Ok(Some(ResourceDirectory::new(rsrc_data)))
- }
-}
-
-impl pe::ImageDataDirectory {
- /// Return the virtual address range of this directory entry.
- pub fn address_range(&self) -> (u32, u32) {
- (self.virtual_address.get(LE), self.size.get(LE))
- }
-
- /// Return the file offset and size of this directory entry.
- ///
- /// This function has some limitations:
- /// - It requires that the data is contained in a single section.
- /// - It uses the size field of the directory entry, which is
- /// not desirable for all data directories.
- /// - It uses the `virtual_address` of the directory entry as an address,
- /// which is not valid for `IMAGE_DIRECTORY_ENTRY_SECURITY`.
- pub fn file_range(&self, sections: &SectionTable<'_>) -> Result<(u32, u32)> {
- let (offset, section_size) = sections
- .pe_file_range_at(self.virtual_address.get(LE))
- .read_error("Invalid data dir virtual address")?;
- let size = self.size.get(LE);
- if size > section_size {
- return Err(Error("Invalid data dir size"));
- }
- Ok((offset, size))
- }
-
- /// Get the data referenced by this directory entry.
- ///
- /// This function has some limitations:
- /// - It requires that the data is contained in a single section.
- /// - It uses the size field of the directory entry, which is
- /// not desirable for all data directories.
- /// - It uses the `virtual_address` of the directory entry as an address,
- /// which is not valid for `IMAGE_DIRECTORY_ENTRY_SECURITY`.
- pub fn data<'data, R: ReadRef<'data>>(
- &self,
- data: R,
- sections: &SectionTable<'data>,
- ) -> Result<&'data [u8]> {
- sections
- .pe_data_at(data, self.virtual_address.get(LE))
- .read_error("Invalid data dir virtual address")?
- .get(..self.size.get(LE) as usize)
- .read_error("Invalid data dir size")
- }
-}
diff --git a/vendor/object/src/read/pe/export.rs b/vendor/object/src/read/pe/export.rs
deleted file mode 100644
index 1aba844..0000000
--- a/vendor/object/src/read/pe/export.rs
+++ /dev/null
@@ -1,333 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-
-use crate::read::{ByteString, Bytes, Error, ReadError, ReadRef, Result};
-use crate::{pe, LittleEndian as LE, U16Bytes, U32Bytes};
-
-/// Where an export is pointing to.
-#[derive(Clone, Copy)]
-pub enum ExportTarget<'data> {
- /// The address of the export, relative to the image base.
- Address(u32),
- /// Forwarded to an export ordinal in another DLL.
- ///
- /// This gives the name of the DLL, and the ordinal.
- ForwardByOrdinal(&'data [u8], u32),
- /// Forwarded to an export name in another DLL.
- ///
- /// This gives the name of the DLL, and the export name.
- ForwardByName(&'data [u8], &'data [u8]),
-}
-
-impl<'data> ExportTarget<'data> {
- /// Returns true if the target is an address.
- pub fn is_address(&self) -> bool {
- match self {
- ExportTarget::Address(_) => true,
- _ => false,
- }
- }
-
- /// Returns true if the export is forwarded to another DLL.
- pub fn is_forward(&self) -> bool {
- !self.is_address()
- }
-}
-
-/// An export from a PE file.
-///
-/// There are multiple kinds of PE exports (with or without a name, and local or forwarded).
-#[derive(Clone, Copy)]
-pub struct Export<'data> {
- /// The ordinal of the export.
- ///
- /// These are sequential, starting at a base specified in the DLL.
- pub ordinal: u32,
- /// The name of the export, if known.
- pub name: Option<&'data [u8]>,
- /// The target of this export.
- pub target: ExportTarget<'data>,
-}
-
-impl<'a> Debug for Export<'a> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
- f.debug_struct("Export")
- .field("ordinal", &self.ordinal)
- .field("name", &self.name.map(ByteString))
- .field("target", &self.target)
- .finish()
- }
-}
-
-impl<'a> Debug for ExportTarget<'a> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
- match self {
- ExportTarget::Address(address) => write!(f, "Address({:#x})", address),
- ExportTarget::ForwardByOrdinal(library, ordinal) => write!(
- f,
- "ForwardByOrdinal({:?}.#{})",
- ByteString(library),
- ordinal
- ),
- ExportTarget::ForwardByName(library, name) => write!(
- f,
- "ForwardByName({:?}.{:?})",
- ByteString(library),
- ByteString(name)
- ),
- }
- }
-}
-
-/// A partially parsed PE export table.
-///
-/// Returned by [`DataDirectories::export_table`](super::DataDirectories::export_table).
-#[derive(Debug, Clone)]
-pub struct ExportTable<'data> {
- data: Bytes<'data>,
- virtual_address: u32,
- directory: &'data pe::ImageExportDirectory,
- addresses: &'data [U32Bytes<LE>],
- names: &'data [U32Bytes<LE>],
- name_ordinals: &'data [U16Bytes<LE>],
-}
-
-impl<'data> ExportTable<'data> {
- /// Parse the export table given its section data and address.
- pub fn parse(data: &'data [u8], virtual_address: u32) -> Result<Self> {
- let directory = Self::parse_directory(data)?;
- let data = Bytes(data);
-
- let mut addresses = &[][..];
- let address_of_functions = directory.address_of_functions.get(LE);
- if address_of_functions != 0 {
- addresses = data
- .read_slice_at::<U32Bytes<_>>(
- address_of_functions.wrapping_sub(virtual_address) as usize,
- directory.number_of_functions.get(LE) as usize,
- )
- .read_error("Invalid PE export address table")?;
- }
-
- let mut names = &[][..];
- let mut name_ordinals = &[][..];
- let address_of_names = directory.address_of_names.get(LE);
- let address_of_name_ordinals = directory.address_of_name_ordinals.get(LE);
- if address_of_names != 0 {
- if address_of_name_ordinals == 0 {
- return Err(Error("Missing PE export ordinal table"));
- }
-
- let number = directory.number_of_names.get(LE) as usize;
- names = data
- .read_slice_at::<U32Bytes<_>>(
- address_of_names.wrapping_sub(virtual_address) as usize,
- number,
- )
- .read_error("Invalid PE export name pointer table")?;
- name_ordinals = data
- .read_slice_at::<U16Bytes<_>>(
- address_of_name_ordinals.wrapping_sub(virtual_address) as usize,
- number,
- )
- .read_error("Invalid PE export ordinal table")?;
- }
-
- Ok(ExportTable {
- data,
- virtual_address,
- directory,
- addresses,
- names,
- name_ordinals,
- })
- }
-
- /// Parse the export directory given its section data.
- pub fn parse_directory(data: &'data [u8]) -> Result<&'data pe::ImageExportDirectory> {
- data.read_at::<pe::ImageExportDirectory>(0)
- .read_error("Invalid PE export dir size")
- }
-
- /// Returns the header of the export table.
- pub fn directory(&self) -> &'data pe::ImageExportDirectory {
- self.directory
- }
-
- /// Returns the base value of ordinals.
- ///
- /// Adding this to an address index will give an ordinal.
- pub fn ordinal_base(&self) -> u32 {
- self.directory.base.get(LE)
- }
-
- /// Returns the unparsed address table.
- ///
- /// An address table entry may be a local address, or the address of a forwarded export entry.
- /// See [`Self::is_forward`] and [`Self::target_from_address`].
- pub fn addresses(&self) -> &'data [U32Bytes<LE>] {
- self.addresses
- }
-
- /// Returns the unparsed name pointer table.
- ///
- /// A name pointer table entry can be used with [`Self::name_from_pointer`].
- pub fn name_pointers(&self) -> &'data [U32Bytes<LE>] {
- self.names
- }
-
- /// Returns the unparsed ordinal table.
- ///
- /// An ordinal table entry is a 0-based index into the address table.
- /// See [`Self::address_by_index`] and [`Self::target_by_index`].
- pub fn name_ordinals(&self) -> &'data [U16Bytes<LE>] {
- self.name_ordinals
- }
-
- /// Returns an iterator for the entries in the name pointer table and ordinal table.
- ///
- /// A name pointer table entry can be used with [`Self::name_from_pointer`].
- ///
- /// An ordinal table entry is a 0-based index into the address table.
- /// See [`Self::address_by_index`] and [`Self::target_by_index`].
- pub fn name_iter(&self) -> impl Iterator<Item = (u32, u16)> + 'data {
- self.names
- .iter()
- .map(|x| x.get(LE))
- .zip(self.name_ordinals.iter().map(|x| x.get(LE)))
- }
-
- /// Returns the export address table entry at the given address index.
- ///
- /// This may be a local address, or the address of a forwarded export entry.
- /// See [`Self::is_forward`] and [`Self::target_from_address`].
- ///
- /// `index` is a 0-based index into the export address table.
- pub fn address_by_index(&self, index: u32) -> Result<u32> {
- Ok(self
- .addresses
- .get(index as usize)
- .read_error("Invalid PE export address index")?
- .get(LE))
- }
-
- /// Returns the export address table entry at the given ordinal.
- ///
- /// This may be a local address, or the address of a forwarded export entry.
- /// See [`Self::is_forward`] and [`Self::target_from_address`].
- pub fn address_by_ordinal(&self, ordinal: u32) -> Result<u32> {
- self.address_by_index(ordinal.wrapping_sub(self.ordinal_base()))
- }
-
- /// Returns the target of the export at the given address index.
- ///
- /// `index` is a 0-based index into the export address table.
- pub fn target_by_index(&self, index: u32) -> Result<ExportTarget<'data>> {
- self.target_from_address(self.address_by_index(index)?)
- }
-
- /// Returns the target of the export at the given ordinal.
- pub fn target_by_ordinal(&self, ordinal: u32) -> Result<ExportTarget<'data>> {
- self.target_from_address(self.address_by_ordinal(ordinal)?)
- }
-
- /// Convert an export address table entry into a target.
- pub fn target_from_address(&self, address: u32) -> Result<ExportTarget<'data>> {
- Ok(if let Some(forward) = self.forward_string(address)? {
- let i = forward
- .iter()
- .position(|x| *x == b'.')
- .read_error("Missing PE forwarded export separator")?;
- let library = &forward[..i];
- match &forward[i + 1..] {
- [b'#', digits @ ..] => {
- let ordinal =
- parse_ordinal(digits).read_error("Invalid PE forwarded export ordinal")?;
- ExportTarget::ForwardByOrdinal(library, ordinal)
- }
- [] => {
- return Err(Error("Missing PE forwarded export name"));
- }
- name => ExportTarget::ForwardByName(library, name),
- }
- } else {
- ExportTarget::Address(address)
- })
- }
-
- fn forward_offset(&self, address: u32) -> Option<usize> {
- let offset = address.wrapping_sub(self.virtual_address) as usize;
- if offset < self.data.len() {
- Some(offset)
- } else {
- None
- }
- }
-
- /// Return true if the export address table entry is a forward.
- pub fn is_forward(&self, address: u32) -> bool {
- self.forward_offset(address).is_some()
- }
-
- /// Return the forward string if the export address table entry is a forward.
- pub fn forward_string(&self, address: u32) -> Result<Option<&'data [u8]>> {
- if let Some(offset) = self.forward_offset(address) {
- self.data
- .read_string_at(offset)
- .read_error("Invalid PE forwarded export address")
- .map(Some)
- } else {
- Ok(None)
- }
- }
-
- /// Convert an export name pointer table entry into a name.
- pub fn name_from_pointer(&self, name_pointer: u32) -> Result<&'data [u8]> {
- let offset = name_pointer.wrapping_sub(self.virtual_address);
- self.data
- .read_string_at(offset as usize)
- .read_error("Invalid PE export name pointer")
- }
-
- /// Returns the parsed exports in this table.
- pub fn exports(&self) -> Result<Vec<Export<'data>>> {
- // First, let's list all exports.
- let mut exports = Vec::new();
- let ordinal_base = self.ordinal_base();
- for (i, address) in self.addresses.iter().enumerate() {
- // Convert from an array index to an ordinal.
- let ordinal = ordinal_base.wrapping_add(i as u32);
- let target = self.target_from_address(address.get(LE))?;
- exports.push(Export {
- ordinal,
- target,
- // Might be populated later.
- name: None,
- });
- }
-
- // Now, check whether some (or all) of them have an associated name.
- // `ordinal_index` is a 0-based index into `addresses`.
- for (name_pointer, ordinal_index) in self.name_iter() {
- let name = self.name_from_pointer(name_pointer)?;
- exports
- .get_mut(ordinal_index as usize)
- .read_error("Invalid PE export ordinal")?
- .name = Some(name);
- }
-
- Ok(exports)
- }
-}
-
-fn parse_ordinal(digits: &[u8]) -> Option<u32> {
- if digits.is_empty() {
- return None;
- }
- let mut result: u32 = 0;
- for &c in digits {
- let x = (c as char).to_digit(10)?;
- result = result.checked_mul(10)?.checked_add(x)?;
- }
- Some(result)
-}
diff --git a/vendor/object/src/read/pe/file.rs b/vendor/object/src/read/pe/file.rs
deleted file mode 100644
index 5372bdd..0000000
--- a/vendor/object/src/read/pe/file.rs
+++ /dev/null
@@ -1,1050 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::{mem, str};
-
-use core::convert::TryInto;
-
-use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
-use crate::read::{
- self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
- Object, ObjectComdat, ObjectKind, ReadError, ReadRef, Result, SectionIndex, SymbolIndex,
-};
-use crate::{pe, ByteString, Bytes, CodeView, LittleEndian as LE, Pod, SubArchitecture, U32};
-
-use super::{
- DataDirectories, ExportTable, ImageThunkData, ImportTable, PeSection, PeSectionIterator,
- PeSegment, PeSegmentIterator, RichHeaderInfo, SectionTable,
-};
-
-/// A PE32 (32-bit) image file.
-///
-/// This is a file that starts with [`pe::ImageNtHeaders32`], and corresponds
-/// to [`crate::FileKind::Pe32`].
-pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>;
-/// A PE32+ (64-bit) image file.
-///
-/// This is a file that starts with [`pe::ImageNtHeaders64`], and corresponds
-/// to [`crate::FileKind::Pe64`].
-pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>;
-
-/// A PE image file.
-///
-/// Most functionality is provided by the [`Object`] trait implementation.
-#[derive(Debug)]
-pub struct PeFile<'data, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- pub(super) dos_header: &'data pe::ImageDosHeader,
- pub(super) nt_headers: &'data Pe,
- pub(super) data_directories: DataDirectories<'data>,
- pub(super) common: CoffCommon<'data, R>,
- pub(super) data: R,
-}
-
-impl<'data, Pe, R> PeFile<'data, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- /// Parse the raw PE file data.
- pub fn parse(data: R) -> Result<Self> {
- let dos_header = pe::ImageDosHeader::parse(data)?;
- let mut offset = dos_header.nt_headers_offset().into();
- let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?;
- let sections = nt_headers.sections(data, offset)?;
- let coff_symbols = nt_headers.symbols(data);
- let image_base = nt_headers.optional_header().image_base();
-
- Ok(PeFile {
- dos_header,
- nt_headers,
- data_directories,
- common: CoffCommon {
- sections,
- // The PE file format deprecates the COFF symbol table (https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image)
- // We do not want to prevent parsing the rest of the PE file for a corrupt COFF header, but rather return an empty symbol table
- symbols: coff_symbols.unwrap_or_default(),
- image_base,
- },
- data,
- })
- }
-
- /// Returns this binary data.
- pub fn data(&self) -> R {
- self.data
- }
-
- /// Return the DOS header of this file.
- pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
- self.dos_header
- }
-
- /// Return the NT Headers of this file.
- pub fn nt_headers(&self) -> &'data Pe {
- self.nt_headers
- }
-
- /// Returns information about the rich header of this file (if any).
- pub fn rich_header_info(&self) -> Option<RichHeaderInfo<'_>> {
- RichHeaderInfo::parse(self.data, self.dos_header.nt_headers_offset().into())
- }
-
- /// Returns the section table of this binary.
- pub fn section_table(&self) -> SectionTable<'data> {
- self.common.sections
- }
-
- /// Returns the data directories of this file.
- pub fn data_directories(&self) -> DataDirectories<'data> {
- self.data_directories
- }
-
- /// Returns the data directory at the given index.
- pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
- self.data_directories.get(id)
- }
-
- /// Returns the export table of this file.
- ///
- /// The export table is located using the data directory.
- pub fn export_table(&self) -> Result<Option<ExportTable<'data>>> {
- self.data_directories
- .export_table(self.data, &self.common.sections)
- }
-
- /// Returns the import table of this file.
- ///
- /// The import table is located using the data directory.
- pub fn import_table(&self) -> Result<Option<ImportTable<'data>>> {
- self.data_directories
- .import_table(self.data, &self.common.sections)
- }
-
- pub(super) fn section_alignment(&self) -> u64 {
- u64::from(self.nt_headers.optional_header().section_alignment())
- }
-}
-
-impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Pe, R> Object<'data, 'file> for PeFile<'data, Pe, R>
-where
- 'data: 'file,
- Pe: ImageNtHeaders,
- R: 'file + ReadRef<'data>,
-{
- type Segment = PeSegment<'data, 'file, Pe, R>;
- type SegmentIterator = PeSegmentIterator<'data, 'file, Pe, R>;
- type Section = PeSection<'data, 'file, Pe, R>;
- type SectionIterator = PeSectionIterator<'data, 'file, Pe, R>;
- type Comdat = PeComdat<'data, 'file, Pe, R>;
- type ComdatIterator = PeComdatIterator<'data, 'file, Pe, R>;
- type Symbol = CoffSymbol<'data, 'file, R>;
- type SymbolIterator = CoffSymbolIterator<'data, 'file, R>;
- type SymbolTable = CoffSymbolTable<'data, 'file, R>;
- type DynamicRelocationIterator = NoDynamicRelocationIterator;
-
- fn architecture(&self) -> Architecture {
- match self.nt_headers.file_header().machine.get(LE) {
- pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm,
- pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => Architecture::Aarch64,
- pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
- pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
- _ => Architecture::Unknown,
- }
- }
-
- fn sub_architecture(&self) -> Option<SubArchitecture> {
- match self.nt_headers.file_header().machine.get(LE) {
- pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC),
- _ => None,
- }
- }
-
- #[inline]
- fn is_little_endian(&self) -> bool {
- // Only little endian is supported.
- true
- }
-
- #[inline]
- fn is_64(&self) -> bool {
- self.nt_headers.is_type_64()
- }
-
- fn kind(&self) -> ObjectKind {
- let characteristics = self.nt_headers.file_header().characteristics.get(LE);
- if characteristics & pe::IMAGE_FILE_DLL != 0 {
- ObjectKind::Dynamic
- } else if characteristics & pe::IMAGE_FILE_SYSTEM != 0 {
- ObjectKind::Unknown
- } else {
- ObjectKind::Executable
- }
- }
-
- fn segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R> {
- PeSegmentIterator {
- file: self,
- iter: self.common.sections.iter(),
- }
- }
-
- fn section_by_name_bytes(
- &'file self,
- section_name: &[u8],
- ) -> Option<PeSection<'data, 'file, Pe, R>> {
- self.common
- .sections
- .section_by_name(self.common.symbols.strings(), section_name)
- .map(|(index, section)| PeSection {
- file: self,
- index: SectionIndex(index),
- section,
- })
- }
-
- fn section_by_index(
- &'file self,
- index: SectionIndex,
- ) -> Result<PeSection<'data, 'file, Pe, R>> {
- let section = self.common.sections.section(index.0)?;
- Ok(PeSection {
- file: self,
- index,
- section,
- })
- }
-
- fn sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R> {
- PeSectionIterator {
- file: self,
- iter: self.common.sections.iter().enumerate(),
- }
- }
-
- fn comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R> {
- PeComdatIterator { file: self }
- }
-
- fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<CoffSymbol<'data, 'file, R>> {
- let symbol = self.common.symbols.symbol(index.0)?;
- Ok(CoffSymbol {
- file: &self.common,
- index,
- symbol,
- })
- }
-
- fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
- CoffSymbolIterator {
- file: &self.common,
- index: 0,
- }
- }
-
- fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
- Some(CoffSymbolTable { file: &self.common })
- }
-
- fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> {
- CoffSymbolIterator {
- file: &self.common,
- // Hack: don't return any.
- index: self.common.symbols.len(),
- }
- }
-
- fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> {
- None
- }
-
- fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> {
- None
- }
-
- fn imports(&self) -> Result<Vec<Import<'data>>> {
- let mut imports = Vec::new();
- if let Some(import_table) = self.import_table()? {
- let mut import_descs = import_table.descriptors()?;
- while let Some(import_desc) = import_descs.next()? {
- let library = import_table.name(import_desc.name.get(LE))?;
- let mut first_thunk = import_desc.original_first_thunk.get(LE);
- if first_thunk == 0 {
- first_thunk = import_desc.first_thunk.get(LE);
- }
- let mut thunks = import_table.thunks(first_thunk)?;
- while let Some(thunk) = thunks.next::<Pe>()? {
- if !thunk.is_ordinal() {
- let (_hint, name) = import_table.hint_name(thunk.address())?;
- imports.push(Import {
- library: ByteString(library),
- name: ByteString(name),
- });
- }
- }
- }
- }
- Ok(imports)
- }
-
- fn exports(&self) -> Result<Vec<Export<'data>>> {
- let mut exports = Vec::new();
- if let Some(export_table) = self.export_table()? {
- for (name_pointer, address_index) in export_table.name_iter() {
- let name = export_table.name_from_pointer(name_pointer)?;
- let address = export_table.address_by_index(address_index.into())?;
- if !export_table.is_forward(address) {
- exports.push(Export {
- name: ByteString(name),
- address: self.common.image_base.wrapping_add(address.into()),
- })
- }
- }
- }
- Ok(exports)
- }
-
- fn pdb_info(&self) -> Result<Option<CodeView<'_>>> {
- let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_DEBUG) {
- Some(data_dir) => data_dir,
- None => return Ok(None),
- };
- let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
- let debug_data_size = data_dir.size.get(LE) as usize;
-
- let count = debug_data_size / mem::size_of::<pe::ImageDebugDirectory>();
- let rem = debug_data_size % mem::size_of::<pe::ImageDebugDirectory>();
- if rem != 0 || count < 1 {
- return Err(Error("Invalid PE debug dir size"));
- }
-
- let debug_dirs = debug_data
- .read_slice_at::<pe::ImageDebugDirectory>(0, count)
- .read_error("Invalid PE debug dir size")?;
-
- for debug_dir in debug_dirs {
- if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
- continue;
- }
-
- let info = self
- .data
- .read_slice_at::<u8>(
- debug_dir.pointer_to_raw_data.get(LE) as u64,
- debug_dir.size_of_data.get(LE) as usize,
- )
- .read_error("Invalid CodeView Info address")?;
-
- let mut info = Bytes(info);
-
- let sig = info
- .read_bytes(4)
- .read_error("Invalid CodeView signature")?;
- if sig.0 != b"RSDS" {
- continue;
- }
-
- let guid: [u8; 16] = info
- .read_bytes(16)
- .read_error("Invalid CodeView GUID")?
- .0
- .try_into()
- .unwrap();
-
- let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
-
- let path = info
- .read_string()
- .read_error("Invalid CodeView file path")?;
-
- return Ok(Some(CodeView {
- path: ByteString(path),
- guid,
- age: age.get(LE),
- }));
- }
- Ok(None)
- }
-
- fn has_debug_symbols(&self) -> bool {
- self.section_by_name(".debug_info").is_some()
- }
-
- fn relative_address_base(&self) -> u64 {
- self.common.image_base
- }
-
- fn entry(&self) -> u64 {
- u64::from(self.nt_headers.optional_header().address_of_entry_point())
- .wrapping_add(self.common.image_base)
- }
-
- fn flags(&self) -> FileFlags {
- FileFlags::Coff {
- characteristics: self.nt_headers.file_header().characteristics.get(LE),
- }
- }
-}
-
-/// An iterator for the COMDAT section groups in a [`PeFile32`].
-pub type PeComdatIterator32<'data, 'file, R = &'data [u8]> =
- PeComdatIterator<'data, 'file, pe::ImageNtHeaders32, R>;
-/// An iterator for the COMDAT section groups in a [`PeFile64`].
-pub type PeComdatIterator64<'data, 'file, R = &'data [u8]> =
- PeComdatIterator<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// An iterator for the COMDAT section groups in a [`PeFile`].
-///
-/// This is a stub that doesn't implement any functionality.
-#[derive(Debug)]
-pub struct PeComdatIterator<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- #[allow(unused)]
- file: &'file PeFile<'data, Pe, R>,
-}
-
-impl<'data, 'file, Pe, R> Iterator for PeComdatIterator<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type Item = PeComdat<'data, 'file, Pe, R>;
-
- #[inline]
- fn next(&mut self) -> Option<Self::Item> {
- None
- }
-}
-
-/// A COMDAT section group in a [`PeFile32`].
-pub type PeComdat32<'data, 'file, R = &'data [u8]> =
- PeComdat<'data, 'file, pe::ImageNtHeaders32, R>;
-/// A COMDAT section group in a [`PeFile64`].
-pub type PeComdat64<'data, 'file, R = &'data [u8]> =
- PeComdat<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// A COMDAT section group in a [`PeFile`].
-///
-/// This is a stub that doesn't implement any functionality.
-#[derive(Debug)]
-pub struct PeComdat<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- #[allow(unused)]
- file: &'file PeFile<'data, Pe, R>,
-}
-
-impl<'data, 'file, Pe, R> read::private::Sealed for PeComdat<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Pe, R> ObjectComdat<'data> for PeComdat<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type SectionIterator = PeComdatSectionIterator<'data, 'file, Pe, R>;
-
- #[inline]
- fn kind(&self) -> ComdatKind {
- unreachable!();
- }
-
- #[inline]
- fn symbol(&self) -> SymbolIndex {
- unreachable!();
- }
-
- #[inline]
- fn name_bytes(&self) -> Result<&[u8]> {
- unreachable!();
- }
-
- #[inline]
- fn name(&self) -> Result<&str> {
- unreachable!();
- }
-
- #[inline]
- fn sections(&self) -> Self::SectionIterator {
- unreachable!();
- }
-}
-
-/// An iterator for the sections in a COMDAT section group in a [`PeFile32`].
-pub type PeComdatSectionIterator32<'data, 'file, R = &'data [u8]> =
- PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
-/// An iterator for the sections in a COMDAT section group in a [`PeFile64`].
-pub type PeComdatSectionIterator64<'data, 'file, R = &'data [u8]> =
- PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// An iterator for the sections in a COMDAT section group in a [`PeFile`].
-///
-/// This is a stub that doesn't implement any functionality.
-#[derive(Debug)]
-pub struct PeComdatSectionIterator<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- #[allow(unused)]
- file: &'file PeFile<'data, Pe, R>,
-}
-
-impl<'data, 'file, Pe, R> Iterator for PeComdatSectionIterator<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type Item = SectionIndex;
-
- fn next(&mut self) -> Option<Self::Item> {
- None
- }
-}
-
-impl pe::ImageDosHeader {
- /// Read the DOS header.
- ///
- /// Also checks that the `e_magic` field in the header is valid.
- pub fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> {
- // DOS header comes first.
- let dos_header = data
- .read_at::<pe::ImageDosHeader>(0)
- .read_error("Invalid DOS header size or alignment")?;
- if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE {
- return Err(Error("Invalid DOS magic"));
- }
- Ok(dos_header)
- }
-
- /// Return the file offset of the nt_headers.
- #[inline]
- pub fn nt_headers_offset(&self) -> u32 {
- self.e_lfanew.get(LE)
- }
-}
-
-/// Find the optional header and read its `magic` field.
-///
-/// It can be useful to know this magic value before trying to
-/// fully parse the NT headers.
-pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result<u16> {
- let dos_header = pe::ImageDosHeader::parse(data)?;
- // NT headers are at an offset specified in the DOS header.
- let offset = dos_header.nt_headers_offset().into();
- // It doesn't matter which NT header type is used for the purpose
- // of reading the optional header magic.
- let nt_headers = data
- .read_at::<pe::ImageNtHeaders32>(offset)
- .read_error("Invalid NT headers offset, size, or alignment")?;
- if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
- return Err(Error("Invalid PE magic"));
- }
- Ok(nt_headers.optional_header().magic())
-}
-
-/// A trait for generic access to [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`].
-#[allow(missing_docs)]
-pub trait ImageNtHeaders: Debug + Pod {
- type ImageOptionalHeader: ImageOptionalHeader;
- type ImageThunkData: ImageThunkData;
-
- /// Return true if this type is a 64-bit header.
- ///
- /// This is a property of the type, not a value in the header data.
- fn is_type_64(&self) -> bool;
-
- /// Return true if the magic field in the optional header is valid.
- fn is_valid_optional_magic(&self) -> bool;
-
- /// Return the signature
- fn signature(&self) -> u32;
-
- /// Return the file header.
- fn file_header(&self) -> &pe::ImageFileHeader;
-
- /// Return the optional header.
- fn optional_header(&self) -> &Self::ImageOptionalHeader;
-
- // Provided methods.
-
- /// Read the NT headers, including the data directories.
- ///
- /// `data` must be for the entire file.
- ///
- /// `offset` must be headers offset, which can be obtained from [`pe::ImageDosHeader::nt_headers_offset`].
- /// It is updated to point after the optional header, which is where the section headers are located.
- ///
- /// Also checks that the `signature` and `magic` fields in the headers are valid.
- fn parse<'data, R: ReadRef<'data>>(
- data: R,
- offset: &mut u64,
- ) -> read::Result<(&'data Self, DataDirectories<'data>)> {
- // Note that this does not include the data directories in the optional header.
- let nt_headers = data
- .read::<Self>(offset)
- .read_error("Invalid PE headers offset or size")?;
- if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE {
- return Err(Error("Invalid PE magic"));
- }
- if !nt_headers.is_valid_optional_magic() {
- return Err(Error("Invalid PE optional header magic"));
- }
-
- // Read the rest of the optional header, and then read the data directories from that.
- let optional_data_size =
- u64::from(nt_headers.file_header().size_of_optional_header.get(LE))
- .checked_sub(mem::size_of::<Self::ImageOptionalHeader>() as u64)
- .read_error("PE optional header size is too small")?;
- let optional_data = data
- .read_bytes(offset, optional_data_size)
- .read_error("Invalid PE optional header size")?;
- let data_directories = DataDirectories::parse(
- optional_data,
- nt_headers.optional_header().number_of_rva_and_sizes(),
- )?;
-
- Ok((nt_headers, data_directories))
- }
-
- /// Read the section table.
- ///
- /// `data` must be for the entire file.
- /// `offset` must be after the optional file header.
- #[inline]
- fn sections<'data, R: ReadRef<'data>>(
- &self,
- data: R,
- offset: u64,
- ) -> read::Result<SectionTable<'data>> {
- SectionTable::parse(self.file_header(), data, offset)
- }
-
- /// Read the COFF symbol table and string table.
- ///
- /// `data` must be the entire file data.
- #[inline]
- fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<SymbolTable<'data, R>> {
- SymbolTable::parse(self.file_header(), data)
- }
-}
-
-/// A trait for generic access to [`pe::ImageOptionalHeader32`] and [`pe::ImageOptionalHeader64`].
-#[allow(missing_docs)]
-pub trait ImageOptionalHeader: Debug + Pod {
- // Standard fields.
- fn magic(&self) -> u16;
- fn major_linker_version(&self) -> u8;
- fn minor_linker_version(&self) -> u8;
- fn size_of_code(&self) -> u32;
- fn size_of_initialized_data(&self) -> u32;
- fn size_of_uninitialized_data(&self) -> u32;
- fn address_of_entry_point(&self) -> u32;
- fn base_of_code(&self) -> u32;
- fn base_of_data(&self) -> Option<u32>;
-
- // NT additional fields.
- fn image_base(&self) -> u64;
- fn section_alignment(&self) -> u32;
- fn file_alignment(&self) -> u32;
- fn major_operating_system_version(&self) -> u16;
- fn minor_operating_system_version(&self) -> u16;
- fn major_image_version(&self) -> u16;
- fn minor_image_version(&self) -> u16;
- fn major_subsystem_version(&self) -> u16;
- fn minor_subsystem_version(&self) -> u16;
- fn win32_version_value(&self) -> u32;
- fn size_of_image(&self) -> u32;
- fn size_of_headers(&self) -> u32;
- fn check_sum(&self) -> u32;
- fn subsystem(&self) -> u16;
- fn dll_characteristics(&self) -> u16;
- fn size_of_stack_reserve(&self) -> u64;
- fn size_of_stack_commit(&self) -> u64;
- fn size_of_heap_reserve(&self) -> u64;
- fn size_of_heap_commit(&self) -> u64;
- fn loader_flags(&self) -> u32;
- fn number_of_rva_and_sizes(&self) -> u32;
-}
-
-impl ImageNtHeaders for pe::ImageNtHeaders32 {
- type ImageOptionalHeader = pe::ImageOptionalHeader32;
- type ImageThunkData = pe::ImageThunkData32;
-
- #[inline]
- fn is_type_64(&self) -> bool {
- false
- }
-
- #[inline]
- fn is_valid_optional_magic(&self) -> bool {
- self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC
- }
-
- #[inline]
- fn signature(&self) -> u32 {
- self.signature.get(LE)
- }
-
- #[inline]
- fn file_header(&self) -> &pe::ImageFileHeader {
- &self.file_header
- }
-
- #[inline]
- fn optional_header(&self) -> &Self::ImageOptionalHeader {
- &self.optional_header
- }
-}
-
-impl ImageOptionalHeader for pe::ImageOptionalHeader32 {
- #[inline]
- fn magic(&self) -> u16 {
- self.magic.get(LE)
- }
-
- #[inline]
- fn major_linker_version(&self) -> u8 {
- self.major_linker_version
- }
-
- #[inline]
- fn minor_linker_version(&self) -> u8 {
- self.minor_linker_version
- }
-
- #[inline]
- fn size_of_code(&self) -> u32 {
- self.size_of_code.get(LE)
- }
-
- #[inline]
- fn size_of_initialized_data(&self) -> u32 {
- self.size_of_initialized_data.get(LE)
- }
-
- #[inline]
- fn size_of_uninitialized_data(&self) -> u32 {
- self.size_of_uninitialized_data.get(LE)
- }
-
- #[inline]
- fn address_of_entry_point(&self) -> u32 {
- self.address_of_entry_point.get(LE)
- }
-
- #[inline]
- fn base_of_code(&self) -> u32 {
- self.base_of_code.get(LE)
- }
-
- #[inline]
- fn base_of_data(&self) -> Option<u32> {
- Some(self.base_of_data.get(LE))
- }
-
- #[inline]
- fn image_base(&self) -> u64 {
- self.image_base.get(LE).into()
- }
-
- #[inline]
- fn section_alignment(&self) -> u32 {
- self.section_alignment.get(LE)
- }
-
- #[inline]
- fn file_alignment(&self) -> u32 {
- self.file_alignment.get(LE)
- }
-
- #[inline]
- fn major_operating_system_version(&self) -> u16 {
- self.major_operating_system_version.get(LE)
- }
-
- #[inline]
- fn minor_operating_system_version(&self) -> u16 {
- self.minor_operating_system_version.get(LE)
- }
-
- #[inline]
- fn major_image_version(&self) -> u16 {
- self.major_image_version.get(LE)
- }
-
- #[inline]
- fn minor_image_version(&self) -> u16 {
- self.minor_image_version.get(LE)
- }
-
- #[inline]
- fn major_subsystem_version(&self) -> u16 {
- self.major_subsystem_version.get(LE)
- }
-
- #[inline]
- fn minor_subsystem_version(&self) -> u16 {
- self.minor_subsystem_version.get(LE)
- }
-
- #[inline]
- fn win32_version_value(&self) -> u32 {
- self.win32_version_value.get(LE)
- }
-
- #[inline]
- fn size_of_image(&self) -> u32 {
- self.size_of_image.get(LE)
- }
-
- #[inline]
- fn size_of_headers(&self) -> u32 {
- self.size_of_headers.get(LE)
- }
-
- #[inline]
- fn check_sum(&self) -> u32 {
- self.check_sum.get(LE)
- }
-
- #[inline]
- fn subsystem(&self) -> u16 {
- self.subsystem.get(LE)
- }
-
- #[inline]
- fn dll_characteristics(&self) -> u16 {
- self.dll_characteristics.get(LE)
- }
-
- #[inline]
- fn size_of_stack_reserve(&self) -> u64 {
- self.size_of_stack_reserve.get(LE).into()
- }
-
- #[inline]
- fn size_of_stack_commit(&self) -> u64 {
- self.size_of_stack_commit.get(LE).into()
- }
-
- #[inline]
- fn size_of_heap_reserve(&self) -> u64 {
- self.size_of_heap_reserve.get(LE).into()
- }
-
- #[inline]
- fn size_of_heap_commit(&self) -> u64 {
- self.size_of_heap_commit.get(LE).into()
- }
-
- #[inline]
- fn loader_flags(&self) -> u32 {
- self.loader_flags.get(LE)
- }
-
- #[inline]
- fn number_of_rva_and_sizes(&self) -> u32 {
- self.number_of_rva_and_sizes.get(LE)
- }
-}
-
-impl ImageNtHeaders for pe::ImageNtHeaders64 {
- type ImageOptionalHeader = pe::ImageOptionalHeader64;
- type ImageThunkData = pe::ImageThunkData64;
-
- #[inline]
- fn is_type_64(&self) -> bool {
- true
- }
-
- #[inline]
- fn is_valid_optional_magic(&self) -> bool {
- self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC
- }
-
- #[inline]
- fn signature(&self) -> u32 {
- self.signature.get(LE)
- }
-
- #[inline]
- fn file_header(&self) -> &pe::ImageFileHeader {
- &self.file_header
- }
-
- #[inline]
- fn optional_header(&self) -> &Self::ImageOptionalHeader {
- &self.optional_header
- }
-}
-
-impl ImageOptionalHeader for pe::ImageOptionalHeader64 {
- #[inline]
- fn magic(&self) -> u16 {
- self.magic.get(LE)
- }
-
- #[inline]
- fn major_linker_version(&self) -> u8 {
- self.major_linker_version
- }
-
- #[inline]
- fn minor_linker_version(&self) -> u8 {
- self.minor_linker_version
- }
-
- #[inline]
- fn size_of_code(&self) -> u32 {
- self.size_of_code.get(LE)
- }
-
- #[inline]
- fn size_of_initialized_data(&self) -> u32 {
- self.size_of_initialized_data.get(LE)
- }
-
- #[inline]
- fn size_of_uninitialized_data(&self) -> u32 {
- self.size_of_uninitialized_data.get(LE)
- }
-
- #[inline]
- fn address_of_entry_point(&self) -> u32 {
- self.address_of_entry_point.get(LE)
- }
-
- #[inline]
- fn base_of_code(&self) -> u32 {
- self.base_of_code.get(LE)
- }
-
- #[inline]
- fn base_of_data(&self) -> Option<u32> {
- None
- }
-
- #[inline]
- fn image_base(&self) -> u64 {
- self.image_base.get(LE)
- }
-
- #[inline]
- fn section_alignment(&self) -> u32 {
- self.section_alignment.get(LE)
- }
-
- #[inline]
- fn file_alignment(&self) -> u32 {
- self.file_alignment.get(LE)
- }
-
- #[inline]
- fn major_operating_system_version(&self) -> u16 {
- self.major_operating_system_version.get(LE)
- }
-
- #[inline]
- fn minor_operating_system_version(&self) -> u16 {
- self.minor_operating_system_version.get(LE)
- }
-
- #[inline]
- fn major_image_version(&self) -> u16 {
- self.major_image_version.get(LE)
- }
-
- #[inline]
- fn minor_image_version(&self) -> u16 {
- self.minor_image_version.get(LE)
- }
-
- #[inline]
- fn major_subsystem_version(&self) -> u16 {
- self.major_subsystem_version.get(LE)
- }
-
- #[inline]
- fn minor_subsystem_version(&self) -> u16 {
- self.minor_subsystem_version.get(LE)
- }
-
- #[inline]
- fn win32_version_value(&self) -> u32 {
- self.win32_version_value.get(LE)
- }
-
- #[inline]
- fn size_of_image(&self) -> u32 {
- self.size_of_image.get(LE)
- }
-
- #[inline]
- fn size_of_headers(&self) -> u32 {
- self.size_of_headers.get(LE)
- }
-
- #[inline]
- fn check_sum(&self) -> u32 {
- self.check_sum.get(LE)
- }
-
- #[inline]
- fn subsystem(&self) -> u16 {
- self.subsystem.get(LE)
- }
-
- #[inline]
- fn dll_characteristics(&self) -> u16 {
- self.dll_characteristics.get(LE)
- }
-
- #[inline]
- fn size_of_stack_reserve(&self) -> u64 {
- self.size_of_stack_reserve.get(LE)
- }
-
- #[inline]
- fn size_of_stack_commit(&self) -> u64 {
- self.size_of_stack_commit.get(LE)
- }
-
- #[inline]
- fn size_of_heap_reserve(&self) -> u64 {
- self.size_of_heap_reserve.get(LE)
- }
-
- #[inline]
- fn size_of_heap_commit(&self) -> u64 {
- self.size_of_heap_commit.get(LE)
- }
-
- #[inline]
- fn loader_flags(&self) -> u32 {
- self.loader_flags.get(LE)
- }
-
- #[inline]
- fn number_of_rva_and_sizes(&self) -> u32 {
- self.number_of_rva_and_sizes.get(LE)
- }
-}
diff --git a/vendor/object/src/read/pe/import.rs b/vendor/object/src/read/pe/import.rs
deleted file mode 100644
index 8e9a9a9..0000000
--- a/vendor/object/src/read/pe/import.rs
+++ /dev/null
@@ -1,337 +0,0 @@
-use core::fmt::Debug;
-use core::mem;
-
-use crate::read::{Bytes, ReadError, Result};
-use crate::{pe, LittleEndian as LE, Pod, U16Bytes};
-
-use super::ImageNtHeaders;
-
-/// Information for parsing a PE import table.
-///
-/// Returned by [`DataDirectories::import_table`](super::DataDirectories::import_table).
-#[derive(Debug, Clone)]
-pub struct ImportTable<'data> {
- section_data: Bytes<'data>,
- section_address: u32,
- import_address: u32,
-}
-
-impl<'data> ImportTable<'data> {
- /// Create a new import table parser.
- ///
- /// The import descriptors start at `import_address`.
- /// The size declared in the `IMAGE_DIRECTORY_ENTRY_IMPORT` data directory is
- /// ignored by the Windows loader, and so descriptors will be parsed until a null entry.
- ///
- /// `section_data` should be from the section containing `import_address`, and
- /// `section_address` should be the address of that section. Pointers within the
- /// descriptors and thunks may point to anywhere within the section data.
- pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
- ImportTable {
- section_data: Bytes(section_data),
- section_address,
- import_address,
- }
- }
-
- /// Return an iterator for the import descriptors.
- pub fn descriptors(&self) -> Result<ImportDescriptorIterator<'data>> {
- let offset = self.import_address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE import descriptor address")?;
- Ok(ImportDescriptorIterator { data })
- }
-
- /// Return a library name given its address.
- ///
- /// This address may be from [`pe::ImageImportDescriptor::name`].
- pub fn name(&self, address: u32) -> Result<&'data [u8]> {
- self.section_data
- .read_string_at(address.wrapping_sub(self.section_address) as usize)
- .read_error("Invalid PE import descriptor name")
- }
-
- /// Return a list of thunks given its address.
- ///
- /// This address may be from [`pe::ImageImportDescriptor::original_first_thunk`]
- /// or [`pe::ImageImportDescriptor::first_thunk`].
- pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
- let offset = address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE import thunk table address")?;
- Ok(ImportThunkList { data })
- }
-
- /// Parse a thunk.
- pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
- if thunk.is_ordinal() {
- Ok(Import::Ordinal(thunk.ordinal()))
- } else {
- let (hint, name) = self.hint_name(thunk.address())?;
- Ok(Import::Name(hint, name))
- }
- }
-
- /// Return the hint and name at the given address.
- ///
- /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`].
- ///
- /// The hint is an index into the export name pointer table in the target library.
- pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
- let offset = address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE import thunk address")?;
- let hint = data
- .read::<U16Bytes<LE>>()
- .read_error("Missing PE import thunk hint")?
- .get(LE);
- let name = data
- .read_string()
- .read_error("Missing PE import thunk name")?;
- Ok((hint, name))
- }
-}
-
-/// A fallible iterator for the descriptors in the import data directory.
-#[derive(Debug, Clone)]
-pub struct ImportDescriptorIterator<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> ImportDescriptorIterator<'data> {
- /// Return the next descriptor.
- ///
- /// Returns `Ok(None)` when a null descriptor is found.
- pub fn next(&mut self) -> Result<Option<&'data pe::ImageImportDescriptor>> {
- let import_desc = self
- .data
- .read::<pe::ImageImportDescriptor>()
- .read_error("Missing PE null import descriptor")?;
- if import_desc.is_null() {
- Ok(None)
- } else {
- Ok(Some(import_desc))
- }
- }
-}
-
-/// A list of import thunks.
-///
-/// These may be in the import lookup table, or the import address table.
-#[derive(Debug, Clone)]
-pub struct ImportThunkList<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> ImportThunkList<'data> {
- /// Get the thunk at the given index.
- pub fn get<Pe: ImageNtHeaders>(&self, index: usize) -> Result<Pe::ImageThunkData> {
- let thunk = self
- .data
- .read_at(index * mem::size_of::<Pe::ImageThunkData>())
- .read_error("Invalid PE import thunk index")?;
- Ok(*thunk)
- }
-
- /// Return the first thunk in the list, and update `self` to point after it.
- ///
- /// Returns `Ok(None)` when a null thunk is found.
- pub fn next<Pe: ImageNtHeaders>(&mut self) -> Result<Option<Pe::ImageThunkData>> {
- let thunk = self
- .data
- .read::<Pe::ImageThunkData>()
- .read_error("Missing PE null import thunk")?;
- if thunk.address() == 0 {
- Ok(None)
- } else {
- Ok(Some(*thunk))
- }
- }
-}
-
-/// A parsed import thunk.
-#[derive(Debug, Clone, Copy)]
-pub enum Import<'data> {
- /// Import by ordinal.
- Ordinal(u16),
- /// Import by name.
- ///
- /// Includes a hint for the index into the export name pointer table in the target library.
- Name(u16, &'data [u8]),
-}
-
-/// A trait for generic access to [`pe::ImageThunkData32`] and [`pe::ImageThunkData64`].
-#[allow(missing_docs)]
-pub trait ImageThunkData: Debug + Pod {
- /// Return the raw thunk value.
- fn raw(self) -> u64;
-
- /// Returns true if the ordinal flag is set.
- fn is_ordinal(self) -> bool;
-
- /// Return the ordinal portion of the thunk.
- ///
- /// Does not check the ordinal flag.
- fn ordinal(self) -> u16;
-
- /// Return the RVA portion of the thunk.
- ///
- /// Does not check the ordinal flag.
- fn address(self) -> u32;
-}
-
-impl ImageThunkData for pe::ImageThunkData64 {
- fn raw(self) -> u64 {
- self.0.get(LE)
- }
-
- fn is_ordinal(self) -> bool {
- self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG64 != 0
- }
-
- fn ordinal(self) -> u16 {
- self.0.get(LE) as u16
- }
-
- fn address(self) -> u32 {
- self.0.get(LE) as u32 & 0x7fff_ffff
- }
-}
-
-impl ImageThunkData for pe::ImageThunkData32 {
- fn raw(self) -> u64 {
- self.0.get(LE).into()
- }
-
- fn is_ordinal(self) -> bool {
- self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG32 != 0
- }
-
- fn ordinal(self) -> u16 {
- self.0.get(LE) as u16
- }
-
- fn address(self) -> u32 {
- self.0.get(LE) & 0x7fff_ffff
- }
-}
-
-/// Information for parsing a PE delay-load import table.
-///
-/// Returned by
-/// [`DataDirectories::delay_load_import_table`](super::DataDirectories::delay_load_import_table).
-#[derive(Debug, Clone)]
-pub struct DelayLoadImportTable<'data> {
- section_data: Bytes<'data>,
- section_address: u32,
- import_address: u32,
-}
-
-impl<'data> DelayLoadImportTable<'data> {
- /// Create a new delay load import table parser.
- ///
- /// The import descriptors start at `import_address`.
- /// This table works in the same way the import table does: descriptors will be
- /// parsed until a null entry.
- ///
- /// `section_data` should be from the section containing `import_address`, and
- /// `section_address` should be the address of that section. Pointers within the
- /// descriptors and thunks may point to anywhere within the section data.
- pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
- DelayLoadImportTable {
- section_data: Bytes(section_data),
- section_address,
- import_address,
- }
- }
-
- /// Return an iterator for the import descriptors.
- pub fn descriptors(&self) -> Result<DelayLoadDescriptorIterator<'data>> {
- let offset = self.import_address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE delay-load import descriptor address")?;
- Ok(DelayLoadDescriptorIterator { data })
- }
-
- /// Return a library name given its address.
- ///
- /// This address may be from [`pe::ImageDelayloadDescriptor::dll_name_rva`].
- pub fn name(&self, address: u32) -> Result<&'data [u8]> {
- self.section_data
- .read_string_at(address.wrapping_sub(self.section_address) as usize)
- .read_error("Invalid PE import descriptor name")
- }
-
- /// Return a list of thunks given its address.
- ///
- /// This address may be from the INT, i.e. from
- /// [`pe::ImageDelayloadDescriptor::import_name_table_rva`].
- ///
- /// Please note that others RVA values from [`pe::ImageDelayloadDescriptor`] are used
- /// by the delay loader at runtime to store values, and thus do not point inside the same
- /// section as the INT. Calling this function on those addresses will fail.
- pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
- let offset = address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE delay load import thunk table address")?;
- Ok(ImportThunkList { data })
- }
-
- /// Parse a thunk.
- pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
- if thunk.is_ordinal() {
- Ok(Import::Ordinal(thunk.ordinal()))
- } else {
- let (hint, name) = self.hint_name(thunk.address())?;
- Ok(Import::Name(hint, name))
- }
- }
-
- /// Return the hint and name at the given address.
- ///
- /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`].
- ///
- /// The hint is an index into the export name pointer table in the target library.
- pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
- let offset = address.wrapping_sub(self.section_address);
- let mut data = self.section_data;
- data.skip(offset as usize)
- .read_error("Invalid PE delay load import thunk address")?;
- let hint = data
- .read::<U16Bytes<LE>>()
- .read_error("Missing PE delay load import thunk hint")?
- .get(LE);
- let name = data
- .read_string()
- .read_error("Missing PE delay load import thunk name")?;
- Ok((hint, name))
- }
-}
-
-/// A fallible iterator for the descriptors in the delay-load data directory.
-#[derive(Debug, Clone)]
-pub struct DelayLoadDescriptorIterator<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> DelayLoadDescriptorIterator<'data> {
- /// Return the next descriptor.
- ///
- /// Returns `Ok(None)` when a null descriptor is found.
- pub fn next(&mut self) -> Result<Option<&'data pe::ImageDelayloadDescriptor>> {
- let import_desc = self
- .data
- .read::<pe::ImageDelayloadDescriptor>()
- .read_error("Missing PE null delay-load import descriptor")?;
- if import_desc.is_null() {
- Ok(None)
- } else {
- Ok(Some(import_desc))
- }
- }
-}
diff --git a/vendor/object/src/read/pe/mod.rs b/vendor/object/src/read/pe/mod.rs
deleted file mode 100644
index ab6011c..0000000
--- a/vendor/object/src/read/pe/mod.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Support for reading PE files.
-//!
-//! Traits are used to abstract over the difference between PE32 and PE32+.
-//! The primary trait for this is [`ImageNtHeaders`].
-//!
-//! ## High level API
-//!
-//! [`PeFile`] implements the [`Object`](crate::read::Object) trait for
-//! PE files. [`PeFile`] is parameterised by [`ImageNtHeaders`] to allow
-//! reading both PE32 and PE32+. There are type aliases for these parameters
-//! ([`PeFile32`] and [`PeFile64`]).
-//!
-//! ## Low level API
-//!
-//! The [`ImageNtHeaders`] trait can be directly used to parse both
-//! [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`].
-//!
-//! ### Example for low level API
-//! ```no_run
-//! use object::pe;
-//! use object::read::pe::ImageNtHeaders;
-//! use std::error::Error;
-//! use std::fs;
-//!
-//! /// Reads a file and displays the name of each section.
-//! fn main() -> Result<(), Box<dyn Error>> {
-//! # #[cfg(feature = "std")] {
-//! let data = fs::read("path/to/binary")?;
-//! let dos_header = pe::ImageDosHeader::parse(&*data)?;
-//! let mut offset = dos_header.nt_headers_offset().into();
-//! let (nt_headers, data_directories) = pe::ImageNtHeaders64::parse(&*data, &mut offset)?;
-//! let sections = nt_headers.sections(&*data, offset)?;
-//! let symbols = nt_headers.symbols(&*data)?;
-//! for section in sections.iter() {
-//! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?));
-//! }
-//! # }
-//! Ok(())
-//! }
-//! ```
-#[cfg(doc)]
-use crate::pe;
-
-mod file;
-pub use file::*;
-
-mod section;
-pub use section::*;
-
-mod data_directory;
-pub use data_directory::*;
-
-mod export;
-pub use export::*;
-
-mod import;
-pub use import::*;
-
-mod relocation;
-pub use relocation::*;
-
-mod resource;
-pub use resource::*;
-
-mod rich;
-pub use rich::*;
-
-pub use super::coff::{SectionTable, SymbolTable};
diff --git a/vendor/object/src/read/pe/relocation.rs b/vendor/object/src/read/pe/relocation.rs
deleted file mode 100644
index 77421b7..0000000
--- a/vendor/object/src/read/pe/relocation.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use core::slice;
-
-use crate::endian::{LittleEndian as LE, U16};
-use crate::pe;
-use crate::read::{Bytes, Error, ReadError, Result};
-
-/// An iterator over the relocation blocks in the `.reloc` section of a PE file.
-///
-/// Returned by [`DataDirectories::relocation_blocks`](super::DataDirectories::relocation_blocks).
-#[derive(Debug, Default, Clone, Copy)]
-pub struct RelocationBlockIterator<'data> {
- data: Bytes<'data>,
-}
-
-impl<'data> RelocationBlockIterator<'data> {
- /// Construct a new iterator from the data of the `.reloc` section.
- pub fn new(data: &'data [u8]) -> Self {
- RelocationBlockIterator { data: Bytes(data) }
- }
-
- /// Read the next relocation page.
- pub fn next(&mut self) -> Result<Option<RelocationIterator<'data>>> {
- if self.data.is_empty() {
- return Ok(None);
- }
- let header = self
- .data
- .read::<pe::ImageBaseRelocation>()
- .read_error("Invalid PE reloc section size")?;
- let virtual_address = header.virtual_address.get(LE);
- let size = header.size_of_block.get(LE);
- if size <= 8 || size & 3 != 0 {
- return Err(Error("Invalid PE reloc block size"));
- }
- let count = (size - 8) / 2;
- let relocs = self
- .data
- .read_slice::<U16<LE>>(count as usize)
- .read_error("Invalid PE reloc block size")?
- .iter();
- Ok(Some(RelocationIterator {
- virtual_address,
- size,
- relocs,
- }))
- }
-}
-
-/// An iterator of the relocations in a block in the `.reloc` section of a PE file.
-#[derive(Debug, Clone)]
-pub struct RelocationIterator<'data> {
- virtual_address: u32,
- size: u32,
- relocs: slice::Iter<'data, U16<LE>>,
-}
-
-impl<'data> RelocationIterator<'data> {
- /// Return the virtual address of the page that this block of relocations applies to.
- pub fn virtual_address(&self) -> u32 {
- self.virtual_address
- }
-
- /// Return the size in bytes of this block of relocations.
- pub fn size(&self) -> u32 {
- self.size
- }
-}
-
-impl<'data> Iterator for RelocationIterator<'data> {
- type Item = Relocation;
-
- fn next(&mut self) -> Option<Relocation> {
- loop {
- let reloc = self.relocs.next()?.get(LE);
- if reloc != 0 {
- return Some(Relocation {
- virtual_address: self.virtual_address.wrapping_add((reloc & 0xfff) as u32),
- typ: reloc >> 12,
- });
- }
- }
- }
-}
-
-/// A relocation in the `.reloc` section of a PE file.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct Relocation {
- /// The virtual address of the relocation.
- pub virtual_address: u32,
- /// One of the `pe::IMAGE_REL_BASED_*` constants.
- pub typ: u16,
-}
diff --git a/vendor/object/src/read/pe/resource.rs b/vendor/object/src/read/pe/resource.rs
deleted file mode 100644
index 331da3f..0000000
--- a/vendor/object/src/read/pe/resource.rs
+++ /dev/null
@@ -1,209 +0,0 @@
-use alloc::string::String;
-use core::char;
-
-use crate::read::{ReadError, ReadRef, Result};
-use crate::{pe, LittleEndian as LE, U16Bytes};
-
-/// The `.rsrc` section of a PE file.
-///
-/// Returned by [`DataDirectories::resource_directory`](super::DataDirectories::resource_directory).
-#[derive(Debug, Clone, Copy)]
-pub struct ResourceDirectory<'data> {
- data: &'data [u8],
-}
-
-impl<'data> ResourceDirectory<'data> {
- /// Construct from the data of the `.rsrc` section.
- pub fn new(data: &'data [u8]) -> Self {
- ResourceDirectory { data }
- }
-
- /// Parses the root resource directory.
- pub fn root(&self) -> Result<ResourceDirectoryTable<'data>> {
- ResourceDirectoryTable::parse(self.data, 0)
- }
-}
-
-/// A table of resource entries.
-#[derive(Debug, Clone)]
-pub struct ResourceDirectoryTable<'data> {
- /// The table header.
- pub header: &'data pe::ImageResourceDirectory,
- /// The table entries.
- pub entries: &'data [pe::ImageResourceDirectoryEntry],
-}
-
-impl<'data> ResourceDirectoryTable<'data> {
- fn parse(data: &'data [u8], offset: u32) -> Result<Self> {
- let mut offset = u64::from(offset);
- let header = data
- .read::<pe::ImageResourceDirectory>(&mut offset)
- .read_error("Invalid resource table header")?;
- let entries_count = header.number_of_id_entries.get(LE) as usize
- + header.number_of_named_entries.get(LE) as usize;
- let entries = data
- .read_slice::<pe::ImageResourceDirectoryEntry>(&mut offset, entries_count)
- .read_error("Invalid resource table entries")?;
- Ok(Self { header, entries })
- }
-}
-
-impl pe::ImageResourceDirectoryEntry {
- /// Returns true if the entry has a name, rather than an ID.
- pub fn has_name(&self) -> bool {
- self.name_or_id.get(LE) & pe::IMAGE_RESOURCE_NAME_IS_STRING != 0
- }
-
- /// Returns the section offset of the name.
- ///
- /// Valid if `has_name()` returns true.
- fn name(&self) -> ResourceName {
- let offset = self.name_or_id.get(LE) & !pe::IMAGE_RESOURCE_NAME_IS_STRING;
- ResourceName { offset }
- }
-
- /// Returns the ID.
- ///
- /// Valid if `has_string_name()` returns false.
- fn id(&self) -> u16 {
- (self.name_or_id.get(LE) & 0x0000_FFFF) as u16
- }
-
- /// Returns the entry name
- pub fn name_or_id(&self) -> ResourceNameOrId {
- if self.has_name() {
- ResourceNameOrId::Name(self.name())
- } else {
- ResourceNameOrId::Id(self.id())
- }
- }
-
- /// Returns true if the entry is a subtable.
- pub fn is_table(&self) -> bool {
- self.offset_to_data_or_directory.get(LE) & pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY != 0
- }
-
- /// Returns the section offset of the associated table or data.
- pub fn data_offset(&self) -> u32 {
- self.offset_to_data_or_directory.get(LE) & !pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY
- }
-
- /// Returns the data associated to this directory entry.
- pub fn data<'data>(
- &self,
- section: ResourceDirectory<'data>,
- ) -> Result<ResourceDirectoryEntryData<'data>> {
- if self.is_table() {
- ResourceDirectoryTable::parse(section.data, self.data_offset())
- .map(ResourceDirectoryEntryData::Table)
- } else {
- section
- .data
- .read_at::<pe::ImageResourceDataEntry>(self.data_offset().into())
- .read_error("Invalid resource entry")
- .map(ResourceDirectoryEntryData::Data)
- }
- }
-}
-
-/// Data associated with a resource directory entry.
-#[derive(Debug, Clone)]
-pub enum ResourceDirectoryEntryData<'data> {
- /// A subtable entry.
- Table(ResourceDirectoryTable<'data>),
- /// A resource data entry.
- Data(&'data pe::ImageResourceDataEntry),
-}
-
-impl<'data> ResourceDirectoryEntryData<'data> {
- /// Converts to an option of table.
- ///
- /// Helper for iterator filtering.
- pub fn table(self) -> Option<ResourceDirectoryTable<'data>> {
- match self {
- Self::Table(dir) => Some(dir),
- _ => None,
- }
- }
-
- /// Converts to an option of data entry.
- ///
- /// Helper for iterator filtering.
- pub fn data(self) -> Option<&'data pe::ImageResourceDataEntry> {
- match self {
- Self::Data(rsc) => Some(rsc),
- _ => None,
- }
- }
-}
-
-/// A resource name.
-#[derive(Debug, Clone, Copy)]
-pub struct ResourceName {
- offset: u32,
-}
-
-impl ResourceName {
- /// Converts to a `String`.
- pub fn to_string_lossy(&self, directory: ResourceDirectory<'_>) -> Result<String> {
- let d = self.data(directory)?.iter().map(|c| c.get(LE));
-
- Ok(char::decode_utf16(d)
- .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
- .collect::<String>())
- }
-
- /// Returns the string unicode buffer.
- pub fn data<'data>(
- &self,
- directory: ResourceDirectory<'data>,
- ) -> Result<&'data [U16Bytes<LE>]> {
- let mut offset = u64::from(self.offset);
- let len = directory
- .data
- .read::<U16Bytes<LE>>(&mut offset)
- .read_error("Invalid resource name offset")?;
- directory
- .data
- .read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
- .read_error("Invalid resource name length")
- }
-
- /// Returns the string buffer as raw bytes.
- pub fn raw_data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u8]> {
- self.data(directory).map(crate::pod::bytes_of_slice)
- }
-}
-
-/// A resource name or ID.
-///
-/// Can be either a string or a numeric ID.
-#[derive(Debug)]
-pub enum ResourceNameOrId {
- /// A resource name.
- Name(ResourceName),
- /// A resource ID.
- Id(u16),
-}
-
-impl ResourceNameOrId {
- /// Converts to an option of name.
- ///
- /// Helper for iterator filtering.
- pub fn name(self) -> Option<ResourceName> {
- match self {
- Self::Name(name) => Some(name),
- _ => None,
- }
- }
-
- /// Converts to an option of ID.
- ///
- /// Helper for iterator filtering.
- pub fn id(self) -> Option<u16> {
- match self {
- Self::Id(id) => Some(id),
- _ => None,
- }
- }
-}
diff --git a/vendor/object/src/read/pe/rich.rs b/vendor/object/src/read/pe/rich.rs
deleted file mode 100644
index 33dd039..0000000
--- a/vendor/object/src/read/pe/rich.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-//! PE rich header handling
-
-use core::mem;
-
-use crate::pod::bytes_of_slice;
-use crate::read::Bytes;
-use crate::{pe, LittleEndian as LE, ReadRef, U32};
-
-/// Parsed information about a Rich Header.
-#[derive(Debug, Clone, Copy)]
-pub struct RichHeaderInfo<'data> {
- /// The offset at which the rich header starts.
- pub offset: usize,
- /// The length (in bytes) of the rich header.
- ///
- /// This includes the payload, but also the 16-byte start sequence and the
- /// 8-byte final "Rich" and XOR key.
- pub length: usize,
- /// The XOR key used to mask the rich header.
- ///
- /// Unless the file has been tampered with, it should be equal to a checksum
- /// of the file header.
- pub xor_key: u32,
- masked_entries: &'data [pe::MaskedRichHeaderEntry],
-}
-
-/// A PE rich header entry after it has been unmasked.
-///
-/// See [`pe::MaskedRichHeaderEntry`].
-#[derive(Debug, Clone, Copy)]
-#[repr(C)]
-pub struct RichHeaderEntry {
- /// ID of the component.
- pub comp_id: u32,
- /// Number of times this component has been used when building this PE.
- pub count: u32,
-}
-
-impl<'data> RichHeaderInfo<'data> {
- /// Try to locate a rich header and its entries in the current PE file.
- pub fn parse<R: ReadRef<'data>>(data: R, nt_header_offset: u64) -> Option<Self> {
- // Locate the rich header, if any.
- // It ends with the "Rich" string and an XOR key, before the NT header.
- let data = data.read_bytes_at(0, nt_header_offset).map(Bytes).ok()?;
- let end_marker_offset = memmem(data.0, b"Rich", 4)?;
- let xor_key = *data.read_at::<U32<LE>>(end_marker_offset + 4).ok()?;
-
- // It starts at the masked "DanS" string and 3 masked zeroes.
- let masked_start_marker = U32::new(LE, 0x536e_6144 ^ xor_key.get(LE));
- let start_header = [masked_start_marker, xor_key, xor_key, xor_key];
- let start_sequence = bytes_of_slice(&start_header);
- let start_marker_offset = memmem(&data.0[..end_marker_offset], start_sequence, 4)?;
-
- // Extract the items between the markers.
- let items_offset = start_marker_offset + start_sequence.len();
- let items_len = end_marker_offset - items_offset;
- let item_count = items_len / mem::size_of::<pe::MaskedRichHeaderEntry>();
- let items = data.read_slice_at(items_offset, item_count).ok()?;
- Some(RichHeaderInfo {
- offset: start_marker_offset,
- // Includes "Rich" marker and the XOR key.
- length: end_marker_offset - start_marker_offset + 8,
- xor_key: xor_key.get(LE),
- masked_entries: items,
- })
- }
-
- /// Returns an iterator over the unmasked entries.
- pub fn unmasked_entries(&self) -> impl Iterator<Item = RichHeaderEntry> + 'data {
- let xor_key = self.xor_key;
- self.masked_entries
- .iter()
- .map(move |entry| RichHeaderEntry {
- comp_id: entry.masked_comp_id.get(LE) ^ xor_key,
- count: entry.masked_count.get(LE) ^ xor_key,
- })
- }
-}
-
-/// Find the offset of the first occurrence of needle in the data.
-///
-/// The offset must have the given alignment.
-fn memmem(data: &[u8], needle: &[u8], align: usize) -> Option<usize> {
- let mut offset = 0;
- loop {
- if data.get(offset..)?.get(..needle.len())? == needle {
- return Some(offset);
- }
- offset += align;
- }
-}
diff --git a/vendor/object/src/read/pe/section.rs b/vendor/object/src/read/pe/section.rs
deleted file mode 100644
index 74c9d7f..0000000
--- a/vendor/object/src/read/pe/section.rs
+++ /dev/null
@@ -1,440 +0,0 @@
-use core::marker::PhantomData;
-use core::{cmp, iter, slice, str};
-
-use crate::endian::LittleEndian as LE;
-use crate::pe;
-use crate::pe::ImageSectionHeader;
-use crate::read::{
- self, CompressedData, CompressedFileRange, ObjectSection, ObjectSegment, ReadError, ReadRef,
- Relocation, Result, SectionFlags, SectionIndex, SectionKind, SegmentFlags,
-};
-
-use super::{ImageNtHeaders, PeFile, SectionTable};
-
-/// An iterator for the loadable sections in a [`PeFile32`](super::PeFile32).
-pub type PeSegmentIterator32<'data, 'file, R = &'data [u8]> =
- PeSegmentIterator<'data, 'file, pe::ImageNtHeaders32, R>;
-/// An iterator for the loadable sections in a [`PeFile64`](super::PeFile64).
-pub type PeSegmentIterator64<'data, 'file, R = &'data [u8]> =
- PeSegmentIterator<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// An iterator for the loadable sections in a [`PeFile`].
-#[derive(Debug)]
-pub struct PeSegmentIterator<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file PeFile<'data, Pe, R>,
- pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>,
-}
-
-impl<'data, 'file, Pe, R> Iterator for PeSegmentIterator<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type Item = PeSegment<'data, 'file, Pe, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|section| PeSegment {
- file: self.file,
- section,
- })
- }
-}
-
-/// A loadable section in a [`PeFile32`](super::PeFile32).
-pub type PeSegment32<'data, 'file, R = &'data [u8]> =
- PeSegment<'data, 'file, pe::ImageNtHeaders32, R>;
-/// A loadable section in a [`PeFile64`](super::PeFile64).
-pub type PeSegment64<'data, 'file, R = &'data [u8]> =
- PeSegment<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// A loadable section in a [`PeFile`].
-///
-/// Most functionality is provided by the [`ObjectSegment`] trait implementation.
-#[derive(Debug)]
-pub struct PeSegment<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- file: &'file PeFile<'data, Pe, R>,
- section: &'data pe::ImageSectionHeader,
-}
-
-impl<'data, 'file, Pe, R> read::private::Sealed for PeSegment<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Pe, R> ObjectSegment<'data> for PeSegment<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- #[inline]
- fn address(&self) -> u64 {
- u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base)
- }
-
- #[inline]
- fn size(&self) -> u64 {
- u64::from(self.section.virtual_size.get(LE))
- }
-
- #[inline]
- fn align(&self) -> u64 {
- self.file.section_alignment()
- }
-
- #[inline]
- fn file_range(&self) -> (u64, u64) {
- let (offset, size) = self.section.pe_file_range();
- (u64::from(offset), u64::from(size))
- }
-
- fn data(&self) -> Result<&'data [u8]> {
- self.section.pe_data(self.file.data)
- }
-
- fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
- Ok(read::util::data_range(
- self.data()?,
- self.address(),
- address,
- size,
- ))
- }
-
- #[inline]
- fn name_bytes(&self) -> Result<Option<&[u8]>> {
- self.section
- .name(self.file.common.symbols.strings())
- .map(Some)
- }
-
- #[inline]
- fn name(&self) -> Result<Option<&str>> {
- let name = self.section.name(self.file.common.symbols.strings())?;
- Ok(Some(
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 PE section name")?,
- ))
- }
-
- #[inline]
- fn flags(&self) -> SegmentFlags {
- let characteristics = self.section.characteristics.get(LE);
- SegmentFlags::Coff { characteristics }
- }
-}
-
-/// An iterator for the sections in a [`PeFile32`](super::PeFile32).
-pub type PeSectionIterator32<'data, 'file, R = &'data [u8]> =
- PeSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
-/// An iterator for the sections in a [`PeFile64`](super::PeFile64).
-pub type PeSectionIterator64<'data, 'file, R = &'data [u8]> =
- PeSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// An iterator for the sections in a [`PeFile`].
-#[derive(Debug)]
-pub struct PeSectionIterator<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file PeFile<'data, Pe, R>,
- pub(super) iter: iter::Enumerate<slice::Iter<'data, pe::ImageSectionHeader>>,
-}
-
-impl<'data, 'file, Pe, R> Iterator for PeSectionIterator<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type Item = PeSection<'data, 'file, Pe, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next().map(|(index, section)| PeSection {
- file: self.file,
- index: SectionIndex(index + 1),
- section,
- })
- }
-}
-
-/// A section in a [`PeFile32`](super::PeFile32).
-pub type PeSection32<'data, 'file, R = &'data [u8]> =
- PeSection<'data, 'file, pe::ImageNtHeaders32, R>;
-/// A section in a [`PeFile64`](super::PeFile64).
-pub type PeSection64<'data, 'file, R = &'data [u8]> =
- PeSection<'data, 'file, pe::ImageNtHeaders64, R>;
-
-/// A section in a [`PeFile`].
-///
-/// Most functionality is provided by the [`ObjectSection`] trait implementation.
-#[derive(Debug)]
-pub struct PeSection<'data, 'file, Pe, R = &'data [u8]>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file PeFile<'data, Pe, R>,
- pub(super) index: SectionIndex,
- pub(super) section: &'data pe::ImageSectionHeader,
-}
-
-impl<'data, 'file, Pe, R> read::private::Sealed for PeSection<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Pe, R> ObjectSection<'data> for PeSection<'data, 'file, Pe, R>
-where
- Pe: ImageNtHeaders,
- R: ReadRef<'data>,
-{
- type RelocationIterator = PeRelocationIterator<'data, 'file, R>;
-
- #[inline]
- fn index(&self) -> SectionIndex {
- self.index
- }
-
- #[inline]
- fn address(&self) -> u64 {
- u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base)
- }
-
- #[inline]
- fn size(&self) -> u64 {
- u64::from(self.section.virtual_size.get(LE))
- }
-
- #[inline]
- fn align(&self) -> u64 {
- self.file.section_alignment()
- }
-
- #[inline]
- fn file_range(&self) -> Option<(u64, u64)> {
- let (offset, size) = self.section.pe_file_range();
- if size == 0 {
- None
- } else {
- Some((u64::from(offset), u64::from(size)))
- }
- }
-
- fn data(&self) -> Result<&'data [u8]> {
- self.section.pe_data(self.file.data)
- }
-
- fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
- Ok(read::util::data_range(
- self.data()?,
- self.address(),
- address,
- size,
- ))
- }
-
- #[inline]
- fn compressed_file_range(&self) -> Result<CompressedFileRange> {
- Ok(CompressedFileRange::none(self.file_range()))
- }
-
- #[inline]
- fn compressed_data(&self) -> Result<CompressedData<'data>> {
- self.data().map(CompressedData::none)
- }
-
- #[inline]
- fn name_bytes(&self) -> Result<&[u8]> {
- self.section.name(self.file.common.symbols.strings())
- }
-
- #[inline]
- fn name(&self) -> Result<&str> {
- let name = self.name_bytes()?;
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 PE section name")
- }
-
- #[inline]
- fn segment_name_bytes(&self) -> Result<Option<&[u8]>> {
- Ok(None)
- }
-
- #[inline]
- fn segment_name(&self) -> Result<Option<&str>> {
- Ok(None)
- }
-
- #[inline]
- fn kind(&self) -> SectionKind {
- self.section.kind()
- }
-
- fn relocations(&self) -> PeRelocationIterator<'data, 'file, R> {
- PeRelocationIterator(PhantomData)
- }
-
- fn flags(&self) -> SectionFlags {
- SectionFlags::Coff {
- characteristics: self.section.characteristics.get(LE),
- }
- }
-}
-
-impl<'data> SectionTable<'data> {
- /// Return the file offset of the given virtual address, and the size up
- /// to the end of the section containing it.
- ///
- /// Returns `None` if no section contains the address.
- pub fn pe_file_range_at(&self, va: u32) -> Option<(u32, u32)> {
- self.iter().find_map(|section| section.pe_file_range_at(va))
- }
-
- /// Return the data starting at the given virtual address, up to the end of the
- /// section containing it.
- ///
- /// Ignores sections with invalid data.
- ///
- /// Returns `None` if no section contains the address.
- pub fn pe_data_at<R: ReadRef<'data>>(&self, data: R, va: u32) -> Option<&'data [u8]> {
- self.iter().find_map(|section| section.pe_data_at(data, va))
- }
-
- /// Return the data of the section that contains the given virtual address in a PE file.
- ///
- /// Also returns the virtual address of that section.
- ///
- /// Ignores sections with invalid data.
- pub fn pe_data_containing<R: ReadRef<'data>>(
- &self,
- data: R,
- va: u32,
- ) -> Option<(&'data [u8], u32)> {
- self.iter()
- .find_map(|section| section.pe_data_containing(data, va))
- }
-
- /// Return the section that contains a given virtual address.
- pub fn section_containing(&self, va: u32) -> Option<&'data ImageSectionHeader> {
- self.iter().find(|section| section.contains_rva(va))
- }
-}
-
-impl pe::ImageSectionHeader {
- /// Return the offset and size of the section in a PE file.
- ///
- /// The size of the range will be the minimum of the file size and virtual size.
- pub fn pe_file_range(&self) -> (u32, u32) {
- // Pointer and size will be zero for uninitialized data; we don't need to validate this.
- let offset = self.pointer_to_raw_data.get(LE);
- let size = cmp::min(self.virtual_size.get(LE), self.size_of_raw_data.get(LE));
- (offset, size)
- }
-
- /// Return the file offset of the given virtual address, and the remaining size up
- /// to the end of the section.
- ///
- /// Returns `None` if the section does not contain the address.
- pub fn pe_file_range_at(&self, va: u32) -> Option<(u32, u32)> {
- let section_va = self.virtual_address.get(LE);
- let offset = va.checked_sub(section_va)?;
- let (section_offset, section_size) = self.pe_file_range();
- // Address must be within section (and not at its end).
- if offset < section_size {
- Some((section_offset.checked_add(offset)?, section_size - offset))
- } else {
- None
- }
- }
-
- /// Return the virtual address and size of the section.
- pub fn pe_address_range(&self) -> (u32, u32) {
- (self.virtual_address.get(LE), self.virtual_size.get(LE))
- }
-
- /// Return the section data in a PE file.
- ///
- /// The length of the data will be the minimum of the file size and virtual size.
- pub fn pe_data<'data, R: ReadRef<'data>>(&self, data: R) -> Result<&'data [u8]> {
- let (offset, size) = self.pe_file_range();
- data.read_bytes_at(offset.into(), size.into())
- .read_error("Invalid PE section offset or size")
- }
-
- /// Return the data starting at the given virtual address, up to the end of the
- /// section.
- ///
- /// Ignores sections with invalid data.
- ///
- /// Returns `None` if the section does not contain the address.
- pub fn pe_data_at<'data, R: ReadRef<'data>>(&self, data: R, va: u32) -> Option<&'data [u8]> {
- let (offset, size) = self.pe_file_range_at(va)?;
- data.read_bytes_at(offset.into(), size.into()).ok()
- }
-
- /// Tests whether a given RVA is part of this section
- pub fn contains_rva(&self, va: u32) -> bool {
- let section_va = self.virtual_address.get(LE);
- match va.checked_sub(section_va) {
- None => false,
- Some(offset) => {
- // Address must be within section (and not at its end).
- offset < self.virtual_size.get(LE)
- }
- }
- }
-
- /// Return the section data if it contains the given virtual address.
- ///
- /// Also returns the virtual address of that section.
- ///
- /// Ignores sections with invalid data.
- pub fn pe_data_containing<'data, R: ReadRef<'data>>(
- &self,
- data: R,
- va: u32,
- ) -> Option<(&'data [u8], u32)> {
- let section_va = self.virtual_address.get(LE);
- let offset = va.checked_sub(section_va)?;
- let (section_offset, section_size) = self.pe_file_range();
- // Address must be within section (and not at its end).
- if offset < section_size {
- let section_data = data
- .read_bytes_at(section_offset.into(), section_size.into())
- .ok()?;
- Some((section_data, section_va))
- } else {
- None
- }
- }
-}
-
-/// An iterator for the relocations in an [`PeSection`].
-///
-/// This is a stub that doesn't implement any functionality.
-#[derive(Debug)]
-pub struct PeRelocationIterator<'data, 'file, R = &'data [u8]>(
- PhantomData<(&'data (), &'file (), R)>,
-);
-
-impl<'data, 'file, R> Iterator for PeRelocationIterator<'data, 'file, R> {
- type Item = (u64, Relocation);
-
- fn next(&mut self) -> Option<Self::Item> {
- None
- }
-}