diff options
Diffstat (limited to 'vendor/object/src/read/pe/import.rs')
-rw-r--r-- | vendor/object/src/read/pe/import.rs | 337 |
1 files changed, 0 insertions, 337 deletions
diff --git a/vendor/object/src/read/pe/import.rs b/vendor/object/src/read/pe/import.rs deleted file mode 100644 index 8e9a9a9..0000000 --- a/vendor/object/src/read/pe/import.rs +++ /dev/null @@ -1,337 +0,0 @@ -use core::fmt::Debug; -use core::mem; - -use crate::read::{Bytes, ReadError, Result}; -use crate::{pe, LittleEndian as LE, Pod, U16Bytes}; - -use super::ImageNtHeaders; - -/// Information for parsing a PE import table. -/// -/// Returned by [`DataDirectories::import_table`](super::DataDirectories::import_table). -#[derive(Debug, Clone)] -pub struct ImportTable<'data> { - section_data: Bytes<'data>, - section_address: u32, - import_address: u32, -} - -impl<'data> ImportTable<'data> { - /// Create a new import table parser. - /// - /// The import descriptors start at `import_address`. - /// The size declared in the `IMAGE_DIRECTORY_ENTRY_IMPORT` data directory is - /// ignored by the Windows loader, and so descriptors will be parsed until a null entry. - /// - /// `section_data` should be from the section containing `import_address`, and - /// `section_address` should be the address of that section. Pointers within the - /// descriptors and thunks may point to anywhere within the section data. - pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self { - ImportTable { - section_data: Bytes(section_data), - section_address, - import_address, - } - } - - /// Return an iterator for the import descriptors. - pub fn descriptors(&self) -> Result<ImportDescriptorIterator<'data>> { - let offset = self.import_address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import descriptor address")?; - Ok(ImportDescriptorIterator { data }) - } - - /// Return a library name given its address. - /// - /// This address may be from [`pe::ImageImportDescriptor::name`]. - pub fn name(&self, address: u32) -> Result<&'data [u8]> { - self.section_data - .read_string_at(address.wrapping_sub(self.section_address) as usize) - .read_error("Invalid PE import descriptor name") - } - - /// Return a list of thunks given its address. - /// - /// This address may be from [`pe::ImageImportDescriptor::original_first_thunk`] - /// or [`pe::ImageImportDescriptor::first_thunk`]. - pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import thunk table address")?; - Ok(ImportThunkList { data }) - } - - /// Parse a thunk. - pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> { - if thunk.is_ordinal() { - Ok(Import::Ordinal(thunk.ordinal())) - } else { - let (hint, name) = self.hint_name(thunk.address())?; - Ok(Import::Name(hint, name)) - } - } - - /// Return the hint and name at the given address. - /// - /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`]. - /// - /// The hint is an index into the export name pointer table in the target library. - pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import thunk address")?; - let hint = data - .read::<U16Bytes<LE>>() - .read_error("Missing PE import thunk hint")? - .get(LE); - let name = data - .read_string() - .read_error("Missing PE import thunk name")?; - Ok((hint, name)) - } -} - -/// A fallible iterator for the descriptors in the import data directory. -#[derive(Debug, Clone)] -pub struct ImportDescriptorIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> ImportDescriptorIterator<'data> { - /// Return the next descriptor. - /// - /// Returns `Ok(None)` when a null descriptor is found. - pub fn next(&mut self) -> Result<Option<&'data pe::ImageImportDescriptor>> { - let import_desc = self - .data - .read::<pe::ImageImportDescriptor>() - .read_error("Missing PE null import descriptor")?; - if import_desc.is_null() { - Ok(None) - } else { - Ok(Some(import_desc)) - } - } -} - -/// A list of import thunks. -/// -/// These may be in the import lookup table, or the import address table. -#[derive(Debug, Clone)] -pub struct ImportThunkList<'data> { - data: Bytes<'data>, -} - -impl<'data> ImportThunkList<'data> { - /// Get the thunk at the given index. - pub fn get<Pe: ImageNtHeaders>(&self, index: usize) -> Result<Pe::ImageThunkData> { - let thunk = self - .data - .read_at(index * mem::size_of::<Pe::ImageThunkData>()) - .read_error("Invalid PE import thunk index")?; - Ok(*thunk) - } - - /// Return the first thunk in the list, and update `self` to point after it. - /// - /// Returns `Ok(None)` when a null thunk is found. - pub fn next<Pe: ImageNtHeaders>(&mut self) -> Result<Option<Pe::ImageThunkData>> { - let thunk = self - .data - .read::<Pe::ImageThunkData>() - .read_error("Missing PE null import thunk")?; - if thunk.address() == 0 { - Ok(None) - } else { - Ok(Some(*thunk)) - } - } -} - -/// A parsed import thunk. -#[derive(Debug, Clone, Copy)] -pub enum Import<'data> { - /// Import by ordinal. - Ordinal(u16), - /// Import by name. - /// - /// Includes a hint for the index into the export name pointer table in the target library. - Name(u16, &'data [u8]), -} - -/// A trait for generic access to [`pe::ImageThunkData32`] and [`pe::ImageThunkData64`]. -#[allow(missing_docs)] -pub trait ImageThunkData: Debug + Pod { - /// Return the raw thunk value. - fn raw(self) -> u64; - - /// Returns true if the ordinal flag is set. - fn is_ordinal(self) -> bool; - - /// Return the ordinal portion of the thunk. - /// - /// Does not check the ordinal flag. - fn ordinal(self) -> u16; - - /// Return the RVA portion of the thunk. - /// - /// Does not check the ordinal flag. - fn address(self) -> u32; -} - -impl ImageThunkData for pe::ImageThunkData64 { - fn raw(self) -> u64 { - self.0.get(LE) - } - - fn is_ordinal(self) -> bool { - self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG64 != 0 - } - - fn ordinal(self) -> u16 { - self.0.get(LE) as u16 - } - - fn address(self) -> u32 { - self.0.get(LE) as u32 & 0x7fff_ffff - } -} - -impl ImageThunkData for pe::ImageThunkData32 { - fn raw(self) -> u64 { - self.0.get(LE).into() - } - - fn is_ordinal(self) -> bool { - self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG32 != 0 - } - - fn ordinal(self) -> u16 { - self.0.get(LE) as u16 - } - - fn address(self) -> u32 { - self.0.get(LE) & 0x7fff_ffff - } -} - -/// Information for parsing a PE delay-load import table. -/// -/// Returned by -/// [`DataDirectories::delay_load_import_table`](super::DataDirectories::delay_load_import_table). -#[derive(Debug, Clone)] -pub struct DelayLoadImportTable<'data> { - section_data: Bytes<'data>, - section_address: u32, - import_address: u32, -} - -impl<'data> DelayLoadImportTable<'data> { - /// Create a new delay load import table parser. - /// - /// The import descriptors start at `import_address`. - /// This table works in the same way the import table does: descriptors will be - /// parsed until a null entry. - /// - /// `section_data` should be from the section containing `import_address`, and - /// `section_address` should be the address of that section. Pointers within the - /// descriptors and thunks may point to anywhere within the section data. - pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self { - DelayLoadImportTable { - section_data: Bytes(section_data), - section_address, - import_address, - } - } - - /// Return an iterator for the import descriptors. - pub fn descriptors(&self) -> Result<DelayLoadDescriptorIterator<'data>> { - let offset = self.import_address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay-load import descriptor address")?; - Ok(DelayLoadDescriptorIterator { data }) - } - - /// Return a library name given its address. - /// - /// This address may be from [`pe::ImageDelayloadDescriptor::dll_name_rva`]. - pub fn name(&self, address: u32) -> Result<&'data [u8]> { - self.section_data - .read_string_at(address.wrapping_sub(self.section_address) as usize) - .read_error("Invalid PE import descriptor name") - } - - /// Return a list of thunks given its address. - /// - /// This address may be from the INT, i.e. from - /// [`pe::ImageDelayloadDescriptor::import_name_table_rva`]. - /// - /// Please note that others RVA values from [`pe::ImageDelayloadDescriptor`] are used - /// by the delay loader at runtime to store values, and thus do not point inside the same - /// section as the INT. Calling this function on those addresses will fail. - pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay load import thunk table address")?; - Ok(ImportThunkList { data }) - } - - /// Parse a thunk. - pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> { - if thunk.is_ordinal() { - Ok(Import::Ordinal(thunk.ordinal())) - } else { - let (hint, name) = self.hint_name(thunk.address())?; - Ok(Import::Name(hint, name)) - } - } - - /// Return the hint and name at the given address. - /// - /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`]. - /// - /// The hint is an index into the export name pointer table in the target library. - pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay load import thunk address")?; - let hint = data - .read::<U16Bytes<LE>>() - .read_error("Missing PE delay load import thunk hint")? - .get(LE); - let name = data - .read_string() - .read_error("Missing PE delay load import thunk name")?; - Ok((hint, name)) - } -} - -/// A fallible iterator for the descriptors in the delay-load data directory. -#[derive(Debug, Clone)] -pub struct DelayLoadDescriptorIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> DelayLoadDescriptorIterator<'data> { - /// Return the next descriptor. - /// - /// Returns `Ok(None)` when a null descriptor is found. - pub fn next(&mut self) -> Result<Option<&'data pe::ImageDelayloadDescriptor>> { - let import_desc = self - .data - .read::<pe::ImageDelayloadDescriptor>() - .read_error("Missing PE null delay-load import descriptor")?; - if import_desc.is_null() { - Ok(None) - } else { - Ok(Some(import_desc)) - } - } -} |