use super::consts::IMAGE_FILE_MACHINE_UNKNOWN;
use super::source::{array, u16_at, u32_at};
pub const FILE_HEADER_SIZE: usize = 20;
pub const BIGOBJ_HEADER_SIZE: usize = 56;
pub const SYMBOL_SIZE: usize = 18;
pub const BIGOBJ_SYMBOL_SIZE: usize = 20;
pub const BIGOBJ_CLASS_ID: [u8; 16] = [
0xc7, 0xa1, 0xba, 0xd1, 0xee, 0xba, 0xa9, 0x4b, 0xaf, 0x20, 0xfa, 0xf6, 0x6a, 0xa4, 0xdc, 0xb8,
];
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct FileHeader {
pub machine: u16,
pub number_of_sections: u32,
pub time_date_stamp: u32,
pub pointer_to_symbol_table: u32,
pub number_of_symbols: u32,
pub size_of_optional_header: u16,
pub characteristics: u16,
pub bigobj: bool,
}
impl FileHeader {
#[must_use]
pub fn parse_regular(data: &[u8]) -> Option<Self> {
Some(Self {
machine: u16_at(data, 0)?,
number_of_sections: u32::from(u16_at(data, 2)?),
time_date_stamp: u32_at(data, 4)?,
pointer_to_symbol_table: u32_at(data, 8)?,
number_of_symbols: u32_at(data, 12)?,
size_of_optional_header: u16_at(data, 16)?,
characteristics: u16_at(data, 18)?,
bigobj: false,
})
}
#[must_use]
pub fn parse_bigobj(data: &[u8]) -> Option<Self> {
if !is_bigobj(data) {
return None;
}
Some(Self {
machine: u16_at(data, 6)?,
time_date_stamp: u32_at(data, 8)?,
number_of_sections: u32_at(data, 44)?,
pointer_to_symbol_table: u32_at(data, 48)?,
number_of_symbols: u32_at(data, 52)?,
size_of_optional_header: 0,
characteristics: 0,
bigobj: true,
})
}
#[must_use]
pub fn header_size(&self) -> usize {
if self.bigobj {
BIGOBJ_HEADER_SIZE
} else {
FILE_HEADER_SIZE
}
}
#[must_use]
pub fn symbol_size(&self) -> usize {
if self.bigobj {
BIGOBJ_SYMBOL_SIZE
} else {
SYMBOL_SIZE
}
}
}
#[must_use]
pub fn is_bigobj(data: &[u8]) -> bool {
u16_at(data, 0) == Some(IMAGE_FILE_MACHINE_UNKNOWN)
&& u16_at(data, 2) == Some(0xffff)
&& u16_at(data, 4).is_some_and(|version| version >= 2)
&& array::<16>(data, 12) == Some(BIGOBJ_CLASS_ID)
}
#[must_use]
pub fn is_import_object(data: &[u8]) -> bool {
u16_at(data, 0) == Some(IMAGE_FILE_MACHINE_UNKNOWN)
&& u16_at(data, 2) == Some(0xffff)
&& u16_at(data, 4) == Some(0)
}