>(
if cookie.is_some() {
return Err(ProgramError::AttachCookieNotSupported);
}
- let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?;
- perf_attach_debugfs(prog_fd, fd, ProbeEvent { kind, event_alias })
+ let (perf_fd, event) = create_as_trace_point::(kind, fn_name, offset, pid)?;
+ perf_attach_debugfs(prog_fd, perf_fd, event)
} else {
- let fd = create_as_probe(kind, fn_name, offset, pid)?;
- perf_attach(prog_fd, fd, cookie)
+ let perf_fd = create_as_probe::
(kind, fn_name, offset, pid)?;
+ perf_attach(prog_fd, perf_fd, cookie)
}?;
program_data.links.insert(T::from(link))
}
-pub(crate) fn detach_debug_fs(event: ProbeEvent) -> Result<(), ProgramError> {
- use ProbeKind::*;
-
+fn detach_debug_fs(event_alias: &OsStr) -> Result<(), ProgramError> {
let tracefs = find_tracefs_path()?;
- let ProbeEvent {
- kind,
- event_alias: _,
- } = &event;
- let kind = *kind;
- let result = delete_probe_event(tracefs, event);
-
- result.map_err(|(filename, io_error)| match kind {
- KProbe | KRetProbe => KProbeError::FileError { filename, io_error }.into(),
- UProbe | URetProbe => UProbeError::FileError { filename, io_error }.into(),
- })
+ delete_probe_event(tracefs, P::PMU, event_alias)
+ .map_err(|(filename, io_error)| P::file_error(filename, io_error).into())
}
-fn create_as_probe(
+fn create_as_probe(
kind: ProbeKind,
fn_name: &OsStr,
offset: u64,
- pid: Option,
+ pid: Option,
) -> Result {
- use ProbeKind::*;
-
- let perf_ty = match kind {
- KProbe | KRetProbe => read_sys_fs_perf_type(kind.pmu())
- .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
- UProbe | URetProbe => read_sys_fs_perf_type(kind.pmu())
- .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
- };
+ let perf_ty = read_sys_fs_perf_type(P::PMU)
+ .map_err(|(filename, io_error)| P::file_error(filename, io_error).into())?;
let ret_bit = match kind {
- KRetProbe => Some(
- read_sys_fs_perf_ret_probe(kind.pmu())
- .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
- ),
- URetProbe => Some(
- read_sys_fs_perf_ret_probe(kind.pmu())
- .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
+ ProbeKind::Return => Some(
+ read_sys_fs_perf_ret_probe(P::PMU)
+ .map_err(|(filename, io_error)| P::file_error(filename, io_error).into())?,
),
- _ => None,
+ ProbeKind::Entry => None,
};
perf_event_open_probe(perf_ty, ret_bit, fn_name, offset, pid)
@@ -184,47 +197,42 @@ fn create_as_probe(
.map_err(Into::into)
}
-fn create_as_trace_point(
+fn create_as_trace_point(
kind: ProbeKind,
name: &OsStr,
offset: u64,
- pid: Option,
-) -> Result<(crate::MockableFd, OsString), ProgramError> {
- use ProbeKind::*;
-
+ pid: Option,
+) -> Result<(crate::MockableFd, ProbeEvent), ProgramError> {
let tracefs = find_tracefs_path()?;
- let event_alias = match kind {
- KProbe | KRetProbe => create_probe_event(tracefs, kind, name, offset)
- .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
- UProbe | URetProbe => create_probe_event(tracefs, kind, name, offset)
- .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
- };
+ let event = create_probe_event::(tracefs, kind, name, offset)
+ .map_err(|(filename, io_error)| P::file_error(filename, io_error).into())?;
- let category = format!("{}s", kind.pmu());
+ let ProbeEvent {
+ event_alias,
+ detach_debug_fs: _,
+ } = &event;
+ let category = format!("{}s", P::PMU);
let tpid = read_sys_fs_trace_point_id(tracefs, &category, event_alias.as_ref())?;
- let fd = perf_event_open_trace_point(tpid, pid).map_err(|io_error| SyscallError {
+ let perf_fd = perf_event_open_trace_point(tpid, pid).map_err(|io_error| SyscallError {
call: "perf_event_open",
io_error,
})?;
- Ok((fd, event_alias))
+ Ok((perf_fd, event))
}
-fn create_probe_event(
+fn create_probe_event(
tracefs: &Path,
kind: ProbeKind,
fn_name: &OsStr,
offset: u64,
-) -> Result {
+) -> Result {
use std::os::unix::ffi::OsStrExt as _;
- use ProbeKind::*;
-
- let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let probe_type_prefix = match kind {
- KProbe | UProbe => 'p',
- KRetProbe | URetProbe => 'r',
+ ProbeKind::Entry => 'p',
+ ProbeKind::Return => 'r',
};
let mut event_alias = OsString::new();
@@ -251,31 +259,34 @@ fn create_probe_event(
.unwrap();
let mut probe = OsString::new();
- write!(&mut probe, "{}:{}s/", probe_type_prefix, kind.pmu()).unwrap();
+ write!(&mut probe, "{}:{}s/", probe_type_prefix, P::PMU).unwrap();
probe.push(&event_alias);
probe.push(" ");
probe.push(fn_name);
- match kind {
- KProbe => write!(&mut probe, "+{offset}").unwrap(),
- UProbe | URetProbe => write!(&mut probe, ":{offset:#x}").unwrap(),
- _ => {}
- };
+ P::write_offset(&mut probe, kind, offset).unwrap();
probe.push("\n");
+ let events_file_name = tracefs.join(format!("{}_events", P::PMU));
OpenOptions::new()
.append(true)
.open(&events_file_name)
.and_then(|mut events_file| events_file.write_all(probe.as_bytes()))
.map_err(|e| (events_file_name, e))?;
- Ok(event_alias)
+ Ok(ProbeEvent {
+ event_alias,
+ detach_debug_fs: Some((detach_debug_fs::, true)),
+ })
}
-fn delete_probe_event(tracefs: &Path, event: ProbeEvent) -> Result<(), (PathBuf, io::Error)> {
+fn delete_probe_event(
+ tracefs: &Path,
+ pmu: &str,
+ event_alias: &OsStr,
+) -> Result<(), (PathBuf, io::Error)> {
use std::os::unix::ffi::OsStrExt as _;
- let ProbeEvent { kind, event_alias } = event;
- let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
+ let events_file_name = tracefs.join(format!("{}_events", pmu));
fs::read(&events_file_name)
.and_then(|events| {
@@ -324,7 +335,7 @@ fn read_sys_fs_perf_type(pmu: &str) -> Result {
.join("type");
fs::read_to_string(&file)
- .and_then(|perf_ty| perf_ty.trim().parse::().map_err(io::Error::other))
+ .and_then(|perf_ty| perf_ty.trim().parse().map_err(io::Error::other))
.map_err(|e| (file, e))
}
@@ -340,7 +351,7 @@ fn read_sys_fs_perf_ret_probe(pmu: &str) -> Result {
.next()
.ok_or_else(|| io::Error::other("invalid format"))?;
- config.parse::().map_err(io::Error::other)
+ config.parse().map_err(io::Error::other)
})
.map_err(|e| (file, e))
}
diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs
index 651e8b13..4fbc83b9 100644
--- a/aya/src/programs/trace_point.rs
+++ b/aya/src/programs/trace_point.rs
@@ -79,12 +79,12 @@ impl TracePoint {
let prog_fd = prog_fd.as_fd();
let tracefs = find_tracefs_path()?;
let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?;
- let fd = perf_event_open_trace_point(id, None).map_err(|io_error| SyscallError {
+ let perf_fd = perf_event_open_trace_point(id, None).map_err(|io_error| SyscallError {
call: "perf_event_open_trace_point",
io_error,
})?;
- let link = perf_attach(prog_fd, fd, None /* cookie */)?;
+ let link = perf_attach(prog_fd, perf_fd, None /* cookie */)?;
self.data.links.insert(TracePointLink::new(link))
}
}
@@ -115,14 +115,14 @@ pub(crate) fn read_sys_fs_trace_point_id(
tracefs: &Path,
category: &str,
name: &Path,
-) -> Result {
+) -> Result {
let filename = tracefs.join("events").join(category).join(name).join("id");
let id = match fs::read_to_string(&filename) {
Ok(id) => id,
Err(io_error) => return Err(TracePointError::FileError { filename, io_error }),
};
- let id = match id.trim().parse::() {
+ let id = match id.trim().parse() {
Ok(id) => id,
Err(error) => {
return Err(TracePointError::FileError {
diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs
index 69378b8c..0e15fc39 100644
--- a/aya/src/programs/uprobe.rs
+++ b/aya/src/programs/uprobe.rs
@@ -2,6 +2,7 @@
use std::{
error::Error,
ffi::{CStr, OsStr, OsString},
+ fmt::{self, Write},
fs,
io::{self, BufRead as _, Cursor, Read as _},
mem,
@@ -11,7 +12,6 @@ use std::{
};
use aya_obj::generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_KPROBE};
-use libc::pid_t;
use object::{Object as _, ObjectSection as _, ObjectSymbol as _, Symbol};
use thiserror::Error;
@@ -21,7 +21,7 @@ use crate::{
FdLink, LinkError, ProgramData, ProgramError, ProgramType, define_link_wrapper,
impl_try_into_fdlink, load_program,
perf_attach::{PerfLinkIdInner, PerfLinkInner},
- probe::{OsStringExt as _, ProbeKind, attach},
+ probe::{OsStringExt as _, Probe, ProbeKind, attach},
},
sys::bpf_link_get_info_by_fd,
util::MMap,
@@ -81,8 +81,8 @@ impl UProbe {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data)
}
- /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the
- /// program is a `uretprobe`.
+ /// Returns [`ProbeKind::Entry`] if the program is a `uprobe`, or
+ /// [`ProbeKind::Return`] if the program is a `uretprobe`.
pub fn kind(&self) -> ProbeKind {
self.kind
}
@@ -109,7 +109,7 @@ impl UProbe {
&mut self,
location: Loc,
target: T,
- pid: Option,
+ pid: Option,
cookie: Option,
) -> Result {
let proc_map = pid.map(ProcMap::new).transpose()?;
@@ -130,8 +130,9 @@ impl UProbe {
offset
};
+ let Self { data, kind } = self;
let path = path.as_os_str();
- attach(&mut self.data, self.kind, path, offset, pid, cookie)
+ attach::(data, *kind, path, offset, pid, cookie)
}
/// Creates a program from a pinned entry on a bpffs.
@@ -146,6 +147,20 @@ impl UProbe {
}
}
+impl Probe for UProbe {
+ const PMU: &'static str = "uprobe";
+
+ type Error = UProbeError;
+
+ fn file_error(filename: PathBuf, io_error: io::Error) -> Self::Error {
+ UProbeError::FileError { filename, io_error }
+ }
+
+ fn write_offset(w: &mut W, _: ProbeKind, offset: u64) -> fmt::Result {
+ write!(w, ":{offset:#x}")
+ }
+}
+
fn resolve_attach_path<'a, 'b, 'c, T>(
target: &'a Path,
proc_map: Option<&'b ProcMap>,
@@ -159,9 +174,10 @@ where
.and_then(|proc_map| {
proc_map
.find_library_path_by_name(target)
- .map_err(|source| UProbeError::ProcMap {
- pid: proc_map.pid,
- source,
+ .map_err(|source| {
+ let ProcMap { pid, data: _ } = proc_map;
+ let pid = *pid;
+ UProbeError::ProcMap { pid, source }
})
.transpose()
})
@@ -190,7 +206,7 @@ where
)]
fn test_resolve_attach_path() {
// Look up the current process's pid.
- let pid = std::process::id().try_into().unwrap();
+ let pid = std::process::id();
let proc_map = ProcMap::new(pid).unwrap();
// Now let's resolve the path to libc. It should exist in the current process's memory map and
@@ -208,6 +224,19 @@ fn test_resolve_attach_path() {
Some(libc_path) if libc_path.contains("libc"),
"libc_path: {}", libc_path.display()
);
+
+ // If we pass an absolute path that doesn't match anything in /proc//maps, we should fall
+ // back to the provided path instead of erroring out. Using a synthetic absolute path keeps the
+ // test hermetic.
+ let synthetic_absolute = Path::new("/tmp/.aya-test-resolve-attach-absolute");
+ let absolute_path =
+ resolve_attach_path(synthetic_absolute, Some(&proc_map)).unwrap_or_else(|err| {
+ match err.source() {
+ Some(source) => panic!("{err}: {source}"),
+ None => panic!("{err}"),
+ }
+ });
+ assert_eq!(absolute_path, synthetic_absolute);
}
define_link_wrapper!(
@@ -274,7 +303,7 @@ pub enum UProbeError {
#[error("error fetching libs for {pid}")]
ProcMap {
/// The pid.
- pid: i32,
+ pid: u32,
/// The [`ProcMapError`] that caused the error.
#[source]
source: ProcMapError,
@@ -406,12 +435,12 @@ impl<'a> ProcMapEntry<'a> {
///
/// The information here may be used to resolve addresses to paths.
struct ProcMap {
- pid: pid_t,
+ pid: u32,
data: T,
}
impl ProcMap> {
- fn new(pid: pid_t) -> Result {
+ fn new(pid: u32) -> Result {
let filename = PathBuf::from(format!("/proc/{pid}/maps"));
let data = fs::read(&filename)
.map_err(|io_error| UProbeError::FileError { filename, io_error })?;
@@ -425,6 +454,8 @@ impl> ProcMap {
data.as_ref()
.split(|&b| b == b'\n')
+ // /proc//maps ends with '\n', so split() yields a trailing empty slice.
+ .filter(|line| !line.is_empty())
.map(ProcMapEntry::parse)
}
@@ -1010,8 +1041,7 @@ mod tests {
7f372288f000-7f3722899000 r--p 00027000 00:24 18097875 /usr/lib64/ld-linux-x86-64.so.2
7f3722899000-7f372289b000 r--p 00030000 00:24 18097875 /usr/lib64/ld-linux-x86-64.so.2
7f372289b000-7f372289d000 rw-p 00032000 00:24 18097875 /usr/lib64/ld-linux-x86-64.so.2
-"#
- .trim_ascii(),
+"#,
};
assert_matches!(
diff --git a/aya/src/sys/perf_event.rs b/aya/src/sys/perf_event.rs
index afedefa9..c5592c83 100644
--- a/aya/src/sys/perf_event.rs
+++ b/aya/src/sys/perf_event.rs
@@ -1,62 +1,131 @@
use std::{
- ffi::{CString, OsStr, c_int},
+ ffi::{CString, OsStr, c_long, c_uint},
io, mem,
os::fd::{BorrowedFd, FromRawFd as _},
};
use aya_obj::generated::{
- PERF_FLAG_FD_CLOEXEC, perf_event_attr,
+ HW_BREAKPOINT_LEN_1, HW_BREAKPOINT_LEN_2, HW_BREAKPOINT_LEN_4, HW_BREAKPOINT_LEN_8,
+ HW_BREAKPOINT_X, PERF_FLAG_FD_CLOEXEC, perf_event_attr,
perf_event_sample_format::PERF_SAMPLE_RAW,
- perf_sw_ids::PERF_COUNT_SW_BPF_OUTPUT,
- perf_type_id::{PERF_TYPE_SOFTWARE, PERF_TYPE_TRACEPOINT},
+ perf_type_id::{
+ PERF_TYPE_BREAKPOINT, PERF_TYPE_HARDWARE, PERF_TYPE_HW_CACHE, PERF_TYPE_RAW,
+ PERF_TYPE_SOFTWARE, PERF_TYPE_TRACEPOINT,
+ },
};
use libc::pid_t;
use super::{PerfEventIoctlRequest, Syscall, syscall};
+use crate::programs::perf_event::{
+ BreakpointConfig, PerfEventConfig, PerfEventScope, SamplePolicy, WakeupPolicy,
+ perf_type_id_to_u32,
+};
-#[expect(clippy::too_many_arguments)]
pub(crate) fn perf_event_open(
- perf_type: u32,
- config: u64,
- pid: pid_t,
- cpu: c_int,
- sample_period: u64,
- sample_frequency: Option,
- wakeup: bool,
+ config: PerfEventConfig,
+ scope: PerfEventScope,
+ sample_policy: SamplePolicy,
+ wakeup_policy: WakeupPolicy,
inherit: bool,
flags: u32,
) -> io::Result {
let mut attr = unsafe { mem::zeroed::() };
+ let (perf_type, config) = match config {
+ PerfEventConfig::Pmu { pmu_type, config } => (pmu_type, config),
+ PerfEventConfig::Hardware(hw_event) => (
+ perf_type_id_to_u32(PERF_TYPE_HARDWARE),
+ u64::from(hw_event.into_primitive()),
+ ),
+ PerfEventConfig::Software(sw_event) => (
+ perf_type_id_to_u32(PERF_TYPE_SOFTWARE),
+ u64::from(sw_event.into_primitive()),
+ ),
+ PerfEventConfig::TracePoint { event_id } => {
+ (perf_type_id_to_u32(PERF_TYPE_TRACEPOINT), event_id)
+ }
+ PerfEventConfig::HwCache {
+ event,
+ operation,
+ result,
+ } => (
+ perf_type_id_to_u32(PERF_TYPE_HW_CACHE),
+ u64::from(event.into_primitive())
+ | (u64::from(operation.into_primitive()) << 8)
+ | (u64::from(result.into_primitive()) << 16),
+ ),
+ PerfEventConfig::Raw { event_id } => (perf_type_id_to_u32(PERF_TYPE_RAW), event_id),
+ PerfEventConfig::Breakpoint(breakpoint) => {
+ let (type_, address, length) = match breakpoint {
+ BreakpointConfig::Data {
+ r#type,
+ address,
+ length,
+ } => (
+ r#type.into_primitive(),
+ address,
+ u64::from(length.into_primitive()),
+ ),
+ BreakpointConfig::Instruction { address } => {
+ const fn length(size: usize) -> c_uint {
+ match size {
+ 1 => HW_BREAKPOINT_LEN_1,
+ 2 => HW_BREAKPOINT_LEN_2,
+ 4 => HW_BREAKPOINT_LEN_4,
+ 8 => HW_BREAKPOINT_LEN_8,
+ // NB: cannot emit the value because:
+ //
+ // error[E0015]: cannot call non-const formatting macro in constant functions
+ _ => panic!("invalid hardware breakpoint size"),
+ }
+ }
+ const LENGTH: c_uint = length(std::mem::size_of::());
+ (HW_BREAKPOINT_X, address, u64::from(LENGTH))
+ }
+ };
+
+ attr.bp_type = type_;
+ attr.__bindgen_anon_3.bp_addr = address;
+ attr.__bindgen_anon_4.bp_len = length;
+ attr.set_precise_ip(2);
+
+ (perf_type_id_to_u32(PERF_TYPE_BREAKPOINT), 0)
+ }
+ };
+
attr.config = config;
attr.size = mem::size_of::() as u32;
attr.type_ = perf_type;
attr.sample_type = PERF_SAMPLE_RAW as u64;
attr.set_inherit(if inherit { 1 } else { 0 });
- attr.__bindgen_anon_2.wakeup_events = u32::from(wakeup);
- if let Some(frequency) = sample_frequency {
- attr.set_freq(1);
- attr.__bindgen_anon_1.sample_freq = frequency;
- } else {
- attr.__bindgen_anon_1.sample_period = sample_period;
+ match sample_policy {
+ SamplePolicy::Period(period) => {
+ attr.__bindgen_anon_1.sample_period = period;
+ }
+ SamplePolicy::Frequency(frequency) => {
+ attr.set_freq(1);
+ attr.__bindgen_anon_1.sample_freq = frequency;
+ }
}
- perf_event_sys(attr, pid, cpu, flags)
-}
+ match wakeup_policy {
+ WakeupPolicy::Events(events) => {
+ attr.__bindgen_anon_2.wakeup_events = events;
+ }
+ WakeupPolicy::Watermark(watermark) => {
+ attr.set_watermark(1);
+ attr.__bindgen_anon_2.wakeup_watermark = watermark;
+ }
+ }
-pub(crate) fn perf_event_open_bpf(cpu: c_int) -> io::Result {
- perf_event_open(
- PERF_TYPE_SOFTWARE as u32,
- PERF_COUNT_SW_BPF_OUTPUT as u64,
- -1,
- cpu,
- 1,
- None,
- true,
- false,
- PERF_FLAG_FD_CLOEXEC,
- )
+ let (pid, cpu) = match scope {
+ PerfEventScope::CallingProcess { cpu } => (0, cpu.map_or(-1, |cpu| cpu as i32)),
+ PerfEventScope::OneProcess { pid, cpu } => (pid as i32, cpu.map_or(-1, |cpu| cpu as i32)),
+ PerfEventScope::AllProcessesOneCpu { cpu } => (-1, cpu as i32),
+ };
+
+ perf_event_sys(attr, pid, cpu, flags)
}
pub(crate) fn perf_event_open_probe(
@@ -64,7 +133,7 @@ pub(crate) fn perf_event_open_probe(
ret_bit: Option,
name: &OsStr,
offset: u64,
- pid: Option,
+ pid: Option,
) -> io::Result {
use std::os::unix::ffi::OsStrExt as _;
@@ -81,26 +150,30 @@ pub(crate) fn perf_event_open_probe(
attr.__bindgen_anon_3.config1 = c_name.as_ptr() as u64;
attr.__bindgen_anon_4.config2 = offset;
- let cpu = if pid.is_some() { -1 } else { 0 };
- let pid = pid.unwrap_or(-1);
+ let (pid, cpu) = match pid {
+ Some(pid) => (pid as i32, -1),
+ None => (-1, 0),
+ };
perf_event_sys(attr, pid, cpu, PERF_FLAG_FD_CLOEXEC)
}
pub(crate) fn perf_event_open_trace_point(
- id: u32,
- pid: Option,
+ event_id: u64,
+ pid: Option,
) -> io::Result {
- let mut attr = unsafe { mem::zeroed::() };
-
- attr.size = mem::size_of::() as u32;
- attr.type_ = PERF_TYPE_TRACEPOINT as u32;
- attr.config = u64::from(id);
-
- let cpu = if pid.is_some() { -1 } else { 0 };
- let pid = pid.unwrap_or(-1);
-
- perf_event_sys(attr, pid, cpu, PERF_FLAG_FD_CLOEXEC)
+ let scope = match pid {
+ Some(pid) => PerfEventScope::OneProcess { pid, cpu: None },
+ None => PerfEventScope::AllProcessesOneCpu { cpu: 0 },
+ };
+ perf_event_open(
+ PerfEventConfig::TracePoint { event_id },
+ scope,
+ SamplePolicy::Period(0),
+ WakeupPolicy::Events(1),
+ false,
+ PERF_FLAG_FD_CLOEXEC,
+ )
}
pub(crate) fn perf_event_ioctl(
diff --git a/aya/src/util.rs b/aya/src/util.rs
index 3a04aa2a..200b80a1 100644
--- a/aya/src/util.rs
+++ b/aya/src/util.rs
@@ -323,7 +323,9 @@ fn parse_kernel_symbols(reader: impl BufRead) -> Result, i
/// # Example
///
/// ```no_run
+/// # #[expect(deprecated)]
/// use aya::util::syscall_prefix;
+/// # #[expect(deprecated)]
/// let prefix = syscall_prefix().unwrap();
/// let syscall_fname = format!("{prefix}exec");
/// ```
diff --git a/clippy.sh b/clippy.sh
index ca314276..9641623b 100755
--- a/clippy.sh
+++ b/clippy.sh
@@ -4,12 +4,12 @@ set -eux
# `-C panic=abort` because "unwinding panics are not supported without std"; integration-ebpf
# contains `#[no_std]` binaries.
-#
+#
# `-Zpanic_abort_tests` because "building tests with panic=abort is not supported without
# `-Zpanic_abort_tests`"; Cargo does this automatically when panic=abort is set via profile but we
# want to preserve unwinding at runtime - here we are just running clippy so we don't care about
# unwinding behavior.
-#
+#
# `+nightly` because "the option `Z` is only accepted on the nightly compiler".
cargo +nightly hack clippy "$@" \
--all-targets \
@@ -18,17 +18,30 @@ cargo +nightly hack clippy "$@" \
-C panic=abort \
-Zpanic_abort_tests
+export CLIPPY_ARGS='--deny=warnings'
+export RUSTDOCFLAGS='--no-run -Z unstable-options --test-builder clippy-driver'
+
+cargo +nightly hack test --doc "$@" --feature-powerset
for arch in aarch64 arm loongarch64 mips powerpc64 riscv64 s390x x86_64; do
+ export RUSTFLAGS="--cfg bpf_target_arch=\"$arch\""
+
for target in bpfeb-unknown-none bpfel-unknown-none; do
- RUSTFLAGS="--cfg bpf_target_arch=\"$arch\"" cargo +nightly hack clippy \
+ cargo +nightly hack clippy \
--target "$target" \
-Zbuild-std=core \
- --package aya-ebpf-bindings \
--package aya-ebpf \
+ --package aya-ebpf-bindings \
--package aya-log-ebpf \
--package integration-ebpf \
--feature-powerset \
-- --deny warnings
- done
+ done
+
+ RUSTDOCFLAGS="$RUSTDOCFLAGS $RUSTFLAGS" cargo +nightly hack test --doc "$@" \
+ --package aya-ebpf \
+ --package aya-ebpf-bindings \
+ --package aya-log-ebpf \
+ --package integration-ebpf \
+ --feature-powerset
done
diff --git a/ebpf/aya-ebpf-bindings/CHANGELOG.md b/ebpf/aya-ebpf-bindings/CHANGELOG.md
index 1bf9dac2..6dc862e8 100644
--- a/ebpf/aya-ebpf-bindings/CHANGELOG.md
+++ b/ebpf/aya-ebpf-bindings/CHANGELOG.md
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+## v0.1.2 (2025-11-17)
+
+### New Features
+
+ - , , Regenerated the bindings from libbpf 324f3c38…, pulling in MIPS and LoongArch64 support alongside the latest kernel constants.
+
+### Maintenance
+
+ - , General lint/build fixes (including the riscv64 build) to keep the generated code warning-free.
+
## v0.1.1 (2024-10-09)
### Other
diff --git a/ebpf/aya-ebpf-bindings/Cargo.toml b/ebpf/aya-ebpf-bindings/Cargo.toml
index a75b8d0a..f906ab5e 100644
--- a/ebpf/aya-ebpf-bindings/Cargo.toml
+++ b/ebpf/aya-ebpf-bindings/Cargo.toml
@@ -1,7 +1,7 @@
[package]
description = "Bindings for Linux Kernel eBPF types and helpers"
name = "aya-ebpf-bindings"
-version = "0.1.1"
+version = "0.1.2"
authors.workspace = true
edition.workspace = true
@@ -13,7 +13,7 @@ repository.workspace = true
workspace = true
[dependencies]
-aya-ebpf-cty = { version = "^0.2.2", path = "../aya-ebpf-cty" }
+aya-ebpf-cty = { version = "^0.2.3", path = "../aya-ebpf-cty" }
[build-dependencies]
-aya-build = { version = "^0.1.2", path = "../../aya-build" }
+aya-build = { version = "^0.1.3", path = "../../aya-build" }
diff --git a/ebpf/aya-ebpf-bindings/include/bindings.h b/ebpf/aya-ebpf-bindings/include/bindings.h
index aa831c57..ba2f9183 100644
--- a/ebpf/aya-ebpf-bindings/include/bindings.h
+++ b/ebpf/aya-ebpf-bindings/include/bindings.h
@@ -6,6 +6,7 @@ typedef __u32 __bitwise __wsum;
#include
#include
+#include
// needed for TC_ACT_*
#include
#include
diff --git a/ebpf/aya-ebpf-bindings/src/aarch64/bindings.rs b/ebpf/aya-ebpf-bindings/src/aarch64/bindings.rs
index 87ef0587..473db3c6 100644
--- a/ebpf/aya-ebpf-bindings/src/aarch64/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/aarch64/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2887,6 +2882,14 @@ pub struct user_pt_regs {
pub pc: __u64,
pub pstate: __u64,
}
+pub type bpf_user_pt_regs_t = user_pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/armv7/bindings.rs b/ebpf/aya-ebpf-bindings/src/armv7/bindings.rs
index 54140c49..50c1d6f7 100644
--- a/ebpf/aya-ebpf-bindings/src/armv7/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/armv7/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2896,6 +2891,14 @@ pub struct bpf_iter_num {
pub struct pt_regs {
pub uregs: [::aya_ebpf_cty::c_long; 18usize],
}
+pub type bpf_user_pt_regs_t = pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/loongarch64/bindings.rs b/ebpf/aya-ebpf-bindings/src/loongarch64/bindings.rs
index f769d7b9..4ffb76ce 100644
--- a/ebpf/aya-ebpf-bindings/src/loongarch64/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/loongarch64/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2888,6 +2883,14 @@ pub struct user_pt_regs {
pub csr_badv: ::aya_ebpf_cty::c_ulong,
pub reserved: [::aya_ebpf_cty::c_ulong; 10usize],
}
+pub type bpf_user_pt_regs_t = user_pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/mips/bindings.rs b/ebpf/aya-ebpf-bindings/src/mips/bindings.rs
index 65333c5c..1bacaa53 100644
--- a/ebpf/aya-ebpf-bindings/src/mips/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/mips/bindings.rs
@@ -366,11 +366,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2903,6 +2898,14 @@ pub struct pt_regs {
pub cp0_status: __u64,
pub cp0_cause: __u64,
}
+pub type bpf_user_pt_regs_t = pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/powerpc64/bindings.rs b/ebpf/aya-ebpf-bindings/src/powerpc64/bindings.rs
index bc1388bf..7e46bcb7 100644
--- a/ebpf/aya-ebpf-bindings/src/powerpc64/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/powerpc64/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2891,6 +2886,14 @@ pub struct pt_regs {
pub dsisr: ::aya_ebpf_cty::c_ulong,
pub result: ::aya_ebpf_cty::c_ulong,
}
+pub type bpf_user_pt_regs_t = pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/riscv64/bindings.rs b/ebpf/aya-ebpf-bindings/src/riscv64/bindings.rs
index 98b85819..c90a7d2a 100644
--- a/ebpf/aya-ebpf-bindings/src/riscv64/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/riscv64/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2915,6 +2910,14 @@ pub struct user_regs_struct {
pub t5: ::aya_ebpf_cty::c_ulong,
pub t6: ::aya_ebpf_cty::c_ulong,
}
+pub type bpf_user_pt_regs_t = user_regs_struct;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/s390x/bindings.rs b/ebpf/aya-ebpf-bindings/src/s390x/bindings.rs
index 15804301..015cafe7 100644
--- a/ebpf/aya-ebpf-bindings/src/s390x/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/s390x/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -3848,6 +3843,14 @@ pub struct user_regs_struct {
pub per_info: per_struct,
pub ieee_instruction_pointer: ::aya_ebpf_cty::c_ulong,
}
+pub type bpf_user_pt_regs_t = user_pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-bindings/src/x86_64/bindings.rs b/ebpf/aya-ebpf-bindings/src/x86_64/bindings.rs
index 89fec488..72c24b75 100644
--- a/ebpf/aya-ebpf-bindings/src/x86_64/bindings.rs
+++ b/ebpf/aya-ebpf-bindings/src/x86_64/bindings.rs
@@ -365,11 +365,6 @@ pub type __be32 = __u32;
pub type __wsum = __u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct bpf_perf_event_data {
- _unused: [u8; 0],
-}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
pub struct linux_binprm {
_unused: [u8; 0],
}
@@ -2899,6 +2894,14 @@ pub struct pt_regs {
pub rsp: ::aya_ebpf_cty::c_ulong,
pub ss: ::aya_ebpf_cty::c_ulong,
}
+pub type bpf_user_pt_regs_t = pt_regs;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct bpf_perf_event_data {
+ pub regs: bpf_user_pt_regs_t,
+ pub sample_period: __u64,
+ pub addr: __u64,
+}
pub type sa_family_t = ::aya_ebpf_cty::c_ushort;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
diff --git a/ebpf/aya-ebpf-cty/CHANGELOG.md b/ebpf/aya-ebpf-cty/CHANGELOG.md
index 23c0b0a1..dd3d09d4 100644
--- a/ebpf/aya-ebpf-cty/CHANGELOG.md
+++ b/ebpf/aya-ebpf-cty/CHANGELOG.md
@@ -5,65 +5,15 @@ This project adheres to $[Semantic Versioning](http://semver.org/).
## [Unreleased]
-## [v0.2.1] - 2019-11-16
+## v0.2.3 (2025-11-17)
-### Added
+### New Features
-- Support for the `xtensa`, `riscv32` and `riscv64` architectures
+ - , Added the missing MIPS and LoongArch definitions so the cty shim covers every architecture supported by Aya.
-## [v0.2.0] - 2019-02-06
+### Maintenance
-### Changed
-
-- [breaking-change] `cty::c_void` is now a type alias of `core::ffi::c_void`.
-
-## [v0.1.5] - 2017-05-29
-
-### Added
-
-- More types like `int32_t`
-
-## [v0.1.4] - 2017-05-29
-
-### Added
-
-- Support for the `msp430` architecture.
-
-### Fixed
-
-- [breaking-change] The type definitions of `c_long` and `c_ulong`.
-
-## [v0.1.3] - 2017-05-29 - YANKED
-
-### Added
-
-- Support for the `nvptx` and `nvptx64` architectures.
-
-## [v0.1.2] - 2017-05-29 - YANKED
-
-### Fixed
-
-- [breaking-change] The type definitions of `c_int` and `c_uint`.
-
-## [v0.1.1] - 2017-05-29 - YANKED
-
-### Fixed
-
-- [breaking-change] The type definitions of `c_long`, `c_ulong` and
- `c_longlong`.
-
-## v0.1.0 - 2017-05-24 - YANKED
-
-- Initial release
-
-[Unreleased]: https://github.com/japaric/cty/compare/v0.2.1...HEAD
-[v0.2.1]: https://github.com/japaric/cty/compare/v0.2.0...v0.2.1
-[v0.2.0]: https://github.com/japaric/cty/compare/v0.1.5...v0.2.0
-[v0.1.5]: https://github.com/japaric/cty/compare/v0.1.4...v0.1.5
-[v0.1.4]: https://github.com/japaric/cty/compare/v0.1.3...v0.1.4
-[v0.1.3]: https://github.com/japaric/cty/compare/v0.1.2...v0.1.3
-[v0.1.2]: https://github.com/japaric/cty/compare/v0.1.1...v0.1.2
-[v0.1.1]: https://github.com/japaric/cty/compare/v0.1.0...v0.1.1
+ - , Tidied the crate (removing the abandoned Travis setup) and refreshed the bindings so downstream riscv64 builds stay green.
## v0.2.2 (2024-10-09)
diff --git a/ebpf/aya-ebpf-cty/Cargo.toml b/ebpf/aya-ebpf-cty/Cargo.toml
index a848b6aa..fc695096 100644
--- a/ebpf/aya-ebpf-cty/Cargo.toml
+++ b/ebpf/aya-ebpf-cty/Cargo.toml
@@ -3,7 +3,7 @@ categories = ["embedded", "external-ffi-bindings", "no-std"]
description = "Type aliases to C types like c_int for use with bindgen"
documentation = "https://docs.rs/aya-bpf-cty"
name = "aya-ebpf-cty"
-version = "0.2.2"
+version = "0.2.3"
authors.workspace = true
edition.workspace = true
@@ -16,4 +16,4 @@ rust-version.workspace = true
workspace = true
[build-dependencies]
-aya-build = { version = "^0.1.2", path = "../../aya-build" }
+aya-build = { version = "^0.1.3", path = "../../aya-build" }
diff --git a/ebpf/aya-ebpf/CHANGELOG.md b/ebpf/aya-ebpf/CHANGELOG.md
index fb00292b..d8c155a8 100644
--- a/ebpf/aya-ebpf/CHANGELOG.md
+++ b/ebpf/aya-ebpf/CHANGELOG.md
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+## v0.1.2 (2025-11-17)
+
+### Breaking Changes
+
+ - Map helper functions now take `*mut c_void`, matching the kernel’s prototypes. Any out-of-tree helpers should update their signatures accordingly.
+
+### New Features
+
+ - Added a `bpf_strncmp` helper binding.
+ - Raw tracepoints now expose their arguments so programs no longer need to guess register layouts.
+ - , Added mips/loongarch register helpers so those targets can implement `FromPtRegs`.
+ - `XdpContext` exposes the interface index, simplifying multi-interface programs.
+ - Added `Array::set()` to update array contents from eBPF code.
+ - Introduced Flow Dissector program support on the eBPF side.
+ - Added `RingBufBytes` so probes can emit raw byte slices efficiently.
+ - , Added BTF array definitions plus `Queue`/`Stack::peek()` helpers for safer data-structure inspection.
+
+### Bug Fixes
+
+ - Fixed riscv64 builds by updating the generated bindings.
+ - Cleaned up ring-buffer code to avoid reliance on `as` casts, preventing UB on strict architectures.
+ - Guarded the libc `mem*` shims behind `cfg(target_arch = "bpf")`, ensuring CPU builds stay well-defined.
+
+### Maintenance
+
+ - , Added configuration flags for `generic_const_exprs` and the loongarch target, plus the usual lint/documentation refresh.
+
## v0.1.1 (2024-10-09)
### New Features
diff --git a/ebpf/aya-ebpf/Cargo.toml b/ebpf/aya-ebpf/Cargo.toml
index e2067982..b597f21f 100644
--- a/ebpf/aya-ebpf/Cargo.toml
+++ b/ebpf/aya-ebpf/Cargo.toml
@@ -1,7 +1,7 @@
[package]
description = "A library for writing eBPF programs"
name = "aya-ebpf"
-version = "0.1.1"
+version = "0.1.2"
authors.workspace = true
edition.workspace = true
@@ -14,10 +14,10 @@ rust-version.workspace = true
workspace = true
[dependencies]
-aya-ebpf-bindings = { version = "^0.1.1", path = "../aya-ebpf-bindings" }
-aya-ebpf-cty = { version = "^0.2.2", path = "../aya-ebpf-cty" }
-aya-ebpf-macros = { version = "^0.1.1", path = "../../aya-ebpf-macros" }
+aya-ebpf-bindings = { version = "^0.1.2", path = "../aya-ebpf-bindings" }
+aya-ebpf-cty = { version = "^0.2.3", path = "../aya-ebpf-cty" }
+aya-ebpf-macros = { version = "^0.1.2", path = "../../aya-ebpf-macros" }
[build-dependencies]
-aya-build = { version = "^0.1.2", path = "../../aya-build" }
+aya-build = { version = "^0.1.3", path = "../../aya-build" }
rustversion = { workspace = true }
diff --git a/ebpf/aya-ebpf/src/helpers.rs b/ebpf/aya-ebpf/src/helpers.rs
index 6e23f1d3..44b61342 100644
--- a/ebpf/aya-ebpf/src/helpers.rs
+++ b/ebpf/aya-ebpf/src/helpers.rs
@@ -35,7 +35,6 @@ use crate::{
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const c_int = 0 as _;
@@ -74,7 +73,6 @@ pub unsafe fn bpf_probe_read(src: *const T) -> Result {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_buf};
/// # fn try_test() -> Result<(), c_long> {
/// # let ptr: *const u8 = 0 as _;
@@ -103,7 +101,6 @@ pub unsafe fn bpf_probe_read_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user};
/// # fn try_test() -> Result<(), c_long> {
/// # let user_ptr: *const c_int = 0 as _;
@@ -140,7 +137,6 @@ pub unsafe fn bpf_probe_read_user(src: *const T) -> Result {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user_buf};
/// # fn try_test() -> Result<(), c_long> {
/// # let user_ptr: *const u8 = 0 as _;
@@ -170,7 +166,6 @@ pub unsafe fn bpf_probe_read_user_buf(src: *const u8, dst: &mut [u8]) -> Result<
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const c_int = 0 as _;
@@ -207,7 +202,6 @@ pub unsafe fn bpf_probe_read_kernel(src: *const T) -> Result {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel_buf};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const u8 = 0 as _;
@@ -240,11 +234,12 @@ pub unsafe fn bpf_probe_read_kernel_buf(src: *const u8, dst: &mut [u8]) -> Resul
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
+/// # #[expect(deprecated)]
/// # use aya_ebpf::{cty::c_long, helpers::bpf_probe_read_str};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const u8 = 0 as _;
/// let mut my_str = [0u8; 16];
+/// # #[expect(deprecated)]
/// let num_read = unsafe { bpf_probe_read_str(kernel_ptr, &mut my_str)? };
///
/// // Do something with num_read and my_str
@@ -276,11 +271,12 @@ pub unsafe fn bpf_probe_read_str(src: *const u8, dest: &mut [u8]) -> Result Result<(), c_long> {
/// # let user_ptr: *const u8 = 0 as _;
/// let mut my_str = [0u8; 16];
+/// # #[expect(deprecated)]
/// let num_read = unsafe { bpf_probe_read_user_str(user_ptr, &mut my_str)? };
///
/// // Do something with num_read and my_str
@@ -315,7 +311,6 @@ pub unsafe fn bpf_probe_read_user_str(src: *const u8, dest: &mut [u8]) -> Result
/// eBPF stack limit is 512 bytes):
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::c_long, helpers::bpf_probe_read_user_str_bytes};
/// # fn try_test() -> Result<(), c_long> {
/// # let user_ptr: *const u8 = 0 as _;
@@ -421,11 +416,12 @@ fn read_str_bytes(len: i64, dest: &[u8]) -> Result<&[u8], c_long> {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
+/// # #[expect(deprecated)]
/// # use aya_ebpf::{cty::c_long, helpers::bpf_probe_read_kernel_str};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const u8 = 0 as _;
/// let mut my_str = [0u8; 16];
+/// # #[expect(deprecated)]
/// let num_read = unsafe { bpf_probe_read_kernel_str(kernel_ptr, &mut my_str)? };
///
/// // Do something with num_read and my_str
@@ -464,7 +460,6 @@ pub unsafe fn bpf_probe_read_kernel_str(src: *const u8, dest: &mut [u8]) -> Resu
/// eBPF stack limit is 512 bytes):
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::c_long, helpers::bpf_probe_read_kernel_str_bytes};
/// # fn try_test() -> Result<(), c_long> {
/// # let kernel_ptr: *const u8 = 0 as _;
@@ -554,7 +549,6 @@ pub unsafe fn bpf_probe_read_kernel_str_bytes(
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::{
/// # cty::{c_int, c_long},
/// # helpers::bpf_probe_write_user,
@@ -587,7 +581,6 @@ pub unsafe fn bpf_probe_write_user(dst: *mut T, src: *const T) -> Result<(),
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::helpers::bpf_get_current_comm;
/// let comm = bpf_get_current_comm();
///
@@ -622,7 +615,6 @@ pub fn bpf_get_current_comm() -> Result<[u8; 16], c_long> {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::helpers::bpf_get_current_pid_tgid;
/// let tgid = (bpf_get_current_pid_tgid() >> 32) as u32;
/// let pid = bpf_get_current_pid_tgid() as u32;
@@ -645,7 +637,6 @@ pub fn bpf_get_current_pid_tgid() -> u64 {
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// # use aya_ebpf::helpers::bpf_get_current_uid_gid;
/// let gid = (bpf_get_current_uid_gid() >> 32) as u32;
/// let uid = bpf_get_current_uid_gid() as u32;
diff --git a/ebpf/aya-ebpf/src/maps/program_array.rs b/ebpf/aya-ebpf/src/maps/program_array.rs
index d56f076a..8241eed2 100644
--- a/ebpf/aya-ebpf/src/maps/program_array.rs
+++ b/ebpf/aya-ebpf/src/maps/program_array.rs
@@ -14,7 +14,6 @@ use crate::{
/// # Examples
///
/// ```no_run
-/// # #![expect(dead_code)]
/// use aya_ebpf::{macros::map, maps::ProgramArray, cty::c_long};
/// # use aya_ebpf::{programs::LsmContext};
///
@@ -24,8 +23,8 @@ use crate::{
/// # unsafe fn try_test(ctx: &LsmContext) -> Result<(), c_long> {
/// let index: u32 = 13;
///
-/// if let Err(e) = JUMP_TABLE.tail_call(ctx, index) {
-/// return Err(e);
+/// unsafe {
+/// JUMP_TABLE.tail_call(ctx, index)?;
/// }
///
/// # Err(-1)
diff --git a/ebpf/aya-ebpf/src/programs/fentry.rs b/ebpf/aya-ebpf/src/programs/fentry.rs
index b67fb35c..0e61236d 100644
--- a/ebpf/aya-ebpf/src/programs/fentry.rs
+++ b/ebpf/aya-ebpf/src/programs/fentry.rs
@@ -16,10 +16,10 @@ impl FEntryContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(non_camel_case_types)]
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::c_int, programs::FEntryContext};
+ /// # #[expect(non_camel_case_types)]
/// # type pid_t = c_int;
+ /// # #[expect(non_camel_case_types)]
/// # struct task_struct {
/// # pid: pid_t,
/// # }
diff --git a/ebpf/aya-ebpf/src/programs/fexit.rs b/ebpf/aya-ebpf/src/programs/fexit.rs
index 20a4c3b5..d936c310 100644
--- a/ebpf/aya-ebpf/src/programs/fexit.rs
+++ b/ebpf/aya-ebpf/src/programs/fexit.rs
@@ -16,10 +16,10 @@ impl FExitContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(non_camel_case_types)]
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{cty::c_int, programs::FExitContext};
+ /// # #[expect(non_camel_case_types)]
/// # type pid_t = c_int;
+ /// # #[expect(non_camel_case_types)]
/// # struct task_struct {
/// # pid: pid_t,
/// # }
diff --git a/ebpf/aya-ebpf/src/programs/lsm.rs b/ebpf/aya-ebpf/src/programs/lsm.rs
index 741aa1b6..4e0111d5 100644
--- a/ebpf/aya-ebpf/src/programs/lsm.rs
+++ b/ebpf/aya-ebpf/src/programs/lsm.rs
@@ -25,7 +25,6 @@ impl LsmContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{programs::LsmContext, cty::{c_int, c_ulong}};
/// unsafe fn try_lsm_mmap_addr(ctx: LsmContext) -> Result {
/// // In the kernel, this hook is defined as:
diff --git a/ebpf/aya-ebpf/src/programs/perf_event.rs b/ebpf/aya-ebpf/src/programs/perf_event.rs
index d847fc31..f8de1c0a 100644
--- a/ebpf/aya-ebpf/src/programs/perf_event.rs
+++ b/ebpf/aya-ebpf/src/programs/perf_event.rs
@@ -1,19 +1,21 @@
use core::ffi::c_void;
+use aya_ebpf_bindings::bindings::bpf_perf_event_data;
+
use crate::EbpfContext;
pub struct PerfEventContext {
- ctx: *mut c_void,
+ pub ctx: *mut bpf_perf_event_data,
}
impl PerfEventContext {
- pub fn new(ctx: *mut c_void) -> Self {
+ pub fn new(ctx: *mut bpf_perf_event_data) -> Self {
Self { ctx }
}
}
impl EbpfContext for PerfEventContext {
fn as_ptr(&self) -> *mut c_void {
- self.ctx
+ self.ctx.cast()
}
}
diff --git a/ebpf/aya-ebpf/src/programs/probe.rs b/ebpf/aya-ebpf/src/programs/probe.rs
index 6c7266c6..e2ee6e0e 100644
--- a/ebpf/aya-ebpf/src/programs/probe.rs
+++ b/ebpf/aya-ebpf/src/programs/probe.rs
@@ -16,16 +16,18 @@ impl ProbeContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(non_camel_case_types)]
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{programs::ProbeContext, cty::c_int, helpers::bpf_probe_read};
+ /// # #[expect(non_camel_case_types)]
/// # type pid_t = c_int;
+ /// # #[expect(non_camel_case_types)]
/// # struct task_struct {
/// # pid: pid_t,
/// # }
/// unsafe fn try_kprobe_try_to_wake_up(ctx: ProbeContext) -> Result {
/// let tp: *const task_struct = ctx.arg(0).ok_or(1u32)?;
- /// let pid = bpf_probe_read(&(*tp).pid as *const pid_t).map_err(|_| 1u32)?;
+ /// let pid = unsafe {
+ /// bpf_probe_read(core::ptr::addr_of!((*tp).pid))
+ /// }.map_err(|err| err as u32)?;
///
/// // Do something with pid or something else with tp
///
diff --git a/ebpf/aya-ebpf/src/programs/retprobe.rs b/ebpf/aya-ebpf/src/programs/retprobe.rs
index c2aec986..c669f25e 100644
--- a/ebpf/aya-ebpf/src/programs/retprobe.rs
+++ b/ebpf/aya-ebpf/src/programs/retprobe.rs
@@ -16,7 +16,6 @@ impl RetProbeContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{programs::RetProbeContext, cty::c_int};
/// unsafe fn try_kretprobe_try_to_wake_up(ctx: RetProbeContext) -> Result {
/// let retval: c_int = ctx.ret();
diff --git a/ebpf/aya-ebpf/src/programs/sk_buff.rs b/ebpf/aya-ebpf/src/programs/sk_buff.rs
index 93b5f5e0..deb9654b 100644
--- a/ebpf/aya-ebpf/src/programs/sk_buff.rs
+++ b/ebpf/aya-ebpf/src/programs/sk_buff.rs
@@ -384,8 +384,8 @@ impl SkBuffContext {
/// fn try_cgroup_skb(ctx: SkBuffContext) -> Result {
/// let len = ETH_HLEN + IP_HLEN + UDP_HLEN;
/// match ctx.pull_data(len as u32) {
- /// Ok(()) => return Ok(0),
- /// Err(ret) => return Err(ret as i32),
+ /// Ok(()) => Ok(0),
+ /// Err(ret) => Err(ret as i32),
/// }
/// }
/// ```
diff --git a/ebpf/aya-ebpf/src/programs/tc.rs b/ebpf/aya-ebpf/src/programs/tc.rs
index e9281d83..8304d58c 100644
--- a/ebpf/aya-ebpf/src/programs/tc.rs
+++ b/ebpf/aya-ebpf/src/programs/tc.rs
@@ -176,8 +176,8 @@ impl TcContext {
/// fn try_classifier(ctx: TcContext) -> Result {
/// let len = ETH_HLEN + IP_HLEN + UDP_HLEN;
/// match ctx.pull_data(len as u32) {
- /// Ok(()) => return Ok(0),
- /// Err(ret) => return Err(ret as i32),
+ /// Ok(()) => Ok(0),
+ /// Err(ret) => Err(ret as i32),
/// }
/// }
/// ```
diff --git a/ebpf/aya-ebpf/src/programs/tp_btf.rs b/ebpf/aya-ebpf/src/programs/tp_btf.rs
index 9e39f2f0..c5daf637 100644
--- a/ebpf/aya-ebpf/src/programs/tp_btf.rs
+++ b/ebpf/aya-ebpf/src/programs/tp_btf.rs
@@ -19,7 +19,6 @@ impl BtfTracePointContext {
/// # Examples
///
/// ```no_run
- /// # #![expect(dead_code)]
/// # use aya_ebpf::{programs::BtfTracePointContext, cty::{c_int, c_ulong, c_char}};
/// unsafe fn try_tp_btf_sched_process_fork(ctx: BtfTracePointContext) -> Result {
/// // Grab arguments
diff --git a/ebpf/aya-log-ebpf/CHANGELOG.md b/ebpf/aya-log-ebpf/CHANGELOG.md
index d25856d3..ac8b22e8 100644
--- a/ebpf/aya-log-ebpf/CHANGELOG.md
+++ b/ebpf/aya-log-ebpf/CHANGELOG.md
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+## 0.1.2 (2025-11-17)
+
+### Breaking Changes
+
+ - Logging from eBPF programs now writes into a ring buffer to match the host transport, requiring Linux 5.8 or later.
+
+### New Features
+
+ - , Added a load-time log level mask and improved verifier hints so disabled log levels are optimised out entirely.
+ - Logging paths now use zero-copy writes into the ring buffer, lowering instruction counts inside probes.
+ - Added raw-pointer formatting so eBPF logs can mirror the new host-side diagnostics.
+
+### Maintenance
+
+ - , Kept the crate in sync with the workspace edition/lint settings and tidied the macro support helpers.
+
## 0.1.1 (2024-10-09)
Maintenance release. Update to latest aya-ebpf version v0.1.1.
diff --git a/ebpf/aya-log-ebpf/Cargo.toml b/ebpf/aya-log-ebpf/Cargo.toml
index 90c54198..89c1ac10 100644
--- a/ebpf/aya-log-ebpf/Cargo.toml
+++ b/ebpf/aya-log-ebpf/Cargo.toml
@@ -1,7 +1,7 @@
[package]
description = "Logging for eBPF programs"
name = "aya-log-ebpf"
-version = "0.1.1"
+version = "0.1.2"
authors.workspace = true
edition.workspace = true
@@ -14,6 +14,6 @@ rust-version.workspace = true
workspace = true
[dependencies]
-aya-ebpf = { version = "^0.1.1", path = "../aya-ebpf" }
-aya-log-common = { version = "^0.1.15", path = "../../aya-log-common" }
-aya-log-ebpf-macros = { version = "^0.1.0", path = "../../aya-log-ebpf-macros" }
+aya-ebpf = { version = "^0.1.2", path = "../aya-ebpf" }
+aya-log-common = { version = "^0.1.16", path = "../../aya-log-common" }
+aya-log-ebpf-macros = { version = "^0.1.1", path = "../../aya-log-ebpf-macros" }
diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml
index cb52e728..33715cfb 100644
--- a/test/integration-ebpf/Cargo.toml
+++ b/test/integration-ebpf/Cargo.toml
@@ -103,3 +103,7 @@ path = "src/xdp_sec.rs"
[[bin]]
name = "uprobe_cookie"
path = "src/uprobe_cookie.rs"
+
+[[bin]]
+name = "perf_event_bp"
+path = "src/perf_event_bp.rs"
diff --git a/test/integration-ebpf/src/log.rs b/test/integration-ebpf/src/log.rs
index 3e7bf5b8..b55b7276 100644
--- a/test/integration-ebpf/src/log.rs
+++ b/test/integration-ebpf/src/log.rs
@@ -115,10 +115,10 @@ fn test_log(ctx: ProbeContext) {
let buf = &buf[..core::cmp::min(len, buf.len())];
info!(&ctx, "variable length buffer: {:x}", buf);
- info!(&ctx, "2KiB array: {:x}", &TWO_KB_ARRAY);
- info!(&ctx, "4KiB array: {:x}", &FOUR_KB_ARRAY);
+ info!(&ctx, "2KiB array: {:x}", TWO_KB_ARRAY.as_slice());
+ info!(&ctx, "4KiB array: {:x}", FOUR_KB_ARRAY.as_slice());
// This one is too big and should be dropped.
- info!(&ctx, "8KiB array: {:x}", &EIGHT_KB_ARRAY);
+ info!(&ctx, "8KiB array: {:x}", EIGHT_KB_ARRAY.as_slice());
}
#[uprobe]
diff --git a/test/integration-ebpf/src/map_test.rs b/test/integration-ebpf/src/map_test.rs
index eac1823d..0135487a 100644
--- a/test/integration-ebpf/src/map_test.rs
+++ b/test/integration-ebpf/src/map_test.rs
@@ -3,9 +3,9 @@
#![expect(unused_crate_dependencies, reason = "used in other bins")]
use aya_ebpf::{
- macros::{map, socket_filter},
+ macros::{map, socket_filter, uprobe},
maps::{Array, HashMap},
- programs::SkBuffContext,
+ programs::{ProbeContext, SkBuffContext},
};
#[cfg(not(test))]
extern crate ebpf_panic;
@@ -35,3 +35,20 @@ fn simple_prog(_ctx: SkBuffContext) -> i64 {
0
}
+
+#[uprobe]
+fn simple_prog_mut(_ctx: ProbeContext) -> i64 {
+ if let Some(array_value) = FOO.get_ptr_mut(0) {
+ unsafe {
+ *array_value += 1;
+ }
+ }
+
+ if let Some(map_value) = BAZ.get_ptr_mut(0) {
+ unsafe {
+ *map_value += 1;
+ }
+ }
+
+ 0
+}
diff --git a/test/integration-ebpf/src/perf_event_bp.rs b/test/integration-ebpf/src/perf_event_bp.rs
new file mode 100644
index 00000000..f6928c01
--- /dev/null
+++ b/test/integration-ebpf/src/perf_event_bp.rs
@@ -0,0 +1,24 @@
+#![no_std]
+#![no_main]
+#![expect(unused_crate_dependencies, reason = "used in other bins")]
+
+use aya_ebpf::{
+ EbpfContext as _,
+ macros::{map, perf_event},
+ maps::HashMap,
+ programs::PerfEventContext,
+};
+
+#[cfg(not(test))]
+extern crate ebpf_panic;
+
+#[map]
+static READERS: HashMap = HashMap::with_max_entries(1, 0);
+
+#[perf_event]
+fn perf_event_bp(ctx: PerfEventContext) -> u32 {
+ let tgid = ctx.tgid();
+ let addr = unsafe { (*ctx.ctx).addr };
+ let _ = READERS.insert(tgid, addr, 0);
+ 0
+}
diff --git a/test/integration-ebpf/src/ring_buf.rs b/test/integration-ebpf/src/ring_buf.rs
index b6f12ac1..cac357f5 100644
--- a/test/integration-ebpf/src/ring_buf.rs
+++ b/test/integration-ebpf/src/ring_buf.rs
@@ -40,7 +40,7 @@ fn ring_buf_test(ctx: ProbeContext) {
Some(arg) => arg,
None => return,
};
- if arg % 2 == 0 {
+ if arg.is_multiple_of(2) {
entry.write(arg);
entry.submit(0);
} else {
diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml
index e443af2f..e81d705c 100644
--- a/test/integration-test/Cargo.toml
+++ b/test/integration-test/Cargo.toml
@@ -14,13 +14,13 @@ rust-version.workspace = true
workspace = true
[dependencies]
-aya = { path = "../../aya", version = "^0.13.1", default-features = false }
+aya = { path = "../../aya", version = "^0.13.2", default-features = false }
[dev-dependencies]
anyhow = { workspace = true, features = ["std"] }
assert_matches = { workspace = true }
-aya-log = { path = "../../aya-log", version = "^0.2.1", default-features = false }
-aya-obj = { path = "../../aya-obj", version = "^0.2.1", default-features = false }
+aya-log = { path = "../../aya-log", version = "^0.2.2", default-features = false }
+aya-obj = { path = "../../aya-obj", version = "^0.2.2", default-features = false }
epoll = { workspace = true }
futures = { workspace = true, features = ["alloc"] }
integration-common = { path = "../integration-common", features = ["user"] }
diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs
index 44a4783a..881cdd57 100644
--- a/test/integration-test/build.rs
+++ b/test/integration-test/build.rs
@@ -219,6 +219,7 @@ fn main() -> Result<()> {
.parent()
.ok_or_else(|| anyhow!("no parent for {manifest_path}"))?
.as_str(),
+ ..Default::default()
};
aya_build::build_ebpf([integration_ebpf_package], aya_build::Toolchain::default())?;
} else {
diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs
index 64f37d18..01e26f03 100644
--- a/test/integration-test/src/lib.rs
+++ b/test/integration-test/src/lib.rs
@@ -46,6 +46,7 @@ bpf_file!(
MEMMOVE_TEST => "memmove_test",
NAME_TEST => "name_test",
PASS => "pass",
+ PERF_EVENT_BP => "perf_event_bp",
RAW_TRACEPOINT => "raw_tracepoint",
REDIRECT => "redirect",
RELOCATIONS => "relocations",
diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs
index b7d4d492..4de831aa 100644
--- a/test/integration-test/src/tests.rs
+++ b/test/integration-test/src/tests.rs
@@ -10,6 +10,8 @@ mod load;
mod log;
mod lsm;
mod map_pin;
+mod maps_disjoint;
+mod perf_event_bp;
mod raw_tracepoint;
mod rbpf;
mod relocations;
diff --git a/test/integration-test/src/tests/info.rs b/test/integration-test/src/tests/info.rs
index 9a4740c3..20c92c75 100644
--- a/test/integration-test/src/tests/info.rs
+++ b/test/integration-test/src/tests/info.rs
@@ -60,7 +60,7 @@ fn test_loaded_programs() {
.unwrap();
let mut p: UProbe = unsafe {
- UProbe::from_program_info(info, "test_uprobe".into(), aya::programs::ProbeKind::UProbe)
+ UProbe::from_program_info(info, "test_uprobe".into(), aya::programs::ProbeKind::Entry)
.unwrap()
};
diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs
index dd50fe2d..26046824 100644
--- a/test/integration-test/src/tests/load.rs
+++ b/test/integration-test/src/tests/load.rs
@@ -557,7 +557,7 @@ fn pin_lifecycle_kprobe() {
let attach = |prog: &mut P| prog.attach("try_to_wake_up", 0).unwrap();
let program_pin = "/sys/fs/bpf/aya-kprobe-test-prog";
let link_pin = "/sys/fs/bpf/aya-kprobe-test-try-to-wake-up";
- let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::KProbe).unwrap();
+ let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::Entry).unwrap();
run_pin_program_lifecycle_test(
crate::TEST,
program_name,
@@ -587,7 +587,7 @@ fn pin_lifecycle_uprobe() {
};
let program_pin = "/sys/fs/bpf/aya-uprobe-test-prog";
let link_pin = "/sys/fs/bpf/aya-uprobe-test-uprobe-function";
- let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::UProbe).unwrap();
+ let from_pin = |program_pin: &str| P::from_pin(program_pin, ProbeKind::Entry).unwrap();
run_pin_program_lifecycle_test(
crate::TEST,
program_name,
diff --git a/test/integration-test/src/tests/maps_disjoint.rs b/test/integration-test/src/tests/maps_disjoint.rs
new file mode 100644
index 00000000..79f6fe23
--- /dev/null
+++ b/test/integration-test/src/tests/maps_disjoint.rs
@@ -0,0 +1,44 @@
+use aya::{
+ Ebpf,
+ maps::{Array, HashMap},
+ programs::UProbe,
+};
+
+#[unsafe(no_mangle)]
+#[inline(never)]
+extern "C" fn trigger_ebpf_program_maps_disjoint() {
+ core::hint::black_box(trigger_ebpf_program_maps_disjoint);
+}
+
+#[test_log::test]
+fn test_maps_disjoint() {
+ let mut bpf: Ebpf = Ebpf::load(crate::MAP_TEST).unwrap();
+ let prog: &mut UProbe = bpf
+ .program_mut("simple_prog_mut")
+ .unwrap()
+ .try_into()
+ .unwrap();
+
+ prog.load().unwrap();
+ prog.attach(
+ "trigger_ebpf_program_maps_disjoint",
+ "/proc/self/exe",
+ None,
+ None,
+ )
+ .unwrap();
+
+ let [foo, bar, baz] = bpf.maps_disjoint_mut(["FOO", "BAR", "BAZ"]);
+
+ let mut foo: Array<_, u32> = Array::try_from(foo.unwrap()).unwrap();
+ let mut bar: HashMap<_, u32, u8> = HashMap::try_from(bar.unwrap()).unwrap();
+ assert!(baz.is_none());
+
+ foo.set(0, 5, 0).unwrap();
+ bar.insert(0, 10, 0).unwrap();
+
+ trigger_ebpf_program_maps_disjoint();
+
+ assert_eq!(foo.get(&0, 0).unwrap(), 6);
+ assert_eq!(bar.get(&0, 0).unwrap(), 11);
+}
diff --git a/test/integration-test/src/tests/perf_event_bp.rs b/test/integration-test/src/tests/perf_event_bp.rs
new file mode 100644
index 00000000..5667fdc5
--- /dev/null
+++ b/test/integration-test/src/tests/perf_event_bp.rs
@@ -0,0 +1,320 @@
+use std::{collections::HashMap, fs, io::ErrorKind, num::ParseIntError, path::PathBuf};
+
+use assert_matches::assert_matches;
+use aya::{
+ Ebpf, maps,
+ programs::{
+ ProgramError,
+ perf_event::{
+ BreakpointConfig, PerfBreakpointLength, PerfBreakpointType, PerfEventConfig,
+ PerfEventScope, SamplePolicy,
+ },
+ },
+ sys::SyscallError,
+ util::online_cpus,
+};
+use scopeguard::defer;
+
+fn find_system_map() -> Vec {
+ const BOOT_PATH: &str = "/boot/";
+ const SYSTEM_MAP_PREFIX: &str = "System.map-";
+ let mut system_maps = Vec::new();
+ for (i, entry) in fs::read_dir(BOOT_PATH)
+ .unwrap_or_else(|error| panic!("fs::read_dir({BOOT_PATH}): {error:?}"))
+ .enumerate()
+ {
+ let entry = entry.unwrap_or_else(|error| {
+ panic!("fs::read_dir({BOOT_PATH}).enumerate().nth({i}): {error:?}")
+ });
+ if !entry
+ .file_name()
+ .as_encoded_bytes()
+ .starts_with(SYSTEM_MAP_PREFIX.as_bytes())
+ {
+ continue;
+ }
+ system_maps.push(entry.path());
+ }
+ system_maps
+}
+
+struct KernelSymbol<'a> {
+ address: u64,
+ #[expect(dead_code)]
+ r#type: &'a str,
+ name: &'a str,
+ #[expect(dead_code)]
+ module: Option<&'a str>,
+}
+
+fn parse_kernel_symbol(line: &str) -> Option> {
+ let mut parts = line.splitn(4, char::is_whitespace);
+ let address = parts.next()?;
+ let r#type = parts.next()?;
+ let name = parts.next()?;
+ let module = parts.next();
+ // TODO(https://github.com/rust-lang/rust-clippy/issues/14112): Remove this allowance
+ // when the lint behaves more sensibly.
+ #[expect(clippy::manual_ok_err)]
+ let address = match u64::from_str_radix(address, 16) {
+ Ok(address) => Some(address),
+ Err(ParseIntError { .. }) => None,
+ }?;
+ Some(KernelSymbol {
+ address,
+ r#type,
+ name,
+ module,
+ })
+}
+
+fn parse_kernel_symbols(content: &str) -> HashMap<&str, Vec> {
+ let mut kernel_symbols = HashMap::<_, Vec<_>>::new();
+ for line in content.lines() {
+ let KernelSymbol {
+ address,
+ r#type: _,
+ name,
+ module: _,
+ } = parse_kernel_symbol(line).unwrap_or_else(|| panic!("parse_kernel_symbol({line})"));
+ kernel_symbols.entry(name).or_default().push(address);
+ }
+ kernel_symbols
+}
+
+#[track_caller]
+fn run_breakpoint_case(config: BreakpointConfig, mut trigger: F, expected_addr: u64)
+where
+ F: FnMut(),
+{
+ let mut bpf = Ebpf::load(crate::PERF_EVENT_BP).unwrap();
+
+ let map: maps::HashMap<_, u32, u64> = bpf.take_map("READERS").unwrap().try_into().unwrap();
+
+ let prog: &mut aya::programs::PerfEvent = bpf
+ .program_mut("perf_event_bp")
+ .unwrap()
+ .try_into()
+ .unwrap();
+ prog.load().unwrap();
+
+ // x86 debug registers cannot trigger on read-only watchpoints, so the
+ // kernel rejects `HW_BREAKPOINT_R` outright, see
+ // https://github.com/torvalds/linux/blob/v6.12/arch/x86/kernel/hw_breakpoint.c#L345-L377.
+ let type_supported = !(cfg!(target_arch = "x86_64")
+ && matches!(
+ config,
+ BreakpointConfig::Data {
+ r#type: PerfBreakpointType::Read,
+ ..
+ }
+ ));
+
+ let mut calling_process_scopes = Vec::new();
+ let mut one_process_scopes = Vec::new();
+ let mut all_processes_one_cpu_scopes = Vec::new();
+
+ let pid = std::process::id();
+ for cpu in online_cpus().unwrap() {
+ calling_process_scopes.push(PerfEventScope::CallingProcess { cpu: Some(cpu) });
+ one_process_scopes.push(PerfEventScope::OneProcess {
+ pid,
+ cpu: Some(cpu),
+ });
+ all_processes_one_cpu_scopes.push(PerfEventScope::AllProcessesOneCpu { cpu });
+ }
+
+ let scope_groups = &[
+ &[PerfEventScope::CallingProcess { cpu: None }][..],
+ &[PerfEventScope::OneProcess { pid, cpu: None }][..],
+ calling_process_scopes.as_slice(),
+ one_process_scopes.as_slice(),
+ all_processes_one_cpu_scopes.as_slice(),
+ ];
+
+ for scope_group in scope_groups {
+ let mut link_ids = Vec::new();
+ for scope in *scope_group {
+ // arm64 rejects per-task kernel breakpoints (the scopes that carry
+ // a PID) to avoid single-step bookkeeping, see
+ // https://github.com/torvalds/linux/blob/v6.12/arch/arm64/kernel/hw_breakpoint.c#L566-L571.
+ let scope_supported = type_supported
+ && (!cfg!(target_arch = "aarch64")
+ || matches!(scope, PerfEventScope::AllProcessesOneCpu { cpu: _ }));
+ let attach = prog.attach(
+ PerfEventConfig::Breakpoint(config),
+ *scope,
+ SamplePolicy::Period(1),
+ true,
+ );
+ if scope_supported {
+ let link_id = attach.unwrap_or_else(|error| {
+ panic!("{config:?} {scope:?} attach failed: {error:?}")
+ });
+ link_ids.push(link_id);
+ } else {
+ assert_matches!(
+ attach.unwrap_err(),
+ ProgramError::SyscallError(SyscallError {
+ call: "perf_event_open",
+ io_error,
+ }) => io_error.kind() == ErrorKind::InvalidInput
+ );
+ }
+ }
+ let attached = !link_ids.is_empty();
+ defer! {
+ for link_id in link_ids {
+ prog.detach(link_id).unwrap();
+ }
+ }
+
+ trigger();
+
+ let lookup = map.get(&pid, 0);
+ if attached {
+ let recorded =
+ lookup.unwrap_or_else(|error| panic!("{config:?} map lookup failed: {error:?}"));
+ assert_eq!(
+ recorded, expected_addr,
+ "{config:?} recorded unexpected address"
+ );
+ } else {
+ assert_matches!(lookup.unwrap_err(), maps::MapError::KeyNotFound);
+ }
+ }
+}
+
+fn get_address(symbols: &HashMap<&str, Vec>, name: &str) -> Option {
+ symbols.get(name).map(|addrs| match addrs.as_slice() {
+ [addr] => *addr,
+ [] => panic!("no address found for {name} in {symbols:?}"),
+ addrs => panic!("multiple addresses found for {name}: {addrs:?}"),
+ })
+}
+
+#[test_log::test]
+fn perf_event_bp() {
+ // Search for the address of modprobe_path. Prefer to grab it directly from
+ // kallsyms, but if it's not there we can grab it from System.map and apply
+ // the kaslr offset.
+ const KALLSYMS_PATH: &str = "/proc/kallsyms";
+ let kernel_symbols = fs::read_to_string(KALLSYMS_PATH)
+ .unwrap_or_else(|error| panic!("fs::read_to_string({KALLSYMS_PATH}): {error:?}"));
+ let kernel_symbols = parse_kernel_symbols(&kernel_symbols);
+
+ let attach_addr = if let Some(addr) = get_address(&kernel_symbols, "modprobe_path") {
+ addr
+ } else {
+ let gunzip_addr = get_address(&kernel_symbols, "gunzip")
+ .unwrap_or_else(|| panic!("gunzip not found in {kernel_symbols:?}"));
+
+ let system_map = find_system_map();
+ let system_map = match system_map.as_slice() {
+ [system_map] => system_map,
+ [] => panic!("no system map found"),
+ system_maps => panic!("multiple system maps found: {:?}", system_maps),
+ };
+ let system_map = fs::read_to_string(system_map).unwrap_or_else(|error| {
+ panic!("fs::read_to_string({}): {error:?}", system_map.display())
+ });
+ let system_map = parse_kernel_symbols(&system_map);
+
+ let gunzip_debug_addr = get_address(&system_map, "gunzip")
+ .unwrap_or_else(|| panic!("gunzip not found in {system_map:?}"));
+ let modprobe_path_debug_addr = get_address(&system_map, "modprobe_path")
+ .unwrap_or_else(|| panic!("modprobe_path not found in {system_map:?}"));
+
+ let kaslr_offset = gunzip_addr.wrapping_sub(gunzip_debug_addr);
+ modprobe_path_debug_addr.wrapping_add(kaslr_offset)
+ };
+
+ // Trigger the hardware breakpoint by reading or writing
+ // /proc/sys/kernel/modprobe, the sysctl connected to modprobe_path.
+ //
+ // See https://github.com/torvalds/linux/blob/v6.17/kernel/module/main.c#L132-L150.
+ const MODPROBE_PATH: &str = "/proc/sys/kernel/modprobe";
+
+ let read = |modprobe_contents: &mut Option| {
+ let contents = fs::read_to_string(MODPROBE_PATH)
+ .unwrap_or_else(|error| panic!("fs::read_to_string({MODPROBE_PATH}): {error:?}"));
+ if let Some(modprobe_contents) = modprobe_contents {
+ assert_eq!(*modprobe_contents, contents);
+ }
+ *modprobe_contents = Some(contents);
+ };
+
+ let write = |contents: &str| {
+ fs::write(MODPROBE_PATH, contents.as_bytes())
+ .unwrap_or_else(|error| panic!("fs::write({MODPROBE_PATH}, ..): {error:?}"));
+ };
+
+ let mut modprobe_contents_before = None;
+ run_breakpoint_case(
+ BreakpointConfig::Data {
+ r#type: PerfBreakpointType::Read,
+ address: attach_addr,
+ length: PerfBreakpointLength::Len1,
+ },
+ || read(&mut modprobe_contents_before),
+ attach_addr,
+ );
+ let modprobe_contents_before = modprobe_contents_before.unwrap();
+
+ run_breakpoint_case(
+ BreakpointConfig::Data {
+ r#type: PerfBreakpointType::Write,
+ address: attach_addr,
+ length: PerfBreakpointLength::Len1,
+ },
+ || write(&modprobe_contents_before),
+ attach_addr,
+ );
+
+ let mut modprobe_contents_after = None;
+ run_breakpoint_case(
+ BreakpointConfig::Data {
+ r#type: PerfBreakpointType::ReadWrite,
+ address: attach_addr,
+ length: PerfBreakpointLength::Len1,
+ },
+ || read(&mut modprobe_contents_after),
+ attach_addr,
+ );
+ let modprobe_contents_after = modprobe_contents_after.unwrap();
+
+ run_breakpoint_case(
+ BreakpointConfig::Data {
+ r#type: PerfBreakpointType::ReadWrite,
+ address: attach_addr,
+ length: PerfBreakpointLength::Len1,
+ },
+ || write(&modprobe_contents_after),
+ attach_addr,
+ );
+
+ // Just for fun.
+ assert_eq!(modprobe_contents_before, modprobe_contents_after);
+
+ let execute_addr = {
+ let getpgid_symbol = if cfg!(target_arch = "x86_64") {
+ "__x64_sys_getpgid"
+ } else if cfg!(target_arch = "aarch64") {
+ "__arm64_sys_getpgid"
+ } else {
+ panic!("unsupported architecture");
+ };
+ get_address(&kernel_symbols, getpgid_symbol)
+ .unwrap_or_else(|| panic!("{getpgid_symbol} not found in {kernel_symbols:?}"))
+ };
+
+ run_breakpoint_case(
+ BreakpointConfig::Instruction {
+ address: execute_addr,
+ },
+ || {
+ nix::unistd::getpgid(None).unwrap();
+ },
+ execute_addr,
+ );
+}
diff --git a/xtask/public-api/aya-build.txt b/xtask/public-api/aya-build.txt
index a9fe663c..a5af3847 100644
--- a/xtask/public-api/aya-build.txt
+++ b/xtask/public-api/aya-build.txt
@@ -27,8 +27,12 @@ pub fn aya_build::Toolchain<'a>::borrow_mut(&mut self) -> &mut T
impl core::convert::From for aya_build::Toolchain<'a>
pub fn aya_build::Toolchain<'a>::from(t: T) -> T
pub struct aya_build::Package<'a>
+pub aya_build::Package::features: &'a [&'a str]
pub aya_build::Package::name: &'a str
+pub aya_build::Package::no_default_features: bool
pub aya_build::Package::root_dir: &'a str
+impl<'a> core::default::Default for aya_build::Package<'a>
+pub fn aya_build::Package<'a>::default() -> aya_build::Package<'a>
impl<'a> core::marker::Freeze for aya_build::Package<'a>
impl<'a> core::marker::Send for aya_build::Package<'a>
impl<'a> core::marker::Sync for aya_build::Package<'a>
diff --git a/xtask/public-api/aya-ebpf-bindings.txt b/xtask/public-api/aya-ebpf-bindings.txt
index 7a38ec39..00a60f70 100644
--- a/xtask/public-api/aya-ebpf-bindings.txt
+++ b/xtask/public-api/aya-ebpf-bindings.txt
@@ -4972,6 +4972,9 @@ pub unsafe fn aya_ebpf_bindings::bindings::bpf_map_info::clone_to_uninit(&self,
impl core::convert::From for aya_ebpf_bindings::bindings::bpf_map_info
pub fn aya_ebpf_bindings::bindings::bpf_map_info::from(t: T) -> T
#[repr(C)] pub struct aya_ebpf_bindings::bindings::bpf_perf_event_data
+pub aya_ebpf_bindings::bindings::bpf_perf_event_data::addr: aya_ebpf_bindings::bindings::__u64
+pub aya_ebpf_bindings::bindings::bpf_perf_event_data::regs: aya_ebpf_bindings::bindings::bpf_user_pt_regs_t
+pub aya_ebpf_bindings::bindings::bpf_perf_event_data::sample_period: aya_ebpf_bindings::bindings::__u64
impl core::clone::Clone for aya_ebpf_bindings::bindings::bpf_perf_event_data
pub fn aya_ebpf_bindings::bindings::bpf_perf_event_data::clone(&self) -> aya_ebpf_bindings::bindings::bpf_perf_event_data
impl core::fmt::Debug for aya_ebpf_bindings::bindings::bpf_perf_event_data
@@ -7057,6 +7060,7 @@ pub type aya_ebpf_bindings::bindings::_bindgen_ty_6 = aya_ebpf_cty::ad::c_uint
pub type aya_ebpf_bindings::bindings::_bindgen_ty_7 = aya_ebpf_cty::ad::c_uint
pub type aya_ebpf_bindings::bindings::_bindgen_ty_8 = aya_ebpf_cty::ad::c_uint
pub type aya_ebpf_bindings::bindings::_bindgen_ty_9 = aya_ebpf_cty::ad::c_uint
+pub type aya_ebpf_bindings::bindings::bpf_user_pt_regs_t = aya_ebpf_bindings::bindings::pt_regs
pub type aya_ebpf_bindings::bindings::sa_family_t = aya_ebpf_cty::c_ushort
pub mod aya_ebpf_bindings::helpers
pub unsafe fn aya_ebpf_bindings::helpers::bpf_bind(ctx: *mut aya_ebpf_bindings::bindings::bpf_sock_addr, addr: *mut aya_ebpf_bindings::bindings::sockaddr, addr_len: aya_ebpf_cty::ad::c_int) -> aya_ebpf_cty::od::c_long
diff --git a/xtask/public-api/aya-ebpf.txt b/xtask/public-api/aya-ebpf.txt
index a78b1758..b8e672ee 100644
--- a/xtask/public-api/aya-ebpf.txt
+++ b/xtask/public-api/aya-ebpf.txt
@@ -1723,8 +1723,9 @@ impl core::convert::From for aya_ebpf::programs::lsm::LsmContext
pub fn aya_ebpf::programs::lsm::LsmContext::from(t: T) -> T
pub mod aya_ebpf::programs::perf_event
pub struct aya_ebpf::programs::perf_event::PerfEventContext
+pub aya_ebpf::programs::perf_event::PerfEventContext::ctx: *mut aya_ebpf_bindings::x86_64::bindings::bpf_perf_event_data
impl aya_ebpf::programs::perf_event::PerfEventContext
-pub fn aya_ebpf::programs::perf_event::PerfEventContext::new(ctx: *mut core::ffi::c_void) -> Self
+pub fn aya_ebpf::programs::perf_event::PerfEventContext::new(ctx: *mut aya_ebpf_bindings::x86_64::bindings::bpf_perf_event_data) -> Self
impl aya_ebpf::EbpfContext for aya_ebpf::programs::perf_event::PerfEventContext
pub fn aya_ebpf::programs::perf_event::PerfEventContext::as_ptr(&self) -> *mut core::ffi::c_void
impl core::marker::Freeze for aya_ebpf::programs::perf_event::PerfEventContext
@@ -2461,8 +2462,9 @@ pub fn aya_ebpf::programs::lsm::LsmContext::borrow_mut(&mut self) -> &mut T
impl core::convert::From for aya_ebpf::programs::lsm::LsmContext
pub fn aya_ebpf::programs::lsm::LsmContext::from(t: T) -> T
pub struct aya_ebpf::programs::PerfEventContext
+pub aya_ebpf::programs::PerfEventContext::ctx: *mut aya_ebpf_bindings::x86_64::bindings::bpf_perf_event_data
impl aya_ebpf::programs::perf_event::PerfEventContext
-pub fn aya_ebpf::programs::perf_event::PerfEventContext::new(ctx: *mut core::ffi::c_void) -> Self
+pub fn aya_ebpf::programs::perf_event::PerfEventContext::new(ctx: *mut aya_ebpf_bindings::x86_64::bindings::bpf_perf_event_data) -> Self
impl aya_ebpf::EbpfContext for aya_ebpf::programs::perf_event::PerfEventContext
pub fn aya_ebpf::programs::perf_event::PerfEventContext::as_ptr(&self) -> *mut core::ffi::c_void
impl core::marker::Freeze for aya_ebpf::programs::perf_event::PerfEventContext
diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt
index 8406f83a..5e59c5ea 100644
--- a/xtask/public-api/aya-obj.txt
+++ b/xtask/public-api/aya-obj.txt
@@ -8057,24 +8057,38 @@ pub const aya_obj::generated::BTF_KIND_VOLATILE: aya_obj::generated::_bindgen_ty
pub const aya_obj::generated::BTF_VAR_GLOBAL_ALLOCATED: aya_obj::generated::_bindgen_ty_43
pub const aya_obj::generated::BTF_VAR_GLOBAL_EXTERN: aya_obj::generated::_bindgen_ty_43
pub const aya_obj::generated::BTF_VAR_STATIC: aya_obj::generated::_bindgen_ty_43
-pub const aya_obj::generated::IFLA_XDP_ATTACHED: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_DRV_PROG_ID: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_EXPECTED_FD: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_FD: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_FLAGS: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_HW_PROG_ID: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_PROG_ID: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_SKB_PROG_ID: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::IFLA_XDP_UNSPEC: aya_obj::generated::_bindgen_ty_92
-pub const aya_obj::generated::NFPROTO_ARP: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_BRIDGE: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_DECNET: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_INET: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_IPV4: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_IPV6: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_NETDEV: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_NUMPROTO: aya_obj::generated::_bindgen_ty_99
-pub const aya_obj::generated::NFPROTO_UNSPEC: aya_obj::generated::_bindgen_ty_99
+pub const aya_obj::generated::HW_BREAKPOINT_EMPTY: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::HW_BREAKPOINT_INVALID: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_1: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_2: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_3: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_4: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_5: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_6: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_7: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_LEN_8: aya_obj::generated::_bindgen_ty_44
+pub const aya_obj::generated::HW_BREAKPOINT_R: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::HW_BREAKPOINT_RW: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::HW_BREAKPOINT_W: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::HW_BREAKPOINT_X: aya_obj::generated::_bindgen_ty_45
+pub const aya_obj::generated::IFLA_XDP_ATTACHED: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_DRV_PROG_ID: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_EXPECTED_FD: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_FD: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_FLAGS: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_HW_PROG_ID: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_PROG_ID: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_SKB_PROG_ID: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::IFLA_XDP_UNSPEC: aya_obj::generated::_bindgen_ty_94
+pub const aya_obj::generated::NFPROTO_ARP: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_BRIDGE: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_DECNET: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_INET: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_IPV4: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_IPV6: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_NETDEV: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_NUMPROTO: aya_obj::generated::_bindgen_ty_101
+pub const aya_obj::generated::NFPROTO_UNSPEC: aya_obj::generated::_bindgen_ty_101
pub const aya_obj::generated::NLMSG_ALIGNTO: u32
pub const aya_obj::generated::NR_BTF_KINDS: aya_obj::generated::_bindgen_ty_42
pub const aya_obj::generated::PERF_EVENT_IOC_DISABLE: u32
@@ -8097,36 +8111,36 @@ pub const aya_obj::generated::PERF_MAX_CONTEXTS_PER_STACK: u32
pub const aya_obj::generated::PERF_MAX_STACK_DEPTH: u32
pub const aya_obj::generated::SO_ATTACH_BPF: u32
pub const aya_obj::generated::SO_DETACH_BPF: u32
-pub const aya_obj::generated::TCA_BPF_ACT: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_CLASSID: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_FD: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_FLAGS: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_FLAGS_GEN: aya_obj::generated::_bindgen_ty_154
+pub const aya_obj::generated::TCA_BPF_ACT: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_CLASSID: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_FD: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_FLAGS: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_FLAGS_GEN: aya_obj::generated::_bindgen_ty_156
pub const aya_obj::generated::TCA_BPF_FLAG_ACT_DIRECT: u32
-pub const aya_obj::generated::TCA_BPF_ID: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_NAME: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_OPS: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_OPS_LEN: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_POLICE: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_TAG: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_BPF_UNSPEC: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::TCA_CHAIN: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_DUMP_FLAGS: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_DUMP_INVISIBLE: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_EGRESS_BLOCK: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_EXT_WARN_MSG: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_FCNT: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_HW_OFFLOAD: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_INGRESS_BLOCK: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_KIND: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_OPTIONS: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_PAD: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_RATE: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_STAB: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_STATS: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_STATS2: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_UNSPEC: aya_obj::generated::_bindgen_ty_174
-pub const aya_obj::generated::TCA_XSTATS: aya_obj::generated::_bindgen_ty_174
+pub const aya_obj::generated::TCA_BPF_ID: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_NAME: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_OPS: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_OPS_LEN: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_POLICE: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_TAG: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_BPF_UNSPEC: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::TCA_CHAIN: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_DUMP_FLAGS: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_DUMP_INVISIBLE: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_EGRESS_BLOCK: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_EXT_WARN_MSG: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_FCNT: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_HW_OFFLOAD: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_INGRESS_BLOCK: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_KIND: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_OPTIONS: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_PAD: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_RATE: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_STAB: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_STATS: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_STATS2: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_UNSPEC: aya_obj::generated::_bindgen_ty_176
+pub const aya_obj::generated::TCA_XSTATS: aya_obj::generated::_bindgen_ty_176
pub const aya_obj::generated::TC_H_CLSACT: u32
pub const aya_obj::generated::TC_H_INGRESS: u32
pub const aya_obj::generated::TC_H_MAJ_MASK: u32
@@ -8143,10 +8157,10 @@ pub const aya_obj::generated::XDP_FLAGS_MODES: u32
pub const aya_obj::generated::XDP_FLAGS_REPLACE: u32
pub const aya_obj::generated::XDP_FLAGS_SKB_MODE: u32
pub const aya_obj::generated::XDP_FLAGS_UPDATE_IF_NOEXIST: u32
-pub const aya_obj::generated::__IFLA_XDP_MAX: aya_obj::generated::_bindgen_ty_92
+pub const aya_obj::generated::__IFLA_XDP_MAX: aya_obj::generated::_bindgen_ty_94
pub const aya_obj::generated::__MAX_BPF_REG: aya_obj::generated::_bindgen_ty_1
-pub const aya_obj::generated::__TCA_BPF_MAX: aya_obj::generated::_bindgen_ty_154
-pub const aya_obj::generated::__TCA_MAX: aya_obj::generated::_bindgen_ty_174
+pub const aya_obj::generated::__TCA_BPF_MAX: aya_obj::generated::_bindgen_ty_156
+pub const aya_obj::generated::__TCA_MAX: aya_obj::generated::_bindgen_ty_176
pub type aya_obj::generated::__s16 = core::ffi::primitives::c_short
pub type aya_obj::generated::__s32 = core::ffi::primitives::c_int
pub type aya_obj::generated::__s64 = core::ffi::primitives::c_longlong
@@ -8155,14 +8169,15 @@ pub type aya_obj::generated::__u32 = core::ffi::primitives::c_uint
pub type aya_obj::generated::__u64 = core::ffi::primitives::c_ulonglong
pub type aya_obj::generated::__u8 = core::ffi::primitives::c_uchar
pub type aya_obj::generated::_bindgen_ty_10 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_101 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_11 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_12 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_13 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_14 = core::ffi::primitives::c_ulong
pub type aya_obj::generated::_bindgen_ty_15 = core::ffi::primitives::c_int
-pub type aya_obj::generated::_bindgen_ty_154 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_156 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_17 = core::ffi::primitives::c_uint
-pub type aya_obj::generated::_bindgen_ty_174 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_176 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_19 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_2 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_21 = core::ffi::primitives::c_uint
@@ -8174,13 +8189,14 @@ pub type aya_obj::generated::_bindgen_ty_4 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_41 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_42 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_43 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_44 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_45 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_5 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_6 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_7 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_8 = core::ffi::primitives::c_uint
pub type aya_obj::generated::_bindgen_ty_9 = core::ffi::primitives::c_uint
-pub type aya_obj::generated::_bindgen_ty_92 = core::ffi::primitives::c_uint
-pub type aya_obj::generated::_bindgen_ty_99 = core::ffi::primitives::c_uint
+pub type aya_obj::generated::_bindgen_ty_94 = core::ffi::primitives::c_uint
pub mod aya_obj::links
pub mod aya_obj::maps
pub enum aya_obj::maps::Map
diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt
index 60309344..3b6618be 100644
--- a/xtask/public-api/aya.txt
+++ b/xtask/public-api/aya.txt
@@ -4781,10 +4781,6 @@ impl aya::programs::links::Link for aya::programs::lsm_cgroup::LsmLink
pub type aya::programs::lsm_cgroup::LsmLink::Id = aya::programs::lsm_cgroup::LsmLinkId
pub fn aya::programs::lsm_cgroup::LsmLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
pub fn aya::programs::lsm_cgroup::LsmLink::id(&self) -> Self::Id
-impl aya::programs::links::Link for aya::programs::perf_attach::PerfLink
-pub type aya::programs::perf_attach::PerfLink::Id = aya::programs::perf_attach::PerfLinkId
-pub fn aya::programs::perf_attach::PerfLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
-pub fn aya::programs::perf_attach::PerfLink::id(&self) -> Self::Id
impl aya::programs::links::Link for aya::programs::perf_event::PerfEventLink
pub type aya::programs::perf_event::PerfEventLink::Id = aya::programs::perf_event::PerfEventLinkId
pub fn aya::programs::perf_event::PerfEventLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
@@ -5225,44 +5221,6 @@ pub fn aya::programs::lsm_cgroup::LsmLinkId::borrow_mut(&mut self) -> &mut T
impl core::convert::From for aya::programs::lsm_cgroup::LsmLinkId
pub fn aya::programs::lsm_cgroup::LsmLinkId::from(t: T) -> T
pub mod aya::programs::perf_attach
-pub struct aya::programs::perf_attach::PerfLink
-impl aya::programs::links::Link for aya::programs::perf_attach::PerfLink
-pub type aya::programs::perf_attach::PerfLink::Id = aya::programs::perf_attach::PerfLinkId
-pub fn aya::programs::perf_attach::PerfLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
-pub fn aya::programs::perf_attach::PerfLink::id(&self) -> Self::Id
-impl core::cmp::Eq for aya::programs::perf_attach::PerfLink
-impl core::cmp::PartialEq for aya::programs::perf_attach::PerfLink
-pub fn aya::programs::perf_attach::PerfLink::eq(&self, other: &Self) -> bool
-impl core::fmt::Debug for aya::programs::perf_attach::PerfLink
-pub fn aya::programs::perf_attach::PerfLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-impl core::hash::Hash for aya::programs::perf_attach::PerfLink
-pub fn aya::programs::perf_attach::PerfLink::hash(&self, state: &mut H)
-impl equivalent::Equivalent for aya::programs::perf_attach::PerfLinkId
-pub fn aya::programs::perf_attach::PerfLinkId::equivalent(&self, key: &aya::programs::perf_attach::PerfLink) -> bool
-impl core::marker::Freeze for aya::programs::perf_attach::PerfLink
-impl core::marker::Send for aya::programs::perf_attach::PerfLink
-impl core::marker::Sync for aya::programs::perf_attach::PerfLink
-impl core::marker::Unpin for aya::programs::perf_attach::PerfLink
-impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_attach::PerfLink
-impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_attach::PerfLink
-impl equivalent::Equivalent for aya::programs::perf_attach::PerfLink where Q: core::cmp::Eq + ?core::marker::Sized, K: core::borrow::Borrow + ?core::marker::Sized
-pub fn aya::programs::perf_attach::PerfLink::equivalent(&self, key: &K) -> bool
-impl core::convert::Into for aya::programs::perf_attach::PerfLink where U: core::convert::From
-pub fn aya::programs::perf_attach::PerfLink::into(self) -> U
-impl core::convert::TryFrom for aya::programs::perf_attach::PerfLink where U: core::convert::Into
-pub type aya::programs::perf_attach::PerfLink::Error = core::convert::Infallible
-pub fn aya::programs::perf_attach::PerfLink::try_from(value: U) -> core::result::Result>::Error>
-impl core::convert::TryInto for aya::programs::perf_attach::PerfLink where U: core::convert::TryFrom
-pub type aya::programs::perf_attach::PerfLink::Error = >::Error
-pub fn aya::programs::perf_attach::PerfLink::try_into(self) -> core::result::Result>::Error>
-impl core::any::Any for aya::programs::perf_attach::PerfLink where T: 'static + ?core::marker::Sized
-pub fn aya::programs::perf_attach::PerfLink::type_id(&self) -> core::any::TypeId
-impl core::borrow::Borrow for aya::programs::perf_attach::PerfLink where T: ?core::marker::Sized
-pub fn aya::programs::perf_attach::PerfLink::borrow(&self) -> &T
-impl core::borrow::BorrowMut for aya::programs::perf_attach::PerfLink where T: ?core::marker::Sized
-pub fn aya::programs::perf_attach::PerfLink::borrow_mut(&mut self) -> &mut T
-impl core::convert::From for aya::programs::perf_attach::PerfLink
-pub fn aya::programs::perf_attach::PerfLink::from(t: T) -> T
pub struct aya::programs::perf_attach::PerfLinkId(_)
impl core::cmp::Eq for aya::programs::perf_attach::PerfLinkId
impl core::cmp::PartialEq for aya::programs::perf_attach::PerfLinkId
@@ -5272,8 +5230,6 @@ pub fn aya::programs::perf_attach::PerfLinkId::fmt(&self, f: &mut core::fmt::For
impl core::hash::Hash for aya::programs::perf_attach::PerfLinkId
pub fn aya::programs::perf_attach::PerfLinkId::hash<__H: core::hash::Hasher>(&self, state: &mut __H)
impl core::marker::StructuralPartialEq for aya::programs::perf_attach::PerfLinkId
-impl equivalent::Equivalent for aya::programs::perf_attach::PerfLinkId
-pub fn aya::programs::perf_attach::PerfLinkId::equivalent(&self, key: &aya::programs::perf_attach::PerfLink) -> bool
impl core::marker::Freeze for aya::programs::perf_attach::PerfLinkId
impl core::marker::Send for aya::programs::perf_attach::PerfLinkId
impl core::marker::Sync for aya::programs::perf_attach::PerfLinkId
@@ -5299,6 +5255,46 @@ pub fn aya::programs::perf_attach::PerfLinkId::borrow_mut(&mut self) -> &mut T
impl core::convert::From for aya::programs::perf_attach::PerfLinkId
pub fn aya::programs::perf_attach::PerfLinkId::from(t: T) -> T
pub mod aya::programs::perf_event
+pub enum aya::programs::perf_event::BreakpointConfig
+pub aya::programs::perf_event::BreakpointConfig::Data
+pub aya::programs::perf_event::BreakpointConfig::Data::address: u64
+pub aya::programs::perf_event::BreakpointConfig::Data::length: aya::programs::perf_event::PerfBreakpointLength
+pub aya::programs::perf_event::BreakpointConfig::Data::type: aya::programs::perf_event::PerfBreakpointType
+pub aya::programs::perf_event::BreakpointConfig::Instruction
+pub aya::programs::perf_event::BreakpointConfig::Instruction::address: u64
+impl core::clone::Clone for aya::programs::perf_event::BreakpointConfig
+pub fn aya::programs::perf_event::BreakpointConfig::clone(&self) -> aya::programs::perf_event::BreakpointConfig
+impl core::fmt::Debug for aya::programs::perf_event::BreakpointConfig
+pub fn aya::programs::perf_event::BreakpointConfig::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::marker::Copy for aya::programs::perf_event::BreakpointConfig
+impl core::marker::Freeze for aya::programs::perf_event::BreakpointConfig
+impl core::marker::Send for aya::programs::perf_event::BreakpointConfig
+impl core::marker::Sync for aya::programs::perf_event::BreakpointConfig
+impl core::marker::Unpin for aya::programs::perf_event::BreakpointConfig
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::BreakpointConfig
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::BreakpointConfig
+impl core::convert::Into for aya::programs::perf_event::BreakpointConfig where U: core::convert::From
+pub fn aya::programs::perf_event::BreakpointConfig::into(self) -> U
+impl core::convert::TryFrom for aya::programs::perf_event::BreakpointConfig where U: core::convert::Into
+pub type aya::programs::perf_event::BreakpointConfig::Error = core::convert::Infallible
+pub fn aya::programs::perf_event::BreakpointConfig::try_from(value: U) -> core::result::Result>::Error>
+impl core::convert::TryInto for aya::programs::perf_event::BreakpointConfig where U: core::convert::TryFrom
+pub type aya::programs::perf_event::BreakpointConfig::Error = >::Error
+pub fn aya::programs::perf_event::BreakpointConfig::try_into(self) -> core::result::Result>::Error>
+impl alloc::borrow::ToOwned for aya::programs::perf_event::BreakpointConfig where T: core::clone::Clone
+pub type aya::programs::perf_event::BreakpointConfig::Owned = T
+pub fn aya::programs::perf_event::BreakpointConfig::clone_into(&self, target: &mut T)
+pub fn aya::programs::perf_event::BreakpointConfig::to_owned(&self) -> T
+impl core::any::Any for aya::programs::perf_event::BreakpointConfig where T: 'static + ?core::marker::Sized
+pub fn aya::programs::perf_event::BreakpointConfig::type_id(&self) -> core::any::TypeId
+impl core::borrow::Borrow for aya::programs::perf_event::BreakpointConfig where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::BreakpointConfig::borrow(&self) -> &T
+impl core::borrow::BorrowMut for aya::programs::perf_event::BreakpointConfig where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::BreakpointConfig::borrow_mut(&mut self) -> &mut T
+impl core::clone::CloneToUninit for aya::programs::perf_event::BreakpointConfig where T: core::clone::Clone
+pub unsafe fn aya::programs::perf_event::BreakpointConfig::clone_to_uninit(&self, dest: *mut u8)
+impl core::convert::From for aya::programs::perf_event::BreakpointConfig
+pub fn aya::programs::perf_event::BreakpointConfig::from(t: T) -> T
#[repr(u32)] pub enum aya::programs::perf_event::HardwareEvent
pub aya::programs::perf_event::HardwareEvent::BranchInstructions = 4
pub aya::programs::perf_event::HardwareEvent::BranchMisses = 5
@@ -5457,8 +5453,83 @@ impl core::clone::CloneToUninit for aya::programs::perf_event::HwCacheResult
pub unsafe fn aya::programs::perf_event::HwCacheResult::clone_to_uninit(&self, dest: *mut u8)
impl core::convert::From for aya::programs::perf_event::HwCacheResult
pub fn aya::programs::perf_event::HwCacheResult::from(t: T) -> T
+#[repr(u32)] pub enum aya::programs::perf_event::PerfBreakpointLength
+pub aya::programs::perf_event::PerfBreakpointLength::Len1 = 1
+pub aya::programs::perf_event::PerfBreakpointLength::Len2 = 2
+pub aya::programs::perf_event::PerfBreakpointLength::Len4 = 4
+pub aya::programs::perf_event::PerfBreakpointLength::Len8 = 8
+impl core::clone::Clone for aya::programs::perf_event::PerfBreakpointLength
+pub fn aya::programs::perf_event::PerfBreakpointLength::clone(&self) -> aya::programs::perf_event::PerfBreakpointLength
+impl core::fmt::Debug for aya::programs::perf_event::PerfBreakpointLength
+pub fn aya::programs::perf_event::PerfBreakpointLength::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::marker::Copy for aya::programs::perf_event::PerfBreakpointLength
+impl core::marker::Freeze for aya::programs::perf_event::PerfBreakpointLength
+impl core::marker::Send for aya::programs::perf_event::PerfBreakpointLength
+impl core::marker::Sync for aya::programs::perf_event::PerfBreakpointLength
+impl core::marker::Unpin for aya::programs::perf_event::PerfBreakpointLength
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfBreakpointLength
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfBreakpointLength
+impl core::convert::Into for aya::programs::perf_event::PerfBreakpointLength where U: core::convert::From
+pub fn aya::programs::perf_event::PerfBreakpointLength::into(self) -> U
+impl core::convert::TryFrom for aya::programs::perf_event::PerfBreakpointLength where U: core::convert::Into
+pub type aya::programs::perf_event::PerfBreakpointLength::Error = core::convert::Infallible
+pub fn aya::programs::perf_event::PerfBreakpointLength::try_from(value: U) -> core::result::Result>::Error>
+impl core::convert::TryInto for aya::programs::perf_event::PerfBreakpointLength where U: core::convert::TryFrom
+pub type aya::programs::perf_event::PerfBreakpointLength::Error = >::Error
+pub fn aya::programs::perf_event::PerfBreakpointLength::try_into(self) -> core::result::Result>::Error>
+impl alloc::borrow::ToOwned for aya::programs::perf_event::PerfBreakpointLength where T: core::clone::Clone
+pub type aya::programs::perf_event::PerfBreakpointLength::Owned = T
+pub fn aya::programs::perf_event::PerfBreakpointLength::clone_into(&self, target: &mut T)
+pub fn aya::programs::perf_event::PerfBreakpointLength::to_owned(&self) -> T
+impl core::any::Any for aya::programs::perf_event::PerfBreakpointLength where T: 'static + ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointLength::type_id(&self) -> core::any::TypeId
+impl core::borrow::Borrow for aya::programs::perf_event::PerfBreakpointLength where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointLength::borrow(&self) -> &T
+impl core::borrow::BorrowMut for aya::programs::perf_event::PerfBreakpointLength where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointLength::borrow_mut(&mut self) -> &mut T
+impl core::clone::CloneToUninit for aya::programs::perf_event::PerfBreakpointLength where T: core::clone::Clone
+pub unsafe fn aya::programs::perf_event::PerfBreakpointLength::clone_to_uninit(&self, dest: *mut u8)
+impl core::convert::From for aya::programs::perf_event::PerfBreakpointLength
+pub fn aya::programs::perf_event::PerfBreakpointLength::from(t: T) -> T
+#[repr(u32)] pub enum aya::programs::perf_event::PerfBreakpointType
+pub aya::programs::perf_event::PerfBreakpointType::Read = 1
+pub aya::programs::perf_event::PerfBreakpointType::ReadWrite = 3
+pub aya::programs::perf_event::PerfBreakpointType::Write = 2
+impl core::clone::Clone for aya::programs::perf_event::PerfBreakpointType
+pub fn aya::programs::perf_event::PerfBreakpointType::clone(&self) -> aya::programs::perf_event::PerfBreakpointType
+impl core::fmt::Debug for aya::programs::perf_event::PerfBreakpointType
+pub fn aya::programs::perf_event::PerfBreakpointType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::marker::Copy for aya::programs::perf_event::PerfBreakpointType
+impl core::marker::Freeze for aya::programs::perf_event::PerfBreakpointType
+impl core::marker::Send for aya::programs::perf_event::PerfBreakpointType
+impl core::marker::Sync for aya::programs::perf_event::PerfBreakpointType
+impl core::marker::Unpin for aya::programs::perf_event::PerfBreakpointType
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfBreakpointType
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfBreakpointType
+impl core::convert::Into for aya::programs::perf_event::PerfBreakpointType where U: core::convert::From
+pub fn aya::programs::perf_event::PerfBreakpointType::into(self) -> U
+impl core::convert::TryFrom for aya::programs::perf_event::PerfBreakpointType where U: core::convert::Into
+pub type aya::programs::perf_event::PerfBreakpointType::Error = core::convert::Infallible
+pub fn aya::programs::perf_event::PerfBreakpointType::try_from(value: U) -> core::result::Result>::Error>
+impl core::convert::TryInto for aya::programs::perf_event::PerfBreakpointType where U: core::convert::TryFrom
+pub type aya::programs::perf_event::PerfBreakpointType::Error = >::Error
+pub fn aya::programs::perf_event::PerfBreakpointType::try_into(self) -> core::result::Result>::Error>
+impl alloc::borrow::ToOwned for aya::programs::perf_event::PerfBreakpointType where T: core::clone::Clone
+pub type aya::programs::perf_event::PerfBreakpointType::Owned = T
+pub fn aya::programs::perf_event::PerfBreakpointType::clone_into(&self, target: &mut T)
+pub fn aya::programs::perf_event::PerfBreakpointType::to_owned(&self) -> T
+impl core::any::Any for aya::programs::perf_event::PerfBreakpointType where T: 'static + ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointType::type_id(&self) -> core::any::TypeId
+impl core::borrow::Borrow for aya::programs::perf_event::PerfBreakpointType where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointType::borrow(&self) -> &T
+impl core::borrow::BorrowMut for aya::programs::perf_event::PerfBreakpointType where T: ?core::marker::Sized
+pub fn aya::programs::perf_event::PerfBreakpointType::borrow_mut(&mut self) -> &mut T
+impl core::clone::CloneToUninit for aya::programs::perf_event::PerfBreakpointType where T: core::clone::Clone
+pub unsafe fn aya::programs::perf_event::PerfBreakpointType::clone_to_uninit(&self, dest: *mut u8)
+impl core::convert::From for aya::programs::perf_event::PerfBreakpointType
+pub fn aya::programs::perf_event::PerfBreakpointType::from(t: T) -> T
pub enum aya::programs::perf_event::PerfEventConfig
-pub aya::programs::perf_event::PerfEventConfig::Breakpoint
+pub aya::programs::perf_event::PerfEventConfig::Breakpoint(aya::programs::perf_event::BreakpointConfig)
pub aya::programs::perf_event::PerfEventConfig::Hardware(aya::programs::perf_event::HardwareEvent)
pub aya::programs::perf_event::PerfEventConfig::HwCache
pub aya::programs::perf_event::PerfEventConfig::HwCache::event: aya::programs::perf_event::HwCacheEvent
@@ -5508,18 +5579,16 @@ pub fn aya::programs::perf_event::PerfEventConfig::from(t: T) -> T
pub enum aya::programs::perf_event::PerfEventScope
pub aya::programs::perf_event::PerfEventScope::AllProcessesOneCpu
pub aya::programs::perf_event::PerfEventScope::AllProcessesOneCpu::cpu: u32
-pub aya::programs::perf_event::PerfEventScope::CallingProcessAnyCpu
-pub aya::programs::perf_event::PerfEventScope::CallingProcessOneCpu
-pub aya::programs::perf_event::PerfEventScope::CallingProcessOneCpu::cpu: u32
-pub aya::programs::perf_event::PerfEventScope::OneProcessAnyCpu
-pub aya::programs::perf_event::PerfEventScope::OneProcessAnyCpu::pid: u32
-pub aya::programs::perf_event::PerfEventScope::OneProcessOneCpu
-pub aya::programs::perf_event::PerfEventScope::OneProcessOneCpu::cpu: u32
-pub aya::programs::perf_event::PerfEventScope::OneProcessOneCpu::pid: u32
+pub aya::programs::perf_event::PerfEventScope::CallingProcess
+pub aya::programs::perf_event::PerfEventScope::CallingProcess::cpu: core::option::Option
+pub aya::programs::perf_event::PerfEventScope::OneProcess
+pub aya::programs::perf_event::PerfEventScope::OneProcess::cpu: core::option::Option
+pub aya::programs::perf_event::PerfEventScope::OneProcess::pid: u32
impl core::clone::Clone for aya::programs::perf_event::PerfEventScope
pub fn aya::programs::perf_event::PerfEventScope::clone(&self) -> aya::programs::perf_event::PerfEventScope
impl core::fmt::Debug for aya::programs::perf_event::PerfEventScope
pub fn aya::programs::perf_event::PerfEventScope::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::marker::Copy for aya::programs::perf_event::PerfEventScope
impl core::marker::Freeze for aya::programs::perf_event::PerfEventScope
impl core::marker::Send for aya::programs::perf_event::PerfEventScope
impl core::marker::Sync for aya::programs::perf_event::PerfEventScope
@@ -5555,6 +5624,7 @@ impl core::clone::Clone for aya::programs::perf_event::SamplePolicy
pub fn aya::programs::perf_event::SamplePolicy::clone(&self) -> aya::programs::perf_event::SamplePolicy
impl core::fmt::Debug for aya::programs::perf_event::SamplePolicy
pub fn aya::programs::perf_event::SamplePolicy::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::marker::Copy for aya::programs::perf_event::SamplePolicy
impl core::marker::Freeze for aya::programs::perf_event::SamplePolicy
impl core::marker::Send for aya::programs::perf_event::SamplePolicy
impl core::marker::Sync for aya::programs::perf_event::SamplePolicy
@@ -5632,7 +5702,7 @@ pub fn aya::programs::perf_event::SoftwareEvent::from(t: T) -> T
pub struct aya::programs::perf_event::PerfEvent
impl aya::programs::perf_event::PerfEvent
pub const aya::programs::perf_event::PerfEvent::PROGRAM_TYPE: aya::programs::ProgramType
-pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, perf_type: aya::programs::perf_event::PerfEventConfig, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result
+pub fn aya::programs::perf_event::PerfEvent::attach(&mut self, config: aya::programs::perf_event::PerfEventConfig, scope: aya::programs::perf_event::PerfEventScope, sample_policy: aya::programs::perf_event::SamplePolicy, inherit: bool) -> core::result::Result
pub fn aya::programs::perf_event::PerfEvent::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
impl aya::programs::perf_event::PerfEvent
pub fn aya::programs::perf_event::PerfEvent::detach(&mut self, link_id: aya::programs::perf_event::PerfEventLinkId) -> core::result::Result<(), aya::programs::ProgramError>
@@ -7304,7 +7374,7 @@ pub aya::programs::uprobe::UProbeError::InvalidLdSoCache::io_error: &'static std
pub aya::programs::uprobe::UProbeError::InvalidTarget
pub aya::programs::uprobe::UProbeError::InvalidTarget::path: std::path::PathBuf
pub aya::programs::uprobe::UProbeError::ProcMap
-pub aya::programs::uprobe::UProbeError::ProcMap::pid: i32
+pub aya::programs::uprobe::UProbeError::ProcMap::pid: u32
pub aya::programs::uprobe::UProbeError::ProcMap::source: aya::programs::uprobe::ProcMapError
pub aya::programs::uprobe::UProbeError::SymbolError
pub aya::programs::uprobe::UProbeError::SymbolError::error: alloc::boxed::Box<(dyn core::error::Error + core::marker::Send + core::marker::Sync)>
@@ -7344,7 +7414,7 @@ pub fn aya::programs::uprobe::UProbeError::from(t: T) -> T
pub struct aya::programs::uprobe::UProbe
impl aya::programs::uprobe::UProbe
pub const aya::programs::uprobe::UProbe::PROGRAM_TYPE: aya::programs::ProgramType
-pub fn aya::programs::uprobe::UProbe::attach<'loc, T: core::convert::AsRef, Loc: core::convert::Into>>(&mut self, location: Loc, target: T, pid: core::option::Option, cookie: core::option::Option) -> core::result::Result
+pub fn aya::programs::uprobe::UProbe::attach<'loc, T: core::convert::AsRef, Loc: core::convert::Into>>(&mut self, location: Loc, target: T, pid: core::option::Option, cookie: core::option::Option) -> core::result::Result
pub fn aya::programs::uprobe::UProbe::from_pin>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result
pub fn aya::programs::uprobe::UProbe::kind(&self) -> aya::programs::ProbeKind
pub fn aya::programs::uprobe::UProbe::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
@@ -7943,54 +8013,9 @@ impl core::clone::CloneToUninit for aya::programs::LsmAttachType where T: cor
pub unsafe fn aya::programs::LsmAttachType::clone_to_uninit(&self, dest: *mut u8)
impl core::convert::From for aya::programs::LsmAttachType
pub fn aya::programs::LsmAttachType::from(t: T) -> T
-pub enum aya::programs::PerfEventScope
-pub aya::programs::PerfEventScope::AllProcessesOneCpu
-pub aya::programs::PerfEventScope::AllProcessesOneCpu::cpu: u32
-pub aya::programs::PerfEventScope::CallingProcessAnyCpu
-pub aya::programs::PerfEventScope::CallingProcessOneCpu
-pub aya::programs::PerfEventScope::CallingProcessOneCpu::cpu: u32
-pub aya::programs::PerfEventScope::OneProcessAnyCpu
-pub aya::programs::PerfEventScope::OneProcessAnyCpu::pid: u32
-pub aya::programs::PerfEventScope::OneProcessOneCpu
-pub aya::programs::PerfEventScope::OneProcessOneCpu::cpu: u32
-pub aya::programs::PerfEventScope::OneProcessOneCpu::pid: u32
-impl core::clone::Clone for aya::programs::perf_event::PerfEventScope
-pub fn aya::programs::perf_event::PerfEventScope::clone(&self) -> aya::programs::perf_event::PerfEventScope
-impl core::fmt::Debug for aya::programs::perf_event::PerfEventScope
-pub fn aya::programs::perf_event::PerfEventScope::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
-impl core::marker::Freeze for aya::programs::perf_event::PerfEventScope
-impl core::marker::Send for aya::programs::perf_event::PerfEventScope
-impl core::marker::Sync for aya::programs::perf_event::PerfEventScope
-impl core::marker::Unpin for aya::programs::perf_event::PerfEventScope
-impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::perf_event::PerfEventScope
-impl core::panic::unwind_safe::UnwindSafe for aya::programs::perf_event::PerfEventScope
-impl core::convert::Into for aya::programs::perf_event::PerfEventScope where U: core::convert::From
-pub fn aya::programs::perf_event::PerfEventScope::into(self) -> U
-impl core::convert::TryFrom for aya::programs::perf_event::PerfEventScope where U: core::convert::Into