linux_perf_data/
record.rs1use byteorder::{BigEndian, ByteOrder, LittleEndian};
2use linux_perf_event_reader::RawEventRecord;
3use linux_perf_event_reader::{Endianness, RawData, RecordType};
4
5use crate::constants::*;
6use crate::thread_map::ThreadMap;
7
8pub enum PerfFileRecord<'a> {
13 EventRecord {
15 attr_index: usize,
17 record: RawEventRecord<'a>,
19 },
20 UserRecord(RawUserRecord<'a>),
22}
23
24#[derive(Debug, Clone)]
26#[non_exhaustive]
27pub enum UserRecord<'a> {
28 ThreadMap(ThreadMap<'a>),
29 Raw(RawUserRecord<'a>),
30}
31
32#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct UserRecordType(RecordType);
35
36impl UserRecordType {
37 pub const PERF_HEADER_ATTR: Self = Self(RecordType(PERF_RECORD_HEADER_ATTR));
38 pub const PERF_HEADER_EVENT_TYPE: Self = Self(RecordType(PERF_RECORD_HEADER_EVENT_TYPE));
39 pub const PERF_HEADER_TRACING_DATA: Self = Self(RecordType(PERF_RECORD_HEADER_TRACING_DATA));
40 pub const PERF_HEADER_BUILD_ID: Self = Self(RecordType(PERF_RECORD_HEADER_BUILD_ID));
41 pub const PERF_FINISHED_ROUND: Self = Self(RecordType(PERF_RECORD_FINISHED_ROUND));
42 pub const PERF_ID_INDEX: Self = Self(RecordType(PERF_RECORD_ID_INDEX));
43 pub const PERF_AUXTRACE_INFO: Self = Self(RecordType(PERF_RECORD_AUXTRACE_INFO));
44 pub const PERF_AUXTRACE: Self = Self(RecordType(PERF_RECORD_AUXTRACE));
45 pub const PERF_AUXTRACE_ERROR: Self = Self(RecordType(PERF_RECORD_AUXTRACE_ERROR));
46 pub const PERF_THREAD_MAP: Self = Self(RecordType(PERF_RECORD_THREAD_MAP));
47 pub const PERF_CPU_MAP: Self = Self(RecordType(PERF_RECORD_CPU_MAP));
48 pub const PERF_STAT_CONFIG: Self = Self(RecordType(PERF_RECORD_STAT_CONFIG));
49 pub const PERF_STAT: Self = Self(RecordType(PERF_RECORD_STAT));
50 pub const PERF_STAT_ROUND: Self = Self(RecordType(PERF_RECORD_STAT_ROUND));
51 pub const PERF_EVENT_UPDATE: Self = Self(RecordType(PERF_RECORD_EVENT_UPDATE));
52 pub const PERF_TIME_CONV: Self = Self(RecordType(PERF_RECORD_TIME_CONV));
53 pub const PERF_HEADER_FEATURE: Self = Self(RecordType(PERF_RECORD_HEADER_FEATURE));
54 pub const PERF_COMPRESSED: Self = Self(RecordType(PERF_RECORD_COMPRESSED));
55
56 pub const SIMPLEPERF_KERNEL_SYMBOL: Self = Self(RecordType(SIMPLE_PERF_RECORD_KERNEL_SYMBOL));
57 pub const SIMPLEPERF_DSO: Self = Self(RecordType(SIMPLE_PERF_RECORD_DSO));
58 pub const SIMPLEPERF_SYMBOL: Self = Self(RecordType(SIMPLE_PERF_RECORD_SYMBOL));
59 pub const SIMPLEPERF_SPLIT: Self = Self(RecordType(SIMPLE_PERF_RECORD_SPLIT));
60 pub const SIMPLEPERF_SPLIT_END: Self = Self(RecordType(SIMPLE_PERF_RECORD_SPLIT_END));
61 pub const SIMPLEPERF_EVENT_ID: Self = Self(RecordType(SIMPLE_PERF_RECORD_EVENT_ID));
62 pub const SIMPLEPERF_CALLCHAIN: Self = Self(RecordType(SIMPLE_PERF_RECORD_CALLCHAIN));
63 pub const SIMPLEPERF_UNWINDING_RESULT: Self =
64 Self(RecordType(SIMPLE_PERF_RECORD_UNWINDING_RESULT));
65 pub const SIMPLEPERF_TRACING_DATA: Self = Self(RecordType(SIMPLE_PERF_RECORD_TRACING_DATA));
66
67 pub fn try_from(record_type: RecordType) -> Option<Self> {
68 if record_type.is_user_type() {
69 Some(Self(record_type))
70 } else {
71 None
72 }
73 }
74
75 pub fn record_type(&self) -> RecordType {
76 self.0
77 }
78}
79
80impl From<UserRecordType> for RecordType {
81 fn from(record_type: UserRecordType) -> Self {
82 record_type.0
83 }
84}
85
86impl std::fmt::Debug for UserRecordType {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 match *self {
89 Self::PERF_HEADER_ATTR => "PERF_HEADER_ATTR".fmt(f),
90 Self::PERF_HEADER_EVENT_TYPE => "PERF_HEADER_EVENT_TYPE".fmt(f),
91 Self::PERF_HEADER_TRACING_DATA => "PERF_HEADER_TRACING_DATA".fmt(f),
92 Self::PERF_HEADER_BUILD_ID => "PERF_HEADER_BUILD_ID".fmt(f),
93 Self::PERF_FINISHED_ROUND => "PERF_FINISHED_ROUND".fmt(f),
94 Self::PERF_ID_INDEX => "PERF_ID_INDEX".fmt(f),
95 Self::PERF_AUXTRACE_INFO => "PERF_AUXTRACE_INFO".fmt(f),
96 Self::PERF_AUXTRACE => "PERF_AUXTRACE".fmt(f),
97 Self::PERF_AUXTRACE_ERROR => "PERF_AUXTRACE_ERROR".fmt(f),
98 Self::PERF_THREAD_MAP => "PERF_THREAD_MAP".fmt(f),
99 Self::PERF_CPU_MAP => "PERF_CPU_MAP".fmt(f),
100 Self::PERF_STAT_CONFIG => "PERF_STAT_CONFIG".fmt(f),
101 Self::PERF_STAT => "PERF_STAT".fmt(f),
102 Self::PERF_STAT_ROUND => "PERF_STAT_ROUND".fmt(f),
103 Self::PERF_EVENT_UPDATE => "PERF_EVENT_UPDATE".fmt(f),
104 Self::PERF_TIME_CONV => "PERF_TIME_CONV".fmt(f),
105 Self::PERF_HEADER_FEATURE => "PERF_HEADER_FEATURE".fmt(f),
106 Self::PERF_COMPRESSED => "PERF_COMPRESSED".fmt(f),
107 Self::SIMPLEPERF_KERNEL_SYMBOL => "SIMPLEPERF_KERNEL_SYMBOL".fmt(f),
108 Self::SIMPLEPERF_DSO => "SIMPLEPERF_DSO".fmt(f),
109 Self::SIMPLEPERF_SYMBOL => "SIMPLEPERF_SYMBOL".fmt(f),
110 Self::SIMPLEPERF_SPLIT => "SIMPLEPERF_SPLIT".fmt(f),
111 Self::SIMPLEPERF_SPLIT_END => "SIMPLEPERF_SPLIT_END".fmt(f),
112 Self::SIMPLEPERF_EVENT_ID => "SIMPLEPERF_EVENT_ID".fmt(f),
113 Self::SIMPLEPERF_CALLCHAIN => "SIMPLEPERF_CALLCHAIN".fmt(f),
114 Self::SIMPLEPERF_UNWINDING_RESULT => "SIMPLEPERF_UNWINDING_RESULT".fmt(f),
115 Self::SIMPLEPERF_TRACING_DATA => "SIMPLEPERF_TRACING_DATA".fmt(f),
116 other => f.write_fmt(format_args!("Unknown UserRecordType {}", other.0 .0)),
117 }
118 }
119}
120
121#[derive(Debug, Clone)]
125pub struct RawUserRecord<'a> {
126 pub record_type: UserRecordType,
127 pub endian: Endianness,
128 pub misc: u16,
129 pub data: RawData<'a>,
130}
131
132impl<'a> RawUserRecord<'a> {
133 pub fn parse(&self) -> Result<UserRecord<'a>, std::io::Error> {
134 match self.endian {
135 Endianness::LittleEndian => self.parse_impl::<LittleEndian>(),
136 Endianness::BigEndian => self.parse_impl::<BigEndian>(),
137 }
138 }
139
140 pub fn parse_impl<T: ByteOrder>(&self) -> Result<UserRecord<'a>, std::io::Error> {
141 let record_type = self.record_type;
142
143 let record = match record_type {
144 UserRecordType::PERF_THREAD_MAP => {
154 UserRecord::ThreadMap(ThreadMap::parse::<T>(self.data)?)
155 }
156 _ => UserRecord::Raw(self.clone()),
174 };
175 Ok(record)
176 }
177}