-
Notifications
You must be signed in to change notification settings - Fork 247
/
perf_attach.rs
88 lines (76 loc) · 2.32 KB
/
perf_attach.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! Perf Attach Links
use libc::close;
use std::os::unix::io::RawFd;
use crate::{
programs::{probe::detach_debug_fs, Link, ProbeKind, ProgramData, ProgramError},
sys::perf_event_ioctl,
PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF,
};
/// PerfLinkId is the identifer of a PerfLink
#[derive(Debug, Hash, Eq, PartialEq)]
pub struct PerfLinkId(RawFd);
/// PerfLink is the attachment type of PerfEvent programs
#[derive(Debug)]
pub struct PerfLink {
perf_fd: RawFd,
probe_kind: Option<ProbeKind>,
event_alias: Option<String>,
}
impl Link for PerfLink {
type Id = PerfLinkId;
fn id(&self) -> Self::Id {
PerfLinkId(self.perf_fd)
}
fn detach(mut self) -> Result<(), ProgramError> {
let _ = perf_event_ioctl(self.perf_fd, PERF_EVENT_IOC_DISABLE, 0);
unsafe { close(self.perf_fd) };
if let Some(probe_kind) = self.probe_kind.take() {
if let Some(event_alias) = self.event_alias.take() {
let _ = detach_debug_fs(probe_kind, &event_alias);
}
}
Ok(())
}
}
pub(crate) fn perf_attach<T: Link + From<PerfLink>>(
data: &mut ProgramData<T>,
fd: RawFd,
) -> Result<T::Id, ProgramError> {
perf_attach_either(data, fd, None, None)
}
pub(crate) fn perf_attach_debugfs<T: Link + From<PerfLink>>(
data: &mut ProgramData<T>,
fd: RawFd,
probe_kind: ProbeKind,
event_alias: String,
) -> Result<T::Id, ProgramError> {
perf_attach_either(data, fd, Some(probe_kind), Some(event_alias))
}
fn perf_attach_either<T: Link + From<PerfLink>>(
data: &mut ProgramData<T>,
fd: RawFd,
probe_kind: Option<ProbeKind>,
event_alias: Option<String>,
) -> Result<T::Id, ProgramError> {
let prog_fd = data.fd_or_err()?;
perf_event_ioctl(fd, PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "PERF_EVENT_IOC_SET_BPF".to_owned(),
io_error,
}
})?;
perf_event_ioctl(fd, PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "PERF_EVENT_IOC_ENABLE".to_owned(),
io_error,
}
})?;
data.links.insert(
PerfLink {
perf_fd: fd,
probe_kind,
event_alias,
}
.into(),
)
}