profile_bee_aya/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 FdLink, LinkError, ProgramData, ProgramError, ProgramType, define_link_wrapper,
14 impl_try_into_fdlink, load_program,
15 perf_attach::{PerfLinkIdInner, PerfLinkInner, perf_attach},
16 utils::find_tracefs_path,
17 },
18 sys::{SyscallError, bpf_link_get_info_by_fd, 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 load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data)
69 }
70
71 pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> {
78 let prog_fd = self.fd()?;
79 let prog_fd = prog_fd.as_fd();
80 let tracefs = find_tracefs_path()?;
81 let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?;
82 let perf_fd = perf_event_open_trace_point(id, None).map_err(|io_error| SyscallError {
83 call: "perf_event_open_trace_point",
84 io_error,
85 })?;
86
87 let link = perf_attach(prog_fd, perf_fd, None )?;
88 self.data.links.insert(TracePointLink::new(link))
89 }
90}
91
92define_link_wrapper!(
93 TracePointLink,
94 TracePointLinkId,
95 PerfLinkInner,
96 PerfLinkIdInner,
97 TracePoint,
98);
99
100impl_try_into_fdlink!(TracePointLink, PerfLinkInner);
101
102impl TryFrom<FdLink> for TracePointLink {
103 type Error = LinkError;
104
105 fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
106 let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?;
107 if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
108 return Ok(Self::new(PerfLinkInner::Fd(fd_link)));
109 }
110 Err(LinkError::InvalidLink)
111 }
112}
113
114pub(crate) fn read_sys_fs_trace_point_id(
115 tracefs: &Path,
116 category: &str,
117 name: &Path,
118) -> Result<u64, TracePointError> {
119 let filename = tracefs.join("events").join(category).join(name).join("id");
120
121 let id = match fs::read_to_string(&filename) {
122 Ok(id) => id,
123 Err(io_error) => return Err(TracePointError::FileError { filename, io_error }),
124 };
125 let id = match id.trim().parse() {
126 Ok(id) => id,
127 Err(error) => {
128 return Err(TracePointError::FileError {
129 filename,
130 io_error: io::Error::other(error),
131 });
132 }
133 };
134
135 Ok(id)
136}