diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 7d3044267..4f115024b 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -288,6 +288,9 @@ pub enum ProgramSection { attach_type: CgroupSockAttachType, }, CgroupDevice, + Iter { + sleepable: bool, + }, } impl FromStr for ProgramSection { @@ -439,6 +442,8 @@ impl FromStr for ProgramSection { "fexit.s" => FExit { sleepable: true }, "freplace" => Extension, "sk_lookup" => SkLookup, + "iter" => Iter { sleepable: false }, + "iter.s" => Iter { sleepable: true }, _ => { return Err(ParseError::InvalidProgramSection { section: section.to_owned(), diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 357232ac5..b812f6f27 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -31,9 +31,9 @@ use crate::{ }, programs::{ BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr, - CgroupSockopt, CgroupSysctl, Extension, FEntry, FExit, KProbe, LircMode2, Lsm, PerfEvent, - ProbeKind, Program, ProgramData, ProgramError, RawTracePoint, SchedClassifier, SkLookup, - SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, + CgroupSockopt, CgroupSysctl, Extension, FEntry, FExit, Iter, KProbe, LircMode2, Lsm, + PerfEvent, ProbeKind, Program, ProgramData, ProgramError, RawTracePoint, SchedClassifier, + SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, }, sys::{ bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported, @@ -410,7 +410,8 @@ impl<'a> EbpfLoader<'a> { | ProgramSection::FEntry { sleepable: _ } | ProgramSection::FExit { sleepable: _ } | ProgramSection::Lsm { sleepable: _ } - | ProgramSection::BtfTracePoint => { + | ProgramSection::BtfTracePoint + | ProgramSection::Iter { sleepable: _ } => { return Err(EbpfError::BtfError(err)) } ProgramSection::KRetProbe @@ -688,6 +689,14 @@ impl<'a> EbpfLoader<'a> { ProgramSection::CgroupDevice => Program::CgroupDevice(CgroupDevice { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), + ProgramSection::Iter { sleepable } => { + let mut data = + ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); + if *sleepable { + data.flags = BPF_F_SLEEPABLE; + } + Program::Iter(Iter { data }) + } } }; (name, program) diff --git a/aya/src/programs/iter.rs b/aya/src/programs/iter.rs new file mode 100644 index 000000000..901105357 --- /dev/null +++ b/aya/src/programs/iter.rs @@ -0,0 +1,164 @@ +//! Iterators. +use std::{ + fs::File, + os::fd::{AsFd, BorrowedFd}, +}; + +use crate::{ + generated::{ + bpf_attach_type::BPF_TRACE_ITER, bpf_link_type::BPF_LINK_TYPE_ITER, + bpf_prog_type::BPF_PROG_TYPE_TRACING, + }, + obj::btf::{Btf, BtfKind}, + programs::{ + define_link_wrapper, load_program, FdLink, LinkError, PerfLinkIdInner, PerfLinkInner, + ProgramData, ProgramError, + }, + sys::{bpf_create_iter, bpf_link_create, bpf_link_get_info_by_fd, LinkTarget, SyscallError}, +}; + +/// A BPF iterator which allows to dump data from the kernel-space into the +/// user-space. +/// +/// It can be seen as an alternative to `/proc` filesystem as it offers more +/// flexibility about what information should be retrieved and how it should be +/// formatted. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 5.8. +/// +/// # Example +/// +/// ```no_run +/// use std::io::{BufRead, BufReader}; +/// use aya::{programs::{Iter, ProgramError}, BtfError, Btf, Ebpf}; +/// # let mut ebpf = Ebpf::load_file("ebpf_programs.o")?; +/// +/// let btf = Btf::from_sys_fs()?; +/// let program: &mut Iter = ebpf.program_mut("iter_prog").unwrap().try_into()?; +/// program.load("task", &btf)?; +/// +/// let link_id = program.attach()?; +/// let link = program.take_link(link_id)?; +/// let file = link.into_file()?; +/// let reader = BufReader::new(file); +/// +/// let mut lines = reader.lines(); +/// for line in lines { +/// let line = line?; +/// println!("{line}"); +/// } +/// # Ok::<(), Box>(()) +/// ``` +#[derive(Debug)] +pub struct Iter { + pub(crate) data: ProgramData, +} + +impl Iter { + /// Loads the program inside the kernel. + pub fn load(&mut self, iter_type: &str, btf: &Btf) -> Result<(), ProgramError> { + self.data.expected_attach_type = Some(BPF_TRACE_ITER); + let type_name = format!("bpf_iter_{iter_type}"); + self.data.attach_btf_id = + Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Func)?); + load_program(BPF_PROG_TYPE_TRACING, &mut self.data) + } + + /// Attaches the program. + /// + /// The returned value can be used to detach, see [`Self::detach`]. + pub fn attach(&mut self) -> Result { + let prog_fd = self.fd()?; + let prog_fd = prog_fd.as_fd(); + let link_fd = bpf_link_create(prog_fd, LinkTarget::Iter, BPF_TRACE_ITER, None, 0, None) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; + + self.data + .links + .insert(IterLink::new(PerfLinkInner::FdLink(FdLink::new(link_fd)))) + } + + /// Detaches the program. + /// + /// See [`Self::attach`]. + pub fn detach(&mut self, link_id: IterLinkId) -> Result<(), ProgramError> { + self.data.links.remove(link_id) + } + + /// Takes ownership of the link referenced by the provided `link_id`. + /// + /// The caller takes the responsibility of managing the lifetime of the + /// link. When the returned [`IterLink`] is dropped, the link is detached. + pub fn take_link(&mut self, link_id: IterLinkId) -> Result { + self.data.take_link(link_id) + } +} + +/// An iterator descriptor. +#[derive(Debug)] +pub struct IterFd { + fd: crate::MockableFd, +} + +impl AsFd for IterFd { + fn as_fd(&self) -> BorrowedFd<'_> { + let Self { fd } = self; + fd.as_fd() + } +} + +impl TryFrom for FdLink { + type Error = LinkError; + + fn try_from(value: IterLink) -> Result { + if let PerfLinkInner::FdLink(fd) = value.into_inner() { + Ok(fd) + } else { + Err(LinkError::InvalidLink) + } + } +} + +impl TryFrom for IterLink { + type Error = LinkError; + + fn try_from(fd_link: FdLink) -> Result { + let info = bpf_link_get_info_by_fd(fd_link.fd.as_fd())?; + if info.type_ == (BPF_LINK_TYPE_ITER as u32) { + return Ok(Self::new(PerfLinkInner::FdLink(fd_link))); + } + Err(LinkError::InvalidLink) + } +} + +define_link_wrapper!( + /// The link used by [`Iter`] programs. + IterLink, + /// The type returned by [`Iter::attach`]. Can be passed to [`Iter::detach`]. + IterLinkId, + PerfLinkInner, + PerfLinkIdInner +); + +impl IterLink { + /// Converts [`IterLink`] into a [`File`] that can be used to retrieve the + /// outputs of the iterator program. + pub fn into_file(self) -> Result { + if let PerfLinkInner::FdLink(fd) = self.into_inner() { + let fd = bpf_create_iter(fd.fd.as_fd()).map_err(|(_, error)| { + LinkError::SyscallError(SyscallError { + call: "bpf_iter_create", + io_error: error, + }) + })?; + Ok(fd.into_inner().into()) + } else { + Err(LinkError::InvalidLink) + } + } +} diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 00d61b01d..b21aadc09 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -51,6 +51,7 @@ pub mod cgroup_sysctl; pub mod extension; pub mod fentry; pub mod fexit; +pub mod iter; pub mod kprobe; pub mod links; pub mod lirc_mode2; @@ -94,6 +95,7 @@ pub use crate::programs::{ extension::{Extension, ExtensionError}, fentry::FEntry, fexit::FExit, + iter::Iter, kprobe::{KProbe, KProbeError}, links::{CgroupAttachMode, Link, LinkOrder}, lirc_mode2::LircMode2, @@ -303,6 +305,8 @@ pub enum Program { CgroupSock(CgroupSock), /// A [`CgroupDevice`] program CgroupDevice(CgroupDevice), + /// An [`Iter`] program + Iter(Iter), } impl Program { @@ -324,7 +328,18 @@ impl Program { Self::PerfEvent(_) => ProgramType::PerfEvent, Self::RawTracePoint(_) => ProgramType::RawTracePoint, Self::Lsm(_) => ProgramType::Lsm, - Self::BtfTracePoint(_) | Self::FEntry(_) | Self::FExit(_) => ProgramType::Tracing, + // The following program types are a subset of `TRACING` programs: + // + // - `BPF_TRACE_RAW_TP` (`BtfTracePoint`) + // - `BTF_TRACE_FENTRY` (`FEntry`) + // - `BPF_MODIFY_RETURN` (not supported yet in Aya) + // - `BPF_TRACE_FEXIT` (`FExit`) + // - `BPF_TRACE_ITER` (`Iter`) + // + // https://github.com/torvalds/linux/blob/v6.12/kernel/bpf/syscall.c#L3935-L3940 + Self::BtfTracePoint(_) | Self::FEntry(_) | Self::FExit(_) | Self::Iter(_) => { + ProgramType::Tracing + } Self::Extension(_) => ProgramType::Extension, Self::CgroupSockAddr(_) => ProgramType::CgroupSockAddr, Self::SkLookup(_) => ProgramType::SkLookup, @@ -360,6 +375,7 @@ impl Program { Self::SkLookup(p) => p.pin(path), Self::CgroupSock(p) => p.pin(path), Self::CgroupDevice(p) => p.pin(path), + Self::Iter(p) => p.pin(path), } } @@ -390,6 +406,7 @@ impl Program { Self::SkLookup(mut p) => p.unload(), Self::CgroupSock(mut p) => p.unload(), Self::CgroupDevice(mut p) => p.unload(), + Self::Iter(mut p) => p.unload(), } } @@ -422,6 +439,7 @@ impl Program { Self::SkLookup(p) => p.fd(), Self::CgroupSock(p) => p.fd(), Self::CgroupDevice(p) => p.fd(), + Self::Iter(p) => p.fd(), } } @@ -455,6 +473,7 @@ impl Program { Self::SkLookup(p) => p.info(), Self::CgroupSock(p) => p.info(), Self::CgroupDevice(p) => p.info(), + Self::Iter(p) => p.info(), } } } @@ -771,6 +790,7 @@ impl_program_unload!( SockOps, CgroupSock, CgroupDevice, + Iter, ); macro_rules! impl_fd { @@ -811,6 +831,7 @@ impl_fd!( SockOps, CgroupSock, CgroupDevice, + Iter, ); /// Trait implemented by the [`Program`] types which support the kernel's @@ -916,6 +937,7 @@ impl_program_pin!( SockOps, CgroupSock, CgroupDevice, + Iter, ); macro_rules! impl_from_pin { @@ -954,6 +976,7 @@ impl_from_pin!( SkLookup, SockOps, CgroupDevice, + Iter, ); macro_rules! impl_try_from_program { @@ -1009,6 +1032,7 @@ impl_try_from_program!( SkLookup, CgroupSock, CgroupDevice, + Iter, ); impl_info!( @@ -1036,6 +1060,7 @@ impl_info!( SockOps, CgroupSock, CgroupDevice, + Iter, ); // TODO(https://github.com/aya-rs/aya/issues/645): this API is currently used in tests. Stabilize diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index a405b3bee..701206f82 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -36,6 +36,16 @@ use crate::{ Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN, FEATURES, }; +pub(crate) fn bpf_create_iter(link_fd: BorrowedFd<'_>) -> SysResult { + let mut attr = unsafe { mem::zeroed::() }; + + let u = unsafe { &mut attr.iter_create }; + u.link_fd = link_fd.as_raw_fd() as u32; + + // SAFETY: BPF_ITER_CREATE returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_ITER_CREATE, &mut attr) } +} + pub(crate) fn bpf_create_map( name: &CStr, def: &obj::Map, @@ -377,6 +387,7 @@ pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult { pub(crate) enum LinkTarget<'f> { Fd(BorrowedFd<'f>), IfIndex(u32), + Iter, } // since kernel 5.7 @@ -399,6 +410,11 @@ pub(crate) fn bpf_link_create( LinkTarget::IfIndex(ifindex) => { attr.link_create.__bindgen_anon_2.target_ifindex = ifindex; } + // When attaching to an iterator program, no target FD is needed. In + // fact, the kernel explicitly rejects non-zero target FDs for + // iterators: + // https://github.com/torvalds/linux/blob/v6.12/kernel/bpf/bpf_iter.c#L517-L518 + LinkTarget::Iter => {} }; attr.link_create.attach_type = attach_type as u32; diff --git a/test/integration-test/bpf/iter.bpf.c b/test/integration-test/bpf/iter.bpf.c new file mode 100644 index 000000000..75f385b57 --- /dev/null +++ b/test/integration-test/bpf/iter.bpf.c @@ -0,0 +1,23 @@ +// clang-format off +#include +#include +// clang-format on + +char _license[] SEC("license") = "GPL"; + +SEC("iter/task") +int iter_task(struct bpf_iter__task *ctx) { + struct seq_file *seq = ctx->meta->seq; + struct task_struct *task = ctx->task; + // Verifier requires this check. + if (task == NULL) { + return 0; + } + + if (ctx->meta->seq_num == 0) { + BPF_SEQ_PRINTF(seq, "tgid pid name\n"); + } + BPF_SEQ_PRINTF(seq, "%-8d %-8d %s\n", task->tgid, task->pid, task->comm); + + return 0; +} diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs index 5266a8ea5..dfa78789d 100644 --- a/test/integration-test/build.rs +++ b/test/integration-test/build.rs @@ -67,6 +67,7 @@ fn main() { const C_BPF: &[(&str, bool)] = &[ ("ext.bpf.c", false), + ("iter.bpf.c", true), ("main.bpf.c", false), ("multimap-btf.bpf.c", false), ("reloc.bpf.c", true), diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 9d72286a9..aa1a0f295 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -1,6 +1,7 @@ use aya::include_bytes_aligned; pub const EXT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ext.bpf.o")); +pub const ITER_TASK: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/iter.bpf.o")); pub const MAIN: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/main.bpf.o")); pub const MULTIMAP_BTF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/multimap-btf.bpf.o")); diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index 4b5c8fcbb..800cc541d 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -2,6 +2,7 @@ mod bpf_probe_read; mod btf_relocations; mod elf; mod info; +mod iter; mod load; mod log; mod rbpf; diff --git a/test/integration-test/src/tests/iter.rs b/test/integration-test/src/tests/iter.rs new file mode 100644 index 000000000..3325ad2e4 --- /dev/null +++ b/test/integration-test/src/tests/iter.rs @@ -0,0 +1,30 @@ +use std::io::BufRead; + +use aya::{programs::Iter, Btf, Ebpf}; +use test_log::test; + +#[test] +fn iter_task() { + let mut ebpf = Ebpf::load(crate::ITER_TASK).unwrap(); + let btf = Btf::from_sys_fs().unwrap(); + let prog: &mut Iter = ebpf.program_mut("iter_task").unwrap().try_into().unwrap(); + prog.load("task", &btf).unwrap(); + + let link_id = prog.attach().unwrap(); + let link = prog.take_link(link_id).unwrap(); + let file = link.into_file().unwrap(); + let reader = std::io::BufReader::new(file); + + let mut lines = reader.lines(); + let line_title = lines.next().unwrap().unwrap(); + let line_init = lines.next().unwrap().unwrap(); + + assert_eq!(line_title, "tgid pid name"); + let expected_values = ["1 1 init", "1 1 systemd"]; + assert!( + expected_values.contains(&line_init.as_str()), + "Unexpected line_init value: '{}', expected one of: {:?}", + line_init, + expected_values + ); +} diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index b88638440..374c56a6f 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -7190,6 +7190,8 @@ pub aya_obj::obj::ProgramSection::FEntry pub aya_obj::obj::ProgramSection::FEntry::sleepable: bool pub aya_obj::obj::ProgramSection::FExit pub aya_obj::obj::ProgramSection::FExit::sleepable: bool +pub aya_obj::obj::ProgramSection::Iter +pub aya_obj::obj::ProgramSection::Iter::sleepable: bool pub aya_obj::obj::ProgramSection::KProbe pub aya_obj::obj::ProgramSection::KRetProbe pub aya_obj::obj::ProgramSection::LircMode2 @@ -8050,6 +8052,8 @@ pub aya_obj::ProgramSection::FEntry pub aya_obj::ProgramSection::FEntry::sleepable: bool pub aya_obj::ProgramSection::FExit pub aya_obj::ProgramSection::FExit::sleepable: bool +pub aya_obj::ProgramSection::Iter +pub aya_obj::ProgramSection::Iter::sleepable: bool pub aya_obj::ProgramSection::KProbe pub aya_obj::ProgramSection::KRetProbe pub aya_obj::ProgramSection::LircMode2 diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 9fdceb2db..d3a82a446 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -3633,6 +3633,155 @@ impl core::borrow::BorrowMut for aya::programs::fexit::FExitLinkId where T pub fn aya::programs::fexit::FExitLinkId::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::fexit::FExitLinkId pub fn aya::programs::fexit::FExitLinkId::from(t: T) -> T +pub mod aya::programs::iter +pub struct aya::programs::iter::Iter +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::attach(&mut self) -> core::result::Result +pub fn aya::programs::iter::Iter::detach(&mut self, link_id: aya::programs::iter::IterLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::Iter::load(&mut self, iter_type: &str, btf: &aya_obj::btf::btf::Btf) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::Iter::take_link(&mut self, link_id: aya::programs::iter::IterLinkId) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::from_pin>(path: P) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::info(&self) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +pub fn aya::programs::iter::Iter::unpin(self) -> core::result::Result<(), std::io::error::Error> +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> +impl core::fmt::Debug for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::ops::drop::Drop for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::drop(&mut self) +impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::iter::Iter +pub type &'a aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a aya::programs::iter::Iter::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::iter::Iter, aya::programs::ProgramError> +impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::iter::Iter +pub type &'a mut aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a mut aya::programs::iter::Iter::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::iter::Iter, aya::programs::ProgramError> +impl core::marker::Freeze for aya::programs::iter::Iter +impl core::marker::Send for aya::programs::iter::Iter +impl core::marker::Sync for aya::programs::iter::Iter +impl core::marker::Unpin for aya::programs::iter::Iter +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::iter::Iter +impl core::panic::unwind_safe::UnwindSafe for aya::programs::iter::Iter +impl core::convert::Into for aya::programs::iter::Iter where U: core::convert::From +pub fn aya::programs::iter::Iter::into(self) -> U +impl core::convert::TryFrom for aya::programs::iter::Iter where U: core::convert::Into +pub type aya::programs::iter::Iter::Error = core::convert::Infallible +pub fn aya::programs::iter::Iter::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::iter::Iter where U: core::convert::TryFrom +pub type aya::programs::iter::Iter::Error = >::Error +pub fn aya::programs::iter::Iter::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::iter::Iter where T: 'static + ?core::marker::Sized +pub fn aya::programs::iter::Iter::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::iter::Iter where T: ?core::marker::Sized +pub fn aya::programs::iter::Iter::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::iter::Iter where T: ?core::marker::Sized +pub fn aya::programs::iter::Iter::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::from(t: T) -> T +pub struct aya::programs::iter::IterFd +impl core::fmt::Debug for aya::programs::iter::IterFd +pub fn aya::programs::iter::IterFd::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl std::os::fd::owned::AsFd for aya::programs::iter::IterFd +pub fn aya::programs::iter::IterFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> +impl core::marker::Freeze for aya::programs::iter::IterFd +impl core::marker::Send for aya::programs::iter::IterFd +impl core::marker::Sync for aya::programs::iter::IterFd +impl core::marker::Unpin for aya::programs::iter::IterFd +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::iter::IterFd +impl core::panic::unwind_safe::UnwindSafe for aya::programs::iter::IterFd +impl core::convert::Into for aya::programs::iter::IterFd where U: core::convert::From +pub fn aya::programs::iter::IterFd::into(self) -> U +impl core::convert::TryFrom for aya::programs::iter::IterFd where U: core::convert::Into +pub type aya::programs::iter::IterFd::Error = core::convert::Infallible +pub fn aya::programs::iter::IterFd::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::iter::IterFd where U: core::convert::TryFrom +pub type aya::programs::iter::IterFd::Error = >::Error +pub fn aya::programs::iter::IterFd::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::iter::IterFd where T: 'static + ?core::marker::Sized +pub fn aya::programs::iter::IterFd::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::iter::IterFd where T: ?core::marker::Sized +pub fn aya::programs::iter::IterFd::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::iter::IterFd where T: ?core::marker::Sized +pub fn aya::programs::iter::IterFd::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::iter::IterFd +pub fn aya::programs::iter::IterFd::from(t: T) -> T +pub struct aya::programs::iter::IterLink(_) +impl aya::programs::iter::IterLink +pub fn aya::programs::iter::IterLink::into_file(self) -> core::result::Result +impl aya::programs::links::Link for aya::programs::iter::IterLink +pub type aya::programs::iter::IterLink::Id = aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::IterLink::id(&self) -> Self::Id +impl core::convert::TryFrom for aya::programs::links::FdLink +pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError +pub fn aya::programs::links::FdLink::try_from(value: aya::programs::iter::IterLink) -> core::result::Result +impl core::convert::TryFrom for aya::programs::iter::IterLink +pub type aya::programs::iter::IterLink::Error = aya::programs::links::LinkError +pub fn aya::programs::iter::IterLink::try_from(fd_link: aya::programs::links::FdLink) -> core::result::Result +impl core::fmt::Debug for aya::programs::iter::IterLink +pub fn aya::programs::iter::IterLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::ops::drop::Drop for aya::programs::iter::IterLink +pub fn aya::programs::iter::IterLink::drop(&mut self) +impl core::marker::Freeze for aya::programs::iter::IterLink +impl core::marker::Send for aya::programs::iter::IterLink +impl core::marker::Sync for aya::programs::iter::IterLink +impl core::marker::Unpin for aya::programs::iter::IterLink +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::iter::IterLink +impl core::panic::unwind_safe::UnwindSafe for aya::programs::iter::IterLink +impl core::convert::Into for aya::programs::iter::IterLink where U: core::convert::From +pub fn aya::programs::iter::IterLink::into(self) -> U +impl core::convert::TryFrom for aya::programs::iter::IterLink where U: core::convert::Into +pub type aya::programs::iter::IterLink::Error = core::convert::Infallible +pub fn aya::programs::iter::IterLink::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::iter::IterLink where U: core::convert::TryFrom +pub type aya::programs::iter::IterLink::Error = >::Error +pub fn aya::programs::iter::IterLink::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::iter::IterLink where T: 'static + ?core::marker::Sized +pub fn aya::programs::iter::IterLink::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::iter::IterLink where T: ?core::marker::Sized +pub fn aya::programs::iter::IterLink::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::iter::IterLink where T: ?core::marker::Sized +pub fn aya::programs::iter::IterLink::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::iter::IterLink +pub fn aya::programs::iter::IterLink::from(t: T) -> T +pub struct aya::programs::iter::IterLinkId(_) +impl core::cmp::Eq for aya::programs::iter::IterLinkId +impl core::cmp::PartialEq for aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLinkId::eq(&self, other: &aya::programs::iter::IterLinkId) -> bool +impl core::fmt::Debug for aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::hash::Hash for aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLinkId::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +impl core::marker::StructuralPartialEq for aya::programs::iter::IterLinkId +impl core::marker::Freeze for aya::programs::iter::IterLinkId +impl core::marker::Send for aya::programs::iter::IterLinkId +impl core::marker::Sync for aya::programs::iter::IterLinkId +impl core::marker::Unpin for aya::programs::iter::IterLinkId +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::iter::IterLinkId +impl core::panic::unwind_safe::UnwindSafe for aya::programs::iter::IterLinkId +impl equivalent::Equivalent for aya::programs::iter::IterLinkId where Q: core::cmp::Eq + ?core::marker::Sized, K: core::borrow::Borrow + ?core::marker::Sized +pub fn aya::programs::iter::IterLinkId::equivalent(&self, key: &K) -> bool +impl core::convert::Into for aya::programs::iter::IterLinkId where U: core::convert::From +pub fn aya::programs::iter::IterLinkId::into(self) -> U +impl core::convert::TryFrom for aya::programs::iter::IterLinkId where U: core::convert::Into +pub type aya::programs::iter::IterLinkId::Error = core::convert::Infallible +pub fn aya::programs::iter::IterLinkId::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::iter::IterLinkId where U: core::convert::TryFrom +pub type aya::programs::iter::IterLinkId::Error = >::Error +pub fn aya::programs::iter::IterLinkId::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::iter::IterLinkId where T: 'static + ?core::marker::Sized +pub fn aya::programs::iter::IterLinkId::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::iter::IterLinkId where T: ?core::marker::Sized +pub fn aya::programs::iter::IterLinkId::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::iter::IterLinkId where T: ?core::marker::Sized +pub fn aya::programs::iter::IterLinkId::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLinkId::from(t: T) -> T pub mod aya::programs::kprobe pub enum aya::programs::kprobe::KProbeError pub aya::programs::kprobe::KProbeError::FileError @@ -3903,9 +4052,15 @@ impl core::convert::From for aya::progra pub fn aya::programs::links::FdLink::from(w: aya::programs::sk_lookup::SkLookupLink) -> aya::programs::links::FdLink impl core::convert::From for aya::programs::links::FdLink pub fn aya::programs::links::FdLink::from(w: aya::programs::tp_btf::BtfTracePointLink) -> aya::programs::links::FdLink +impl core::convert::TryFrom for aya::programs::links::FdLink +pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError +pub fn aya::programs::links::FdLink::try_from(value: aya::programs::iter::IterLink) -> core::result::Result impl core::convert::TryFrom for aya::programs::links::FdLink pub type aya::programs::links::FdLink::Error = aya::programs::links::LinkError pub fn aya::programs::links::FdLink::try_from(value: aya::programs::kprobe::KProbeLink) -> core::result::Result +impl core::convert::TryFrom for aya::programs::iter::IterLink +pub type aya::programs::iter::IterLink::Error = aya::programs::links::LinkError +pub fn aya::programs::iter::IterLink::try_from(fd_link: aya::programs::links::FdLink) -> core::result::Result impl core::convert::TryFrom for aya::programs::kprobe::KProbeLink pub type aya::programs::kprobe::KProbeLink::Error = aya::programs::links::LinkError pub fn aya::programs::kprobe::KProbeLink::try_from(fd_link: aya::programs::links::FdLink) -> core::result::Result @@ -4175,6 +4330,10 @@ impl aya::programs::links::Link for aya::programs::fexit::FExitLink pub type aya::programs::fexit::FExitLink::Id = aya::programs::fexit::FExitLinkId pub fn aya::programs::fexit::FExitLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::fexit::FExitLink::id(&self) -> Self::Id +impl aya::programs::links::Link for aya::programs::iter::IterLink +pub type aya::programs::iter::IterLink::Id = aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::IterLink::id(&self) -> Self::Id impl aya::programs::links::Link for aya::programs::kprobe::KProbeLink pub type aya::programs::kprobe::KProbeLink::Id = aya::programs::kprobe::KProbeLinkId pub fn aya::programs::kprobe::KProbeLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> @@ -6819,6 +6978,7 @@ pub aya::programs::Program::CgroupSysctl(aya::programs::cgroup_sysctl::CgroupSys pub aya::programs::Program::Extension(aya::programs::extension::Extension) pub aya::programs::Program::FEntry(aya::programs::fentry::FEntry) pub aya::programs::Program::FExit(aya::programs::fexit::FExit) +pub aya::programs::Program::Iter(aya::programs::iter::Iter) pub aya::programs::Program::KProbe(aya::programs::kprobe::KProbe) pub aya::programs::Program::LircMode2(aya::programs::lirc_mode2::LircMode2) pub aya::programs::Program::Lsm(aya::programs::lsm::Lsm) @@ -6868,6 +7028,9 @@ pub fn &'a aya::programs::fentry::FEntry::try_from(program: &'a aya::programs::P impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::fexit::FExit pub type &'a aya::programs::fexit::FExit::Error = aya::programs::ProgramError pub fn &'a aya::programs::fexit::FExit::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::fexit::FExit, aya::programs::ProgramError> +impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::iter::Iter +pub type &'a aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a aya::programs::iter::Iter::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::iter::Iter, aya::programs::ProgramError> impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::kprobe::KProbe pub type &'a aya::programs::kprobe::KProbe::Error = aya::programs::ProgramError pub fn &'a aya::programs::kprobe::KProbe::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::kprobe::KProbe, aya::programs::ProgramError> @@ -6940,6 +7103,9 @@ pub fn &'a mut aya::programs::fentry::FEntry::try_from(program: &'a mut aya::pro impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::fexit::FExit pub type &'a mut aya::programs::fexit::FExit::Error = aya::programs::ProgramError pub fn &'a mut aya::programs::fexit::FExit::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::fexit::FExit, aya::programs::ProgramError> +impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::iter::Iter +pub type &'a mut aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a mut aya::programs::iter::Iter::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::iter::Iter, aya::programs::ProgramError> impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::kprobe::KProbe pub type &'a mut aya::programs::kprobe::KProbe::Error = aya::programs::ProgramError pub fn &'a mut aya::programs::kprobe::KProbe::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::kprobe::KProbe, aya::programs::ProgramError> @@ -7950,6 +8116,55 @@ impl core::borrow::BorrowMut for aya::programs::fexit::FExit where T: ?cor pub fn aya::programs::fexit::FExit::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from(t: T) -> T +pub struct aya::programs::Iter +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::attach(&mut self) -> core::result::Result +pub fn aya::programs::iter::Iter::detach(&mut self, link_id: aya::programs::iter::IterLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::Iter::load(&mut self, iter_type: &str, btf: &aya_obj::btf::btf::Btf) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::Iter::take_link(&mut self, link_id: aya::programs::iter::IterLinkId) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::from_pin>(path: P) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::info(&self) -> core::result::Result +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> +pub fn aya::programs::iter::Iter::unpin(self) -> core::result::Result<(), std::io::error::Error> +impl aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> +impl core::fmt::Debug for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::ops::drop::Drop for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::drop(&mut self) +impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::iter::Iter +pub type &'a aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a aya::programs::iter::Iter::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::iter::Iter, aya::programs::ProgramError> +impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::iter::Iter +pub type &'a mut aya::programs::iter::Iter::Error = aya::programs::ProgramError +pub fn &'a mut aya::programs::iter::Iter::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::iter::Iter, aya::programs::ProgramError> +impl core::marker::Freeze for aya::programs::iter::Iter +impl core::marker::Send for aya::programs::iter::Iter +impl core::marker::Sync for aya::programs::iter::Iter +impl core::marker::Unpin for aya::programs::iter::Iter +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::iter::Iter +impl core::panic::unwind_safe::UnwindSafe for aya::programs::iter::Iter +impl core::convert::Into for aya::programs::iter::Iter where U: core::convert::From +pub fn aya::programs::iter::Iter::into(self) -> U +impl core::convert::TryFrom for aya::programs::iter::Iter where U: core::convert::Into +pub type aya::programs::iter::Iter::Error = core::convert::Infallible +pub fn aya::programs::iter::Iter::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::iter::Iter where U: core::convert::TryFrom +pub type aya::programs::iter::Iter::Error = >::Error +pub fn aya::programs::iter::Iter::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::programs::iter::Iter where T: 'static + ?core::marker::Sized +pub fn aya::programs::iter::Iter::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::iter::Iter where T: ?core::marker::Sized +pub fn aya::programs::iter::Iter::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::iter::Iter where T: ?core::marker::Sized +pub fn aya::programs::iter::Iter::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::programs::iter::Iter +pub fn aya::programs::iter::Iter::from(t: T) -> T pub struct aya::programs::KProbe impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::attach>(&mut self, fn_name: T, offset: u64) -> core::result::Result @@ -8928,6 +9143,10 @@ impl aya::programs::links::Link for aya::programs::fexit::FExitLink pub type aya::programs::fexit::FExitLink::Id = aya::programs::fexit::FExitLinkId pub fn aya::programs::fexit::FExitLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::fexit::FExitLink::id(&self) -> Self::Id +impl aya::programs::links::Link for aya::programs::iter::IterLink +pub type aya::programs::iter::IterLink::Id = aya::programs::iter::IterLinkId +pub fn aya::programs::iter::IterLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::iter::IterLink::id(&self) -> Self::Id impl aya::programs::links::Link for aya::programs::kprobe::KProbeLink pub type aya::programs::kprobe::KProbeLink::Id = aya::programs::kprobe::KProbeLinkId pub fn aya::programs::kprobe::KProbeLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>