summaryrefslogtreecommitdiffstats
path: root/third_party/rust/goblin/src/pe/optional_header.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/goblin/src/pe/optional_header.rs
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/goblin/src/pe/optional_header.rs')
-rw-r--r--third_party/rust/goblin/src/pe/optional_header.rs319
1 files changed, 319 insertions, 0 deletions
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<StandardFields32> 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<StandardFields64> 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<WindowsFields32> 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<WindowsFields32> 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<container::Container> {
+ 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::<u16>(0, LE)?;
+ let offset = &mut 0;
+ let (standard_fields, windows_fields): (StandardFields, WindowsFields) = match magic {
+ MAGIC_32 => {
+ let standard_fields = bytes.gread_with::<StandardFields32>(offset, LE)?.into();
+ let windows_fields = bytes.gread_with::<WindowsFields32>(offset, LE)?.into();
+ (standard_fields, windows_fields)
+ }
+ MAGIC_64 => {
+ let standard_fields = bytes.gread_with::<StandardFields64>(offset, LE)?.into();
+ let windows_fields = bytes.gread_with::<WindowsFields64>(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::<StandardFields32>(),
+ SIZEOF_STANDARD_FIELDS_32
+ );
+ }
+ #[test]
+ fn sizeof_windows32() {
+ assert_eq!(
+ ::std::mem::size_of::<WindowsFields32>(),
+ SIZEOF_WINDOWS_FIELDS_32
+ );
+ }
+ #[test]
+ fn sizeof_standards64() {
+ assert_eq!(
+ ::std::mem::size_of::<StandardFields64>(),
+ SIZEOF_STANDARD_FIELDS_64
+ );
+ }
+ #[test]
+ fn sizeof_windows64() {
+ assert_eq!(
+ ::std::mem::size_of::<WindowsFields64>(),
+ SIZEOF_WINDOWS_FIELDS_64
+ );
+ }
+}