|
|
@ -1,11 +1,10 @@
|
|
|
|
//! Perf attach links.
|
|
|
|
//! Perf attach links.
|
|
|
|
use libc::close;
|
|
|
|
use std::os::fd::{AsFd as _, AsRawFd as _, OwnedFd, RawFd};
|
|
|
|
use std::os::fd::RawFd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
use crate::{
|
|
|
|
generated::bpf_attach_type::BPF_PERF_EVENT,
|
|
|
|
generated::bpf_attach_type::BPF_PERF_EVENT,
|
|
|
|
programs::{probe::detach_debug_fs, FdLink, Link, ProbeKind, ProgramError},
|
|
|
|
programs::{probe::detach_debug_fs, FdLink, Link, ProbeKind, ProgramError},
|
|
|
|
sys::{bpf_link_create, perf_event_ioctl},
|
|
|
|
sys::{bpf_link_create, perf_event_ioctl, SysResult},
|
|
|
|
FEATURES, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF,
|
|
|
|
FEATURES, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -46,7 +45,7 @@ pub struct PerfLinkId(RawFd);
|
|
|
|
/// The attachment type of PerfEvent programs.
|
|
|
|
/// The attachment type of PerfEvent programs.
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct PerfLink {
|
|
|
|
pub struct PerfLink {
|
|
|
|
perf_fd: RawFd,
|
|
|
|
perf_fd: OwnedFd,
|
|
|
|
probe_kind: Option<ProbeKind>,
|
|
|
|
probe_kind: Option<ProbeKind>,
|
|
|
|
event_alias: Option<String>,
|
|
|
|
event_alias: Option<String>,
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -55,16 +54,15 @@ impl Link for PerfLink {
|
|
|
|
type Id = PerfLinkId;
|
|
|
|
type Id = PerfLinkId;
|
|
|
|
|
|
|
|
|
|
|
|
fn id(&self) -> Self::Id {
|
|
|
|
fn id(&self) -> Self::Id {
|
|
|
|
PerfLinkId(self.perf_fd)
|
|
|
|
PerfLinkId(self.perf_fd.as_raw_fd())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn detach(mut self) -> Result<(), ProgramError> {
|
|
|
|
fn detach(mut self) -> Result<(), ProgramError> {
|
|
|
|
let _ = perf_event_ioctl(self.perf_fd, PERF_EVENT_IOC_DISABLE, 0);
|
|
|
|
let _: SysResult<_> = perf_event_ioctl(self.perf_fd.as_fd(), PERF_EVENT_IOC_DISABLE, 0);
|
|
|
|
unsafe { close(self.perf_fd) };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(probe_kind) = self.probe_kind.take() {
|
|
|
|
if let Some(probe_kind) = self.probe_kind.take() {
|
|
|
|
if let Some(event_alias) = self.event_alias.take() {
|
|
|
|
if let Some(event_alias) = self.event_alias.take() {
|
|
|
|
let _ = detach_debug_fs(probe_kind, &event_alias);
|
|
|
|
let _: Result<_, _> = detach_debug_fs(probe_kind, &event_alias);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -72,15 +70,14 @@ impl Link for PerfLink {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn perf_attach(prog_fd: RawFd, fd: RawFd) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
pub(crate) fn perf_attach(prog_fd: RawFd, fd: OwnedFd) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
if FEATURES.bpf_perf_link() {
|
|
|
|
if FEATURES.bpf_perf_link() {
|
|
|
|
let link_fd =
|
|
|
|
let link_fd = bpf_link_create(prog_fd, fd.as_raw_fd(), BPF_PERF_EVENT, None, 0).map_err(
|
|
|
|
bpf_link_create(prog_fd, fd, BPF_PERF_EVENT, None, 0).map_err(|(_, io_error)| {
|
|
|
|
|(_, io_error)| ProgramError::SyscallError {
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
call: "bpf_link_create",
|
|
|
|
call: "bpf_link_create",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)? as RawFd;
|
|
|
|
})? as RawFd;
|
|
|
|
|
|
|
|
Ok(PerfLinkInner::FdLink(FdLink::new(link_fd)))
|
|
|
|
Ok(PerfLinkInner::FdLink(FdLink::new(link_fd)))
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
perf_attach_either(prog_fd, fd, None, None)
|
|
|
|
perf_attach_either(prog_fd, fd, None, None)
|
|
|
@ -89,7 +86,7 @@ pub(crate) fn perf_attach(prog_fd: RawFd, fd: RawFd) -> Result<PerfLinkInner, Pr
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn perf_attach_debugfs(
|
|
|
|
pub(crate) fn perf_attach_debugfs(
|
|
|
|
prog_fd: RawFd,
|
|
|
|
prog_fd: RawFd,
|
|
|
|
fd: RawFd,
|
|
|
|
fd: OwnedFd,
|
|
|
|
probe_kind: ProbeKind,
|
|
|
|
probe_kind: ProbeKind,
|
|
|
|
event_alias: String,
|
|
|
|
event_alias: String,
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
@ -98,17 +95,17 @@ pub(crate) fn perf_attach_debugfs(
|
|
|
|
|
|
|
|
|
|
|
|
fn perf_attach_either(
|
|
|
|
fn perf_attach_either(
|
|
|
|
prog_fd: RawFd,
|
|
|
|
prog_fd: RawFd,
|
|
|
|
fd: RawFd,
|
|
|
|
fd: OwnedFd,
|
|
|
|
probe_kind: Option<ProbeKind>,
|
|
|
|
probe_kind: Option<ProbeKind>,
|
|
|
|
event_alias: Option<String>,
|
|
|
|
event_alias: Option<String>,
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
) -> Result<PerfLinkInner, ProgramError> {
|
|
|
|
perf_event_ioctl(fd, PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| {
|
|
|
|
perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| {
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
call: "PERF_EVENT_IOC_SET_BPF",
|
|
|
|
call: "PERF_EVENT_IOC_SET_BPF",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
})?;
|
|
|
|
perf_event_ioctl(fd, PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| {
|
|
|
|
perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| {
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
call: "PERF_EVENT_IOC_ENABLE",
|
|
|
|
call: "PERF_EVENT_IOC_ENABLE",
|
|
|
|
io_error,
|
|
|
|
io_error,
|
|
|
|