perf_event_open/sample/record/
bpf.rs

1use super::RecordId;
2
3#[cfg(feature = "linux-5.1")]
4const BPF_TAG_SIZE: u32 = crate::ffi::bindings::BPF_TAG_SIZE;
5// NOTE: There is no `BPF_TAG_SIZE` before Linux 5.1, if the tag size changes
6// in the future we need to ensure ABI compatibility.
7#[cfg(not(feature = "linux-5.1"))]
8const BPF_TAG_SIZE: u32 = 8;
9
10/// BPF event.
11///
12/// # Examples
13///
14/// Running this example may require root privileges.
15///
16/// ```rust, no_run
17/// # tokio_test::block_on(async {
18/// use std::sync::atomic::{AtomicBool, Ordering};
19/// use std::sync::mpsc::channel;
20/// use std::thread;
21///
22/// use perf_event_open::config::{Cpu, Opts, Proc, WakeUpOn};
23/// use perf_event_open::count::Counter;
24/// use perf_event_open::event::sw::Software;
25///
26/// static WAIT: AtomicBool = AtomicBool::new(true);
27///
28/// let (tid_tx, tid_rx) = channel();
29/// thread::spawn(move || {
30///     tid_tx.send(unsafe { libc::gettid() }).unwrap();
31///
32///     while WAIT.load(Ordering::Relaxed) {
33///         std::hint::spin_loop();
34///     }
35///
36///     // Load a BPF program to trigger a `BpfEvent` record.
37///     aya::Ebpf::load_file("HelloWorld.bpf.o").unwrap();
38/// });
39///
40/// let event = Software::Dummy;
41/// let target = (Proc(tid_rx.recv().unwrap() as _), Cpu::ALL);
42///
43/// let mut opts = Opts::default();
44/// opts.wake_up.on = WakeUpOn::Bytes(1);
45/// opts.extra_record.bpf_event = true;
46///
47/// let counter = Counter::new(event, target, opts).unwrap();
48/// let sampler = counter.sampler(5).unwrap();
49///
50/// counter.enable().unwrap();
51/// WAIT.store(false, Ordering::Relaxed);
52///
53/// let mut iter = sampler.iter().into_async().unwrap();
54/// while let Some(it) = iter.next().await {
55///     println!("{:-?}", it);
56/// }
57/// # });
58/// ```
59///
60/// Since `linux-5.1`: <https://github.com/torvalds/linux/commit/6ee52e2a3fe4ea35520720736e6791df1fb67106>
61#[derive(Clone)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub struct BpfEvent {
64    /// Record IDs.
65    pub record_id: Option<RecordId>,
66
67    /// BPF event type.
68    pub ty: Type,
69    /// BPF program ID.
70    pub id: u32,
71    /// BPF program tag.
72    pub tag: [u8; BPF_TAG_SIZE as _],
73    /// Flags.
74    pub flags: u16,
75}
76
77impl BpfEvent {
78    #[cfg(feature = "linux-5.1")]
79    pub(crate) unsafe fn from_ptr(
80        mut ptr: *const u8,
81        sample_id_all: Option<super::SampleType>,
82    ) -> Self {
83        use super::SampleType;
84        use crate::ffi::{bindings as b, deref_offset};
85
86        // https://github.com/torvalds/linux/blob/v6.13/include/uapi/linux/perf_event.h#L1175
87        // struct {
88        //     struct perf_event_header header;
89        //     u16 type;
90        //     u16 flags;
91        //     u32 id;
92        //     u8 tag[BPF_TAG_SIZE];
93        //     struct sample_id sample_id;
94        // };
95
96        let ty = match deref_offset::<u16>(&mut ptr) as _ {
97            b::PERF_BPF_EVENT_PROG_LOAD => Type::ProgLoad,
98            b::PERF_BPF_EVENT_PROG_UNLOAD => Type::ProgUnload,
99            b::PERF_BPF_EVENT_UNKNOWN => Type::Unknown,
100            _ => Type::Unknown, // For compatibility, not ABI.
101        };
102        let flags = deref_offset(&mut ptr);
103        let id = deref_offset(&mut ptr);
104        let tag = deref_offset(&mut ptr);
105        let record_id = sample_id_all.map(|SampleType(ty)| RecordId::from_ptr(ptr, ty));
106
107        Self {
108            record_id,
109            ty,
110            id,
111            tag,
112            flags,
113        }
114    }
115}
116
117super::from!(BpfEvent);
118
119super::debug!(BpfEvent {
120    {record_id?},
121    {ty},
122    {id},
123    {tag},
124    {flags},
125});
126
127// https://github.com/torvalds/linux/blob/v6.13/include/uapi/linux/perf_event.h#L1245
128/// BPF event type.
129#[derive(Clone, Debug)]
130#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131pub enum Type {
132    // PERF_BPF_EVENT_PROG_LOAD
133    /// BPF program load.
134    ProgLoad,
135    // PERF_BPF_EVENT_PROG_UNLOAD
136    /// BPF program unload.
137    ProgUnload,
138    // PERF_BPF_EVENT_UNKNOWN
139    /// Unknown.
140    Unknown,
141}