diff options
Diffstat (limited to 'vendor/object/src/read/coff')
-rw-r--r-- | vendor/object/src/read/coff/comdat.rs | 211 | ||||
-rw-r--r-- | vendor/object/src/read/coff/file.rs | 381 | ||||
-rw-r--r-- | vendor/object/src/read/coff/import.rs | 220 | ||||
-rw-r--r-- | vendor/object/src/read/coff/mod.rs | 66 | ||||
-rw-r--r-- | vendor/object/src/read/coff/relocation.rs | 106 | ||||
-rw-r--r-- | vendor/object/src/read/coff/section.rs | 585 | ||||
-rw-r--r-- | vendor/object/src/read/coff/symbol.rs | 635 |
7 files changed, 0 insertions, 2204 deletions
diff --git a/vendor/object/src/read/coff/comdat.rs b/vendor/object/src/read/coff/comdat.rs deleted file mode 100644 index 90c29be..0000000 --- a/vendor/object/src/read/coff/comdat.rs +++ /dev/null @@ -1,211 +0,0 @@ -use core::str; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::{ - self, ComdatKind, ObjectComdat, ReadError, ReadRef, Result, SectionIndex, SymbolIndex, -}; - -use super::{CoffFile, CoffHeader, ImageSymbol}; - -/// An iterator for the COMDAT section groups in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigComdatIterator<'data, 'file, R = &'data [u8]> = - CoffComdatIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the COMDAT section groups in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffComdatIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffComdatIterator<'data, 'file, R, Coff> -{ - type Item = CoffComdat<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option<Self::Item> { - loop { - let index = self.index; - let symbol = self.file.common.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - if let Some(comdat) = CoffComdat::parse(self.file, symbol, index) { - return Some(comdat); - } - } - } -} - -/// A COMDAT section group in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -pub type CoffBigComdat<'data, 'file, R = &'data [u8]> = - CoffComdat<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A COMDAT section group in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -#[derive(Debug)] -pub struct CoffComdat< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - file: &'file CoffFile<'data, R, Coff>, - symbol_index: SymbolIndex, - symbol: &'data Coff::ImageSymbol, - selection: u8, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffComdat<'data, 'file, R, Coff> { - fn parse( - file: &'file CoffFile<'data, R, Coff>, - section_symbol: &'data Coff::ImageSymbol, - index: usize, - ) -> Option<CoffComdat<'data, 'file, R, Coff>> { - // Must be a section symbol. - if !section_symbol.has_aux_section() { - return None; - } - - // Auxiliary record must have a non-associative selection. - let aux = file.common.symbols.aux_section(index).ok()?; - let selection = aux.selection; - if selection == 0 || selection == pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE { - return None; - } - - // Find the COMDAT symbol. - let mut symbol_index = index; - let mut symbol = section_symbol; - let section_number = section_symbol.section_number(); - loop { - symbol_index += 1 + symbol.number_of_aux_symbols() as usize; - symbol = file.common.symbols.symbol(symbol_index).ok()?; - if section_number == symbol.section_number() { - break; - } - } - - Some(CoffComdat { - file, - symbol_index: SymbolIndex(symbol_index), - symbol, - selection, - }) - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffComdat<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectComdat<'data> - for CoffComdat<'data, 'file, R, Coff> -{ - type SectionIterator = CoffComdatSectionIterator<'data, 'file, R, Coff>; - - #[inline] - fn kind(&self) -> ComdatKind { - match self.selection { - pe::IMAGE_COMDAT_SELECT_NODUPLICATES => ComdatKind::NoDuplicates, - pe::IMAGE_COMDAT_SELECT_ANY => ComdatKind::Any, - pe::IMAGE_COMDAT_SELECT_SAME_SIZE => ComdatKind::SameSize, - pe::IMAGE_COMDAT_SELECT_EXACT_MATCH => ComdatKind::ExactMatch, - pe::IMAGE_COMDAT_SELECT_LARGEST => ComdatKind::Largest, - pe::IMAGE_COMDAT_SELECT_NEWEST => ComdatKind::Newest, - _ => ComdatKind::Unknown, - } - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - self.symbol_index - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - // Find the name of first symbol referring to the section. - self.symbol.name(self.file.common.symbols.strings()) - } - - #[inline] - fn name(&self) -> Result<&str> { - let bytes = self.name_bytes()?; - str::from_utf8(bytes) - .ok() - .read_error("Non UTF-8 COFF COMDAT name") - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - CoffComdatSectionIterator { - file: self.file, - section_number: self.symbol.section_number(), - index: 0, - } - } -} - -/// An iterator for the sections in a COMDAT section group in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigComdatSectionIterator<'data, 'file, R = &'data [u8]> = - CoffComdatSectionIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the sections in a COMDAT section group in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffComdatSectionIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - file: &'file CoffFile<'data, R, Coff>, - section_number: i32, - index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffComdatSectionIterator<'data, 'file, R, Coff> -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option<Self::Item> { - // Find associated COMDAT symbols. - // TODO: it seems gcc doesn't use associated symbols for this - loop { - let index = self.index; - let symbol = self.file.common.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - - // Must be a section symbol. - if !symbol.has_aux_section() { - continue; - } - - let section_number = symbol.section_number(); - - let aux = self.file.common.symbols.aux_section(index).ok()?; - if aux.selection == pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE { - let number = if Coff::is_type_bigobj() { - u32::from(aux.number.get(LE)) | (u32::from(aux.high_number.get(LE)) << 16) - } else { - u32::from(aux.number.get(LE)) - }; - if number as i32 == self.section_number { - return Some(SectionIndex(section_number as usize)); - } - } else if aux.selection != 0 { - if section_number == self.section_number { - return Some(SectionIndex(section_number as usize)); - } - } - } - } -} diff --git a/vendor/object/src/read/coff/file.rs b/vendor/object/src/read/coff/file.rs deleted file mode 100644 index 40b9e70..0000000 --- a/vendor/object/src/read/coff/file.rs +++ /dev/null @@ -1,381 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; - -use crate::read::{ - self, Architecture, Export, FileFlags, Import, NoDynamicRelocationIterator, Object, ObjectKind, - ObjectSection, ReadError, ReadRef, Result, SectionIndex, SubArchitecture, SymbolIndex, -}; -use crate::{pe, LittleEndian as LE, Pod}; - -use super::{ - CoffComdat, CoffComdatIterator, CoffSection, CoffSectionIterator, CoffSegment, - CoffSegmentIterator, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, ImageSymbol, - SectionTable, SymbolTable, -}; - -/// The common parts of `PeFile` and `CoffFile`. -#[derive(Debug)] -pub(crate) struct CoffCommon<'data, R: ReadRef<'data>, Coff: CoffHeader = pe::ImageFileHeader> { - pub(crate) sections: SectionTable<'data>, - pub(crate) symbols: SymbolTable<'data, R, Coff>, - pub(crate) image_base: u64, -} - -/// A COFF bigobj object file with 32-bit section numbers. -/// -/// This is a file that starts with [`pe::AnonObjectHeaderBigobj`], and corresponds -/// to [`crate::FileKind::CoffBig`]. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -pub type CoffBigFile<'data, R = &'data [u8]> = CoffFile<'data, R, pe::AnonObjectHeaderBigobj>; - -/// A COFF object file. -/// -/// This is a file that starts with [`pe::ImageFileHeader`], and corresponds -/// to [`crate::FileKind::Coff`]. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct CoffFile<'data, R: ReadRef<'data> = &'data [u8], Coff: CoffHeader = pe::ImageFileHeader> -{ - pub(super) header: &'data Coff, - pub(super) common: CoffCommon<'data, R, Coff>, - pub(super) data: R, -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> CoffFile<'data, R, Coff> { - /// Parse the raw COFF file data. - pub fn parse(data: R) -> Result<Self> { - let mut offset = 0; - let header = Coff::parse(data, &mut offset)?; - let sections = header.sections(data, offset)?; - let symbols = header.symbols(data)?; - - Ok(CoffFile { - header, - common: CoffCommon { - sections, - symbols, - image_base: 0, - }, - data, - }) - } -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffFile<'data, R, Coff> -{ -} - -impl<'data, 'file, R, Coff> Object<'data, 'file> for CoffFile<'data, R, Coff> -where - 'data: 'file, - R: 'file + ReadRef<'data>, - Coff: CoffHeader, -{ - type Segment = CoffSegment<'data, 'file, R, Coff>; - type SegmentIterator = CoffSegmentIterator<'data, 'file, R, Coff>; - type Section = CoffSection<'data, 'file, R, Coff>; - type SectionIterator = CoffSectionIterator<'data, 'file, R, Coff>; - type Comdat = CoffComdat<'data, 'file, R, Coff>; - type ComdatIterator = CoffComdatIterator<'data, 'file, R, Coff>; - type Symbol = CoffSymbol<'data, 'file, R, Coff>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R, Coff>; - type SymbolTable = CoffSymbolTable<'data, 'file, R, Coff>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - fn architecture(&self) -> Architecture { - match self.header.machine() { - 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.header.machine() { - pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC), - _ => None, - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - true - } - - #[inline] - fn is_64(&self) -> bool { - // Windows COFF is always 32-bit, even for 64-bit architectures. This could be confusing. - false - } - - fn kind(&self) -> ObjectKind { - ObjectKind::Relocatable - } - - fn segments(&'file self) -> CoffSegmentIterator<'data, 'file, R, Coff> { - CoffSegmentIterator { - file: self, - iter: self.common.sections.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option<CoffSection<'data, 'file, R, Coff>> { - self.sections() - .find(|section| section.name_bytes() == Ok(section_name)) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> Result<CoffSection<'data, 'file, R, Coff>> { - let section = self.common.sections.section(index.0)?; - Ok(CoffSection { - file: self, - index, - section, - }) - } - - fn sections(&'file self) -> CoffSectionIterator<'data, 'file, R, Coff> { - CoffSectionIterator { - file: self, - iter: self.common.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> CoffComdatIterator<'data, 'file, R, Coff> { - CoffComdatIterator { - file: self, - index: 0, - } - } - - fn symbol_by_index( - &'file self, - index: SymbolIndex, - ) -> Result<CoffSymbol<'data, 'file, R, Coff>> { - let symbol = self.common.symbols.symbol(index.0)?; - Ok(CoffSymbol { - file: &self.common, - index, - symbol, - }) - } - - fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R, Coff> { - CoffSymbolIterator { - file: &self.common, - index: 0, - } - } - - #[inline] - fn symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R, Coff>> { - Some(CoffSymbolTable { file: &self.common }) - } - - fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R, Coff> { - CoffSymbolIterator { - file: &self.common, - // Hack: don't return any. - index: self.common.symbols.len(), - } - } - - #[inline] - fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R, Coff>> { - None - } - - #[inline] - fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> { - None - } - - #[inline] - fn imports(&self) -> Result<Vec<Import<'data>>> { - // TODO: this could return undefined symbols, but not needed yet. - Ok(Vec::new()) - } - - #[inline] - fn exports(&self) -> Result<Vec<Export<'data>>> { - // TODO: this could return global symbols, but not needed yet. - Ok(Vec::new()) - } - - fn has_debug_symbols(&self) -> bool { - self.section_by_name(".debug_info").is_some() - } - - fn relative_address_base(&self) -> u64 { - 0 - } - - #[inline] - fn entry(&self) -> u64 { - 0 - } - - fn flags(&self) -> FileFlags { - FileFlags::Coff { - characteristics: self.header.characteristics(), - } - } -} - -/// Read the `class_id` field from a [`pe::AnonObjectHeader`]. -/// -/// This can be used to determine the format of the header. -pub fn anon_object_class_id<'data, R: ReadRef<'data>>(data: R) -> Result<pe::ClsId> { - let header = data - .read_at::<pe::AnonObjectHeader>(0) - .read_error("Invalid anon object header size or alignment")?; - Ok(header.class_id) -} - -/// A trait for generic access to [`pe::ImageFileHeader`] and [`pe::AnonObjectHeaderBigobj`]. -#[allow(missing_docs)] -pub trait CoffHeader: Debug + Pod { - type ImageSymbol: ImageSymbol; - type ImageSymbolBytes: Debug + Pod; - - /// Return true if this type is [`pe::AnonObjectHeaderBigobj`]. - /// - /// This is a property of the type, not a value in the header data. - fn is_type_bigobj() -> bool; - - fn machine(&self) -> u16; - fn number_of_sections(&self) -> u32; - fn pointer_to_symbol_table(&self) -> u32; - fn number_of_symbols(&self) -> u32; - fn characteristics(&self) -> u16; - - /// Read the file header. - /// - /// `data` must be the entire file data. - /// `offset` must be the file header offset. It is updated to point after the optional header, - /// which is where the section headers are located. - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self>; - - /// Read the section table. - /// - /// `data` must be the entire file data. - /// `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, data, offset) - } - - /// Read the 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, Self>> { - SymbolTable::parse(self, data) - } -} - -impl CoffHeader for pe::ImageFileHeader { - type ImageSymbol = pe::ImageSymbol; - type ImageSymbolBytes = pe::ImageSymbolBytes; - - fn is_type_bigobj() -> bool { - false - } - - fn machine(&self) -> u16 { - self.machine.get(LE) - } - - fn number_of_sections(&self) -> u32 { - self.number_of_sections.get(LE).into() - } - - fn pointer_to_symbol_table(&self) -> u32 { - self.pointer_to_symbol_table.get(LE) - } - - fn number_of_symbols(&self) -> u32 { - self.number_of_symbols.get(LE) - } - - fn characteristics(&self) -> u16 { - self.characteristics.get(LE) - } - - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self> { - let header = data - .read::<pe::ImageFileHeader>(offset) - .read_error("Invalid COFF file header size or alignment")?; - - // Skip over the optional header. - *offset = offset - .checked_add(header.size_of_optional_header.get(LE).into()) - .read_error("Invalid COFF optional header size")?; - - // TODO: maybe validate that the machine is known? - Ok(header) - } -} - -impl CoffHeader for pe::AnonObjectHeaderBigobj { - type ImageSymbol = pe::ImageSymbolEx; - type ImageSymbolBytes = pe::ImageSymbolExBytes; - - fn is_type_bigobj() -> bool { - true - } - - fn machine(&self) -> u16 { - self.machine.get(LE) - } - - fn number_of_sections(&self) -> u32 { - self.number_of_sections.get(LE) - } - - fn pointer_to_symbol_table(&self) -> u32 { - self.pointer_to_symbol_table.get(LE) - } - - fn number_of_symbols(&self) -> u32 { - self.number_of_symbols.get(LE) - } - - fn characteristics(&self) -> u16 { - 0 - } - - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self> { - let header = data - .read::<pe::AnonObjectHeaderBigobj>(offset) - .read_error("Invalid COFF bigobj file header size or alignment")?; - - if header.sig1.get(LE) != pe::IMAGE_FILE_MACHINE_UNKNOWN - || header.sig2.get(LE) != 0xffff - || header.version.get(LE) < 2 - || header.class_id != pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID - { - return Err(read::Error("Invalid COFF bigobj header values")); - } - - // TODO: maybe validate that the machine is known? - Ok(header) - } -} diff --git a/vendor/object/src/read/coff/import.rs b/vendor/object/src/read/coff/import.rs deleted file mode 100644 index a296ac3..0000000 --- a/vendor/object/src/read/coff/import.rs +++ /dev/null @@ -1,220 +0,0 @@ -//! Support for reading short import files. -//! -//! These are used by some Windows linkers as a more compact way to describe -//! dynamically imported symbols. - -use crate::read::{Architecture, Error, ReadError, ReadRef, Result}; -use crate::{pe, ByteString, Bytes, LittleEndian as LE, SubArchitecture}; - -/// A Windows short form description of a symbol to import. -/// -/// Used in Windows import libraries to provide a mapping from -/// a symbol name to a DLL export. This is not an object file. -/// -/// This is a file that starts with [`pe::ImportObjectHeader`], and corresponds -/// to [`crate::FileKind::CoffImport`]. -#[derive(Debug, Clone)] -pub struct ImportFile<'data> { - header: &'data pe::ImportObjectHeader, - kind: ImportType, - dll: ByteString<'data>, - symbol: ByteString<'data>, - import: Option<ByteString<'data>>, -} - -impl<'data> ImportFile<'data> { - /// Parse it. - pub fn parse<R: ReadRef<'data>>(data: R) -> Result<Self> { - let mut offset = 0; - let header = pe::ImportObjectHeader::parse(data, &mut offset)?; - let data = header.parse_data(data, &mut offset)?; - - // Unmangles a name by removing a `?`, `@` or `_` prefix. - fn strip_prefix(s: &[u8]) -> &[u8] { - match s.split_first() { - Some((b, rest)) if [b'?', b'@', b'_'].contains(b) => rest, - _ => s, - } - } - Ok(Self { - header, - dll: data.dll, - symbol: data.symbol, - kind: match header.import_type() { - pe::IMPORT_OBJECT_CODE => ImportType::Code, - pe::IMPORT_OBJECT_DATA => ImportType::Data, - pe::IMPORT_OBJECT_CONST => ImportType::Const, - _ => return Err(Error("Invalid COFF import library import type")), - }, - import: match header.name_type() { - pe::IMPORT_OBJECT_ORDINAL => None, - pe::IMPORT_OBJECT_NAME => Some(data.symbol()), - pe::IMPORT_OBJECT_NAME_NO_PREFIX => Some(strip_prefix(data.symbol())), - pe::IMPORT_OBJECT_NAME_UNDECORATE => Some( - strip_prefix(data.symbol()) - .split(|&b| b == b'@') - .next() - .unwrap(), - ), - pe::IMPORT_OBJECT_NAME_EXPORTAS => data.export(), - _ => return Err(Error("Unknown COFF import library name type")), - } - .map(ByteString), - }) - } - - /// Get the machine type. - pub fn architecture(&self) -> Architecture { - match self.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, - } - } - - /// Get the sub machine type, if available. - pub fn sub_architecture(&self) -> Option<SubArchitecture> { - match self.header.machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC), - _ => None, - } - } - - /// The public symbol name. - pub fn symbol(&self) -> &'data [u8] { - self.symbol.0 - } - - /// The name of the DLL to import the symbol from. - pub fn dll(&self) -> &'data [u8] { - self.dll.0 - } - - /// The name exported from the DLL. - pub fn import(&self) -> ImportName<'data> { - match self.import { - Some(name) => ImportName::Name(name.0), - None => ImportName::Ordinal(self.header.ordinal_or_hint.get(LE)), - } - } - - /// The type of import. Usually either a function or data. - pub fn import_type(&self) -> ImportType { - self.kind - } -} - -/// The name or ordinal to import from a DLL. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ImportName<'data> { - /// Import by ordinal. Ordinarily this is a 1-based index. - Ordinal(u16), - /// Import by name. - Name(&'data [u8]), -} - -/// The kind of import symbol. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ImportType { - /// An executable code symbol. - Code, - /// A data symbol. - Data, - /// A constant value. - Const, -} - -impl pe::ImportObjectHeader { - /// Read the short import header. - /// - /// Also checks that the signature and version are valid. - /// Directly following this header will be the string data. - pub fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> { - let header = data - .read::<pe::ImportObjectHeader>(offset) - .read_error("Invalid COFF import library header size")?; - if header.sig1.get(LE) != 0 || header.sig2.get(LE) != pe::IMPORT_OBJECT_HDR_SIG2 { - Err(Error("Invalid COFF import library header")) - } else if header.version.get(LE) != 0 { - Err(Error("Unknown COFF import library header version")) - } else { - Ok(header) - } - } - - /// Parse the data following the header. - pub fn parse_data<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: &mut u64, - ) -> Result<ImportObjectData<'data>> { - let mut data = Bytes( - data.read_bytes(offset, u64::from(self.size_of_data.get(LE))) - .read_error("Invalid COFF import library data size")?, - ); - let symbol = data - .read_string() - .map(ByteString) - .read_error("Could not read COFF import library symbol name")?; - let dll = data - .read_string() - .map(ByteString) - .read_error("Could not read COFF import library DLL name")?; - let export = if self.name_type() == pe::IMPORT_OBJECT_NAME_EXPORTAS { - data.read_string() - .map(ByteString) - .map(Some) - .read_error("Could not read COFF import library export name")? - } else { - None - }; - Ok(ImportObjectData { - symbol, - dll, - export, - }) - } - - /// The type of import. - /// - /// This is one of the `IMPORT_OBJECT_*` constants. - pub fn import_type(&self) -> u16 { - self.name_type.get(LE) & pe::IMPORT_OBJECT_TYPE_MASK - } - - /// The type of import name. - /// - /// This is one of the `IMPORT_OBJECT_*` constants. - pub fn name_type(&self) -> u16 { - (self.name_type.get(LE) >> pe::IMPORT_OBJECT_NAME_SHIFT) & pe::IMPORT_OBJECT_NAME_MASK - } -} - -/// The data following [`pe::ImportObjectHeader`]. -#[derive(Debug, Clone)] -pub struct ImportObjectData<'data> { - symbol: ByteString<'data>, - dll: ByteString<'data>, - export: Option<ByteString<'data>>, -} - -impl<'data> ImportObjectData<'data> { - /// The public symbol name. - pub fn symbol(&self) -> &'data [u8] { - self.symbol.0 - } - - /// The name of the DLL to import the symbol from. - pub fn dll(&self) -> &'data [u8] { - self.dll.0 - } - - /// The name exported from the DLL. - /// - /// This is only set if the name is not derived from the symbol name. - pub fn export(&self) -> Option<&'data [u8]> { - self.export.map(|export| export.0) - } -} diff --git a/vendor/object/src/read/coff/mod.rs b/vendor/object/src/read/coff/mod.rs deleted file mode 100644 index de397da..0000000 --- a/vendor/object/src/read/coff/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Support for reading Windows COFF files. -//! -//! Traits are used to abstract over the difference between COFF object files -//! and COFF bigobj files. The primary trait for this is [`CoffHeader`]. -//! -//! ## High level API -//! -//! [`CoffFile`] implements the [`Object`](crate::read::Object) trait for -//! COFF files. [`CoffFile`] is parameterised by [`CoffHeader`]. -//! The default parameter allows reading regular COFF object files, -//! while the type alias [`CoffBigFile`] allows reading COFF bigobj files. -//! -//! [`ImportFile`] allows reading COFF short imports that are used in import -//! libraries. Currently these are not integrated with the unified read API. -//! -//! ## Low level API -//! -//! The [`CoffHeader`] trait can be directly used to parse both COFF -//! object files (which start with [`pe::ImageFileHeader`]) and COFF bigobj -//! files (which start with [`pe::AnonObjectHeaderBigobj`]). -//! -//! ### Example for low level API -//! ```no_run -//! use object::pe; -//! use object::read::coff::{CoffHeader, ImageSymbol as _}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each section and symbol. -//! fn main() -> Result<(), Box<dyn Error>> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let mut offset = 0; -//! let header = pe::ImageFileHeader::parse(&*data, &mut offset)?; -//! let sections = header.sections(&*data, offset)?; -//! let symbols = header.symbols(&*data)?; -//! for section in sections.iter() { -//! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?)); -//! } -//! for (_index, symbol) in symbols.iter() { -//! println!("{}", String::from_utf8_lossy(symbol.name(symbols.strings())?)); -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::pe; - -mod file; -pub use file::*; - -mod section; -pub use section::*; - -mod symbol; -pub use symbol::*; - -mod relocation; -pub use relocation::*; - -mod comdat; -pub use comdat::*; - -mod import; -pub use import::*; diff --git a/vendor/object/src/read/coff/relocation.rs b/vendor/object/src/read/coff/relocation.rs deleted file mode 100644 index e990944..0000000 --- a/vendor/object/src/read/coff/relocation.rs +++ /dev/null @@ -1,106 +0,0 @@ -use alloc::fmt; -use core::slice; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::{ - ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget, SymbolIndex, -}; - -use super::{CoffFile, CoffHeader}; - -/// An iterator for the relocations in a [`CoffBigSection`](super::CoffBigSection). -pub type CoffBigRelocationIterator<'data, 'file, R = &'data [u8]> = - CoffRelocationIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the relocations in a [`CoffSection`](super::CoffSection). -pub struct CoffRelocationIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: slice::Iter<'data, pe::ImageRelocation>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffRelocationIterator<'data, 'file, R, Coff> -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|relocation| { - let (kind, size, addend) = match self.file.header.machine() { - pe::IMAGE_FILE_MACHINE_ARMNT => match relocation.typ.get(LE) { - pe::IMAGE_REL_ARM_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_ARM_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_ARM_REL32 => (RelocationKind::Relative, 32, -4), - pe::IMAGE_REL_ARM_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_ARM_SECREL => (RelocationKind::SectionOffset, 32, 0), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => { - match relocation.typ.get(LE) { - pe::IMAGE_REL_ARM64_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_ARM64_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_ARM64_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_ARM64_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_ARM64_ADDR64 => (RelocationKind::Absolute, 64, 0), - pe::IMAGE_REL_ARM64_REL32 => (RelocationKind::Relative, 32, -4), - typ => (RelocationKind::Coff(typ), 0, 0), - } - } - pe::IMAGE_FILE_MACHINE_I386 => match relocation.typ.get(LE) { - pe::IMAGE_REL_I386_DIR16 => (RelocationKind::Absolute, 16, 0), - pe::IMAGE_REL_I386_REL16 => (RelocationKind::Relative, 16, 0), - pe::IMAGE_REL_I386_DIR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_I386_DIR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_I386_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_I386_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_I386_SECREL7 => (RelocationKind::SectionOffset, 7, 0), - pe::IMAGE_REL_I386_REL32 => (RelocationKind::Relative, 32, -4), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - pe::IMAGE_FILE_MACHINE_AMD64 => match relocation.typ.get(LE) { - pe::IMAGE_REL_AMD64_ADDR64 => (RelocationKind::Absolute, 64, 0), - pe::IMAGE_REL_AMD64_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_AMD64_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_AMD64_REL32 => (RelocationKind::Relative, 32, -4), - pe::IMAGE_REL_AMD64_REL32_1 => (RelocationKind::Relative, 32, -5), - pe::IMAGE_REL_AMD64_REL32_2 => (RelocationKind::Relative, 32, -6), - pe::IMAGE_REL_AMD64_REL32_3 => (RelocationKind::Relative, 32, -7), - pe::IMAGE_REL_AMD64_REL32_4 => (RelocationKind::Relative, 32, -8), - pe::IMAGE_REL_AMD64_REL32_5 => (RelocationKind::Relative, 32, -9), - pe::IMAGE_REL_AMD64_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_AMD64_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_AMD64_SECREL7 => (RelocationKind::SectionOffset, 7, 0), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - _ => (RelocationKind::Coff(relocation.typ.get(LE)), 0, 0), - }; - let target = RelocationTarget::Symbol(SymbolIndex( - relocation.symbol_table_index.get(LE) as usize, - )); - ( - u64::from(relocation.virtual_address.get(LE)), - Relocation { - kind, - encoding: RelocationEncoding::Generic, - size, - target, - addend, - implicit_addend: true, - }, - ) - }) - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug - for CoffRelocationIterator<'data, 'file, R, Coff> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffRelocationIterator").finish() - } -} diff --git a/vendor/object/src/read/coff/section.rs b/vendor/object/src/read/coff/section.rs deleted file mode 100644 index 84a3fa9..0000000 --- a/vendor/object/src/read/coff/section.rs +++ /dev/null @@ -1,585 +0,0 @@ -use core::convert::TryFrom; -use core::{iter, result, slice, str}; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::util::StringTable; -use crate::read::{ - self, CompressedData, CompressedFileRange, Error, ObjectSection, ObjectSegment, ReadError, - ReadRef, Result, SectionFlags, SectionIndex, SectionKind, SegmentFlags, -}; - -use super::{CoffFile, CoffHeader, CoffRelocationIterator}; - -/// The table of section headers in a COFF or PE file. -/// -/// Returned by [`CoffHeader::sections`] and -/// [`ImageNtHeaders::sections`](crate::read::pe::ImageNtHeaders::sections). -#[derive(Debug, Default, Clone, Copy)] -pub struct SectionTable<'data> { - sections: &'data [pe::ImageSectionHeader], -} - -impl<'data> SectionTable<'data> { - /// Parse the section table. - /// - /// `data` must be the entire file data. - /// `offset` must be after the optional file header. - pub fn parse<Coff: CoffHeader, R: ReadRef<'data>>( - header: &Coff, - data: R, - offset: u64, - ) -> Result<Self> { - let sections = data - .read_slice_at(offset, header.number_of_sections() as usize) - .read_error("Invalid COFF/PE section headers")?; - Ok(SectionTable { sections }) - } - - /// Iterate over the section headers. - /// - /// Warning: sections indices start at 1. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, pe::ImageSectionHeader> { - self.sections.iter() - } - - /// Return true if the section table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.sections.is_empty() - } - - /// The number of section headers. - #[inline] - pub fn len(&self) -> usize { - self.sections.len() - } - - /// Return the section header at the given index. - /// - /// The index is 1-based. - pub fn section(&self, index: usize) -> read::Result<&'data pe::ImageSectionHeader> { - self.sections - .get(index.wrapping_sub(1)) - .read_error("Invalid COFF/PE section index") - } - - /// Return the section header with the given name. - /// - /// The returned index is 1-based. - /// - /// Ignores sections with invalid names. - pub fn section_by_name<R: ReadRef<'data>>( - &self, - strings: StringTable<'data, R>, - name: &[u8], - ) -> Option<(usize, &'data pe::ImageSectionHeader)> { - self.sections - .iter() - .enumerate() - .find(|(_, section)| section.name(strings) == Ok(name)) - .map(|(index, section)| (index + 1, section)) - } - - /// Compute the maximum file offset used by sections. - /// - /// This will usually match the end of file, unless the PE file has a - /// [data overlay](https://security.stackexchange.com/questions/77336/how-is-the-file-overlay-read-by-an-exe-virus) - pub fn max_section_file_offset(&self) -> u64 { - let mut max = 0; - for section in self.iter() { - match (section.pointer_to_raw_data.get(LE) as u64) - .checked_add(section.size_of_raw_data.get(LE) as u64) - { - None => { - // This cannot happen, we're suming two u32 into a u64 - continue; - } - Some(end_of_section) => { - if end_of_section > max { - max = end_of_section; - } - } - } - } - max - } -} - -/// An iterator for the loadable sections in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSegmentIterator<'data, 'file, R = &'data [u8]> = - CoffSegmentIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the loadable sections in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffSegmentIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSegmentIterator<'data, 'file, R, Coff> -{ - type Item = CoffSegment<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|section| CoffSegment { - file: self.file, - section, - }) - } -} - -/// A loadable section in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -pub type CoffBigSegment<'data, 'file, R = &'data [u8]> = - CoffSegment<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A loadable section in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -#[derive(Debug)] -pub struct CoffSegment< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSegment<'data, 'file, R, Coff> { - fn bytes(&self) -> Result<&'data [u8]> { - self.section - .coff_data(self.file.data) - .read_error("Invalid COFF section offset or size") - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSegment<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSegment<'data> - for CoffSegment<'data, 'file, R, Coff> -{ - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)) - } - - #[inline] - fn size(&self) -> u64 { - u64::from(self.section.virtual_size.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.section.coff_alignment() - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - let (offset, size) = self.section.coff_file_range().unwrap_or((0, 0)); - (u64::from(offset), u64::from(size)) - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { - Ok(read::util::data_range( - self.bytes()?, - 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())?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF section name") - .map(Some) - } - - #[inline] - fn flags(&self) -> SegmentFlags { - let characteristics = self.section.characteristics.get(LE); - SegmentFlags::Coff { characteristics } - } -} - -/// An iterator for the sections in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSectionIterator<'data, 'file, R = &'data [u8]> = - CoffSectionIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the sections in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffSectionIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: iter::Enumerate<slice::Iter<'data, pe::ImageSectionHeader>>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSectionIterator<'data, 'file, R, Coff> -{ - type Item = CoffSection<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(index, section)| CoffSection { - file: self.file, - index: SectionIndex(index + 1), - section, - }) - } -} - -/// A section in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -pub type CoffBigSection<'data, 'file, R = &'data [u8]> = - CoffSection<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A section in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct CoffSection< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) index: SectionIndex, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSection<'data, 'file, R, Coff> { - fn bytes(&self) -> Result<&'data [u8]> { - self.section - .coff_data(self.file.data) - .read_error("Invalid COFF section offset or size") - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSection<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSection<'data> - for CoffSection<'data, 'file, R, Coff> -{ - type RelocationIterator = CoffRelocationIterator<'data, 'file, R, Coff>; - - #[inline] - fn index(&self) -> SectionIndex { - self.index - } - - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)) - } - - #[inline] - fn size(&self) -> u64 { - // TODO: This may need to be the length from the auxiliary symbol for this section. - u64::from(self.section.size_of_raw_data.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.section.coff_alignment() - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - let (offset, size) = self.section.coff_file_range()?; - Some((u64::from(offset), u64::from(size))) - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { - Ok(read::util::data_range( - self.bytes()?, - 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 COFF 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) -> CoffRelocationIterator<'data, 'file, R, Coff> { - let relocations = self.section.coff_relocations(self.file.data).unwrap_or(&[]); - CoffRelocationIterator { - file: self.file, - iter: relocations.iter(), - } - } - - fn flags(&self) -> SectionFlags { - SectionFlags::Coff { - characteristics: self.section.characteristics.get(LE), - } - } -} - -impl pe::ImageSectionHeader { - pub(crate) fn kind(&self) -> SectionKind { - let characteristics = self.characteristics.get(LE); - if characteristics & (pe::IMAGE_SCN_CNT_CODE | pe::IMAGE_SCN_MEM_EXECUTE) != 0 { - SectionKind::Text - } else if characteristics & pe::IMAGE_SCN_CNT_INITIALIZED_DATA != 0 { - if characteristics & pe::IMAGE_SCN_MEM_DISCARDABLE != 0 { - SectionKind::Other - } else if characteristics & pe::IMAGE_SCN_MEM_WRITE != 0 { - SectionKind::Data - } else { - SectionKind::ReadOnlyData - } - } else if characteristics & pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 { - SectionKind::UninitializedData - } else if characteristics & pe::IMAGE_SCN_LNK_INFO != 0 { - SectionKind::Linker - } else { - SectionKind::Unknown - } - } -} - -impl pe::ImageSectionHeader { - /// Return the string table offset of the section name. - /// - /// Returns `Ok(None)` if the name doesn't use the string table - /// and can be obtained with `raw_name` instead. - pub fn name_offset(&self) -> Result<Option<u32>> { - let bytes = &self.name; - if bytes[0] != b'/' { - return Ok(None); - } - - if bytes[1] == b'/' { - let mut offset = 0; - for byte in bytes[2..].iter() { - let digit = match byte { - b'A'..=b'Z' => byte - b'A', - b'a'..=b'z' => byte - b'a' + 26, - b'0'..=b'9' => byte - b'0' + 52, - b'+' => 62, - b'/' => 63, - _ => return Err(Error("Invalid COFF section name base-64 offset")), - }; - offset = offset * 64 + digit as u64; - } - u32::try_from(offset) - .ok() - .read_error("Invalid COFF section name base-64 offset") - .map(Some) - } else { - let mut offset = 0; - for byte in bytes[1..].iter() { - let digit = match byte { - b'0'..=b'9' => byte - b'0', - 0 => break, - _ => return Err(Error("Invalid COFF section name base-10 offset")), - }; - offset = offset * 10 + digit as u32; - } - Ok(Some(offset)) - } - } - - /// Return the section name. - /// - /// This handles decoding names that are offsets into the symbol string table. - pub fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - if let Some(offset) = self.name_offset()? { - strings - .get(offset) - .read_error("Invalid COFF section name offset") - } else { - Ok(self.raw_name()) - } - } - - /// Return the raw section name. - pub fn raw_name(&self) -> &[u8] { - let bytes = &self.name; - match memchr::memchr(b'\0', bytes) { - Some(end) => &bytes[..end], - None => &bytes[..], - } - } - - /// Return the offset and size of the section in a COFF file. - /// - /// Returns `None` for sections that have no data in the file. - pub fn coff_file_range(&self) -> Option<(u32, u32)> { - if self.characteristics.get(LE) & pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 { - None - } else { - let offset = self.pointer_to_raw_data.get(LE); - // Note: virtual size is not used for COFF. - let size = self.size_of_raw_data.get(LE); - Some((offset, size)) - } - } - - /// Return the section data in a COFF file. - /// - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values. - pub fn coff_data<'data, R: ReadRef<'data>>(&self, data: R) -> result::Result<&'data [u8], ()> { - if let Some((offset, size)) = self.coff_file_range() { - data.read_bytes_at(offset.into(), size.into()) - } else { - Ok(&[]) - } - } - - /// Return the section alignment in bytes. - /// - /// This is only valid for sections in a COFF file. - pub fn coff_alignment(&self) -> u64 { - match self.characteristics.get(LE) & pe::IMAGE_SCN_ALIGN_MASK { - pe::IMAGE_SCN_ALIGN_1BYTES => 1, - pe::IMAGE_SCN_ALIGN_2BYTES => 2, - pe::IMAGE_SCN_ALIGN_4BYTES => 4, - pe::IMAGE_SCN_ALIGN_8BYTES => 8, - pe::IMAGE_SCN_ALIGN_16BYTES => 16, - pe::IMAGE_SCN_ALIGN_32BYTES => 32, - pe::IMAGE_SCN_ALIGN_64BYTES => 64, - pe::IMAGE_SCN_ALIGN_128BYTES => 128, - pe::IMAGE_SCN_ALIGN_256BYTES => 256, - pe::IMAGE_SCN_ALIGN_512BYTES => 512, - pe::IMAGE_SCN_ALIGN_1024BYTES => 1024, - pe::IMAGE_SCN_ALIGN_2048BYTES => 2048, - pe::IMAGE_SCN_ALIGN_4096BYTES => 4096, - pe::IMAGE_SCN_ALIGN_8192BYTES => 8192, - _ => 16, - } - } - - /// Read the relocations in a COFF file. - /// - /// `data` must be the entire file data. - pub fn coff_relocations<'data, R: ReadRef<'data>>( - &self, - data: R, - ) -> read::Result<&'data [pe::ImageRelocation]> { - let mut pointer = self.pointer_to_relocations.get(LE).into(); - let mut number: usize = self.number_of_relocations.get(LE).into(); - if number == core::u16::MAX.into() - && self.characteristics.get(LE) & pe::IMAGE_SCN_LNK_NRELOC_OVFL != 0 - { - // Extended relocations. Read first relocation (which contains extended count) & adjust - // relocations pointer. - let extended_relocation_info = data - .read_at::<pe::ImageRelocation>(pointer) - .read_error("Invalid COFF relocation offset or number")?; - number = extended_relocation_info.virtual_address.get(LE) as usize; - if number == 0 { - return Err(Error("Invalid COFF relocation number")); - } - pointer += core::mem::size_of::<pe::ImageRelocation>() as u64; - // Extended relocation info does not contribute to the count of sections. - number -= 1; - } - data.read_slice_at(pointer, number) - .read_error("Invalid COFF relocation offset or number") - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn name_offset() { - let mut section = pe::ImageSectionHeader::default(); - section.name = *b"xxxxxxxx"; - assert_eq!(section.name_offset(), Ok(None)); - section.name = *b"/0\0\0\0\0\0\0"; - assert_eq!(section.name_offset(), Ok(Some(0))); - section.name = *b"/9999999"; - assert_eq!(section.name_offset(), Ok(Some(999_9999))); - section.name = *b"//AAAAAA"; - assert_eq!(section.name_offset(), Ok(Some(0))); - section.name = *b"//D/////"; - assert_eq!(section.name_offset(), Ok(Some(0xffff_ffff))); - section.name = *b"//EAAAAA"; - assert!(section.name_offset().is_err()); - section.name = *b"////////"; - assert!(section.name_offset().is_err()); - } -} diff --git a/vendor/object/src/read/coff/symbol.rs b/vendor/object/src/read/coff/symbol.rs deleted file mode 100644 index 4f8a0c6..0000000 --- a/vendor/object/src/read/coff/symbol.rs +++ /dev/null @@ -1,635 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::convert::TryInto; -use core::fmt::Debug; -use core::str; - -use super::{CoffCommon, CoffHeader, SectionTable}; -use crate::endian::{LittleEndian as LE, U32Bytes}; -use crate::pe; -use crate::pod::{bytes_of, bytes_of_slice, Pod}; -use crate::read::util::StringTable; -use crate::read::{ - self, Bytes, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex, - SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection, -}; - -/// A table of symbol entries in a COFF or PE file. -/// -/// Also includes the string table used for the symbol names. -/// -/// Returned by [`CoffHeader::symbols`] and -/// [`ImageNtHeaders::symbols`](crate::read::pe::ImageNtHeaders::symbols). -#[derive(Debug)] -pub struct SymbolTable<'data, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - symbols: &'data [Coff::ImageSymbolBytes], - strings: StringTable<'data, R>, -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> Default for SymbolTable<'data, R, Coff> { - fn default() -> Self { - Self { - symbols: &[], - strings: StringTable::default(), - } - } -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> SymbolTable<'data, R, Coff> { - /// Read the symbol table. - pub fn parse(header: &Coff, data: R) -> Result<Self> { - // The symbol table may not be present. - let mut offset = header.pointer_to_symbol_table().into(); - let (symbols, strings) = if offset != 0 { - let symbols = data - .read_slice(&mut offset, header.number_of_symbols() as usize) - .read_error("Invalid COFF symbol table offset or size")?; - - // Note: don't update data when reading length; the length includes itself. - let length = data - .read_at::<U32Bytes<_>>(offset) - .read_error("Missing COFF string table")? - .get(LE); - let str_end = offset - .checked_add(length as u64) - .read_error("Invalid COFF string table length")?; - let strings = StringTable::new(data, offset, str_end); - - (symbols, strings) - } else { - (&[][..], StringTable::default()) - }; - - Ok(SymbolTable { symbols, strings }) - } - - /// Return the string table used for the symbol names. - #[inline] - pub fn strings(&self) -> StringTable<'data, R> { - self.strings - } - - /// Return true if the symbol table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// The number of symbol table entries. - /// - /// This includes auxiliary symbol table entries. - #[inline] - pub fn len(&self) -> usize { - self.symbols.len() - } - - /// Iterate over the symbols. - #[inline] - pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, R, Coff> { - SymbolIterator { - symbols: self, - index: 0, - } - } - - /// Return the symbol table entry at the given index. - #[inline] - pub fn symbol(&self, index: usize) -> Result<&'data Coff::ImageSymbol> { - self.get::<Coff::ImageSymbol>(index, 0) - } - - /// Return the auxiliary function symbol for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - #[inline] - pub fn aux_function(&self, index: usize) -> Result<&'data pe::ImageAuxSymbolFunction> { - self.get::<pe::ImageAuxSymbolFunction>(index, 1) - } - - /// Return the auxiliary section symbol for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - #[inline] - pub fn aux_section(&self, index: usize) -> Result<&'data pe::ImageAuxSymbolSection> { - self.get::<pe::ImageAuxSymbolSection>(index, 1) - } - - /// Return the auxiliary file name for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - pub fn aux_file_name(&self, index: usize, aux_count: u8) -> Result<&'data [u8]> { - let entries = index - .checked_add(1) - .and_then(|x| Some(x..x.checked_add(aux_count.into())?)) - .and_then(|x| self.symbols.get(x)) - .read_error("Invalid COFF symbol index")?; - let bytes = bytes_of_slice(entries); - // The name is padded with nulls. - Ok(match memchr::memchr(b'\0', bytes) { - Some(end) => &bytes[..end], - None => bytes, - }) - } - - /// Return the symbol table entry or auxiliary record at the given index and offset. - pub fn get<T: Pod>(&self, index: usize, offset: usize) -> Result<&'data T> { - let bytes = index - .checked_add(offset) - .and_then(|x| self.symbols.get(x)) - .read_error("Invalid COFF symbol index")?; - Bytes(bytes_of(bytes)) - .read() - .read_error("Invalid COFF symbol data") - } - - /// Construct a map from addresses to a user-defined map entry. - pub fn map<Entry: SymbolMapEntry, F: Fn(&'data Coff::ImageSymbol) -> Option<Entry>>( - &self, - f: F, - ) -> SymbolMap<Entry> { - let mut symbols = Vec::with_capacity(self.symbols.len()); - for (_, symbol) in self.iter() { - if !symbol.is_definition() { - continue; - } - if let Some(entry) = f(symbol) { - symbols.push(entry); - } - } - SymbolMap::new(symbols) - } -} - -/// An iterator for symbol entries in a COFF or PE file. -/// -/// Yields the index and symbol structure for each symbol. -#[derive(Debug)] -pub struct SymbolIterator<'data, 'table, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - symbols: &'table SymbolTable<'data, R, Coff>, - index: usize, -} - -impl<'data, 'table, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for SymbolIterator<'data, 'table, R, Coff> -{ - type Item = (usize, &'data Coff::ImageSymbol); - - fn next(&mut self) -> Option<Self::Item> { - let index = self.index; - let symbol = self.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - Some((index, symbol)) - } -} - -/// A symbol table in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSymbolTable<'data, 'file, R = &'data [u8]> = - CoffSymbolTable<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A symbol table in a [`CoffFile`](super::CoffFile) -/// or [`PeFile`](crate::read::pe::PeFile). -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbolTable<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSymbolTable<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbolTable<'data> - for CoffSymbolTable<'data, 'file, R, Coff> -{ - type Symbol = CoffSymbol<'data, 'file, R, Coff>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R, Coff>; - - fn symbols(&self) -> Self::SymbolIterator { - CoffSymbolIterator { - file: self.file, - index: 0, - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> { - let symbol = self.file.symbols.symbol(index.0)?; - Ok(CoffSymbol { - file: self.file, - index, - symbol, - }) - } -} - -/// An iterator for the symbols in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSymbolIterator<'data, 'file, R = &'data [u8]> = - CoffSymbolIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the symbols in a [`CoffFile`](super::CoffFile) -/// or [`PeFile`](crate::read::pe::PeFile). -pub struct CoffSymbolIterator<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, - pub(crate) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug - for CoffSymbolIterator<'data, 'file, R, Coff> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffSymbolIterator").finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSymbolIterator<'data, 'file, R, Coff> -{ - type Item = CoffSymbol<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option<Self::Item> { - let index = self.index; - let symbol = self.file.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - Some(CoffSymbol { - file: self.file, - index: SymbolIndex(index), - symbol, - }) - } -} - -/// A symbol in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -pub type CoffBigSymbol<'data, 'file, R = &'data [u8]> = - CoffSymbol<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A symbol in a [`CoffFile`](super::CoffFile) or [`PeFile`](crate::read::pe::PeFile). -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbol<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, - pub(crate) index: SymbolIndex, - pub(crate) symbol: &'data Coff::ImageSymbol, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSymbol<'data, 'file, R, Coff> { - #[inline] - /// Get the raw `ImageSymbol` struct. - pub fn raw_symbol(&self) -> &'data Coff::ImageSymbol { - self.symbol - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSymbol<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbol<'data> - for CoffSymbol<'data, 'file, R, Coff> -{ - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - fn name_bytes(&self) -> read::Result<&'data [u8]> { - if self.symbol.has_aux_file_name() { - self.file - .symbols - .aux_file_name(self.index.0, self.symbol.number_of_aux_symbols()) - } else { - self.symbol.name(self.file.symbols.strings()) - } - } - - fn name(&self) -> read::Result<&'data str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF symbol name") - } - - fn address(&self) -> u64 { - // Only return an address for storage classes that we know use an address. - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC - | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL - | pe::IMAGE_SYM_CLASS_LABEL => {} - pe::IMAGE_SYM_CLASS_EXTERNAL => { - if self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED { - // Undefined or common data, neither of which have an address. - return 0; - } - } - _ => return 0, - } - self.symbol - .address(self.file.image_base, &self.file.sections) - .unwrap_or(0) - } - - fn size(&self) -> u64 { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => { - // Section symbols may duplicate the size from the section table. - if self.symbol.has_aux_section() { - if let Ok(aux) = self.file.symbols.aux_section(self.index.0) { - u64::from(aux.length.get(LE)) - } else { - 0 - } - } else { - 0 - } - } - pe::IMAGE_SYM_CLASS_EXTERNAL => { - if self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED { - // For undefined symbols, symbol.value is 0 and the size is 0. - // For common data, symbol.value is the size. - u64::from(self.symbol.value()) - } else if self.symbol.has_aux_function() { - // Function symbols may have a size. - if let Ok(aux) = self.file.symbols.aux_function(self.index.0) { - u64::from(aux.total_size.get(LE)) - } else { - 0 - } - } else { - 0 - } - } - // Most symbols don't have sizes. - _ => 0, - } - } - - fn kind(&self) -> SymbolKind { - let derived_kind = if self.symbol.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION { - SymbolKind::Text - } else { - SymbolKind::Data - }; - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => { - if self.symbol.has_aux_section() { - SymbolKind::Section - } else { - derived_kind - } - } - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => derived_kind, - pe::IMAGE_SYM_CLASS_SECTION => SymbolKind::Section, - pe::IMAGE_SYM_CLASS_FILE => SymbolKind::File, - pe::IMAGE_SYM_CLASS_LABEL => SymbolKind::Label, - _ => SymbolKind::Unknown, - } - } - - fn section(&self) -> SymbolSection { - match self.symbol.section_number() { - pe::IMAGE_SYM_UNDEFINED => { - if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL { - if self.symbol.value() == 0 { - SymbolSection::Undefined - } else { - SymbolSection::Common - } - } else if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_SECTION { - SymbolSection::Undefined - } else { - SymbolSection::Unknown - } - } - pe::IMAGE_SYM_ABSOLUTE => SymbolSection::Absolute, - pe::IMAGE_SYM_DEBUG => { - if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_FILE { - SymbolSection::None - } else { - SymbolSection::Unknown - } - } - index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)), - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value() == 0 - } - - #[inline] - fn is_definition(&self) -> bool { - self.symbol.is_definition() - } - - #[inline] - fn is_common(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value() != 0 - } - - #[inline] - fn is_weak(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL - } - - #[inline] - fn scope(&self) -> SymbolScope { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => { - // TODO: determine if symbol is exported - SymbolScope::Linkage - } - _ => SymbolScope::Compilation, - } - } - - #[inline] - fn is_global(&self) -> bool { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true, - _ => false, - } - } - - #[inline] - fn is_local(&self) -> bool { - !self.is_global() - } - - fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> { - if self.symbol.has_aux_section() { - if let Ok(aux) = self.file.symbols.aux_section(self.index.0) { - let number = if Coff::is_type_bigobj() { - u32::from(aux.number.get(LE)) | (u32::from(aux.high_number.get(LE)) << 16) - } else { - u32::from(aux.number.get(LE)) - }; - return SymbolFlags::CoffSection { - selection: aux.selection, - associative_section: if number == 0 { - None - } else { - Some(SectionIndex(number as usize)) - }, - }; - } - } - SymbolFlags::None - } -} - -/// A trait for generic access to [`pe::ImageSymbol`] and [`pe::ImageSymbolEx`]. -#[allow(missing_docs)] -pub trait ImageSymbol: Debug + Pod { - fn raw_name(&self) -> &[u8; 8]; - fn value(&self) -> u32; - fn section_number(&self) -> i32; - fn typ(&self) -> u16; - fn storage_class(&self) -> u8; - fn number_of_aux_symbols(&self) -> u8; - - /// Parse a COFF symbol name. - /// - /// `strings` must be the string table used for symbol names. - fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - let name = self.raw_name(); - if name[0] == 0 { - // If the name starts with 0 then the last 4 bytes are a string table offset. - let offset = u32::from_le_bytes(name[4..8].try_into().unwrap()); - strings - .get(offset) - .read_error("Invalid COFF symbol name offset") - } else { - // The name is inline and padded with nulls. - Ok(match memchr::memchr(b'\0', name) { - Some(end) => &name[..end], - None => &name[..], - }) - } - } - - /// Return the symbol address. - /// - /// This takes into account the image base and the section address. - fn address(&self, image_base: u64, sections: &SectionTable<'_>) -> Result<u64> { - let section_number = self.section_number() as usize; - let section = sections.section(section_number)?; - let virtual_address = u64::from(section.virtual_address.get(LE)); - let value = u64::from(self.value()); - Ok(image_base + virtual_address + value) - } - - /// Return true if the symbol is a definition of a function or data object. - fn is_definition(&self) -> bool { - if self.section_number() <= 0 { - return false; - } - match self.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => !self.has_aux_section(), - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true, - _ => false, - } - } - - /// Return true if the symbol has an auxiliary file name. - fn has_aux_file_name(&self) -> bool { - self.number_of_aux_symbols() > 0 && self.storage_class() == pe::IMAGE_SYM_CLASS_FILE - } - - /// Return true if the symbol has an auxiliary function symbol. - fn has_aux_function(&self) -> bool { - self.number_of_aux_symbols() > 0 && self.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION - } - - /// Return true if the symbol has an auxiliary section symbol. - fn has_aux_section(&self) -> bool { - self.number_of_aux_symbols() > 0 - && self.storage_class() == pe::IMAGE_SYM_CLASS_STATIC - && self.typ() == 0 - } - - fn base_type(&self) -> u16 { - self.typ() & pe::N_BTMASK - } - - fn derived_type(&self) -> u16 { - (self.typ() & pe::N_TMASK) >> pe::N_BTSHFT - } -} - -impl ImageSymbol for pe::ImageSymbol { - fn raw_name(&self) -> &[u8; 8] { - &self.name - } - fn value(&self) -> u32 { - self.value.get(LE) - } - fn section_number(&self) -> i32 { - let section_number = self.section_number.get(LE); - if section_number >= pe::IMAGE_SYM_SECTION_MAX { - (section_number as i16) as i32 - } else { - section_number as i32 - } - } - fn typ(&self) -> u16 { - self.typ.get(LE) - } - fn storage_class(&self) -> u8 { - self.storage_class - } - fn number_of_aux_symbols(&self) -> u8 { - self.number_of_aux_symbols - } -} - -impl ImageSymbol for pe::ImageSymbolEx { - fn raw_name(&self) -> &[u8; 8] { - &self.name - } - fn value(&self) -> u32 { - self.value.get(LE) - } - fn section_number(&self) -> i32 { - self.section_number.get(LE) - } - fn typ(&self) -> u16 { - self.typ.get(LE) - } - fn storage_class(&self) -> u8 { - self.storage_class - } - fn number_of_aux_symbols(&self) -> u8 { - self.number_of_aux_symbols - } -} |