From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- third_party/rust/goblin/src/pe/optional_header.rs | 319 ++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 third_party/rust/goblin/src/pe/optional_header.rs (limited to 'third_party/rust/goblin/src/pe/optional_header.rs') diff --git a/third_party/rust/goblin/src/pe/optional_header.rs b/third_party/rust/goblin/src/pe/optional_header.rs new file mode 100644 index 0000000000..56523c53bb --- /dev/null +++ b/third_party/rust/goblin/src/pe/optional_header.rs @@ -0,0 +1,319 @@ +use crate::container; +use crate::error; + +use crate::pe::data_directories; + +use scroll::{ctx, Endian, LE}; +use scroll::{Pread, Pwrite, SizeWith}; + +/// standard COFF fields +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)] +pub struct StandardFields32 { + pub magic: u16, + pub major_linker_version: u8, + pub minor_linker_version: u8, + pub size_of_code: u32, + pub size_of_initialized_data: u32, + pub size_of_uninitialized_data: u32, + pub address_of_entry_point: u32, + pub base_of_code: u32, + /// absent in 64-bit PE32+ + pub base_of_data: u32, +} + +pub const SIZEOF_STANDARD_FIELDS_32: usize = 28; + +/// standard 64-bit COFF fields +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)] +pub struct StandardFields64 { + pub magic: u16, + pub major_linker_version: u8, + pub minor_linker_version: u8, + pub size_of_code: u32, + pub size_of_initialized_data: u32, + pub size_of_uninitialized_data: u32, + pub address_of_entry_point: u32, + pub base_of_code: u32, +} + +pub const SIZEOF_STANDARD_FIELDS_64: usize = 24; + +/// Unified 32/64-bit COFF fields +#[derive(Debug, PartialEq, Copy, Clone, Default)] +pub struct StandardFields { + pub magic: u16, + pub major_linker_version: u8, + pub minor_linker_version: u8, + pub size_of_code: u64, + pub size_of_initialized_data: u64, + pub size_of_uninitialized_data: u64, + pub address_of_entry_point: u64, + pub base_of_code: u64, + /// absent in 64-bit PE32+ + pub base_of_data: u32, +} + +impl From for StandardFields { + fn from(fields: StandardFields32) -> Self { + StandardFields { + magic: fields.magic, + major_linker_version: fields.major_linker_version, + minor_linker_version: fields.minor_linker_version, + size_of_code: u64::from(fields.size_of_code), + size_of_initialized_data: u64::from(fields.size_of_initialized_data), + size_of_uninitialized_data: u64::from(fields.size_of_uninitialized_data), + address_of_entry_point: u64::from(fields.address_of_entry_point), + base_of_code: u64::from(fields.base_of_code), + base_of_data: fields.base_of_data, + } + } +} + +impl From for StandardFields { + fn from(fields: StandardFields64) -> Self { + StandardFields { + magic: fields.magic, + major_linker_version: fields.major_linker_version, + minor_linker_version: fields.minor_linker_version, + size_of_code: u64::from(fields.size_of_code), + size_of_initialized_data: u64::from(fields.size_of_initialized_data), + size_of_uninitialized_data: u64::from(fields.size_of_uninitialized_data), + address_of_entry_point: u64::from(fields.address_of_entry_point), + base_of_code: u64::from(fields.base_of_code), + base_of_data: 0, + } + } +} + +/// Standard fields magic number for 32-bit binary +pub const MAGIC_32: u16 = 0x10b; +/// Standard fields magic number for 64-bit binary +pub const MAGIC_64: u16 = 0x20b; + +/// Windows specific fields +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)] +pub struct WindowsFields32 { + pub image_base: u32, + pub section_alignment: u32, + pub file_alignment: u32, + pub major_operating_system_version: u16, + pub minor_operating_system_version: u16, + pub major_image_version: u16, + pub minor_image_version: u16, + pub major_subsystem_version: u16, + pub minor_subsystem_version: u16, + pub win32_version_value: u32, + pub size_of_image: u32, + pub size_of_headers: u32, + pub check_sum: u32, + pub subsystem: u16, + pub dll_characteristics: u16, + pub size_of_stack_reserve: u32, + pub size_of_stack_commit: u32, + pub size_of_heap_reserve: u32, + pub size_of_heap_commit: u32, + pub loader_flags: u32, + pub number_of_rva_and_sizes: u32, +} + +pub const SIZEOF_WINDOWS_FIELDS_32: usize = 68; + +/// 64-bit Windows specific fields +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)] +pub struct WindowsFields64 { + pub image_base: u64, + pub section_alignment: u32, + pub file_alignment: u32, + pub major_operating_system_version: u16, + pub minor_operating_system_version: u16, + pub major_image_version: u16, + pub minor_image_version: u16, + pub major_subsystem_version: u16, + pub minor_subsystem_version: u16, + pub win32_version_value: u32, + pub size_of_image: u32, + pub size_of_headers: u32, + pub check_sum: u32, + pub subsystem: u16, + pub dll_characteristics: u16, + pub size_of_stack_reserve: u64, + pub size_of_stack_commit: u64, + pub size_of_heap_reserve: u64, + pub size_of_heap_commit: u64, + pub loader_flags: u32, + pub number_of_rva_and_sizes: u32, +} + +pub const SIZEOF_WINDOWS_FIELDS_64: usize = 88; + +// /// Generic 32/64-bit Windows specific fields +// #[derive(Debug, PartialEq, Copy, Clone, Default)] +// pub struct WindowsFields { +// pub image_base: u64, +// pub section_alignment: u32, +// pub file_alignment: u32, +// pub major_operating_system_version: u16, +// pub minor_operating_system_version: u16, +// pub major_image_version: u16, +// pub minor_image_version: u16, +// pub major_subsystem_version: u16, +// pub minor_subsystem_version: u16, +// pub win32_version_value: u32, +// pub size_of_image: u32, +// pub size_of_headers: u32, +// pub check_sum: u32, +// pub subsystem: u16, +// pub dll_characteristics: u16, +// pub size_of_stack_reserve: u64, +// pub size_of_stack_commit: u64, +// pub size_of_heap_reserve: u64, +// pub size_of_heap_commit: u64, +// pub loader_flags: u32, +// pub number_of_rva_and_sizes: u32, +// } + +impl From for WindowsFields { + fn from(windows: WindowsFields32) -> Self { + WindowsFields { + image_base: u64::from(windows.image_base), + section_alignment: windows.section_alignment, + file_alignment: windows.file_alignment, + major_operating_system_version: windows.major_operating_system_version, + minor_operating_system_version: windows.minor_operating_system_version, + major_image_version: windows.major_image_version, + minor_image_version: windows.minor_image_version, + major_subsystem_version: windows.major_subsystem_version, + minor_subsystem_version: windows.minor_subsystem_version, + win32_version_value: windows.win32_version_value, + size_of_image: windows.size_of_image, + size_of_headers: windows.size_of_headers, + check_sum: windows.check_sum, + subsystem: windows.subsystem, + dll_characteristics: windows.dll_characteristics, + size_of_stack_reserve: u64::from(windows.size_of_stack_reserve), + size_of_stack_commit: u64::from(windows.size_of_stack_commit), + size_of_heap_reserve: u64::from(windows.size_of_heap_reserve), + size_of_heap_commit: u64::from(windows.size_of_heap_commit), + loader_flags: windows.loader_flags, + number_of_rva_and_sizes: windows.number_of_rva_and_sizes, + } + } +} + +// impl From for WindowsFields { +// fn from(windows: WindowsFields32) -> Self { +// WindowsFields { +// image_base: windows.image_base, +// section_alignment: windows.section_alignment, +// file_alignment: windows.file_alignment, +// major_operating_system_version: windows.major_operating_system_version, +// minor_operating_system_version: windows.minor_operating_system_version, +// major_image_version: windows.major_image_version, +// minor_image_version: windows.minor_image_version, +// major_subsystem_version: windows.major_subsystem_version, +// minor_subsystem_version: windows.minor_subsystem_version, +// win32_version_value: windows.win32_version_value, +// size_of_image: windows.size_of_image, +// size_of_headers: windows.size_of_headers, +// check_sum: windows.check_sum, +// subsystem: windows.subsystem, +// dll_characteristics: windows.dll_characteristics, +// size_of_stack_reserve: windows.size_of_stack_reserve, +// size_of_stack_commit: windows.size_of_stack_commit, +// size_of_heap_reserve: windows.size_of_heap_reserve, +// size_of_heap_commit: windows.size_of_heap_commit, +// loader_flags: windows.loader_flags, +// number_of_rva_and_sizes: windows.number_of_rva_and_sizes, +// } +// } +// } + +pub type WindowsFields = WindowsFields64; + +#[derive(Debug, PartialEq, Copy, Clone)] +pub struct OptionalHeader { + pub standard_fields: StandardFields, + pub windows_fields: WindowsFields, + pub data_directories: data_directories::DataDirectories, +} + +impl OptionalHeader { + pub fn container(&self) -> error::Result { + match self.standard_fields.magic { + MAGIC_32 => Ok(container::Container::Little), + MAGIC_64 => Ok(container::Container::Big), + magic => Err(error::Error::BadMagic(u64::from(magic))), + } + } +} + +impl<'a> ctx::TryFromCtx<'a, Endian> for OptionalHeader { + type Error = crate::error::Error; + fn try_from_ctx(bytes: &'a [u8], _: Endian) -> error::Result<(Self, usize)> { + let magic = bytes.pread_with::(0, LE)?; + let offset = &mut 0; + let (standard_fields, windows_fields): (StandardFields, WindowsFields) = match magic { + MAGIC_32 => { + let standard_fields = bytes.gread_with::(offset, LE)?.into(); + let windows_fields = bytes.gread_with::(offset, LE)?.into(); + (standard_fields, windows_fields) + } + MAGIC_64 => { + let standard_fields = bytes.gread_with::(offset, LE)?.into(); + let windows_fields = bytes.gread_with::(offset, LE)?; + (standard_fields, windows_fields) + } + _ => return Err(error::Error::BadMagic(u64::from(magic))), + }; + let data_directories = data_directories::DataDirectories::parse( + &bytes, + windows_fields.number_of_rva_and_sizes as usize, + offset, + )?; + Ok(( + OptionalHeader { + standard_fields, + windows_fields, + data_directories, + }, + 0, + )) // TODO: FIXME + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn sizeof_standards32() { + assert_eq!( + ::std::mem::size_of::(), + SIZEOF_STANDARD_FIELDS_32 + ); + } + #[test] + fn sizeof_windows32() { + assert_eq!( + ::std::mem::size_of::(), + SIZEOF_WINDOWS_FIELDS_32 + ); + } + #[test] + fn sizeof_standards64() { + assert_eq!( + ::std::mem::size_of::(), + SIZEOF_STANDARD_FIELDS_64 + ); + } + #[test] + fn sizeof_windows64() { + assert_eq!( + ::std::mem::size_of::(), + SIZEOF_WINDOWS_FIELDS_64 + ); + } +} -- cgit v1.2.3