use core::mem;
use core::ops;
use crate::display;
use crate::perf_abi;
use crate::perf_session;
use crate::byte_reader::PerfByteReader;
use crate::perf_event_desc::PerfEventDesc;
use crate::perf_event_format::PerfEventFormat;
#[derive(Clone, Copy, Debug, Default)]
pub struct PerfEventBytes<'dat> {
pub header: perf_abi::PerfEventHeader,
pub data: &'dat [u8],
}
impl<'dat> PerfEventBytes<'dat> {
pub const fn new(header: perf_abi::PerfEventHeader, data: &'dat [u8]) -> PerfEventBytes<'dat> {
debug_assert!(data.len() >= mem::size_of::<perf_abi::PerfEventHeader>());
return PerfEventBytes { header, data };
}
}
#[derive(Clone, Debug)]
pub struct PerfNonSampleEventInfo<'a> {
pub data: &'a [u8],
pub session_info: &'a perf_session::PerfSessionInfo,
pub event_desc: &'a PerfEventDesc,
pub id: u64,
pub cpu: u32,
pub cpu_reserved: u32,
pub stream_id: u64,
pub time: u64,
pub pid: u32,
pub tid: u32,
}
impl<'a> PerfNonSampleEventInfo<'a> {
pub const fn new(
data: &'a [u8],
session_info: &'a perf_session::PerfSessionInfo,
event_desc: &'a PerfEventDesc,
) -> Self {
debug_assert!(data.len() >= mem::size_of::<perf_abi::PerfEventHeader>());
return Self {
data,
session_info,
event_desc,
id: 0,
cpu: 0,
cpu_reserved: 0,
stream_id: 0,
time: 0,
pid: 0,
tid: 0,
};
}
pub const fn source_big_endian(&self) -> bool {
self.session_info.source_big_endian()
}
pub const fn byte_reader(&self) -> PerfByteReader {
self.session_info.byte_reader()
}
pub fn header(&self) -> perf_abi::PerfEventHeader {
let array = self.data[..8].try_into().unwrap();
return perf_abi::PerfEventHeader::from_bytes(&array, self.session_info.byte_reader());
}
pub const fn sample_type(&self) -> perf_abi::PerfEventAttrSampleType {
self.event_desc.attr().sample_type
}
pub fn name(&self) -> &str {
self.event_desc.name()
}
pub fn json_name_display(&self) -> display::JsonEscapeDisplay {
display::JsonEscapeDisplay::new(self.name())
}
pub const fn time_spec(&self) -> perf_session::PerfTimeSpec {
self.session_info.time_to_time_spec(self.time)
}
pub const fn json_meta_display(&self) -> display::EventInfoJsonMetaDisplay {
display::EventInfoJsonMetaDisplay::new(
self.session_info,
self.event_desc,
self.time,
self.cpu,
self.pid,
self.tid,
)
}
}
#[derive(Clone, Debug)]
pub struct PerfSampleEventInfo<'a> {
pub data: &'a [u8],
pub session_info: &'a perf_session::PerfSessionInfo,
pub event_desc: &'a PerfEventDesc,
pub id: u64,
pub ip: u64,
pub pid: u32,
pub tid: u32,
pub time: u64,
pub addr: u64,
pub stream_id: u64,
pub cpu: u32,
pub cpu_reserved: u32,
pub period: u64,
pub read_range: ops::Range<u16>,
pub callchain_range: ops::Range<u16>,
pub raw_range: ops::Range<u16>,
}
impl<'a> PerfSampleEventInfo<'a> {
pub const fn new(
data: &'a [u8],
session_info: &'a perf_session::PerfSessionInfo,
event_desc: &'a PerfEventDesc,
) -> Self {
debug_assert!(data.len() >= mem::size_of::<perf_abi::PerfEventHeader>());
return Self {
data,
session_info,
event_desc,
id: 0,
ip: 0,
pid: 0,
tid: 0,
time: 0,
addr: 0,
stream_id: 0,
cpu: 0,
cpu_reserved: 0,
period: 0,
read_range: 0..0,
callchain_range: 0..0,
raw_range: 0..0,
};
}
pub const fn source_big_endian(&self) -> bool {
self.session_info.source_big_endian()
}
pub const fn byte_reader(&self) -> PerfByteReader {
self.session_info.byte_reader()
}
pub fn header(&self) -> perf_abi::PerfEventHeader {
let array = self.data[..8].try_into().unwrap();
return perf_abi::PerfEventHeader::from_bytes(&array, self.session_info.byte_reader());
}
pub const fn sample_type(&self) -> perf_abi::PerfEventAttrSampleType {
self.event_desc.attr().sample_type
}
pub fn name(&self) -> &str {
self.event_desc.name()
}
pub fn json_name_display(&self) -> display::JsonEscapeDisplay {
display::JsonEscapeDisplay::new(self.name())
}
pub const fn time_spec(&self) -> perf_session::PerfTimeSpec {
self.session_info.time_to_time_spec(self.time)
}
pub fn format(&self) -> Option<&PerfEventFormat> {
self.event_desc.format()
}
pub fn read_format(&self) -> &'a [u8] {
&self.data[self.read_range.start as usize..self.read_range.end as usize]
}
pub fn callchain(&self) -> &'a [u8] {
&self.data[self.callchain_range.start as usize..self.callchain_range.end as usize]
}
pub fn raw_data(&self) -> &'a [u8] {
&self.data[self.raw_range.start as usize..self.raw_range.end as usize]
}
pub fn user_data(&self) -> &'a [u8] {
if let Some(format) = self.format() {
let raw_len = self.raw_range.end - self.raw_range.start;
let user_offset = format.common_fields_size();
if user_offset <= raw_len {
return &self.data
[(self.raw_range.start + user_offset) as usize..self.raw_range.end as usize];
}
}
return &[];
}
pub const fn json_meta_display(&self) -> display::EventInfoJsonMetaDisplay {
display::EventInfoJsonMetaDisplay::new(
self.session_info,
self.event_desc,
self.time,
self.cpu,
self.pid,
self.tid,
)
}
}