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
use bitflags::bitflags;
use perf_event_open_sys::bindings;

use crate::prelude::*;

/// AUX records indicate that new data is available in the aux buffer region.
///
/// This struct corresponds to `PERF_RECORD_AUX`. See the [manpage] for more
/// documentation.
///
/// [manpage]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Aux {
    pub aux_offset: u64,
    pub aux_size: u64,
    pub flags: AuxFlags,
}

bitflags! {
    /// Flags describing the aux buffer update.
    ///
    /// Some flags are documented in the [manpage], others are not yet
    /// documented in the manpage but are instead documented in the [source].
    ///
    /// [manpage]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
    /// [source]: https://sourcegraph.com/github.com/torvalds/linux@eb7081409f94a9a8608593d0fb63a1aa3d6f95d8/-/blob/tools/include/uapi/linux/perf_event.h?L1248
    #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
    pub struct AuxFlags : u64 {
        /// The data returned was truncated to fit within the buffer size.
        const TRUNCATED = bindings::PERF_AUX_FLAG_TRUNCATED as _;

        /// The data returned overwrote previous data.
        const OVERWRITE = bindings::PERF_AUX_FLAG_OVERWRITE as _;

        /// The record contains gaps.
        const PARTIAL = bindings::PERF_AUX_FLAG_PARTIAL as _;

        /// The aux sample collided with another.
        const COLLISION = bindings::PERF_AUX_FLAG_COLLISION as _;

        /// Certain bits actually contain a [`AuxPmuFormat`] enum.
        const PMU_FORMAT_MASK = bindings::PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK as _;
    }
}

c_enum! {
    /// PMU-specific trace format type
    #[derive(Copy, Clone, Eq, PartialEq, Hash)]
    pub enum AuxPmuFormatType : u8 {
        CORESIGHT = (bindings::PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT >> 8) as _,
        CORESIGHT_RAW = (bindings::PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW >> 8) as _,
    }

    #[allow(missing_docs)]
    impl {}
}

impl AuxPmuFormatType {
    /// Create a new `AuxPmuFormatType`.
    pub const fn new(value: u8) -> Self {
        Self(value)
    }
}

impl AuxFlags {
    /// PMU-specific trace format type.
    pub fn pmu_format_type(&self) -> AuxPmuFormatType {
        AuxPmuFormatType(((*self & Self::PMU_FORMAT_MASK).bits() >> 8) as u8)
    }
}

impl<'p> Parse<'p> for Aux {
    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
    where
        E: Endian,
        B: ParseBuf<'p>,
    {
        Ok(Self {
            aux_offset: p.parse()?,
            aux_size: p.parse()?,
            flags: p.parse()?,
        })
    }
}

impl<'p> Parse<'p> for AuxFlags {
    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
    where
        E: Endian,
        B: ParseBuf<'p>,
    {
        p.parse().map(Self::from_bits_retain)
    }
}