|
|
|
@ -3,11 +3,42 @@ 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,
|
|
|
|
|
generated::bpf_attach_type::BPF_PERF_EVENT,
|
|
|
|
|
programs::{probe::detach_debug_fs, FdLink, Link, ProbeKind, ProgramError},
|
|
|
|
|
sys::{bpf_link_create, perf_event_ioctl},
|
|
|
|
|
FEATURES, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Hash, Eq, PartialEq)]
|
|
|
|
|
pub(crate) enum PerfLinkIdInner {
|
|
|
|
|
FdLinkId(<FdLink as Link>::Id),
|
|
|
|
|
PerfLinkId(<PerfLink as Link>::Id),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub(crate) enum PerfLinkInner {
|
|
|
|
|
FdLink(FdLink),
|
|
|
|
|
PerfLink(PerfLink),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Link for PerfLinkInner {
|
|
|
|
|
type Id = PerfLinkIdInner;
|
|
|
|
|
|
|
|
|
|
fn id(&self) -> Self::Id {
|
|
|
|
|
match self {
|
|
|
|
|
PerfLinkInner::FdLink(link) => PerfLinkIdInner::FdLinkId(link.id()),
|
|
|
|
|
PerfLinkInner::PerfLink(link) => PerfLinkIdInner::PerfLinkId(link.id()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn detach(self) -> Result<(), ProgramError> {
|
|
|
|
|
match self {
|
|
|
|
|
PerfLinkInner::FdLink(link) => link.detach(),
|
|
|
|
|
PerfLinkInner::PerfLink(link) => link.detach(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The identifer of a PerfLink.
|
|
|
|
|
#[derive(Debug, Hash, Eq, PartialEq)]
|
|
|
|
|
pub struct PerfLinkId(RawFd);
|
|
|
|
@ -41,29 +72,36 @@ impl Link for PerfLink {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(prog_fd: RawFd, fd: RawFd) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
|
if FEATURES.bpf_perf_link {
|
|
|
|
|
let link_fd =
|
|
|
|
|
bpf_link_create(prog_fd, fd, BPF_PERF_EVENT, None, 0).map_err(|(_, io_error)| {
|
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
|
call: "bpf_link_create".to_owned(),
|
|
|
|
|
io_error,
|
|
|
|
|
}
|
|
|
|
|
})? as RawFd;
|
|
|
|
|
Ok(PerfLinkInner::FdLink(FdLink::new(link_fd)))
|
|
|
|
|
} else {
|
|
|
|
|
perf_attach_either(prog_fd, fd, None, None)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn perf_attach_debugfs<T: Link + From<PerfLink>>(
|
|
|
|
|
data: &mut ProgramData<T>,
|
|
|
|
|
pub(crate) fn perf_attach_debugfs(
|
|
|
|
|
prog_fd: RawFd,
|
|
|
|
|
fd: RawFd,
|
|
|
|
|
probe_kind: ProbeKind,
|
|
|
|
|
event_alias: String,
|
|
|
|
|
) -> Result<T::Id, ProgramError> {
|
|
|
|
|
perf_attach_either(data, fd, Some(probe_kind), Some(event_alias))
|
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
|
perf_attach_either(prog_fd, fd, Some(probe_kind), Some(event_alias))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn perf_attach_either<T: Link + From<PerfLink>>(
|
|
|
|
|
data: &mut ProgramData<T>,
|
|
|
|
|
fn perf_attach_either(
|
|
|
|
|
prog_fd: RawFd,
|
|
|
|
|
fd: RawFd,
|
|
|
|
|
probe_kind: Option<ProbeKind>,
|
|
|
|
|
event_alias: Option<String>,
|
|
|
|
|
) -> Result<T::Id, ProgramError> {
|
|
|
|
|
let prog_fd = data.fd_or_err()?;
|
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
|
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(),
|
|
|
|
@ -77,12 +115,9 @@ fn perf_attach_either<T: Link + From<PerfLink>>(
|
|
|
|
|
}
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
data.links.insert(
|
|
|
|
|
PerfLink {
|
|
|
|
|
perf_fd: fd,
|
|
|
|
|
probe_kind,
|
|
|
|
|
event_alias,
|
|
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
)
|
|
|
|
|
Ok(PerfLinkInner::PerfLink(PerfLink {
|
|
|
|
|
perf_fd: fd,
|
|
|
|
|
probe_kind,
|
|
|
|
|
event_alias,
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|