linux_perf_event_reader/
parse_info.rs1use crate::{AttrFlags, BranchSampleFormat, Endianness, PerfEventAttr, ReadFormat, SampleFormat};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub struct RecordParseInfo {
5 pub endian: Endianness,
6 pub sample_format: SampleFormat,
7 pub branch_sample_format: BranchSampleFormat,
8 pub read_format: ReadFormat,
9 pub common_data_offset_from_end: Option<u8>, pub sample_regs_user: u64,
11 pub user_regs_count: u8, pub sample_regs_intr: u64,
13 pub intr_regs_count: u8, pub id_parse_info: RecordIdParseInfo,
15 pub nonsample_record_time_offset_from_end: Option<u8>, pub sample_record_time_offset_from_start: Option<u8>, }
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub struct RecordIdParseInfo {
21 pub nonsample_record_id_offset_from_end: Option<u8>, pub sample_record_id_offset_from_start: Option<u8>, }
24
25impl RecordParseInfo {
26 pub fn new(attr: &PerfEventAttr, endian: Endianness) -> Self {
27 let sample_format = attr.sample_format;
28 let branch_sample_format = attr.branch_sample_format;
29 let read_format = attr.read_format;
30
31 let common_data_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL) {
40 Some(
41 sample_format
42 .intersection(
43 SampleFormat::TID
44 | SampleFormat::TIME
45 | SampleFormat::ID
46 | SampleFormat::STREAM_ID
47 | SampleFormat::CPU
48 | SampleFormat::IDENTIFIER,
49 )
50 .bits()
51 .count_ones() as u8
52 * 8,
53 )
54 } else {
55 None
56 };
57 let sample_regs_user = attr.sample_regs_user;
58 let user_regs_count = sample_regs_user.count_ones() as u8;
59 let sample_regs_intr = attr.sample_regs_intr;
60 let intr_regs_count = sample_regs_intr.count_ones() as u8;
61 let nonsample_record_time_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL)
62 && sample_format.contains(SampleFormat::TIME)
63 {
64 Some(
65 sample_format
66 .intersection(
67 SampleFormat::TIME
68 | SampleFormat::ID
69 | SampleFormat::STREAM_ID
70 | SampleFormat::CPU
71 | SampleFormat::IDENTIFIER,
72 )
73 .bits()
74 .count_ones() as u8
75 * 8,
76 )
77 } else {
78 None
79 };
80
81 let sample_record_time_offset_from_start = if sample_format.contains(SampleFormat::TIME) {
88 Some(
89 sample_format
90 .intersection(SampleFormat::IDENTIFIER | SampleFormat::IP | SampleFormat::TID)
91 .bits()
92 .count_ones() as u8
93 * 8,
94 )
95 } else {
96 None
97 };
98
99 Self {
100 endian,
101 sample_format,
102 branch_sample_format,
103 read_format,
104 common_data_offset_from_end,
105 sample_regs_user,
106 user_regs_count,
107 sample_regs_intr,
108 intr_regs_count,
109 nonsample_record_time_offset_from_end,
110 sample_record_time_offset_from_start,
111 id_parse_info: RecordIdParseInfo::new(attr),
112 }
113 }
114}
115
116impl RecordIdParseInfo {
117 pub fn new(attr: &PerfEventAttr) -> Self {
118 let sample_format = attr.sample_format;
119 let nonsample_record_id_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL)
120 && sample_format.intersects(SampleFormat::ID | SampleFormat::IDENTIFIER)
121 {
122 if sample_format.contains(SampleFormat::IDENTIFIER) {
123 Some(8)
124 } else {
125 Some(
126 sample_format
127 .intersection(
128 SampleFormat::ID
129 | SampleFormat::STREAM_ID
130 | SampleFormat::CPU
131 | SampleFormat::IDENTIFIER,
132 )
133 .bits()
134 .count_ones() as u8
135 * 8,
136 )
137 }
138 } else {
139 None
140 };
141
142 let sample_record_id_offset_from_start = if sample_format.contains(SampleFormat::IDENTIFIER)
149 {
150 Some(0)
151 } else if sample_format.contains(SampleFormat::ID) {
152 Some(
153 sample_format
154 .intersection(
155 SampleFormat::IP
156 | SampleFormat::TID
157 | SampleFormat::TIME
158 | SampleFormat::ADDR,
159 )
160 .bits()
161 .count_ones() as u8
162 * 8,
163 )
164 } else {
165 None
166 };
167
168 Self {
169 nonsample_record_id_offset_from_end,
170 sample_record_id_offset_from_start,
171 }
172 }
173}