diff options
Diffstat (limited to 'vendor/object-0.29.0/src/read/coff')
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/comdat.rs | 167 | ||||
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/file.rs | 247 | ||||
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/mod.rs | 18 | ||||
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/relocation.rs | 91 | ||||
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/section.rs | 524 | ||||
-rw-r--r-- | vendor/object-0.29.0/src/read/coff/symbol.rs | 518 |
6 files changed, 0 insertions, 1565 deletions
diff --git a/vendor/object-0.29.0/src/read/coff/comdat.rs b/vendor/object-0.29.0/src/read/coff/comdat.rs deleted file mode 100644 index 3be69ecc2..000000000 --- a/vendor/object-0.29.0/src/read/coff/comdat.rs +++ /dev/null @@ -1,167 +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; - -/// An iterator over the COMDAT section groups of a `CoffFile`. -#[derive(Debug)] -pub struct CoffComdatIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffComdatIterator<'data, 'file, R> { - type Item = CoffComdat<'data, 'file, R>; - - 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 of a `CoffFile`. -#[derive(Debug)] -pub struct CoffComdat<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - file: &'file CoffFile<'data, R>, - symbol_index: SymbolIndex, - symbol: &'data pe::ImageSymbol, - selection: u8, -} - -impl<'data, 'file, R: ReadRef<'data>> CoffComdat<'data, 'file, R> { - fn parse( - file: &'file CoffFile<'data, R>, - section_symbol: &'data pe::ImageSymbol, - index: usize, - ) -> Option<CoffComdat<'data, 'file, R>> { - // 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.get(LE); - 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.get(LE) { - break; - } - } - - Some(CoffComdat { - file, - symbol_index: SymbolIndex(symbol_index), - symbol, - selection, - }) - } -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffComdat<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for CoffComdat<'data, 'file, R> { - type SectionIterator = CoffComdatSectionIterator<'data, 'file, R>; - - #[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.get(LE), - index: 0, - } - } -} - -/// An iterator over the sections in a COMDAT section group of a `CoffFile`. -#[derive(Debug)] -pub struct CoffComdatSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - file: &'file CoffFile<'data, R>, - section_number: u16, - index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffComdatSectionIterator<'data, 'file, R> { - 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.get(LE); - - let aux = self.file.common.symbols.aux_section(index).ok()?; - if aux.selection == pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE { - // TODO: use high_number for bigobj - if aux.number.get(LE) == 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-0.29.0/src/read/coff/file.rs b/vendor/object-0.29.0/src/read/coff/file.rs deleted file mode 100644 index c6cc9f846..000000000 --- a/vendor/object-0.29.0/src/read/coff/file.rs +++ /dev/null @@ -1,247 +0,0 @@ -use alloc::vec::Vec; - -use crate::read::{ - self, Architecture, Export, FileFlags, Import, NoDynamicRelocationIterator, Object, ObjectKind, - ObjectSection, ReadError, ReadRef, Result, SectionIndex, SymbolIndex, -}; -use crate::{pe, LittleEndian as LE}; - -use super::{ - CoffComdat, CoffComdatIterator, CoffSection, CoffSectionIterator, CoffSegment, - CoffSegmentIterator, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SectionTable, - SymbolTable, -}; - -/// The common parts of `PeFile` and `CoffFile`. -#[derive(Debug)] -pub(crate) struct CoffCommon<'data, R: ReadRef<'data>> { - pub(crate) sections: SectionTable<'data>, - // TODO: ImageSymbolExBytes - pub(crate) symbols: SymbolTable<'data, R>, - pub(crate) image_base: u64, -} - -/// A COFF object file. -#[derive(Debug)] -pub struct CoffFile<'data, R: ReadRef<'data> = &'data [u8]> { - pub(super) header: &'data pe::ImageFileHeader, - pub(super) common: CoffCommon<'data, R>, - pub(super) data: R, -} - -impl<'data, R: ReadRef<'data>> CoffFile<'data, R> { - /// Parse the raw COFF file data. - pub fn parse(data: R) -> Result<Self> { - let mut offset = 0; - let header = pe::ImageFileHeader::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>> read::private::Sealed for CoffFile<'data, R> {} - -impl<'data, 'file, R> Object<'data, 'file> for CoffFile<'data, R> -where - 'data: 'file, - R: 'file + ReadRef<'data>, -{ - type Segment = CoffSegment<'data, 'file, R>; - type SegmentIterator = CoffSegmentIterator<'data, 'file, R>; - type Section = CoffSection<'data, 'file, R>; - type SectionIterator = CoffSectionIterator<'data, 'file, R>; - type Comdat = CoffComdat<'data, 'file, R>; - type ComdatIterator = CoffComdatIterator<'data, 'file, 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.header.machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm, - pe::IMAGE_FILE_MACHINE_ARM64 => Architecture::Aarch64, - pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386, - pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64, - _ => Architecture::Unknown, - } - } - - #[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> { - CoffSegmentIterator { - file: self, - iter: self.common.sections.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option<CoffSection<'data, 'file, R>> { - self.sections() - .find(|section| section.name_bytes() == Ok(section_name)) - } - - fn section_by_index(&'file self, index: SectionIndex) -> Result<CoffSection<'data, 'file, R>> { - let section = self.common.sections.section(index.0)?; - Ok(CoffSection { - file: self, - index, - section, - }) - } - - fn sections(&'file self) -> CoffSectionIterator<'data, 'file, R> { - CoffSectionIterator { - file: self, - iter: self.common.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> CoffComdatIterator<'data, 'file, R> { - CoffComdatIterator { - file: self, - index: 0, - } - } - - 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, - } - } - - #[inline] - 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(), - } - } - - #[inline] - fn dynamic_symbol_table(&'file self) -> Option<CoffSymbolTable<'data, 'file, R>> { - 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.get(LE), - } - } -} - -impl pe::ImageFileHeader { - /// 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. - pub 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) - } - - /// Read the section table. - /// - /// `data` must be the entire file data. - /// `offset` must be after the optional file header. - #[inline] - pub 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] - pub fn symbols<'data, R: ReadRef<'data>>( - &self, - data: R, - ) -> read::Result<SymbolTable<'data, R>> { - SymbolTable::parse(self, data) - } -} diff --git a/vendor/object-0.29.0/src/read/coff/mod.rs b/vendor/object-0.29.0/src/read/coff/mod.rs deleted file mode 100644 index d5b3caf32..000000000 --- a/vendor/object-0.29.0/src/read/coff/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Support for reading Windows COFF files. -//! -//! Provides `CoffFile` and related types which implement the `Object` trait. - -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::*; diff --git a/vendor/object-0.29.0/src/read/coff/relocation.rs b/vendor/object-0.29.0/src/read/coff/relocation.rs deleted file mode 100644 index 9a1fcb618..000000000 --- a/vendor/object-0.29.0/src/read/coff/relocation.rs +++ /dev/null @@ -1,91 +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; - -/// An iterator over the relocations in a `CoffSection`. -pub struct CoffRelocationIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) iter: slice::Iter<'data, pe::ImageRelocation>, -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffRelocationIterator<'data, 'file, R> { - 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.get(LE) { - 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 => 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>> fmt::Debug for CoffRelocationIterator<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffRelocationIterator").finish() - } -} diff --git a/vendor/object-0.29.0/src/read/coff/section.rs b/vendor/object-0.29.0/src/read/coff/section.rs deleted file mode 100644 index 731e37ca8..000000000 --- a/vendor/object-0.29.0/src/read/coff/section.rs +++ /dev/null @@ -1,524 +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, CoffRelocationIterator}; - -/// The table of section headers in a COFF or PE file. -#[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<R: ReadRef<'data>>( - header: &pe::ImageFileHeader, - data: R, - offset: u64, - ) -> Result<Self> { - let sections = data - .read_slice_at(offset, header.number_of_sections.get(LE).into()) - .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 over the loadable sections of a `CoffFile`. -#[derive(Debug)] -pub struct CoffSegmentIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>, -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffSegmentIterator<'data, 'file, R> { - type Item = CoffSegment<'data, 'file, R>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|section| CoffSegment { - file: self.file, - section, - }) - } -} - -/// A loadable section of a `CoffFile`. -#[derive(Debug)] -pub struct CoffSegment<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>> CoffSegment<'data, 'file, R> { - 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>> read::private::Sealed for CoffSegment<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for CoffSegment<'data, 'file, R> { - #[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 over the sections of a `CoffFile`. -#[derive(Debug)] -pub struct CoffSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) iter: iter::Enumerate<slice::Iter<'data, pe::ImageSectionHeader>>, -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffSectionIterator<'data, 'file, R> { - type Item = CoffSection<'data, 'file, R>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(index, section)| CoffSection { - file: self.file, - index: SectionIndex(index + 1), - section, - }) - } -} - -/// A section of a `CoffFile`. -#[derive(Debug)] -pub struct CoffSection<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - pub(super) file: &'file CoffFile<'data, R>, - pub(super) index: SectionIndex, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>> CoffSection<'data, 'file, R> { - 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>> read::private::Sealed for CoffSection<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for CoffSection<'data, 'file, R> { - type RelocationIterator = CoffRelocationIterator<'data, 'file, R>; - - #[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> { - 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-0.29.0/src/read/coff/symbol.rs b/vendor/object-0.29.0/src/read/coff/symbol.rs deleted file mode 100644 index c954c8a29..000000000 --- a/vendor/object-0.29.0/src/read/coff/symbol.rs +++ /dev/null @@ -1,518 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::convert::TryInto; -use core::str; - -use super::{CoffCommon, SectionTable}; -use crate::endian::{LittleEndian as LE, U32Bytes}; -use crate::pe; -use crate::pod::{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. -#[derive(Debug)] -pub struct SymbolTable<'data, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - symbols: &'data [pe::ImageSymbolBytes], - strings: StringTable<'data, R>, -} - -impl<'data, R: ReadRef<'data>> Default for SymbolTable<'data, R> { - fn default() -> Self { - Self { - symbols: &[], - strings: StringTable::default(), - } - } -} - -impl<'data, R: ReadRef<'data>> SymbolTable<'data, R> { - /// Read the symbol table. - pub fn parse(header: &pe::ImageFileHeader, data: R) -> Result<Self> { - // The symbol table may not be present. - let mut offset = header.pointer_to_symbol_table.get(LE).into(); - let (symbols, strings) = if offset != 0 { - let symbols = data - .read_slice(&mut offset, header.number_of_symbols.get(LE) 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> { - SymbolIterator { - symbols: self, - index: 0, - } - } - - /// Return the symbol table entry at the given index. - #[inline] - pub fn symbol(&self, index: usize) -> Result<&'data pe::ImageSymbol> { - self.get::<pe::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.0[..]) - .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 pe::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]> -where - R: ReadRef<'data>, -{ - symbols: &'table SymbolTable<'data, R>, - index: usize, -} - -impl<'data, 'table, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'table, R> { - type Item = (usize, &'data pe::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)) - } -} - -impl pe::ImageSymbol { - /// Parse a COFF symbol name. - /// - /// `strings` must be the string table used for symbol names. - pub fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - if self.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(self.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', &self.name) { - Some(end) => &self.name[..end], - None => &self.name[..], - }) - } - } - - /// Return the symbol address. - /// - /// This takes into account the image base and the section address. - pub fn address(&self, image_base: u64, sections: &SectionTable) -> Result<u64> { - let section_number = self.section_number.get(LE) as usize; - let section = sections.section(section_number)?; - let virtual_address = u64::from(section.virtual_address.get(LE)); - let value = u64::from(self.value.get(LE)); - Ok(image_base + virtual_address + value) - } - - /// Return true if the symbol is a definition of a function or data object. - pub fn is_definition(&self) -> bool { - let section_number = self.section_number.get(LE); - if section_number == pe::IMAGE_SYM_UNDEFINED { - return false; - } - match self.storage_class { - pe::IMAGE_SYM_CLASS_STATIC => { - // Exclude section symbols. - !(self.value.get(LE) == 0 && self.number_of_aux_symbols > 0) - } - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true, - _ => false, - } - } - - /// Return true if the symbol has an auxiliary file name. - pub 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. - pub 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. - pub fn has_aux_section(&self) -> bool { - self.number_of_aux_symbols > 0 - && self.storage_class == pe::IMAGE_SYM_CLASS_STATIC - && self.value.get(LE) == 0 - } -} - -/// A symbol table of a `CoffFile`. -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbolTable<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - pub(crate) file: &'file CoffCommon<'data, R>, -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffSymbolTable<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data> - for CoffSymbolTable<'data, 'file, R> -{ - type Symbol = CoffSymbol<'data, 'file, R>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R>; - - 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 over the symbols of a `CoffFile`. -pub struct CoffSymbolIterator<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - pub(crate) file: &'file CoffCommon<'data, R>, - pub(crate) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for CoffSymbolIterator<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffSymbolIterator").finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for CoffSymbolIterator<'data, 'file, R> { - type Item = CoffSymbol<'data, 'file, R>; - - 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 of a `CoffFile`. -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbol<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - pub(crate) file: &'file CoffCommon<'data, R>, - pub(crate) index: SymbolIndex, - pub(crate) symbol: &'data pe::ImageSymbol, -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffSymbol<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for CoffSymbol<'data, 'file, R> { - #[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.get(LE) == 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.get(LE) == 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.get(LE)) - } 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.value.get(LE) == 0 && self.symbol.number_of_aux_symbols > 0 { - 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.get(LE) { - pe::IMAGE_SYM_UNDEFINED => { - if self.symbol.storage_class == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.value.get(LE) == 0 - { - SymbolSection::Undefined - } else { - SymbolSection::Common - } - } - 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.into())), - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.storage_class == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.section_number.get(LE) == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value.get(LE) == 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.get(LE) == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value.get(LE) != 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> { - if self.symbol.has_aux_section() { - if let Ok(aux) = self.file.symbols.aux_section(self.index.0) { - // TODO: use high_number for bigobj - let number = aux.number.get(LE) as usize; - return SymbolFlags::CoffSection { - selection: aux.selection, - associative_section: if number == 0 { - None - } else { - Some(SectionIndex(number)) - }, - }; - } - } - SymbolFlags::None - } -} |