bpf_api/platform/linux/
probes.rs1use crate::error::Error;
2use crate::platform::linux::bpf::{CallBpf, Command};
3use crate::platform::linux::perf::{perf_event_attach, perf_event_enable, perf_event_open_by_name};
4use crate::platform::linux::prog::Program;
5use crate::platform::linux::syscalls::{cbzero, close};
6
7use std::collections::HashMap;
8
9#[derive(Default)]
10#[repr(C, align(8))]
11struct BpfRawTracepointOpenAttr {
12 pub name: u64,
13 pub prog_fd: u32,
14}
15
16impl CallBpf for BpfRawTracepointOpenAttr {}
17
18#[derive(Default)]
19#[repr(C, align(8))]
20struct BpfLinkCreateAttr {
21 pub prog_fd: u32,
22 pub target_fd: u32,
23 pub attach_type: u32,
24 pub flags: u32,
25 pub target_btf_id: u32,
26}
27
28impl CallBpf for BpfLinkCreateAttr {}
29
30#[derive(Clone)]
31pub enum AttachInfo {
32 RawTracepoint(String),
33 KProbe((String, u64)),
34 UProbe((String, u64)),
35}
36
37pub struct Probe {
38 attach_info: AttachInfo,
39 attach_fds: HashMap<u32, Vec<u32>>,
40}
41
42impl Probe {
43 pub fn create(attach_info: AttachInfo) -> Self {
49 Self {
50 attach_info,
51 attach_fds: HashMap::new(),
52 }
53 }
54
55 pub fn attach(&mut self, program: &Program) -> Result<(), Error> {
57 let attach_info = self.attach_info.clone();
58 match &attach_info {
59 AttachInfo::RawTracepoint(name) => self.attach_raw_tracepoint(program, name),
60 AttachInfo::KProbe((name, addr)) => self.attach_probe(program, "kprobe", name, *addr),
61 AttachInfo::UProbe((name, addr)) => self.attach_probe(program, "uprobe", name, *addr),
62 }
63 }
64
65 fn attach_probe(
66 &mut self,
67 program: &Program,
68 probe_name: &str,
69 name: &str,
70 addr: u64,
71 ) -> Result<(), Error> {
72 let perf_event_fds = perf_event_open_by_name(probe_name, name, addr)?;
73
74 let mut fds = vec![];
75 for fd in perf_event_fds {
76 perf_event_attach(fd, program.get_fd())?;
77 perf_event_enable(fd)?;
78 fds.push(fd);
79 }
80 self.attach_fds.insert(program.get_fd(), fds);
81
82 Ok(())
83 }
84
85 fn attach_raw_tracepoint(&mut self, program: &Program, name: &str) -> Result<(), Error> {
86 let mut bpf_attr = BpfRawTracepointOpenAttr::default();
87
88 cbzero(&mut bpf_attr);
94
95 let mut attach_name = String::from("");
100 attach_name.push_str(name);
101 attach_name.push('\0');
102
103 bpf_attr.prog_fd = program.get_fd();
104 bpf_attr.name = attach_name.as_ptr() as u64;
105
106 let fds = vec![bpf_attr.call_bpf(Command::RawTracepointOpen)?];
107 self.attach_fds.insert(program.get_fd(), fds);
108
109 Ok(())
110 }
111
112 pub fn detach(&mut self, program: &Program) -> Result<(), Error> {
114 if let Some(fds) = self.attach_fds.get(&program.get_fd()) {
115 for fd in fds {
116 close(*fd);
117 }
118 }
119 self.attach_fds.remove(&program.get_fd());
120
121 Ok(())
122 }
123}
124
125impl Drop for Probe {
126 fn drop(&mut self) {
127 for fds in self.attach_fds.values() {
128 for fd in fds {
129 close(*fd);
130 }
131 }
132 }
133}