use std::fmt;
use crate::common::*;
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct ImageSectionHeader {
pub name: [u8; 8],
pub physical_address: u32,
pub virtual_address: u32,
pub size_of_raw_data: u32,
pub pointer_to_raw_data: u32,
pub pointer_to_relocations: u32,
pub pointer_to_line_numbers: u32,
pub number_of_relocations: u16,
pub number_of_line_numbers: u16,
pub characteristics: u32,
}
impl ImageSectionHeader {
pub(crate) fn parse(parse_buffer: &mut ParseBuffer<'_>) -> Result<Self> {
let name_bytes = parse_buffer.take(8)?;
Ok(ImageSectionHeader {
name: [
name_bytes[0],
name_bytes[1],
name_bytes[2],
name_bytes[3],
name_bytes[4],
name_bytes[5],
name_bytes[6],
name_bytes[7],
],
physical_address: parse_buffer.parse_u32()?,
virtual_address: parse_buffer.parse_u32()?,
size_of_raw_data: parse_buffer.parse_u32()?,
pointer_to_raw_data: parse_buffer.parse_u32()?,
pointer_to_relocations: parse_buffer.parse_u32()?,
pointer_to_line_numbers: parse_buffer.parse_u32()?,
number_of_relocations: parse_buffer.parse_u16()?,
number_of_line_numbers: parse_buffer.parse_u16()?,
characteristics: parse_buffer.parse_u32()?,
})
}
pub fn name(&self) -> &str {
let end = self
.name
.iter()
.position(|ch| *ch == 0)
.unwrap_or_else(|| self.name.len());
std::str::from_utf8(&self.name[0..end]).unwrap_or("")
}
}
impl fmt::Debug for ImageSectionHeader {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ImageSectionHeader")
.field("name()", &self.name().to_string())
.field("physical_address", &FixedHexFmt(self.physical_address))
.field("virtual_address", &FixedHexFmt(self.virtual_address))
.field("size_of_raw_data", &self.size_of_raw_data)
.field("pointer_to_raw_data", &HexFmt(self.pointer_to_raw_data))
.field(
"pointer_to_relocations",
&HexFmt(self.pointer_to_relocations),
)
.field(
"pointer_to_line_numbers",
&HexFmt(self.pointer_to_line_numbers),
)
.field("number_of_relocations", &self.number_of_relocations)
.field("number_of_line_numbers", &self.number_of_line_numbers)
.field("characteristics", &FixedHexFmt(self.characteristics))
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn image_section_header() {
let bytes: Vec<u8> = vec![
0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x48, 0x35, 0x09, 0x00, 0x00, 0xD0,
0x1E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xA2, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8,
];
let mut parse_buffer = ParseBuffer::from(bytes.as_slice());
let ish = ImageSectionHeader::parse(&mut parse_buffer).expect("parse");
assert_eq!(&ish.name, b".data\0\0\0");
assert_eq!(ish.name(), ".data");
assert_eq!(ish.physical_address, 0x93548);
assert_eq!(ish.virtual_address, 0x001e_d000);
assert_eq!(ish.size_of_raw_data, 0xfe00);
assert_eq!(ish.pointer_to_raw_data, 0x001e_a200);
assert_eq!(ish.pointer_to_relocations, 0);
assert_eq!(ish.pointer_to_line_numbers, 0);
assert_eq!(ish.number_of_relocations, 0);
assert_eq!(ish.number_of_line_numbers, 0);
assert_eq!(ish.characteristics, 0xc800_0040);
}
}