use std::io::Read;
use byteorder::{ByteOrder, ReadBytesExt};
#[derive(Debug, Clone, Copy)]
pub struct PerfHeader {
pub magic: [u8; 8],
pub header_size: u64,
pub attr_size: u64,
pub attr_section: PerfFileSection,
pub data_section: PerfFileSection,
pub flags: [u64; 4],
}
impl PerfHeader {
pub fn parse<R: Read>(reader: &mut R) -> Result<Self, std::io::Error> {
let mut magic = [0; 8];
reader.read_exact(&mut magic)?;
if magic[0] == b'P' {
Self::parse_impl::<R, byteorder::LittleEndian>(reader, magic)
} else {
Self::parse_impl::<R, byteorder::BigEndian>(reader, magic)
}
}
fn parse_impl<R: Read, T: ByteOrder>(
reader: &mut R,
magic: [u8; 8],
) -> Result<Self, std::io::Error> {
let header_size = reader.read_u64::<T>()?;
let attr_size = reader.read_u64::<T>()?;
let attr_section = PerfFileSection::parse::<R, T>(reader)?;
let data_section = PerfFileSection::parse::<R, T>(reader)?;
let _event_types_section = PerfFileSection::parse::<R, T>(reader)?;
let flags = [
reader.read_u64::<T>()?,
reader.read_u64::<T>()?,
reader.read_u64::<T>()?,
reader.read_u64::<T>()?,
];
Ok(Self {
magic,
header_size,
attr_size,
attr_section,
data_section,
flags,
})
}
}
#[derive(Debug, Clone, Copy)]
pub struct PerfFileSection {
pub offset: u64,
pub size: u64,
}
impl PerfFileSection {
pub fn parse<R: Read, T: ByteOrder>(reader: &mut R) -> Result<Self, std::io::Error> {
let offset = reader.read_u64::<T>()?;
let size = reader.read_u64::<T>()?;
Ok(Self { offset, size })
}
}