aya_friday/programs/
trace_point.rs1use std::{
3 fs, io,
4 os::fd::AsFd as _,
5 path::{Path, PathBuf},
6};
7
8use aya_obj::generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT};
9use thiserror::Error;
10
11use crate::{
12 programs::{
13 ProgramData, ProgramError, ProgramType, define_link_wrapper, impl_try_from_fdlink,
14 impl_try_into_fdlink, load_program_without_attach_type,
15 perf_attach::{PerfLinkIdInner, PerfLinkInner, perf_attach},
16 utils::find_tracefs_path,
17 },
18 sys::{SyscallError, perf_event_open_trace_point},
19};
20
21#[derive(Debug, Error)]
23pub enum TracePointError {
24 #[error("`{filename}`")]
26 FileError {
27 filename: PathBuf,
29 #[source]
31 io_error: io::Error,
32 },
33}
34
35#[derive(Debug)]
57#[doc(alias = "BPF_PROG_TYPE_TRACEPOINT")]
58pub struct TracePoint {
59 pub(crate) data: ProgramData<TracePointLink>,
60}
61
62impl TracePoint {
63 pub const PROGRAM_TYPE: ProgramType = ProgramType::TracePoint;
65
66 pub fn load(&mut self) -> Result<(), ProgramError> {
68 let Self { data } = self;
69 load_program_without_attach_type(BPF_PROG_TYPE_TRACEPOINT, data)
70 }
71
72 pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> {
79 let prog_fd = self.fd()?;
80 let prog_fd = prog_fd.as_fd();
81 let tracefs = find_tracefs_path()?;
82 let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?;
83 let perf_fd = perf_event_open_trace_point(id, None).map_err(|io_error| SyscallError {
84 call: "perf_event_open_trace_point",
85 io_error,
86 })?;
87
88 let link = perf_attach(prog_fd, perf_fd, None )?;
89 self.data.links.insert(TracePointLink::new(link))
90 }
91}
92
93define_link_wrapper!(
94 TracePointLink,
95 TracePointLinkId,
96 PerfLinkInner,
97 PerfLinkIdInner,
98 TracePoint,
99);
100
101impl_try_into_fdlink!(TracePointLink, PerfLinkInner);
102impl_try_from_fdlink!(
103 TracePointLink,
104 PerfLinkInner,
105 bpf_link_type::BPF_LINK_TYPE_PERF_EVENT
106);
107
108pub(crate) fn read_sys_fs_trace_point_id(
109 tracefs: &Path,
110 category: &str,
111 name: &Path,
112) -> Result<u64, TracePointError> {
113 let filename = tracefs.join("events").join(category).join(name).join("id");
114
115 let id = match fs::read_to_string(&filename) {
116 Ok(id) => id,
117 Err(io_error) => return Err(TracePointError::FileError { filename, io_error }),
118 };
119 let id = match id.trim().parse() {
120 Ok(id) => id,
121 Err(error) => {
122 return Err(TracePointError::FileError {
123 filename,
124 io_error: io::Error::other(error),
125 });
126 }
127 };
128
129 Ok(id)
130}