linux_perf_event_reader/
types.rs

1use crate::constants::*;
2use bitflags::bitflags;
3
4bitflags! {
5    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6    pub struct SampleFormat: u64 {
7        const IP = PERF_SAMPLE_IP;
8        const TID = PERF_SAMPLE_TID;
9        const TIME = PERF_SAMPLE_TIME;
10        const ADDR = PERF_SAMPLE_ADDR;
11        const READ = PERF_SAMPLE_READ;
12        const CALLCHAIN = PERF_SAMPLE_CALLCHAIN;
13        const ID = PERF_SAMPLE_ID;
14        const CPU = PERF_SAMPLE_CPU;
15        const PERIOD = PERF_SAMPLE_PERIOD;
16        const STREAM_ID = PERF_SAMPLE_STREAM_ID;
17        const RAW = PERF_SAMPLE_RAW;
18        const BRANCH_STACK = PERF_SAMPLE_BRANCH_STACK;
19        const REGS_USER = PERF_SAMPLE_REGS_USER;
20        const STACK_USER = PERF_SAMPLE_STACK_USER;
21        const WEIGHT = PERF_SAMPLE_WEIGHT;
22        const DATA_SRC = PERF_SAMPLE_DATA_SRC;
23        const IDENTIFIER = PERF_SAMPLE_IDENTIFIER;
24        const TRANSACTION = PERF_SAMPLE_TRANSACTION;
25        const REGS_INTR = PERF_SAMPLE_REGS_INTR;
26        const PHYS_ADDR = PERF_SAMPLE_PHYS_ADDR;
27        const AUX = PERF_SAMPLE_AUX;
28        const CGROUP = PERF_SAMPLE_CGROUP;
29        const DATA_PAGE_SIZE = PERF_SAMPLE_DATA_PAGE_SIZE;
30        const CODE_PAGE_SIZE = PERF_SAMPLE_CODE_PAGE_SIZE;
31        const WEIGHT_STRUCT = PERF_SAMPLE_WEIGHT_STRUCT;
32    }
33
34    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
35    pub struct BranchSampleFormat: u64 {
36        /// user branches
37        const USER = PERF_SAMPLE_BRANCH_USER;
38        /// kernel branches
39        const KERNEL = PERF_SAMPLE_BRANCH_KERNEL;
40        /// hypervisor branches
41        const HV = PERF_SAMPLE_BRANCH_HV;
42        /// any branch types
43        const ANY = PERF_SAMPLE_BRANCH_ANY;
44        /// any call branch
45        const ANY_CALL = PERF_SAMPLE_BRANCH_ANY_CALL;
46        /// any return branch
47        const ANY_RETURN = PERF_SAMPLE_BRANCH_ANY_RETURN;
48        /// indirect calls
49        const IND_CALL = PERF_SAMPLE_BRANCH_IND_CALL;
50        /// transaction aborts
51        const ABORT_TX = PERF_SAMPLE_BRANCH_ABORT_TX;
52        /// in transaction
53        const IN_TX = PERF_SAMPLE_BRANCH_IN_TX;
54        /// not in transaction
55        const NO_TX = PERF_SAMPLE_BRANCH_NO_TX;
56        /// conditional branches
57        const COND = PERF_SAMPLE_BRANCH_COND;
58        /// call/ret stack
59        const CALL_STACK = PERF_SAMPLE_BRANCH_CALL_STACK;
60        /// indirect jumps
61        const IND_JUMP = PERF_SAMPLE_BRANCH_IND_JUMP;
62        /// direct call
63        const CALL = PERF_SAMPLE_BRANCH_CALL;
64        /// no flags
65        const NO_FLAGS = PERF_SAMPLE_BRANCH_NO_FLAGS;
66        /// no cycles
67        const NO_CYCLES = PERF_SAMPLE_BRANCH_NO_CYCLES;
68        /// save branch type
69        const TYPE_SAVE = PERF_SAMPLE_BRANCH_TYPE_SAVE;
70        /// save low level index of raw branch records
71        const HW_INDEX = PERF_SAMPLE_BRANCH_HW_INDEX;
72    }
73
74    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
75    pub struct AttrFlags: u64 {
76        /// off by default
77        const DISABLED = ATTR_FLAG_BIT_DISABLED;
78        /// children inherit it
79        const INHERIT = ATTR_FLAG_BIT_INHERIT;
80        /// must always be on PMU
81        const PINNED = ATTR_FLAG_BIT_PINNED;
82        /// only group on PMU
83        const EXCLUSIVE = ATTR_FLAG_BIT_EXCLUSIVE;
84        /// don't count user
85        const EXCLUDE_USER = ATTR_FLAG_BIT_EXCLUDE_USER;
86        /// don't count kernel
87        const EXCLUDE_KERNEL = ATTR_FLAG_BIT_EXCLUDE_KERNEL;
88        /// don't count hypervisor
89        const EXCLUDE_HV = ATTR_FLAG_BIT_EXCLUDE_HV;
90        /// don't count when idle
91        const EXCLUDE_IDLE = ATTR_FLAG_BIT_EXCLUDE_IDLE;
92        /// include mmap data
93        const MMAP = ATTR_FLAG_BIT_MMAP;
94        /// include comm data
95        const COMM = ATTR_FLAG_BIT_COMM;
96        /// use freq, not period
97        const FREQ = ATTR_FLAG_BIT_FREQ;
98        /// per task counts
99        const INHERIT_STAT = ATTR_FLAG_BIT_INHERIT_STAT;
100        /// next exec enables
101        const ENABLE_ON_EXEC = ATTR_FLAG_BIT_ENABLE_ON_EXEC;
102        /// trace fork/exit
103        const TASK = ATTR_FLAG_BIT_TASK;
104        /// wakeup_watermark
105        const WATERMARK = ATTR_FLAG_BIT_WATERMARK;
106        /// one of the two PRECISE_IP bitmask bits
107        const PRECISE_IP_BIT_15 = 1 << 15;
108        /// one of the two PRECISE_IP bitmask bits
109        const PRECISE_IP_BIT_16 = 1 << 16;
110        /// the full PRECISE_IP bitmask
111        const PRECISE_IP_BITMASK = ATTR_FLAG_BITMASK_PRECISE_IP;
112        /// non-exec mmap data
113        const MMAP_DATA = ATTR_FLAG_BIT_MMAP_DATA;
114        /// sample_type all events
115        const SAMPLE_ID_ALL = ATTR_FLAG_BIT_SAMPLE_ID_ALL;
116        /// don't count in host
117        const EXCLUDE_HOST = ATTR_FLAG_BIT_EXCLUDE_HOST;
118        /// don't count in guest
119        const EXCLUDE_GUEST = ATTR_FLAG_BIT_EXCLUDE_GUEST;
120        /// exclude kernel callchains
121        const EXCLUDE_CALLCHAIN_KERNEL = ATTR_FLAG_BIT_EXCLUDE_CALLCHAIN_KERNEL;
122        /// exclude user callchains
123        const EXCLUDE_CALLCHAIN_USER = ATTR_FLAG_BIT_EXCLUDE_CALLCHAIN_USER;
124        /// include mmap with inode data
125        const MMAP2 = ATTR_FLAG_BIT_MMAP2;
126        /// flag comm events that are due to exec
127        const COMM_EXEC = ATTR_FLAG_BIT_COMM_EXEC;
128        /// use @clockid for time fields
129        const USE_CLOCKID = ATTR_FLAG_BIT_USE_CLOCKID;
130        /// context switch data
131        const CONTEXT_SWITCH = ATTR_FLAG_BIT_CONTEXT_SWITCH;
132        /// Write ring buffer from end to beginning
133        const WRITE_BACKWARD = ATTR_FLAG_BIT_WRITE_BACKWARD;
134        /// include namespaces data
135        const NAMESPACES = ATTR_FLAG_BIT_NAMESPACES;
136        /// include ksymbol events
137        const KSYMBOL = ATTR_FLAG_BIT_KSYMBOL;
138        /// include bpf events
139        const BPF_EVENT = ATTR_FLAG_BIT_BPF_EVENT;
140        /// generate AUX records instead of events
141        const AUX_OUTPUT = ATTR_FLAG_BIT_AUX_OUTPUT;
142        /// include cgroup events
143        const CGROUP = ATTR_FLAG_BIT_CGROUP;
144        /// include text poke events
145        const TEXT_POKE = ATTR_FLAG_BIT_TEXT_POKE;
146        /// use build id in mmap2 events
147        const BUILD_ID = ATTR_FLAG_BIT_BUILD_ID;
148        /// children only inherit if cloned with CLONE_THREAD
149        const INHERIT_THREAD = ATTR_FLAG_BIT_INHERIT_THREAD;
150        /// event is removed from task on exec
151        const REMOVE_ON_EXEC = ATTR_FLAG_BIT_REMOVE_ON_EXEC;
152        /// send synchronous SIGTRAP on event
153        const SIGTRAP = ATTR_FLAG_BIT_SIGTRAP;
154    }
155
156    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157    pub struct HwBreakpointType: u32 {
158        /// No breakpoint. (`HW_BREAKPOINT_EMPTY`)
159        const EMPTY = 0;
160        /// Count when we read the memory location. (`HW_BREAKPOINT_R`)
161        const R = 1;
162        /// Count when we write the memory location. (`HW_BREAKPOINT_W`)
163        const W = 2;
164        /// Count when we read or write the memory location. (`HW_BREAKPOINT_RW`)
165        const RW = Self::R.bits() | Self::W.bits();
166        /// Count when we execute code at the memory location. (`HW_BREAKPOINT_X`)
167        const X = 4;
168        /// The combination of `HW_BREAKPOINT_R` or `HW_BREAKPOINT_W` with
169        //// `HW_BREAKPOINT_X` is not allowed. (`HW_BREAKPOINT_INVALID`)
170        const INVALID = Self::RW.bits() | Self::X.bits();
171    }
172
173    /// The format of the data returned by read() on a perf event fd,
174    /// as specified by attr.read_format:
175    ///
176    /// ```pseudo-c
177    /// struct read_format {
178    /// 	{ u64 value;
179    /// 	  { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
180    /// 	  { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
181    /// 	  { u64 id;           } && PERF_FORMAT_ID
182    /// 	} && !PERF_FORMAT_GROUP
183    ///
184    /// 	{ u64 nr;
185    /// 	  { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
186    /// 	  { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
187    /// 	  { u64 value;
188    /// 	    { u64	id;           } && PERF_FORMAT_ID
189    /// 	  } cntr[nr];
190    /// 	} && PERF_FORMAT_GROUP
191    /// };
192    /// ```
193    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
194    pub struct ReadFormat: u64 {
195        const TOTAL_TIME_ENABLED = PERF_FORMAT_TOTAL_TIME_ENABLED;
196        const TOTAL_TIME_RUNNING = PERF_FORMAT_TOTAL_TIME_RUNNING;
197        const ID = PERF_FORMAT_ID;
198        const GROUP = PERF_FORMAT_GROUP;
199    }
200}
201
202/// Specifies how precise the instruction address should be.
203/// With `perf record -e` you can set the precision by appending /p to the
204/// event name, with varying numbers of `p`s.
205#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
206pub enum IpSkidConstraint {
207    /// 0 - SAMPLE_IP can have arbitrary skid
208    ArbitrarySkid,
209    /// 1 - SAMPLE_IP must have constant skid
210    ConstantSkid,
211    /// 2 - SAMPLE_IP requested to have 0 skid
212    ZeroSkid,
213    /// 3 - SAMPLE_IP must have 0 skid, or uses randomization to avoid
214    /// sample shadowing effects.
215    ZeroSkidOrRandomization,
216}
217
218impl AttrFlags {
219    /// Extract the IpSkidConstraint from the bits.
220    pub fn ip_skid_constraint(&self) -> IpSkidConstraint {
221        match (self.bits() & Self::PRECISE_IP_BITMASK.bits()) >> 15 {
222            0 => IpSkidConstraint::ArbitrarySkid,
223            1 => IpSkidConstraint::ConstantSkid,
224            2 => IpSkidConstraint::ZeroSkid,
225            3 => IpSkidConstraint::ZeroSkidOrRandomization,
226            _ => unreachable!(),
227        }
228    }
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
232#[non_exhaustive]
233pub enum ClockId {
234    Realtime,
235    Monotonic,
236    ProcessCputimeId,
237    ThreadCputimeId,
238    MonotonicRaw,
239    RealtimeCoarse,
240    MonotonicCoarse,
241    Boottime,
242    RealtimeAlarm,
243    BoottimeAlarm,
244}
245
246impl ClockId {
247    pub fn from_u32(clockid: u32) -> Option<Self> {
248        Some(match clockid {
249            0 => Self::Realtime,
250            1 => Self::Monotonic,
251            2 => Self::ProcessCputimeId,
252            3 => Self::ThreadCputimeId,
253            4 => Self::MonotonicRaw,
254            5 => Self::RealtimeCoarse,
255            6 => Self::MonotonicCoarse,
256            7 => Self::Boottime,
257            8 => Self::RealtimeAlarm,
258            9 => Self::BoottimeAlarm,
259            _ => return None,
260        })
261    }
262}
263
264#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
265pub struct RecordType(pub u32);
266
267impl RecordType {
268    // Kernel-built-in record types
269    pub const MMAP: Self = Self(PERF_RECORD_MMAP);
270    pub const LOST: Self = Self(PERF_RECORD_LOST);
271    pub const COMM: Self = Self(PERF_RECORD_COMM);
272    pub const EXIT: Self = Self(PERF_RECORD_EXIT);
273    pub const THROTTLE: Self = Self(PERF_RECORD_THROTTLE);
274    pub const UNTHROTTLE: Self = Self(PERF_RECORD_UNTHROTTLE);
275    pub const FORK: Self = Self(PERF_RECORD_FORK);
276    pub const READ: Self = Self(PERF_RECORD_READ);
277    pub const SAMPLE: Self = Self(PERF_RECORD_SAMPLE);
278    pub const MMAP2: Self = Self(PERF_RECORD_MMAP2);
279    pub const AUX: Self = Self(PERF_RECORD_AUX);
280    pub const ITRACE_START: Self = Self(PERF_RECORD_ITRACE_START);
281    pub const LOST_SAMPLES: Self = Self(PERF_RECORD_LOST_SAMPLES);
282    pub const SWITCH: Self = Self(PERF_RECORD_SWITCH);
283    pub const SWITCH_CPU_WIDE: Self = Self(PERF_RECORD_SWITCH_CPU_WIDE);
284    pub const NAMESPACES: Self = Self(PERF_RECORD_NAMESPACES);
285    pub const KSYMBOL: Self = Self(PERF_RECORD_KSYMBOL);
286    pub const BPF_EVENT: Self = Self(PERF_RECORD_BPF_EVENT);
287    pub const CGROUP: Self = Self(PERF_RECORD_CGROUP);
288    pub const TEXT_POKE: Self = Self(PERF_RECORD_TEXT_POKE);
289    pub const AUX_OUTPUT_HW_ID: Self = Self(PERF_RECORD_AUX_OUTPUT_HW_ID);
290
291    pub fn is_builtin_type(&self) -> bool {
292        self.0 < PERF_RECORD_USER_TYPE_START
293    }
294
295    pub fn is_user_type(&self) -> bool {
296        self.0 >= PERF_RECORD_USER_TYPE_START
297    }
298}
299
300impl std::fmt::Debug for RecordType {
301    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
302        let s = match *self {
303            Self::MMAP => "MMAP",
304            Self::LOST => "LOST",
305            Self::COMM => "COMM",
306            Self::EXIT => "EXIT",
307            Self::THROTTLE => "THROTTLE",
308            Self::UNTHROTTLE => "UNTHROTTLE",
309            Self::FORK => "FORK",
310            Self::READ => "READ",
311            Self::SAMPLE => "SAMPLE",
312            Self::MMAP2 => "MMAP2",
313            Self::AUX => "AUX",
314            Self::ITRACE_START => "ITRACE_START",
315            Self::LOST_SAMPLES => "LOST_SAMPLES",
316            Self::SWITCH => "SWITCH",
317            Self::SWITCH_CPU_WIDE => "SWITCH_CPU_WIDE",
318            Self::NAMESPACES => "NAMESPACES",
319            Self::KSYMBOL => "KSYMBOL",
320            Self::BPF_EVENT => "BPF_EVENT",
321            Self::CGROUP => "CGROUP",
322            Self::TEXT_POKE => "TEXT_POKE",
323            Self::AUX_OUTPUT_HW_ID => "AUX_OUTPUT_HW_ID",
324            other if self.is_builtin_type() => {
325                return fmt.write_fmt(format_args!("Unknown built-in: {}", other.0));
326            }
327            other => {
328                return fmt.write_fmt(format_args!("User type: {}", other.0));
329            }
330        };
331        fmt.write_str(s)
332    }
333}
334
335#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
336#[non_exhaustive]
337pub enum CpuMode {
338    Unknown,
339    Kernel,
340    User,
341    Hypervisor,
342    GuestKernel,
343    GuestUser,
344}
345
346impl CpuMode {
347    /// Initialize from the misc field of the perf event header.
348    pub fn from_misc(misc: u16) -> Self {
349        match misc & PERF_RECORD_MISC_CPUMODE_MASK {
350            PERF_RECORD_MISC_CPUMODE_UNKNOWN => Self::Unknown,
351            PERF_RECORD_MISC_KERNEL => Self::Kernel,
352            PERF_RECORD_MISC_USER => Self::User,
353            PERF_RECORD_MISC_HYPERVISOR => Self::Hypervisor,
354            PERF_RECORD_MISC_GUEST_KERNEL => Self::GuestKernel,
355            PERF_RECORD_MISC_GUEST_USER => Self::GuestUser,
356            _ => Self::Unknown,
357        }
358    }
359}