From dc12a1008de2bb4cc4aa27565a95c771137c9ca3 Mon Sep 17 00:00:00 2001
From: Dave Tucker <dave@dtucker.co.uk>
Date: Thu, 6 Mar 2025 17:01:18 +0000
Subject: [PATCH] feat: Allow conversions to Program from ProgramInfo

Allow for a ProgramInfo to be converted into one of the program types
that we support. This allows for a user of Aya access to reattach,
pin or unload a program that was either, previously loaded, or was
loaded by another process.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
---
 aya/src/bpf.rs                          |   6 +-
 aya/src/programs/cgroup_skb.rs          |  16 ++-
 aya/src/programs/kprobe.rs              |  60 +++++++++-
 aya/src/programs/mod.rs                 | 151 ++++++++++++++++++++++++
 aya/src/programs/probe.rs               |   2 +-
 aya/src/programs/uprobe.rs              |  59 ++++++++-
 test/integration-test/src/tests/info.rs |   6 +
 xtask/public-api/aya.txt                |  83 +++++++++++++
 8 files changed, 368 insertions(+), 15 deletions(-)

diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs
index dc32e2f6..9d30159c 100644
--- a/aya/src/bpf.rs
+++ b/aya/src/bpf.rs
@@ -613,15 +613,15 @@ impl<'a> EbpfLoader<'a> {
                         }
                         ProgramSection::CgroupSkb => Program::CgroupSkb(CgroupSkb {
                             data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
-                            expected_attach_type: None,
+                            attach_type: None,
                         }),
                         ProgramSection::CgroupSkbIngress => Program::CgroupSkb(CgroupSkb {
                             data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
-                            expected_attach_type: Some(CgroupSkbAttachType::Ingress),
+                            attach_type: Some(CgroupSkbAttachType::Ingress),
                         }),
                         ProgramSection::CgroupSkbEgress => Program::CgroupSkb(CgroupSkb {
                             data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
-                            expected_attach_type: Some(CgroupSkbAttachType::Egress),
+                            attach_type: Some(CgroupSkbAttachType::Egress),
                         }),
                         ProgramSection::CgroupSockAddr { attach_type, .. } => {
                             Program::CgroupSockAddr(CgroupSockAddr {
diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs
index 26f5490d..f0d00915 100644
--- a/aya/src/programs/cgroup_skb.rs
+++ b/aya/src/programs/cgroup_skb.rs
@@ -57,18 +57,16 @@ use crate::{
 #[doc(alias = "BPF_PROG_TYPE_CGROUP_SKB")]
 pub struct CgroupSkb {
     pub(crate) data: ProgramData<CgroupSkbLink>,
-    pub(crate) expected_attach_type: Option<CgroupSkbAttachType>,
+    pub(crate) attach_type: Option<CgroupSkbAttachType>,
 }
 
 impl CgroupSkb {
     /// Loads the program inside the kernel.
     pub fn load(&mut self) -> Result<(), ProgramError> {
-        self.data.expected_attach_type =
-            self.expected_attach_type
-                .map(|attach_type| match attach_type {
-                    CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS,
-                    CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS,
-                });
+        self.data.expected_attach_type = self.attach_type.map(|attach_type| match attach_type {
+            CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS,
+            CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS,
+        });
         load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data)
     }
 
@@ -79,7 +77,7 @@ impl CgroupSkb {
     /// method returns `None` for programs defined with the generic section
     /// `cgroup/skb`.
     pub fn expected_attach_type(&self) -> &Option<CgroupSkbAttachType> {
-        &self.expected_attach_type
+        &self.attach_type
     }
 
     /// Attaches the program to the given cgroup.
@@ -138,7 +136,7 @@ impl CgroupSkb {
         let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
         Ok(Self {
             data,
-            expected_attach_type: Some(expected_attach_type),
+            attach_type: Some(expected_attach_type),
         })
     }
 }
diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs
index 95ef6a24..7dcf1437 100644
--- a/aya/src/programs/kprobe.rs
+++ b/aya/src/programs/kprobe.rs
@@ -9,10 +9,12 @@ use std::{
 use aya_obj::generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_KPROBE};
 use thiserror::Error;
 
+use super::ProgramType;
 use crate::{
     VerifierLogLevel,
     programs::{
-        FdLink, LinkError, ProgramData, ProgramError, define_link_wrapper, load_program,
+        FdLink, LinkError, ProgramData, ProgramError, ProgramInfo, define_link_wrapper,
+        load_program,
         perf_attach::{PerfLinkIdInner, PerfLinkInner},
         probe::{ProbeKind, attach},
     },
@@ -97,6 +99,62 @@ impl KProbe {
         let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
         Ok(Self { data, kind })
     }
+
+    /// Constructs an instance of [KProbe] from a [ProgramInfo].
+    ///
+    /// This allows you to get a handle to an already loaded program
+    /// from the kernel without having to load it again.
+    ///
+    /// # Safety
+    ///
+    /// The type of program in the [ProgramInfo] may not be of
+    /// [`ProgramType::KProbe`]. This function is unable to
+    /// check since the kernel doesn't expose this information.
+    /// The caller is responsible for ensuring that the program
+    /// type is correct (i.e they previously loaded it) otherwise
+    /// the behavior is undefined.
+    ///
+    /// # Errors
+    ///
+    /// - If the program type is not  [`ProgramType::KProbe`]
+    /// - If the file descriptor of the program cannot be cloned
+    ///
+    /// # Example
+    /// ```no_run
+    /// # use aya::programs::loaded_programs;
+    /// # use aya::programs::{KProbe, ProbeKind, ProgramInfo, ProgramType};
+    ///
+    /// for program in loaded_programs() {
+    ///    let program = program?;
+    ///    if program.program_type()? == ProgramType::KProbe {
+    ///       let p = unsafe { KProbe::from_program_info(None, program, ProbeKind::KProbe)? };
+    ///       // do something with the program
+    ///     }
+    /// }
+    /// # Ok::<(), aya::programs::ProgramError>(())
+    /// ```
+    pub unsafe fn from_program_info(
+        name: Option<String>,
+        info: ProgramInfo,
+        kind: ProbeKind,
+    ) -> Result<Self, ProgramError> {
+        if info.program_type()? != ProgramType::KProbe {
+            return Err(ProgramError::UnexpectedProgramType {});
+        }
+        if kind != ProbeKind::KProbe && kind != ProbeKind::KRetProbe {
+            return Err(ProgramError::UnexpectedProgramType {});
+        }
+        Ok(Self {
+            data: ProgramData::from_bpf_prog_info(
+                name,
+                crate::MockableFd::from_fd(info.fd()?.as_fd().try_clone_to_owned()?),
+                Path::new(""),
+                info.0,
+                VerifierLogLevel::default(),
+            )?,
+            kind,
+        })
+    }
 }
 
 define_link_wrapper!(
diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs
index 45171628..68633bc7 100644
--- a/aya/src/programs/mod.rs
+++ b/aya/src/programs/mod.rs
@@ -990,6 +990,157 @@ impl_from_pin!(
     Iter,
 );
 
+macro_rules! impl_from_prog_info {
+    ($($struct_name:ident),+ $(,)?) => {
+        $(
+            impl $struct_name {
+                /// Consructs a program from a [ProgramInfo].
+                ///
+                /// This allows you to get a handle to an already loaded program
+                /// from the kernel without having to load it again.
+                ///
+                /// # Errors
+                ///
+                /// - If the program type is not a match
+                /// - If the file descriptor of the program cannot be cloned
+                pub fn from_program_info(
+                    name: Option<String>,
+                    info: ProgramInfo,
+                ) -> Result<$struct_name, ProgramError> {
+                    if info.program_type()? != ProgramType::$struct_name {
+                        return Err(ProgramError::UnexpectedProgramType {});
+                    }
+                    Ok($struct_name {
+                        data: ProgramData::from_bpf_prog_info(
+                            name,
+                            crate::MockableFd::from_fd(info.fd()?.as_fd().try_clone_to_owned()?),
+                            Path::new(""),
+                            info.0,
+                            VerifierLogLevel::default(),
+                        )?,
+                    })
+                }
+            }
+        )+
+    }
+}
+
+macro_rules! impl_from_prog_info_attach_type {
+    ($($struct_name:ident, $attach_type:ty),+ $(,)?) => {
+        $(
+            impl $struct_name {
+
+                /// Consructs a program from a [ProgramInfo].
+                ///
+                /// This allows you to get a handle to an already loaded program
+                /// from the kernel without having to load it again.
+                ///
+                /// # Errors
+                ///
+                /// - If the program type is not a match
+                /// - If the file descriptor of the program cannot be cloned
+                pub fn from_program_info(
+                    name: Option<String>,
+                    info: ProgramInfo,
+                    attach_type: $attach_type,
+                ) -> Result<$struct_name, ProgramError> {
+                    if info.program_type()? != ProgramType::$struct_name {
+                        return Err(ProgramError::UnexpectedProgramType {});
+                    }
+                    Ok($struct_name {
+                        data: ProgramData::from_bpf_prog_info(
+                            name,
+                            crate::MockableFd::from_fd(info.fd()?.as_fd().try_clone_to_owned()?),
+                            Path::new(""),
+                            info.0,
+                            VerifierLogLevel::default(),
+                        )?,
+                        attach_type,
+                    })
+                }
+            }
+        )+
+    }
+}
+
+macro_rules! impl_from_prog_info_unsafe {
+    ($($struct_name:ident, $prog_type:expr),+ $(,)?) => {
+        $(
+            impl $struct_name {
+
+                /// Consructs a program from a [ProgramInfo].
+                ///
+                /// This allows you to get a handle to an already loaded program
+                /// from the kernel without having to load it again.
+                ///
+                /// # Errors
+                ///
+                /// - If the program type is not a match
+                /// - If the file descriptor of the program cannot be cloned
+                ///
+                /// # Safety
+                ///
+                /// The type of program in the [ProgramInfo] may be
+                /// ambiguous due to missing information in the kernel.
+                /// The caller is responsible for ensuring that the program
+                /// type is correct otherwise the behavior is undefined.
+                pub unsafe fn from_program_info(
+                    name: Option<String>,
+                    info: ProgramInfo,
+                ) -> Result<$struct_name, ProgramError> {
+                    if info.program_type()? != $prog_type {
+                        return Err(ProgramError::UnexpectedProgramType {});
+                    }
+                    Ok($struct_name {
+                        data: ProgramData::from_bpf_prog_info(
+                            name,
+                            crate::MockableFd::from_fd(info.fd()?.as_fd().try_clone_to_owned()?),
+                            Path::new(""),
+                            info.0,
+                            VerifierLogLevel::default(),
+                        )?,
+                    })
+                }
+            }
+        )+
+    }
+}
+
+impl_from_prog_info_unsafe!(
+    BtfTracePoint,
+    ProgramType::Tracing,
+    FEntry,
+    ProgramType::Tracing,
+    FExit,
+    ProgramType::Tracing,
+);
+
+impl_from_prog_info!(
+    CgroupDevice,
+    CgroupSysctl,
+    Extension,
+    LircMode2,
+    Lsm,
+    PerfEvent,
+    RawTracePoint,
+    SkLookup,
+    SkMsg,
+    SockOps,
+    SocketFilter,
+    SchedClassifier,
+);
+
+impl_from_prog_info_attach_type!(
+    CgroupSkb,
+    Option<CgroupSkbAttachType>,
+    CgroupSockAddr,
+    CgroupSockAddrAttachType,
+    CgroupSock,
+    CgroupSockAttachType,
+    CgroupSockopt,
+    CgroupSockoptAttachType,
+);
+
 macro_rules! impl_try_from_program {
     ($($ty:ident),+ $(,)?) => {
         $(
diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs
index 8c82d626..85d3258f 100644
--- a/aya/src/programs/probe.rs
+++ b/aya/src/programs/probe.rs
@@ -24,7 +24,7 @@ use crate::{
 static PROBE_NAME_INDEX: AtomicUsize = AtomicUsize::new(0);
 
 /// Kind of probe program
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 pub enum ProbeKind {
     /// Kernel probe
     KProbe,
diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs
index 72844899..9d69ba88 100644
--- a/aya/src/programs/uprobe.rs
+++ b/aya/src/programs/uprobe.rs
@@ -18,7 +18,8 @@ use thiserror::Error;
 use crate::{
     VerifierLogLevel,
     programs::{
-        FdLink, LinkError, ProgramData, ProgramError, define_link_wrapper, load_program,
+        FdLink, LinkError, ProgramData, ProgramError, ProgramInfo, ProgramType,
+        define_link_wrapper, load_program,
         perf_attach::{PerfLinkIdInner, PerfLinkInner},
         probe::{OsStringExt as _, ProbeKind, attach},
     },
@@ -139,6 +140,62 @@ impl UProbe {
         let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
         Ok(Self { data, kind })
     }
+
+    /// Constructs an instance of [UProbe] from a [ProgramInfo].
+    ///
+    /// This allows you to get a handle to an already loaded program
+    /// from the kernel without having to load it again.
+    ///
+    /// # Safety
+    ///
+    /// The type of program in the [ProgramInfo] may not be of
+    /// [`ProgramType::KProbe`]. This function is unable to
+    /// check since the kernel doesn't expose this information.
+    /// The caller is responsible for ensuring that the program
+    /// type is correct (i.e they previously loaded it) otherwise
+    /// the behavior is undefined.
+    ///
+    /// # Errors
+    ///
+    /// - If the program type is not  [`ProgramType::KProbe`]
+    /// - If the file descriptor of the program cannot be cloned
+    ///
+    /// # Example
+    /// ```no_run
+    /// # use aya::programs::loaded_programs;
+    /// # use aya::programs::{UProbe, ProbeKind, ProgramInfo, ProgramType};
+    ///
+    /// for program in loaded_programs() {
+    ///    let program = program?;
+    ///    if program.program_type()? == ProgramType::KProbe {
+    ///       let p = unsafe { UProbe::from_program_info(None, program, ProbeKind::UProbe)? };
+    ///       // do something with the program
+    ///     }
+    /// }
+    /// # Ok::<(), aya::programs::ProgramError>(())
+    /// ```
+    pub unsafe fn from_program_info(
+        name: Option<String>,
+        info: ProgramInfo,
+        kind: ProbeKind,
+    ) -> Result<Self, ProgramError> {
+        if info.program_type()? != ProgramType::KProbe {
+            return Err(ProgramError::UnexpectedProgramType {});
+        }
+        if kind != ProbeKind::UProbe && kind != ProbeKind::URetProbe {
+            return Err(ProgramError::UnexpectedProgramType {});
+        }
+        Ok(Self {
+            data: ProgramData::from_bpf_prog_info(
+                name,
+                crate::MockableFd::from_fd(info.fd()?.as_fd().try_clone_to_owned()?),
+                Path::new(""),
+                info.0,
+                VerifierLogLevel::default(),
+            )?,
+            kind,
+        })
+    }
 }
 
 fn resolve_attach_path<'a, 'b, 'c, T>(
diff --git a/test/integration-test/src/tests/info.rs b/test/integration-test/src/tests/info.rs
index 05b7a849..71395084 100644
--- a/test/integration-test/src/tests/info.rs
+++ b/test/integration-test/src/tests/info.rs
@@ -55,6 +55,12 @@ fn test_loaded_programs() {
         programs.any(|prog| prog.id() == test_prog.id()),
         KernelVersion::new(4, 13, 0)
     );
+
+    for program in programs {
+        let mut p: SocketFilter =
+            SocketFilter::from_program_info(Some("simple_prog".to_string()), program).unwrap();
+        p.unload().unwrap();
+    }
 }
 
 #[test]
diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt
index 6ed2a959..b818bd92 100644
--- a/xtask/public-api/aya.txt
+++ b/xtask/public-api/aya.txt
@@ -2539,6 +2539,8 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re
 impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::cgroup_device::CgroupDevice
+pub fn aya::programs::cgroup_device::CgroupDevice::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::cgroup_device::CgroupDevice, aya::programs::ProgramError>
+impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -2701,6 +2703,8 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya::
 impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_skb::CgroupSkb
+pub fn aya::programs::cgroup_skb::CgroupSkb::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: core::option::Option<aya::programs::cgroup_skb::CgroupSkbAttachType>) -> core::result::Result<aya::programs::cgroup_skb::CgroupSkb, aya::programs::ProgramError>
+impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -2827,6 +2831,8 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya
 impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sock::CgroupSock
+pub fn aya::programs::cgroup_sock::CgroupSock::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sock::CgroupSockAttachType) -> core::result::Result<aya::programs::cgroup_sock::CgroupSock, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -2953,6 +2959,8 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
+pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sock_addr::CgroupSockAddrAttachType) -> core::result::Result<aya::programs::cgroup_sock_addr::CgroupSockAddr, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::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::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -3079,6 +3087,8 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i
 impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sockopt::CgroupSockopt
+pub fn aya::programs::cgroup_sockopt::CgroupSockopt::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> core::result::Result<aya::programs::cgroup_sockopt::CgroupSockopt, aya::programs::ProgramError>
+impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -3205,6 +3215,8 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re
 impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::cgroup_sysctl::CgroupSysctl
+pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::cgroup_sysctl::CgroupSysctl, aya::programs::ProgramError>
+impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -3365,6 +3377,8 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a
 impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::extension::Extension
+pub fn aya::programs::extension::Extension::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::extension::Extension, aya::programs::ProgramError>
+impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -3495,6 +3509,8 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr
 impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::fentry::FEntry
+pub unsafe fn aya::programs::fentry::FEntry::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::fentry::FEntry, aya::programs::ProgramError>
+impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -3625,6 +3641,8 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog
 impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::fexit::FExit
+pub unsafe fn aya::programs::fexit::FExit::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::fexit::FExit, aya::programs::ProgramError>
+impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -3944,6 +3962,7 @@ pub struct aya::programs::kprobe::KProbe
 impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::attach<T: core::convert::AsRef<std::ffi::os_str::OsStr>>(&mut self, fn_name: T, offset: u64) -> core::result::Result<aya::programs::kprobe::KProbeLinkId, aya::programs::ProgramError>
 pub fn aya::programs::kprobe::KProbe::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
+pub unsafe fn aya::programs::kprobe::KProbe::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
 pub fn aya::programs::kprobe::KProbe::kind(&self) -> aya::programs::ProbeKind
 pub fn aya::programs::kprobe::KProbe::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl aya::programs::kprobe::KProbe
@@ -4649,6 +4668,8 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<&
 impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::lirc_mode2::LircMode2
+pub fn aya::programs::lirc_mode2::LircMode2::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::lirc_mode2::LircMode2, aya::programs::ProgramError>
+impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -4700,6 +4721,8 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs
 impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::lsm::Lsm
+pub fn aya::programs::lsm::Lsm::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::lsm::Lsm, aya::programs::ProgramError>
+impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -5026,6 +5049,8 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<&
 impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::perf_event::PerfEvent
+pub fn aya::programs::perf_event::PerfEvent::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::perf_event::PerfEvent, aya::programs::ProgramError>
+impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -5158,6 +5183,8 @@ pub fn aya::programs::raw_trace_point::RawTracePoint::fd(&self) -> core::result:
 impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::raw_trace_point::RawTracePoint
+pub fn aya::programs::raw_trace_point::RawTracePoint::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::raw_trace_point::RawTracePoint, aya::programs::ProgramError>
+impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -5288,6 +5315,8 @@ pub fn aya::programs::sk_lookup::SkLookup::fd(&self) -> core::result::Result<&ay
 impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sk_lookup::SkLookup
+pub fn aya::programs::sk_lookup::SkLookup::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sk_lookup::SkLookup, aya::programs::ProgramError>
+impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -5418,6 +5447,8 @@ pub fn aya::programs::sk_msg::SkMsg::fd(&self) -> core::result::Result<&aya::pro
 impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sk_msg::SkMsg
+pub fn aya::programs::sk_msg::SkMsg::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sk_msg::SkMsg, aya::programs::ProgramError>
+impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -5713,6 +5744,8 @@ pub fn aya::programs::sock_ops::SockOps::fd(&self) -> core::result::Result<&aya:
 impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sock_ops::SockOps
+pub fn aya::programs::sock_ops::SockOps::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sock_ops::SockOps, aya::programs::ProgramError>
+impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -5873,6 +5906,8 @@ pub fn aya::programs::socket_filter::SocketFilter::fd(&self) -> core::result::Re
 impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::socket_filter::SocketFilter
+pub fn aya::programs::socket_filter::SocketFilter::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::socket_filter::SocketFilter, aya::programs::ProgramError>
+impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -6151,6 +6186,8 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr
 impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::tc::SchedClassifier
+pub fn aya::programs::tc::SchedClassifier::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::tc::SchedClassifier, aya::programs::ProgramError>
+impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -6297,6 +6334,8 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<&
 impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::tp_btf::BtfTracePoint
+pub unsafe fn aya::programs::tp_btf::BtfTracePoint::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::tp_btf::BtfTracePoint, aya::programs::ProgramError>
+impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -6699,6 +6738,7 @@ pub struct aya::programs::uprobe::UProbe
 impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::attach<'loc, T: core::convert::AsRef<std::path::Path>, Loc: core::convert::Into<aya::programs::uprobe::UProbeAttachLocation<'loc>>>(&mut self, location: Loc, target: T, pid: core::option::Option<libc::unix::pid_t>, cookie: core::option::Option<u64>) -> core::result::Result<aya::programs::uprobe::UProbeLinkId, aya::programs::ProgramError>
 pub fn aya::programs::uprobe::UProbe::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
+pub unsafe fn aya::programs::uprobe::UProbe::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
 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>
 impl aya::programs::uprobe::UProbe
@@ -7341,9 +7381,12 @@ pub aya::programs::ProbeKind::UProbe
 pub aya::programs::ProbeKind::URetProbe
 impl core::clone::Clone for aya::programs::ProbeKind
 pub fn aya::programs::ProbeKind::clone(&self) -> aya::programs::ProbeKind
+impl core::cmp::PartialEq for aya::programs::ProbeKind
+pub fn aya::programs::ProbeKind::eq(&self, other: &aya::programs::ProbeKind) -> bool
 impl core::fmt::Debug for aya::programs::ProbeKind
 pub fn aya::programs::ProbeKind::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
 impl core::marker::Copy for aya::programs::ProbeKind
+impl core::marker::StructuralPartialEq for aya::programs::ProbeKind
 impl core::marker::Freeze for aya::programs::ProbeKind
 impl core::marker::Send for aya::programs::ProbeKind
 impl core::marker::Sync for aya::programs::ProbeKind
@@ -8053,6 +8096,8 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<&
 impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::tp_btf::BtfTracePoint
+pub unsafe fn aya::programs::tp_btf::BtfTracePoint::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::tp_btf::BtfTracePoint, aya::programs::ProgramError>
+impl aya::programs::tp_btf::BtfTracePoint
 pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8104,6 +8149,8 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re
 impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::cgroup_device::CgroupDevice
+pub fn aya::programs::cgroup_device::CgroupDevice::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::cgroup_device::CgroupDevice, aya::programs::ProgramError>
+impl aya::programs::cgroup_device::CgroupDevice
 pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8154,6 +8201,8 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya::
 impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_skb::CgroupSkb
+pub fn aya::programs::cgroup_skb::CgroupSkb::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: core::option::Option<aya::programs::cgroup_skb::CgroupSkbAttachType>) -> core::result::Result<aya::programs::cgroup_skb::CgroupSkb, aya::programs::ProgramError>
+impl aya::programs::cgroup_skb::CgroupSkb
 pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8203,6 +8252,8 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya
 impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sock::CgroupSock
+pub fn aya::programs::cgroup_sock::CgroupSock::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sock::CgroupSockAttachType) -> core::result::Result<aya::programs::cgroup_sock::CgroupSock, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock::CgroupSock
 pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8252,6 +8303,8 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sock_addr::CgroupSockAddr
+pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sock_addr::CgroupSockAddrAttachType) -> core::result::Result<aya::programs::cgroup_sock_addr::CgroupSockAddr, aya::programs::ProgramError>
+impl aya::programs::cgroup_sock_addr::CgroupSockAddr
 pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::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::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -8301,6 +8354,8 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i
 impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::cgroup_sockopt::CgroupSockopt
+pub fn aya::programs::cgroup_sockopt::CgroupSockopt::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, attach_type: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> core::result::Result<aya::programs::cgroup_sockopt::CgroupSockopt, aya::programs::ProgramError>
+impl aya::programs::cgroup_sockopt::CgroupSockopt
 pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8351,6 +8406,8 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re
 impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::cgroup_sysctl::CgroupSysctl
+pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::cgroup_sysctl::CgroupSysctl, aya::programs::ProgramError>
+impl aya::programs::cgroup_sysctl::CgroupSysctl
 pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8402,6 +8459,8 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a
 impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::extension::Extension
+pub fn aya::programs::extension::Extension::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::extension::Extension, aya::programs::ProgramError>
+impl aya::programs::extension::Extension
 pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8452,6 +8511,8 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr
 impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::fentry::FEntry
+pub unsafe fn aya::programs::fentry::FEntry::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::fentry::FEntry, aya::programs::ProgramError>
+impl aya::programs::fentry::FEntry
 pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8502,6 +8563,8 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog
 impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::fexit::FExit
+pub unsafe fn aya::programs::fexit::FExit::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::fexit::FExit, aya::programs::ProgramError>
+impl aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8594,6 +8657,7 @@ pub struct aya::programs::KProbe
 impl aya::programs::kprobe::KProbe
 pub fn aya::programs::kprobe::KProbe::attach<T: core::convert::AsRef<std::ffi::os_str::OsStr>>(&mut self, fn_name: T, offset: u64) -> core::result::Result<aya::programs::kprobe::KProbeLinkId, aya::programs::ProgramError>
 pub fn aya::programs::kprobe::KProbe::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
+pub unsafe fn aya::programs::kprobe::KProbe::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
 pub fn aya::programs::kprobe::KProbe::kind(&self) -> aya::programs::ProbeKind
 pub fn aya::programs::kprobe::KProbe::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 impl aya::programs::kprobe::KProbe
@@ -8688,6 +8752,8 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<&
 impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::lirc_mode2::LircMode2
+pub fn aya::programs::lirc_mode2::LircMode2::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::lirc_mode2::LircMode2, aya::programs::ProgramError>
+impl aya::programs::lirc_mode2::LircMode2
 pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8738,6 +8804,8 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs
 impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::lsm::Lsm
+pub fn aya::programs::lsm::Lsm::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::lsm::Lsm, aya::programs::ProgramError>
+impl aya::programs::lsm::Lsm
 pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8788,6 +8856,8 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<&
 impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::perf_event::PerfEvent
+pub fn aya::programs::perf_event::PerfEvent::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::perf_event::PerfEvent, aya::programs::ProgramError>
+impl aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -8936,6 +9006,8 @@ pub fn aya::programs::raw_trace_point::RawTracePoint::fd(&self) -> core::result:
 impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::raw_trace_point::RawTracePoint
+pub fn aya::programs::raw_trace_point::RawTracePoint::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::raw_trace_point::RawTracePoint, aya::programs::ProgramError>
+impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::raw_trace_point::RawTracePoint
 pub fn aya::programs::raw_trace_point::RawTracePoint::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -8988,6 +9060,8 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr
 impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
 impl aya::programs::tc::SchedClassifier
+pub fn aya::programs::tc::SchedClassifier::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::tc::SchedClassifier, aya::programs::ProgramError>
+impl aya::programs::tc::SchedClassifier
 pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 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>
@@ -9040,6 +9114,8 @@ pub fn aya::programs::sk_lookup::SkLookup::fd(&self) -> core::result::Result<&ay
 impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sk_lookup::SkLookup
+pub fn aya::programs::sk_lookup::SkLookup::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sk_lookup::SkLookup, aya::programs::ProgramError>
+impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sk_lookup::SkLookup
 pub fn aya::programs::sk_lookup::SkLookup::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -9090,6 +9166,8 @@ pub fn aya::programs::sk_msg::SkMsg::fd(&self) -> core::result::Result<&aya::pro
 impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sk_msg::SkMsg
+pub fn aya::programs::sk_msg::SkMsg::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sk_msg::SkMsg, aya::programs::ProgramError>
+impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sk_msg::SkMsg
 pub fn aya::programs::sk_msg::SkMsg::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -9189,6 +9267,8 @@ pub fn aya::programs::sock_ops::SockOps::fd(&self) -> core::result::Result<&aya:
 impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::sock_ops::SockOps
+pub fn aya::programs::sock_ops::SockOps::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::sock_ops::SockOps, aya::programs::ProgramError>
+impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::sock_ops::SockOps
 pub fn aya::programs::sock_ops::SockOps::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -9238,6 +9318,8 @@ pub fn aya::programs::socket_filter::SocketFilter::fd(&self) -> core::result::Re
 impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
 impl aya::programs::socket_filter::SocketFilter
+pub fn aya::programs::socket_filter::SocketFilter::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo) -> core::result::Result<aya::programs::socket_filter::SocketFilter, aya::programs::ProgramError>
+impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
 impl aya::programs::socket_filter::SocketFilter
 pub fn aya::programs::socket_filter::SocketFilter::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
@@ -9330,6 +9412,7 @@ pub struct aya::programs::UProbe
 impl aya::programs::uprobe::UProbe
 pub fn aya::programs::uprobe::UProbe::attach<'loc, T: core::convert::AsRef<std::path::Path>, Loc: core::convert::Into<aya::programs::uprobe::UProbeAttachLocation<'loc>>>(&mut self, location: Loc, target: T, pid: core::option::Option<libc::unix::pid_t>, cookie: core::option::Option<u64>) -> core::result::Result<aya::programs::uprobe::UProbeLinkId, aya::programs::ProgramError>
 pub fn aya::programs::uprobe::UProbe::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
+pub unsafe fn aya::programs::uprobe::UProbe::from_program_info(name: core::option::Option<alloc::string::String>, info: aya::programs::ProgramInfo, kind: aya::programs::ProbeKind) -> core::result::Result<Self, aya::programs::ProgramError>
 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>
 impl aya::programs::uprobe::UProbe