diff --git a/libbpf-rs/CHANGELOG.md b/libbpf-rs/CHANGELOG.md index 285ab530..c5aff45e 100644 --- a/libbpf-rs/CHANGELOG.md +++ b/libbpf-rs/CHANGELOG.md @@ -13,6 +13,7 @@ Unreleased - Adjusted `UprobeOpts::func_name` to be an `Option` - Implemented `Sync` for `Link` - Updated `libbpf-sys` dependency to `1.5.0` +- Added `Program::attach_perf_event_with_opts` for attaching to perf events. 0.25.0-beta.1 diff --git a/libbpf-rs/src/lib.rs b/libbpf-rs/src/lib.rs index d03a6c4a..d49db7a2 100644 --- a/libbpf-rs/src/lib.rs +++ b/libbpf-rs/src/lib.rs @@ -149,6 +149,7 @@ pub use crate::program::OpenProgram; pub use crate::program::OpenProgramImpl; pub use crate::program::OpenProgramMut; pub use crate::program::Output as ProgramOutput; +pub use crate::program::PerfEventOpts; pub use crate::program::Program; pub use crate::program::ProgramAttachType; pub use crate::program::ProgramImpl; diff --git a/libbpf-rs/src/program.rs b/libbpf-rs/src/program.rs index 5fa818fd..eb713173 100644 --- a/libbpf-rs/src/program.rs +++ b/libbpf-rs/src/program.rs @@ -129,6 +129,35 @@ pub struct KprobeMultiOpts { pub _non_exhaustive: (), } +/// Options to optionally be provided when attaching to a perf event. +#[derive(Clone, Debug, Default)] +pub struct PerfEventOpts { + /// Custom user-provided value accessible through `bpf_get_attach_cookie`. + pub cookie: u64, + /// Force use of the old style ioctl attachment instead of the newer BPF link method. + pub force_ioctl_attach: bool, + #[doc(hidden)] + pub _non_exhaustive: (), +} + +impl From for libbpf_sys::bpf_perf_event_opts { + fn from(opts: PerfEventOpts) -> Self { + let PerfEventOpts { + cookie, + force_ioctl_attach, + _non_exhaustive, + } = opts; + + #[allow(clippy::needless_update)] + libbpf_sys::bpf_perf_event_opts { + sz: size_of::() as _, + bpf_cookie: cookie, + force_ioctl_attach, + // bpf_perf_event_opts might have padding fields on some platform + ..Default::default() + } + } +} /// An immutable parsed but not yet loaded BPF program. pub type OpenProgram<'obj> = OpenProgramImpl<'obj>; @@ -818,6 +847,23 @@ impl<'obj> ProgramMut<'obj> { Ok(link) } + /// Attach this program to a [perf event](https://linux.die.net/man/2/perf_event_open), + /// providing additional options. + pub fn attach_perf_event_with_opts(&self, pfd: i32, opts: PerfEventOpts) -> Result { + let libbpf_opts = libbpf_sys::bpf_perf_event_opts::from(opts); + let ptr = unsafe { + libbpf_sys::bpf_program__attach_perf_event_opts( + self.ptr.as_ptr(), + pfd, + &libbpf_opts as *const _, + ) + }; + let ptr = validate_bpf_ret(ptr).context("failed to attach perf event")?; + // SAFETY: the pointer came from libbpf and has been checked for errors. + let link = unsafe { Link::new(ptr) }; + Ok(link) + } + /// Attach this program to a [userspace /// probe](https://www.kernel.org/doc/html/latest/trace/uprobetracer.html). pub fn attach_uprobe>(