1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use crate::{AttrFlags, BranchSampleFormat, Endianness, PerfEventAttr, ReadFormat, SampleFormat};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RecordParseInfo {
pub endian: Endianness,
pub sample_format: SampleFormat,
pub branch_sample_format: BranchSampleFormat,
pub read_format: ReadFormat,
pub common_data_offset_from_end: Option<usize>,
pub sample_regs_user: u64,
pub regs_count: usize,
pub nonsample_record_time_offset_from_end: Option<usize>,
pub nonsample_record_id_offset_from_end: Option<usize>,
pub sample_record_time_offset_from_start: Option<usize>,
pub sample_record_id_offset_from_start: Option<usize>,
}
impl RecordParseInfo {
pub fn new(attr: &PerfEventAttr, endian: Endianness) -> Self {
let sample_format = attr.sample_format;
let branch_sample_format = attr.branch_sample_format;
let read_format = attr.read_format;
let common_data_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL) {
Some(
sample_format
.intersection(
SampleFormat::TID
| SampleFormat::TIME
| SampleFormat::ID
| SampleFormat::STREAM_ID
| SampleFormat::CPU
| SampleFormat::IDENTIFIER,
)
.bits()
.count_ones() as usize
* 8,
)
} else {
None
};
let sample_regs_user = attr.sample_regs_user;
let regs_count = sample_regs_user.count_ones() as usize;
let nonsample_record_time_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL)
&& sample_format.contains(SampleFormat::TIME)
{
Some(
sample_format
.intersection(
SampleFormat::TIME
| SampleFormat::ID
| SampleFormat::STREAM_ID
| SampleFormat::CPU
| SampleFormat::IDENTIFIER,
)
.bits()
.count_ones() as usize
* 8,
)
} else {
None
};
let nonsample_record_id_offset_from_end = if attr.flags.contains(AttrFlags::SAMPLE_ID_ALL)
&& sample_format.intersects(SampleFormat::ID | SampleFormat::IDENTIFIER)
{
if sample_format.contains(SampleFormat::IDENTIFIER) {
Some(8)
} else {
Some(
sample_format
.intersection(
SampleFormat::ID
| SampleFormat::STREAM_ID
| SampleFormat::CPU
| SampleFormat::IDENTIFIER,
)
.bits()
.count_ones() as usize
* 8,
)
}
} else {
None
};
let sample_record_id_offset_from_start = if sample_format.contains(SampleFormat::IDENTIFIER)
{
Some(0)
} else if sample_format.contains(SampleFormat::ID) {
Some(
sample_format
.intersection(
SampleFormat::IP
| SampleFormat::TID
| SampleFormat::TIME
| SampleFormat::ADDR,
)
.bits()
.count_ones() as usize
* 8,
)
} else {
None
};
let sample_record_time_offset_from_start = if sample_format.contains(SampleFormat::TIME) {
Some(
sample_format
.intersection(SampleFormat::IDENTIFIER | SampleFormat::IP | SampleFormat::TID)
.bits()
.count_ones() as usize
* 8,
)
} else {
None
};
Self {
endian,
sample_format,
branch_sample_format,
read_format,
common_data_offset_from_end,
sample_regs_user,
regs_count,
nonsample_record_time_offset_from_end,
nonsample_record_id_offset_from_end,
sample_record_time_offset_from_start,
sample_record_id_offset_from_start,
}
}
}