perf_event_data/impls/
perf_event_attr.rs

1use perf_event_open_sys::bindings::*;
2
3use crate::error::ParseError;
4use crate::prelude::*;
5
6/// Maximum supported size of perf_event_attr.
7///
8/// If you update this make sure to update the parsing code below so that it
9/// properly handles the new version.
10const PERF_ATTR_SIZE_MAX: u32 = PERF_ATTR_SIZE_VER8;
11
12impl<'p> Parse<'p> for perf_event_attr {
13    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
14    where
15        E: Endian,
16        B: ParseBuf<'p>,
17    {
18        use std::mem;
19
20        let mut attr = perf_event_attr::default();
21
22        attr.type_ = p.parse()?;
23        attr.size = p.parse()?;
24
25        match attr.size {
26            // Concrete sizes defined by the kernel headers.
27            // We support all of these.
28            PERF_ATTR_SIZE_VER0 | PERF_ATTR_SIZE_VER1 | PERF_ATTR_SIZE_VER2
29            | PERF_ATTR_SIZE_VER3 | PERF_ATTR_SIZE_VER4 | PERF_ATTR_SIZE_VER5
30            | PERF_ATTR_SIZE_VER6 | PERF_ATTR_SIZE_VER7 | PERF_ATTR_SIZE_VER8 => (),
31
32            // We support larger sizes since they may be introduced in the future.
33            size if size > PERF_ATTR_SIZE_MAX => (),
34
35            // We do not support odd sizes that are not one of the kernel's defined constants.
36            size => {
37                return Err(ParseError::custom(
38                    ErrorKind::InvalidRecord,
39                    format_args!("{size} is not a valid size for a perf_event_attr struct"),
40                ))
41            }
42        }
43
44        let mut p = p.split_at(attr.size as usize - mem::size_of_val(&attr.size))?;
45
46        if attr.size >= PERF_ATTR_SIZE_VER0 {
47            attr.config = p.parse()?;
48            attr.__bindgen_anon_1.sample_period = p.parse()?;
49            attr.sample_type = p.parse()?;
50            attr.read_format = p.parse()?;
51            attr._bitfield_1 = __BindgenBitfieldUnit::new(u64::to_ne_bytes(p.parse()?));
52            attr.__bindgen_anon_2.wakeup_events = p.parse()?;
53            attr.bp_type = p.parse()?;
54            attr.__bindgen_anon_3.config1 = p.parse()?;
55        }
56
57        if attr.size >= PERF_ATTR_SIZE_VER1 {
58            attr.__bindgen_anon_4.config2 = p.parse()?;
59        }
60
61        if attr.size >= PERF_ATTR_SIZE_VER2 {
62            attr.branch_sample_type = p.parse()?;
63        }
64
65        if attr.size >= PERF_ATTR_SIZE_VER3 {
66            attr.sample_regs_user = p.parse()?;
67            attr.sample_stack_user = p.parse()?;
68            attr.clockid = p.parse_u32()? as _;
69        }
70
71        if attr.size >= PERF_ATTR_SIZE_VER4 {
72            attr.sample_regs_intr = p.parse()?;
73        }
74
75        if attr.size >= PERF_ATTR_SIZE_VER5 {
76            attr.aux_watermark = p.parse()?;
77            attr.sample_max_stack = p.parse()?;
78            let _ = p.parse_u16()?;
79        }
80
81        if attr.size >= PERF_ATTR_SIZE_VER6 {
82            attr.aux_sample_size = p.parse()?;
83            let _ = p.parse_u32()?;
84        }
85
86        if attr.size >= PERF_ATTR_SIZE_VER7 {
87            attr.sig_data = p.parse()?;
88        }
89
90        if attr.size >= PERF_ATTR_SIZE_VER8 {
91            attr.config3 = p.parse()?;
92        }
93
94        if attr.size > PERF_ATTR_SIZE_MAX {
95            let rest = p.parse_rest()?;
96            let all_zeros = rest.iter().copied().all(|b| b == 0);
97
98            if !all_zeros {
99                return Err(ParseError::custom(
100                    ErrorKind::UnsupportedData,
101                    "\
102                    serialized perf_event_attr contains fields not supported \
103                    by this version of perf-event-data\
104                    ",
105                ));
106            }
107        }
108
109        Ok(attr)
110    }
111}