linux_perf_data/jitdump/
header.rs1use std::io::ErrorKind;
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian};
4use linux_perf_event_reader::RawData;
5
6use super::error::JitDumpError;
7
8#[derive(Debug, Clone)]
10pub struct JitDumpHeader {
11 pub magic: [u8; 4],
15 pub version: u32,
17 pub total_size: u32,
19 pub elf_machine_arch: u32,
21 pub pid: u32,
23 pub timestamp: u64,
25 pub flags: u64,
27}
28
29impl JitDumpHeader {
30 pub const SIZE: usize = 40; pub fn parse(mut data: RawData) -> Result<Self, JitDumpError> {
33 let mut magic = [0; 4];
34 data.read_exact(&mut magic)?;
35 let header_result = match &magic {
36 b"JiTD" => Self::parse_after_magic::<BigEndian>(magic, data),
37 b"DTiJ" => Self::parse_after_magic::<LittleEndian>(magic, data),
38 _ => return Err(JitDumpError::InvalidMagicBytes(magic)),
39 };
40 let header = match header_result {
41 Ok(header) => header,
42 Err(e) if e.kind() == ErrorKind::UnexpectedEof => {
43 return Err(JitDumpError::NotEnoughBytesForHeader)
44 }
45 Err(e) => panic!("Unexpected error type {e}"),
46 };
47 if header.total_size < Self::SIZE as u32 {
48 return Err(JitDumpError::InvalidHeaderSize(header.total_size));
49 }
50
51 Ok(header)
52 }
53
54 pub fn parse_after_magic<O: ByteOrder>(
55 magic: [u8; 4],
56 data: RawData,
57 ) -> Result<Self, std::io::Error> {
58 let mut cur = data;
59 let version = cur.read_u32::<O>()?;
60 let total_size = cur.read_u32::<O>()?;
61
62 let mut full_header = data;
64 full_header.skip(total_size.saturating_sub(4) as usize)?;
65
66 let elf_machine_arch = cur.read_u32::<O>()?;
67 let _pad1 = cur.read_u32::<O>()?;
68 let pid = cur.read_u32::<O>()?;
69 let timestamp = cur.read_u64::<O>()?;
70 let flags = cur.read_u64::<O>()?;
71 Ok(Self {
72 magic,
73 version,
74 total_size,
75 elf_machine_arch,
76 pid,
77 timestamp,
78 flags,
79 })
80 }
81}