|
@@ -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,
|
|
|
+ }))
|
|
|
}
|