Browse Source

Merge pull request #637 from astoycos/helpers

Add more helpful methods to `ProgramInfo`
Andrew Stoycos 1 year ago
parent
commit
bcc9743254

+ 2 - 7
aya/src/programs/lirc_mode2.rs

@@ -4,10 +4,7 @@ use std::os::fd::{AsRawFd, IntoRawFd as _, RawFd};
 use crate::{
     generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2},
     programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo},
-    sys::{
-        bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd,
-        SyscallError,
-    },
+    sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, SyscallError},
 };
 
 use libc::{close, dup};
@@ -131,9 +128,7 @@ impl LircLink {
 
     /// Get ProgramInfo from this link
     pub fn info(&self) -> Result<ProgramInfo, ProgramError> {
-        bpf_prog_get_info_by_fd(self.prog_fd, &mut [])
-            .map(ProgramInfo)
-            .map_err(Into::into)
+        ProgramInfo::new_from_fd(self.prog_fd)
     }
 }
 

+ 133 - 9
aya/src/programs/mod.rs

@@ -68,9 +68,11 @@ use libc::ENOSPC;
 use std::{
     ffi::CString,
     io,
+    num::NonZeroU32,
     os::fd::{AsFd, AsRawFd, IntoRawFd as _, OwnedFd, RawFd},
     path::{Path, PathBuf},
     sync::Arc,
+    time::{Duration, SystemTime},
 };
 use thiserror::Error;
 
@@ -108,6 +110,7 @@ use crate::{
     maps::MapError,
     obj::{self, btf::BtfError, Function, VerifierLog},
     pin::PinError,
+    programs::utils::{boot_time, get_fdinfo},
     sys::{
         bpf_btf_get_fd_by_id, bpf_get_object, bpf_link_get_fd_by_id, bpf_link_get_info_by_fd,
         bpf_load_program, bpf_pin_object, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd,
@@ -476,14 +479,15 @@ impl<T: Link> ProgramData<T> {
     ) -> Result<ProgramData<T>, ProgramError> {
         let path_string =
             CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap();
+
         let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
             call: "bpf_obj_get",
             io_error,
         })?;
 
-        let info = bpf_prog_get_info_by_fd(fd.as_raw_fd(), &mut [])?;
-        let name = ProgramInfo(info).name_as_str().map(|s| s.to_string());
-        ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info, verifier_log_level)
+        let info = ProgramInfo::new_from_fd(fd.as_raw_fd())?;
+        let name = info.name_as_str().map(|s| s.to_string());
+        ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info.0, verifier_log_level)
     }
 }
 
@@ -901,11 +905,65 @@ impl_try_from_program!(
     CgroupDevice,
 );
 
+/// Returns information about a loaded program with the [`ProgramInfo`] structure.
+///
+/// This information is populated at load time by the kernel and can be used
+/// to correlate a given [`Program`] to it's corresponding [`ProgramInfo`]
+/// metadata.
+macro_rules! impl_program_info {
+    ($($struct_name:ident),+ $(,)?) => {
+        $(
+            impl $struct_name {
+                /// Returns the file descriptor of this Program.
+                pub fn program_info(&self) -> Result<ProgramInfo, ProgramError> {
+                    let fd = self.data.fd_or_err()?;
+
+                    ProgramInfo::new_from_fd(fd.as_raw_fd())
+                }
+            }
+        )+
+    }
+}
+
+impl_program_info!(
+    KProbe,
+    UProbe,
+    TracePoint,
+    SocketFilter,
+    Xdp,
+    SkMsg,
+    SkSkb,
+    SchedClassifier,
+    CgroupSkb,
+    CgroupSysctl,
+    CgroupSockopt,
+    LircMode2,
+    PerfEvent,
+    Lsm,
+    RawTracePoint,
+    BtfTracePoint,
+    FEntry,
+    FExit,
+    Extension,
+    CgroupSockAddr,
+    SkLookup,
+    SockOps,
+    CgroupSock,
+    CgroupDevice,
+);
+
 /// Provides information about a loaded program, like name, id and statistics
 #[derive(Debug)]
 pub struct ProgramInfo(bpf_prog_info);
 
 impl ProgramInfo {
+    fn new_from_fd(fd: RawFd) -> Result<Self, ProgramError> {
+        Ok(ProgramInfo(bpf_prog_get_info_by_fd(
+            fd.as_raw_fd(),
+            &mut [],
+        )?))
+    }
+
     /// The name of the program as was provided when it was load. This is limited to 16 bytes
     pub fn name(&self) -> &[u8] {
         let length = self
@@ -921,23 +979,89 @@ impl ProgramInfo {
         unsafe { std::slice::from_raw_parts(self.0.name.as_ptr() as *const _, length) }
     }
 
-    /// The name of the program as a &str. If the name was not valid unicode, None is returned
+    /// The name of the program as a &str. If the name was not valid unicode, None is returned.
     pub fn name_as_str(&self) -> Option<&str> {
         std::str::from_utf8(self.name()).ok()
     }
 
-    /// The program id for this program. Each program has a unique id.
+    /// The id for this program. Each program has a unique id.
     pub fn id(&self) -> u32 {
         self.0.id
     }
 
-    /// Returns the fd associated with the program.
+    /// The program tag.
+    ///
+    /// The program tag is a SHA sum of the program's instructions which be used as an alternative to
+    /// [`Self::id()`]". A program's id can vary every time it's loaded or unloaded, but the tag
+    /// will remain the same.
+    pub fn tag(&self) -> u64 {
+        u64::from_be_bytes(self.0.tag)
+    }
+
+    /// The program type as defined by the linux kernel enum
+    /// [`bpf_prog_type`](https://elixir.bootlin.com/linux/v6.4.4/source/include/uapi/linux/bpf.h#L948).
+    pub fn program_type(&self) -> u32 {
+        self.0.type_
+    }
+
+    /// Returns true if the program is defined with a GPL-compatible license.
+    pub fn gpl_compatible(&self) -> bool {
+        self.0.gpl_compatible() != 0
+    }
+
+    /// The ids of the maps used by the program.
+    pub fn map_ids(&self) -> Result<Vec<u32>, ProgramError> {
+        let fd = self.fd()?;
+        let mut map_ids = vec![0u32; self.0.nr_map_ids as usize];
+
+        bpf_prog_get_info_by_fd(fd.as_raw_fd(), &mut map_ids)?;
+
+        Ok(map_ids)
+    }
+
+    /// The btf id for the program.
+    pub fn btf_id(&self) -> Option<NonZeroU32> {
+        NonZeroU32::new(self.0.btf_id)
+    }
+
+    /// The size in bytes of the program's translated eBPF bytecode, which is
+    /// the bytecode after it has been passed though the verifier where it was
+    /// possibly modified by the kernel.
+    pub fn size_translated(&self) -> u32 {
+        self.0.xlated_prog_len
+    }
+
+    /// The size in bytes of the program's JIT-compiled machine code.
+    pub fn size_jitted(&self) -> u32 {
+        self.0.jited_prog_len
+    }
+
+    /// How much memory in bytes has been allocated and locked for the program.
+    pub fn memory_locked(&self) -> Result<u32, ProgramError> {
+        get_fdinfo(self.fd()?.as_fd(), "memlock")
+    }
+
+    /// The number of verified instructions in the program.
+    ///
+    /// This may be less than the total number of instructions in the compiled
+    /// program due to dead code elimination in the verifier.
+    pub fn verified_instruction_count(&self) -> u32 {
+        self.0.verified_insns
+    }
+
+    /// The time the program was loaded.
+    pub fn loaded_at(&self) -> SystemTime {
+        boot_time() + Duration::from_nanos(self.0.load_time)
+    }
+
+    /// Returns a file descriptor referencing the program.
     ///
-    /// The returned fd must be closed when no longer needed.
-    pub fn fd(&self) -> Result<RawFd, ProgramError> {
+    /// The returned file descriptor can be closed at any time and doing so does
+    /// not influence the life cycle of the program.
+    pub fn fd(&self) -> Result<OwnedFd, ProgramError> {
         let Self(info) = self;
         let fd = bpf_prog_get_fd_by_id(info.id)?;
-        Ok(fd.into_raw_fd())
+        Ok(fd)
     }
 
     /// Loads a program from a pinned path in bpffs.

+ 46 - 2
aya/src/programs/utils.rs

@@ -1,5 +1,12 @@
 //! Common functions shared between multiple eBPF program types.
-use std::{ffi::CStr, io, path::Path};
+use std::{
+    ffi::CStr,
+    fs::File,
+    io::{self, BufRead, BufReader},
+    os::fd::{AsRawFd as _, BorrowedFd},
+    path::Path,
+    time::{Duration, SystemTime, UNIX_EPOCH},
+};
 
 use crate::{
     programs::{FdLink, Link, ProgramData, ProgramError},
@@ -22,7 +29,7 @@ pub(crate) fn attach_raw_tracepoint<T: Link + From<FdLink>>(
     program_data.links.insert(FdLink::new(pfd).into())
 }
 
-/// Find tracefs filesystem path
+/// Find tracefs filesystem path.
 pub(crate) fn find_tracefs_path() -> Result<&'static Path, ProgramError> {
     lazy_static::lazy_static! {
         static ref TRACE_FS: Option<&'static Path> = {
@@ -50,3 +57,40 @@ pub(crate) fn find_tracefs_path() -> Result<&'static Path, ProgramError> {
         .as_deref()
         .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "tracefs not found").into())
 }
+
+/// The time at which the system is booted.
+pub(crate) fn boot_time() -> SystemTime {
+    let get_time = |clock_id| {
+        let mut time = unsafe { std::mem::zeroed::<libc::timespec>() };
+        assert_eq!(
+            unsafe { libc::clock_gettime(clock_id, &mut time) },
+            0,
+            "clock_gettime({}, _)",
+            clock_id
+        );
+        let libc::timespec { tv_sec, tv_nsec } = time;
+
+        Duration::new(tv_sec as u64, tv_nsec as u32)
+    };
+    let since_boot = get_time(libc::CLOCK_BOOTTIME);
+    let since_epoch = get_time(libc::CLOCK_REALTIME);
+    UNIX_EPOCH + since_boot - since_epoch
+}
+
+/// Get the specified information from a file descriptor's fdinfo.
+pub(crate) fn get_fdinfo(fd: BorrowedFd, key: &str) -> Result<u32, ProgramError> {
+    let info = File::open(format!("/proc/self/fdinfo/{}", fd.as_raw_fd()))?;
+    let reader = BufReader::new(info);
+    for line in reader.lines() {
+        let line = line.map_err(ProgramError::IOError)?;
+        if !line.contains(key) {
+            continue;
+        }
+
+        let (_key, val) = line.rsplit_once('\t').unwrap();
+
+        return Ok(val.parse().unwrap());
+    }
+
+    Ok(0)
+}

+ 30 - 1
test/integration-test/src/tests/smoke.rs

@@ -1,5 +1,5 @@
 use aya::{
-    programs::{Extension, TracePoint, Xdp, XdpFlags},
+    programs::{loaded_programs, Extension, TracePoint, Xdp, XdpFlags},
     util::KernelVersion,
     Bpf, BpfLoader,
 };
@@ -65,3 +65,32 @@ fn extension() {
     let drop_: &mut Extension = bpf.program_mut("xdp_drop").unwrap().try_into().unwrap();
     drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap();
 }
+
+#[test]
+fn list_loaded_programs() {
+    // Load a program.
+    let mut bpf = Bpf::load(crate::PASS).unwrap();
+    let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap();
+    dispatcher.load().unwrap();
+    dispatcher.attach("lo", XdpFlags::default()).unwrap();
+
+    // Ensure the loaded_programs() api doesn't panic.
+    let prog = loaded_programs()
+        .map(|p| p.unwrap())
+        .find(|p| p.name_as_str().unwrap() == "pass")
+        .unwrap();
+
+    // Ensure all relevant helper functions don't panic.
+    prog.name();
+    prog.id();
+    prog.tag();
+    prog.program_type();
+    prog.gpl_compatible();
+    prog.map_ids().unwrap();
+    prog.btf_id();
+    prog.size_translated();
+    prog.memory_locked().unwrap();
+    prog.verified_instruction_count();
+    prog.loaded_at();
+    prog.fd().unwrap();
+}

+ 95 - 1
xtask/public-api/aya.txt

@@ -1811,6 +1811,8 @@ impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_device::CgroupDevice
+pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self)
@@ -1952,6 +1954,8 @@ impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_skb::CgroupSkb
+pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self)
@@ -2060,6 +2064,8 @@ impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sock::CgroupSock
+pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self)
@@ -2168,6 +2174,8 @@ impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
+pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self)
@@ -2276,6 +2284,8 @@ impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sockopt::CgroupSockopt
+pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self)
@@ -2384,6 +2394,8 @@ impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sysctl::CgroupSysctl
+pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self)
@@ -2527,6 +2539,8 @@ impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::extension::Extension
+pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::drop(&mut self)
@@ -2639,6 +2653,8 @@ impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::fentry::FEntry
+pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::drop(&mut self)
@@ -2751,6 +2767,8 @@ impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::fexit::FExit
+pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::drop(&mut self)
@@ -2900,6 +2918,8 @@ impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::kprobe::KProbe
+pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::drop(&mut self)
@@ -3400,6 +3420,8 @@ impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::lirc_mode2::LircMode2
+pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self)
@@ -3447,6 +3469,8 @@ impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::lsm::Lsm
+pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::drop(&mut self)
@@ -3732,6 +3756,8 @@ impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::perf_event::PerfEvent
+pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::drop(&mut self)
@@ -3924,6 +3950,8 @@ impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::tc::SchedClassifier
+pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::drop(&mut self)
@@ -4064,6 +4092,8 @@ impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::tp_btf::BtfTracePoint
+pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self)
@@ -4213,6 +4243,8 @@ impl aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::trace_point::TracePoint
+pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::drop(&mut self)
@@ -4371,6 +4403,8 @@ impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::uprobe::UProbe
+pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::drop(&mut self)
@@ -4523,6 +4557,8 @@ impl aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::xdp::Xdp
+pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::drop(&mut self)
@@ -5531,6 +5567,8 @@ impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::tp_btf::BtfTracePoint
+pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self)
@@ -5577,6 +5615,8 @@ impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_device::CgroupDevice
+pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self)
@@ -5623,6 +5663,8 @@ impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_skb::CgroupSkb
+pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self)
@@ -5668,6 +5710,8 @@ impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sock::CgroupSock
+pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self)
@@ -5713,6 +5757,8 @@ impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
+pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self)
@@ -5758,6 +5804,8 @@ impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sockopt::CgroupSockopt
+pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self)
@@ -5804,6 +5852,8 @@ impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::cgroup_sysctl::CgroupSysctl
+pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self)
@@ -5851,6 +5901,8 @@ impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::extension::Extension
+pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::drop(&mut self)
@@ -5897,6 +5949,8 @@ impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::fentry::FEntry
+pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::drop(&mut self)
@@ -5943,6 +5997,8 @@ impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::fexit::FExit
+pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::drop(&mut self)
@@ -5989,6 +6045,8 @@ impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::kprobe::KProbe
+pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::drop(&mut self)
@@ -6036,6 +6094,8 @@ impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::lirc_mode2::LircMode2
+pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self)
@@ -6082,6 +6142,8 @@ impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::lsm::Lsm
+pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::drop(&mut self)
@@ -6128,6 +6190,8 @@ impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::perf_event::PerfEvent
+pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::drop(&mut self)
@@ -6193,11 +6257,21 @@ impl<T> core::convert::From<T> for aya::programs::ProgramFd
 pub fn aya::programs::ProgramFd::from(t: T) -> T
 pub struct aya::programs::ProgramInfo(_)
 impl aya::programs::ProgramInfo
-pub fn aya::programs::ProgramInfo::fd(&self) -> core::result::Result<std::os::fd::raw::RawFd, aya::programs::ProgramError>
+pub fn aya::programs::ProgramInfo::btf_id(&self) -> core::option::Option<core::num::nonzero::NonZeroU32>
+pub fn aya::programs::ProgramInfo::fd(&self) -> core::result::Result<std::os::fd::owned::OwnedFd, aya::programs::ProgramError>
 pub fn aya::programs::ProgramInfo::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+pub fn aya::programs::ProgramInfo::gpl_compatible(&self) -> bool
 pub fn aya::programs::ProgramInfo::id(&self) -> u32
+pub fn aya::programs::ProgramInfo::loaded_at(&self) -> std::time::SystemTime
+pub fn aya::programs::ProgramInfo::map_ids(&self) -> core::result::Result<alloc::vec::Vec<u32>, aya::programs::ProgramError>
+pub fn aya::programs::ProgramInfo::memory_locked(&self) -> core::result::Result<u32, aya::programs::ProgramError>
 pub fn aya::programs::ProgramInfo::name(&self) -> &[u8]
 pub fn aya::programs::ProgramInfo::name_as_str(&self) -> core::option::Option<&str>
+pub fn aya::programs::ProgramInfo::program_type(&self) -> u32
+pub fn aya::programs::ProgramInfo::size_jitted(&self) -> u32
+pub fn aya::programs::ProgramInfo::size_translated(&self) -> u32
+pub fn aya::programs::ProgramInfo::tag(&self) -> u64
+pub fn aya::programs::ProgramInfo::verified_instruction_count(&self) -> u32
 impl core::fmt::Debug for aya::programs::ProgramInfo
 pub fn aya::programs::ProgramInfo::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
 impl core::marker::Send for aya::programs::ProgramInfo
@@ -6235,6 +6309,8 @@ impl aya::programs::RawTracePoint
 pub fn aya::programs::RawTracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::RawTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::RawTracePoint
+pub fn aya::programs::RawTracePoint::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::RawTracePoint
 pub fn aya::programs::RawTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::RawTracePoint
 pub fn aya::programs::RawTracePoint::drop(&mut self)
@@ -6281,6 +6357,8 @@ impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::tc::SchedClassifier
+pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::drop(&mut self)
@@ -6327,6 +6405,8 @@ impl aya::programs::SkLookup
 pub fn aya::programs::SkLookup::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::SkLookup::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::SkLookup
+pub fn aya::programs::SkLookup::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::SkLookup
 pub fn aya::programs::SkLookup::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::SkLookup
 pub fn aya::programs::SkLookup::drop(&mut self)
@@ -6373,6 +6453,8 @@ impl aya::programs::SkMsg
 pub fn aya::programs::SkMsg::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::SkMsg::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::SkMsg
+pub fn aya::programs::SkMsg::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::SkMsg
 pub fn aya::programs::SkMsg::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::SkMsg
 pub fn aya::programs::SkMsg::drop(&mut self)
@@ -6418,6 +6500,8 @@ impl aya::programs::SkSkb
 pub fn aya::programs::SkSkb::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::SkSkb::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::SkSkb
+pub fn aya::programs::SkSkb::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::SkSkb
 pub fn aya::programs::SkSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::SkSkb
 pub fn aya::programs::SkSkb::drop(&mut self)
@@ -6464,6 +6548,8 @@ impl aya::programs::SockOps
 pub fn aya::programs::SockOps::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::SockOps::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::SockOps
+pub fn aya::programs::SockOps::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::SockOps
 pub fn aya::programs::SockOps::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::SockOps
 pub fn aya::programs::SockOps::drop(&mut self)
@@ -6510,6 +6596,8 @@ impl aya::programs::SocketFilter
 pub fn aya::programs::SocketFilter::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::SocketFilter::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::SocketFilter
+pub fn aya::programs::SocketFilter::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::SocketFilter
 pub fn aya::programs::SocketFilter::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::SocketFilter
 pub fn aya::programs::SocketFilter::drop(&mut self)
@@ -6556,6 +6644,8 @@ impl aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::trace_point::TracePoint
+pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint
 pub fn aya::programs::trace_point::TracePoint::drop(&mut self)
@@ -6602,6 +6692,8 @@ impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::uprobe::UProbe
+pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::drop(&mut self)
@@ -6650,6 +6742,8 @@ impl aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error>
 impl aya::programs::xdp::Xdp
+pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl core::ops::drop::Drop for aya::programs::xdp::Xdp
 pub fn aya::programs::xdp::Xdp::drop(&mut self)