From e816582726fdc9f570a8de9e312c3ddaafca6819 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 27 Jan 2026 00:41:39 +0100 Subject: [PATCH 1/2] aya-ebpf: generalize btf_map_def macro type parameters Modify the btf_map_def! macro to generate flat #[repr(C)] structs instead of UnsafeCell wrappers. This produces BTF that both aya and libbpf can parse. Support type parameters with optional defaults and const generics with configurable types. Allow trailing commas and improve formatting. Also remove UnsafeCell traversal code from aya-obj loader since it is no longer needed with flat struct layout. --- aya-obj/src/btf/btf.rs | 4 - aya-obj/src/obj.rs | 43 --- ebpf/aya-ebpf/src/btf_maps/array.rs | 41 ++- ebpf/aya-ebpf/src/btf_maps/mod.rs | 103 +++++-- ebpf/aya-ebpf/src/btf_maps/ring_buf.rs | 44 ++- ebpf/aya-ebpf/src/btf_maps/sk_storage.rs | 44 ++- xtask/public-api/aya-ebpf.txt | 346 ++++++++++------------- xtask/public-api/aya-obj.txt | 1 - 8 files changed, 283 insertions(+), 343 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index bddc715bb..ff31887be 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -160,10 +160,6 @@ pub enum BtfError { /// unable to get symbol name #[error("Unable to get symbol name")] InvalidSymbolName, - - /// BTF map wrapper's layout is unexpected - #[error("BTF map wrapper's layout is unexpected: {0:?}")] - UnexpectedBtfMapWrapperLayout(Struct), } /// Available BTF features diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 0ed3fc132..e87474f40 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -1267,49 +1267,6 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe } }; - // In aya-ebpf, the BTF map definition types are not used directly in the - // map variables. Instead, they are wrapped in two nested types: - // - // * A struct representing the map type (e.g., `Array`, `HashMap`) that - // provides methods for interacting with the map type (e.g. - // `HashMap::get`, `RingBuf::reserve`). - // * It has a single field with name `__0`. - // * An `UnsafeCell`, which informs the Rust compiler that the type is - // thread-safe and can be safely mutated even as a global variable. The - // kernel guarantees map operation safety. - // * It has a single field with name `value`. - // - // Therefore, the traversal to the actual map definition looks like: - // - // HashMap -> __0 -> value - let mut s = s; - for (index, expected_field_name) in ["__0", "value"].into_iter().enumerate() { - match s.members.as_slice() { - [m] => { - let field_name = btf.string_at(m.name_offset)?; - if field_name.as_ref() != expected_field_name { - return Err(BtfError::UnexpectedBtfMapWrapperLayout(s.clone())); - } - s = match btf.type_by_id(m.btf_type)? { - BtfType::Struct(s) => s, - _ => { - return Err(BtfError::UnexpectedBtfType { - type_id: m.btf_type, - }); - } - }; - } - // If the first wrapper level is missing, use the original struct. - _ => { - if index == 0 { - break; - } else { - return Err(BtfError::UnexpectedBtfMapWrapperLayout(s.clone())); - } - } - } - } - for m in &s.members { match btf.string_at(m.name_offset)?.as_ref() { "type" => { diff --git a/ebpf/aya-ebpf/src/btf_maps/array.rs b/ebpf/aya-ebpf/src/btf_maps/array.rs index 91878fa2b..35bae3a14 100644 --- a/ebpf/aya-ebpf/src/btf_maps/array.rs +++ b/ebpf/aya-ebpf/src/btf_maps/array.rs @@ -1,17 +1,11 @@ -use core::{borrow::Borrow, cell::UnsafeCell, ptr::NonNull}; +use core::{borrow::Borrow, ptr::NonNull}; -use crate::{bindings::bpf_map_type::BPF_MAP_TYPE_ARRAY, btf_map_def, cty::c_long, insert, lookup}; +use crate::{btf_maps::btf_map_def, cty::c_long, insert, lookup}; -btf_map_def!(ArrayDef, BPF_MAP_TYPE_ARRAY); - -#[repr(transparent)] -pub struct Array(UnsafeCell>); - -unsafe impl Sync for Array {} - -impl Array { - /// Creates a new [`Array`] instance with elements of type `T`, maximum - /// capacity of `M` and additional flags `F`. +btf_map_def!( + /// A BTF-compatible BPF array map. + /// + /// This map type stores elements of type `T` indexed by `u32` keys. /// /// # Example /// @@ -19,16 +13,17 @@ impl Array { /// use aya_ebpf::{btf_maps::Array, macros::btf_map}; /// /// #[btf_map] - /// static ARRAY: Array = Array::new(); + /// static ARRAY: Array = Array::new(); /// ``` - #[expect( - clippy::new_without_default, - reason = "BPF maps are always used as static variables, therefore this method has to be `const`. `Default::default` is not `const`." - )] - pub const fn new() -> Self { - Self(UnsafeCell::new(ArrayDef::new())) - } - + pub struct Array, + map_type: BPF_MAP_TYPE_ARRAY, + max_entries: MAX_ENTRIES, + map_flags: FLAGS, + key_type: u32, + value_type: T, +); + +impl Array { #[inline(always)] pub fn get(&self, index: u32) -> Option<&T> { unsafe { self.lookup(index).map(|p| p.as_ref()) } @@ -46,12 +41,12 @@ impl Array { #[inline(always)] unsafe fn lookup(&self, index: u32) -> Option> { - lookup(self.0.get().cast(), &index) + lookup(self.as_ptr(), &index) } /// Sets the value of the element at the given index. #[inline(always)] pub fn set(&self, index: u32, value: impl Borrow, flags: u64) -> Result<(), c_long> { - insert(self.0.get().cast(), &index, value.borrow(), flags) + insert(self.as_ptr(), &index, value.borrow(), flags) } } diff --git a/ebpf/aya-ebpf/src/btf_maps/mod.rs b/ebpf/aya-ebpf/src/btf_maps/mod.rs index f0de57f37..c1b794217 100644 --- a/ebpf/aya-ebpf/src/btf_maps/mod.rs +++ b/ebpf/aya-ebpf/src/btf_maps/mod.rs @@ -19,42 +19,103 @@ impl AyaBtfMapMarker { } } -#[macro_export] +/// Defines a BTF-compatible map struct with flat `#[repr(C)]` layout. +/// +/// This macro generates a map definition struct that produces BTF metadata +/// compatible with both aya and libbpf loaders. +/// +/// The invoker provides `key_type` and `value_type` types without the `*const` +/// wrapper; the macro adds `*const` internally (this is a BTF implementation +/// detail). +/// +/// Generics are limited to type parameters (with optional defaults) followed by +/// a semicolon and const parameters (with optional defaults). Lifetimes and +/// bounds are not supported. +#[allow(unused_macro_rules)] macro_rules! btf_map_def { - ($name:ident, $t:ident $(, $field:ident : $ty:ty)* $(,)?) => { - #[expect( - dead_code, - reason = "These fields exist only for BTF metadata exposure. None of them are actually used." - )] - pub struct $name { - r#type: *const [i32; $t as usize], - key: *const K, - value: *const V, - max_entries: *const [i32; M], - map_flags: *const [i32; F], - - $($field: $ty,)* + ( + $(#[$attr:meta])* + $vis:vis struct $name:ident< + $($ty_gen:ident $(= $ty_default:ty)?),+ + $(; $(const $const_gen:ident : $const_ty:ty $(= $const_default:tt)?),+)? + $(,)? + >, + map_type: $map_type:ident, + max_entries: $max_entries:expr, + map_flags: $map_flags:expr, + key_type: $key_ty:ty, + value_type: $value_ty:ty + $(, $extra_field:ident : $extra_ty:ty)* + $(,)? + ) => { + $(#[$attr])* + // repr(C) is required to ensure fields maintain their declared order in BTF. + // Without it, Rust may reorder fields and libbpf will fail to parse the map definition. + #[repr(C)] + $vis struct $name< + $($ty_gen $(= $ty_default)?),+ + $(, $(const $const_gen : $const_ty $(= $const_default)?),+)? + > { + r#type: *const [i32; $crate::bindings::bpf_map_type::$map_type as usize], + key: *const $key_ty, + value: *const $value_ty, + + max_entries: *const [i32; $max_entries], + map_flags: *const [i32; $map_flags], + + $($extra_field: $extra_ty,)* // Anonymize the struct. _anon: $crate::btf_maps::AyaBtfMapMarker, } - #[expect( - clippy::new_without_default, - reason = "BPF maps are always used as static variables, therefore this method has to be `const`. `Default::default` is not `const`." - )] - impl $name { - pub const fn new() -> $name { + unsafe impl< + $($ty_gen),+ + $(, $(const $const_gen : $const_ty),+)? + > Sync for $name< + $($ty_gen),+ + $(, $($const_gen),+)? + > {} + + impl< + $($ty_gen),+ + $(, $(const $const_gen : $const_ty),+)? + > Default for $name< + $($ty_gen),+ + $(, $($const_gen),+)? + > { + fn default() -> Self { + Self::new() + } + } + + impl< + $($ty_gen),+ + $(, $(const $const_gen : $const_ty),+)? + > $name< + $($ty_gen),+ + $(, $($const_gen),+)? + > { + pub const fn new() -> Self { Self { r#type: ::core::ptr::null(), key: ::core::ptr::null(), value: ::core::ptr::null(), - $($field: ::core::ptr::null(),)* + max_entries: ::core::ptr::null(), map_flags: ::core::ptr::null(), + + $($extra_field: ::core::ptr::null(),)* _anon: $crate::btf_maps::AyaBtfMapMarker::new(), } } + + #[inline(always)] + pub(crate) fn as_ptr(&self) -> *mut ::core::ffi::c_void { + ::core::ptr::from_ref(self).cast_mut().cast() + } } }; } + +pub(crate) use btf_map_def; diff --git a/ebpf/aya-ebpf/src/btf_maps/ring_buf.rs b/ebpf/aya-ebpf/src/btf_maps/ring_buf.rs index dfa22ac61..60eedd942 100644 --- a/ebpf/aya-ebpf/src/btf_maps/ring_buf.rs +++ b/ebpf/aya-ebpf/src/btf_maps/ring_buf.rs @@ -1,30 +1,27 @@ -use core::{borrow::Borrow, cell::UnsafeCell, mem::MaybeUninit, ptr}; +use core::{borrow::Borrow, mem::MaybeUninit, ptr}; #[cfg(generic_const_exprs)] use crate::const_assert::{Assert, IsTrue}; use crate::{ - bindings::bpf_map_type::BPF_MAP_TYPE_RINGBUF, - btf_map_def, + btf_maps::btf_map_def, helpers::{bpf_ringbuf_output, bpf_ringbuf_reserve}, maps::ring_buf::{RingBufBytes, RingBufEntry}, }; -btf_map_def!(RingBufDef, BPF_MAP_TYPE_RINGBUF, value_size: *const [i32; 0]); - -#[repr(transparent)] -pub struct RingBuf(UnsafeCell>); - -unsafe impl Sync for RingBuf {} - -impl RingBuf { - #[expect( - clippy::new_without_default, - reason = "BPF maps are always used as static variables, therefore this method has to be `const`. `Default::default` is not `const`." - )] - pub const fn new() -> Self { - Self(UnsafeCell::new(RingBufDef::new())) - } +btf_map_def!( + /// A BTF-compatible BPF ring buffer map. + /// + /// Ring buffers have a special `value_size` field set to 0. + pub struct RingBuf, + map_type: BPF_MAP_TYPE_RINGBUF, + max_entries: MAX_ENTRIES, + map_flags: FLAGS, + key_type: (), + value_type: T, + value_size: *const [i32; 0], +); +impl RingBuf { /// Reserve a dynamically sized byte buffer in the ring buffer. /// /// Returns `None` if the ring buffer is full. @@ -33,8 +30,7 @@ impl RingBuf { /// allocation sizes. In other words, it is incumbent upon users of this function to convince /// the verifier that `size` is a compile-time constant. Good luck! pub fn reserve_bytes(&self, size: usize, flags: u64) -> Option> { - let ptr = - unsafe { bpf_ringbuf_reserve(self.0.get().cast(), size as u64, flags) }.cast::(); + let ptr = unsafe { bpf_ringbuf_reserve(self.as_ptr(), size as u64, flags) }.cast::(); unsafe { RingBufBytes::from_raw(ptr, size) } } @@ -45,7 +41,7 @@ impl RingBuf { pub fn reserve(&self, flags: u64) -> Option> where T: 'static, - Assert<{ 8 % mem::align_of::() == 0 }>: IsTrue, + Assert<{ 8 % align_of::() == 0 }>: IsTrue, { self.reserve_untyped::(flags) } @@ -72,7 +68,7 @@ impl RingBuf { #[cfg(generic_const_exprs)] pub fn reserve_untyped(&self, flags: u64) -> Option> where - Assert<{ 8 % mem::align_of::() == 0 }>: IsTrue, + Assert<{ 8 % align_of::() == 0 }>: IsTrue, { self.reserve_impl::(flags) } @@ -87,7 +83,7 @@ impl RingBuf { } fn reserve_impl(&self, flags: u64) -> Option> { - let ptr = unsafe { bpf_ringbuf_reserve(self.0.get().cast(), size_of::() as u64, flags) } + let ptr = unsafe { bpf_ringbuf_reserve(self.as_ptr(), size_of::() as u64, flags) } .cast::>(); unsafe { RingBufEntry::from_raw(ptr) } } @@ -117,7 +113,7 @@ impl RingBuf { assert_eq!(8 % align_of_val(data), 0); let ret = unsafe { bpf_ringbuf_output( - self.0.get().cast(), + self.as_ptr(), ptr::from_ref(data).cast_mut().cast(), size_of_val(data) as u64, flags, diff --git a/ebpf/aya-ebpf/src/btf_maps/sk_storage.rs b/ebpf/aya-ebpf/src/btf_maps/sk_storage.rs index 9519a708d..cb3a81baa 100644 --- a/ebpf/aya-ebpf/src/btf_maps/sk_storage.rs +++ b/ebpf/aya-ebpf/src/btf_maps/sk_storage.rs @@ -1,41 +1,35 @@ -use core::{cell::UnsafeCell, ptr}; +use core::ptr; -use aya_ebpf_bindings::bindings::{ - BPF_F_NO_PREALLOC, BPF_SK_STORAGE_GET_F_CREATE, bpf_map_type::BPF_MAP_TYPE_SK_STORAGE, bpf_sock, -}; +use aya_ebpf_bindings::bindings::{BPF_F_NO_PREALLOC, BPF_SK_STORAGE_GET_F_CREATE, bpf_sock}; use aya_ebpf_cty::c_long; use crate::{ - btf_map_def, + btf_maps::btf_map_def, helpers::generated::{bpf_sk_storage_delete, bpf_sk_storage_get}, programs::sock_addr::SockAddrContext, }; -btf_map_def!(SkStorageDef, BPF_MAP_TYPE_SK_STORAGE); - -// TODO(https://github.com/rust-lang/rust/issues/76560): this should be: -// -// { F | BPF_F_NO_PREALLOC as usize }. -#[repr(transparent)] -pub struct SkStorage(UnsafeCell>); - -unsafe impl Sync for SkStorage {} +btf_map_def!( + /// A BTF-compatible BPF socket storage map. + /// + /// Socket storage maps require `BPF_F_NO_PREALLOC` flag and `max_entries: 0`. + pub struct SkStorage, + map_type: BPF_MAP_TYPE_SK_STORAGE, + max_entries: 0, + // TODO(https://github.com/rust-lang/rust/issues/76560): this should be: + // + // { F | BPF_F_NO_PREALLOC as usize }. + map_flags: BPF_F_NO_PREALLOC as usize, + key_type: i32, + value_type: T, +); impl SkStorage { - #[expect( - clippy::new_without_default, - reason = "BPF maps are always used as static variables, therefore this method has to be `const`. `Default::default` is not `const`." - )] - pub const fn new() -> Self { - Self(UnsafeCell::new(SkStorageDef::new())) - } - #[inline(always)] fn get_ptr(&self, ctx: &SockAddrContext, value: *mut T, flags: u64) -> *mut T { let sock_addr = unsafe { &*ctx.sock_addr }; let sk = unsafe { sock_addr.__bindgen_anon_1.sk }; - unsafe { bpf_sk_storage_get(self.0.get().cast(), sk.cast(), value.cast(), flags) } - .cast::() + unsafe { bpf_sk_storage_get(self.as_ptr(), sk.cast(), value.cast(), flags) }.cast::() } /// Gets a mutable reference to the value associated with `sk`. @@ -75,7 +69,7 @@ impl SkStorage { /// This function may dereference the pointer `sk`. #[inline(always)] pub unsafe fn delete(&self, sk: *mut bpf_sock) -> Result<(), c_long> { - let ret = unsafe { bpf_sk_storage_delete(self.0.get().cast(), sk.cast()) }; + let ret = unsafe { bpf_sk_storage_delete(self.as_ptr(), sk.cast()) }; if ret == 0 { Ok(()) } else { Err(ret) } } } diff --git a/xtask/public-api/aya-ebpf.txt b/xtask/public-api/aya-ebpf.txt index 155db7d49..6e49c3a12 100644 --- a/xtask/public-api/aya-ebpf.txt +++ b/xtask/public-api/aya-ebpf.txt @@ -6,128 +6,87 @@ pub use aya_ebpf::bindings::<> pub use aya_ebpf::bindings::pt_regs pub mod aya_ebpf::btf_maps pub mod aya_ebpf::btf_maps::array -#[repr(transparent)] pub struct aya_ebpf::btf_maps::array::Array(_) -impl aya_ebpf::btf_maps::array::Array -pub fn aya_ebpf::btf_maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> -pub fn aya_ebpf::btf_maps::array::Array::get_ptr(&self, index: u32) -> core::option::Option<*const T> -pub fn aya_ebpf::btf_maps::array::Array::get_ptr_mut(&self, index: u32) -> core::option::Option<*mut T> -pub const fn aya_ebpf::btf_maps::array::Array::new() -> Self -pub fn aya_ebpf::btf_maps::array::Array::set(&self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya_ebpf_cty::od::c_long> -impl core::marker::Sync for aya_ebpf::btf_maps::array::Array -impl !core::marker::Freeze for aya_ebpf::btf_maps::array::Array -impl !core::marker::Send for aya_ebpf::btf_maps::array::Array -impl core::marker::Unpin for aya_ebpf::btf_maps::array::Array -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::array::Array -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::array::Array where U: core::convert::From -pub fn aya_ebpf::btf_maps::array::Array::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::array::Array where U: core::convert::Into -pub type aya_ebpf::btf_maps::array::Array::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::array::Array::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::array::Array where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::array::Array::Error = >::Error -pub fn aya_ebpf::btf_maps::array::Array::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::array::Array where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::array::Array -pub fn aya_ebpf::btf_maps::array::Array::from(t: T) -> T -pub struct aya_ebpf::btf_maps::array::ArrayDef -impl aya_ebpf::btf_maps::array::ArrayDef -pub const fn aya_ebpf::btf_maps::array::ArrayDef::new() -> aya_ebpf::btf_maps::array::ArrayDef -impl core::marker::Freeze for aya_ebpf::btf_maps::array::ArrayDef -impl !core::marker::Send for aya_ebpf::btf_maps::array::ArrayDef -impl !core::marker::Sync for aya_ebpf::btf_maps::array::ArrayDef -impl core::marker::Unpin for aya_ebpf::btf_maps::array::ArrayDef -impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::array::ArrayDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::array::ArrayDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::array::ArrayDef where U: core::convert::From -pub fn aya_ebpf::btf_maps::array::ArrayDef::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::array::ArrayDef where U: core::convert::Into -pub type aya_ebpf::btf_maps::array::ArrayDef::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::array::ArrayDef::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::array::ArrayDef where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::array::ArrayDef::Error = >::Error -pub fn aya_ebpf::btf_maps::array::ArrayDef::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::array::ArrayDef where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::ArrayDef::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::array::ArrayDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::ArrayDef::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::array::ArrayDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::ArrayDef::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::array::ArrayDef -pub fn aya_ebpf::btf_maps::array::ArrayDef::from(t: T) -> T +#[repr(C)] pub struct aya_ebpf::btf_maps::array::Array +impl aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> +pub fn aya_ebpf::btf_maps::array::Array::get_ptr(&self, index: u32) -> core::option::Option<*const T> +pub fn aya_ebpf::btf_maps::array::Array::get_ptr_mut(&self, index: u32) -> core::option::Option<*mut T> +pub fn aya_ebpf::btf_maps::array::Array::set(&self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya_ebpf_cty::od::c_long> +impl aya_ebpf::btf_maps::array::Array +pub const fn aya_ebpf::btf_maps::array::Array::new() -> Self +impl core::default::Default for aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::array::Array +impl core::marker::Freeze for aya_ebpf::btf_maps::array::Array +impl !core::marker::Send for aya_ebpf::btf_maps::array::Array +impl core::marker::Unpin for aya_ebpf::btf_maps::array::Array +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe +impl core::convert::Into for aya_ebpf::btf_maps::array::Array where U: core::convert::From +pub fn aya_ebpf::btf_maps::array::Array::into(self) -> U +impl core::convert::TryFrom for aya_ebpf::btf_maps::array::Array where U: core::convert::Into +pub type aya_ebpf::btf_maps::array::Array::Error = core::convert::Infallible +pub fn aya_ebpf::btf_maps::array::Array::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_ebpf::btf_maps::array::Array where U: core::convert::TryFrom +pub type aya_ebpf::btf_maps::array::Array::Error = >::Error +pub fn aya_ebpf::btf_maps::array::Array::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_ebpf::btf_maps::array::Array where T: 'static + ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::from(t: T) -> T pub mod aya_ebpf::btf_maps::ring_buf -#[repr(transparent)] pub struct aya_ebpf::btf_maps::ring_buf::RingBuf(_) -impl aya_ebpf::btf_maps::ring_buf::RingBuf -pub const fn aya_ebpf::btf_maps::ring_buf::RingBuf::new() -> Self -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output_untyped(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where T: 'static -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_bytes(&self, size: usize, flags: u64) -> core::option::Option> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_untyped(&self, flags: u64) -> core::option::Option> -impl core::marker::Sync for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::marker::Freeze for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::marker::Send for aya_ebpf::btf_maps::ring_buf::RingBuf -impl core::marker::Unpin for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::From -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::Into -pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = >::Error -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::ring_buf::RingBuf where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::ring_buf::RingBuf -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::from(t: T) -> T -pub struct aya_ebpf::btf_maps::ring_buf::RingBufDef -impl aya_ebpf::btf_maps::ring_buf::RingBufDef -pub const fn aya_ebpf::btf_maps::ring_buf::RingBufDef::new() -> aya_ebpf::btf_maps::ring_buf::RingBufDef -impl core::marker::Freeze for aya_ebpf::btf_maps::ring_buf::RingBufDef -impl !core::marker::Send for aya_ebpf::btf_maps::ring_buf::RingBufDef -impl !core::marker::Sync for aya_ebpf::btf_maps::ring_buf::RingBufDef -impl core::marker::Unpin for aya_ebpf::btf_maps::ring_buf::RingBufDef -impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBufDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBufDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::ring_buf::RingBufDef where U: core::convert::From -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::ring_buf::RingBufDef where U: core::convert::Into -pub type aya_ebpf::btf_maps::ring_buf::RingBufDef::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::ring_buf::RingBufDef where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::ring_buf::RingBufDef::Error = >::Error -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::ring_buf::RingBufDef where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::ring_buf::RingBufDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::ring_buf::RingBufDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::ring_buf::RingBufDef -pub fn aya_ebpf::btf_maps::ring_buf::RingBufDef::from(t: T) -> T +#[repr(C)] pub struct aya_ebpf::btf_maps::ring_buf::RingBuf +impl aya_ebpf::btf_maps::ring_buf::RingBuf +pub const fn aya_ebpf::btf_maps::ring_buf::RingBuf::new() -> Self +impl aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output_untyped(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where T: 'static +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_bytes(&self, size: usize, flags: u64) -> core::option::Option> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_untyped(&self, flags: u64) -> core::option::Option> +impl core::default::Default for aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::marker::Freeze for aya_ebpf::btf_maps::ring_buf::RingBuf +impl !core::marker::Send for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::marker::Unpin for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::convert::Into for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = >::Error +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_ebpf::btf_maps::ring_buf::RingBuf where T: 'static + ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::from(t: T) -> T pub mod aya_ebpf::btf_maps::sk_storage -#[repr(transparent)] pub struct aya_ebpf::btf_maps::sk_storage::SkStorage(_) +#[repr(C)] pub struct aya_ebpf::btf_maps::sk_storage::SkStorage impl aya_ebpf::btf_maps::sk_storage::SkStorage pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::delete(&self, sk: *mut aya_ebpf_bindings::x86_64::bindings::bpf_sock) -> core::result::Result<(), aya_ebpf_cty::od::c_long> pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::get_or_insert_ptr_mut(&self, ctx: &aya_ebpf::programs::sock_addr::SockAddrContext, value: core::option::Option<&mut T>) -> *mut T pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::get_ptr_mut(&self, ctx: &aya_ebpf::programs::sock_addr::SockAddrContext) -> *mut T +impl aya_ebpf::btf_maps::sk_storage::SkStorage pub const fn aya_ebpf::btf_maps::sk_storage::SkStorage::new() -> Self -impl core::marker::Sync for aya_ebpf::btf_maps::sk_storage::SkStorage -impl !core::marker::Freeze for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::default::Default for aya_ebpf::btf_maps::sk_storage::SkStorage +pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::marker::Freeze for aya_ebpf::btf_maps::sk_storage::SkStorage impl !core::marker::Send for aya_ebpf::btf_maps::sk_storage::SkStorage impl core::marker::Unpin for aya_ebpf::btf_maps::sk_storage::SkStorage -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage where T: core::panic::unwind_safe::RefUnwindSafe impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage where T: core::panic::unwind_safe::RefUnwindSafe impl core::convert::Into for aya_ebpf::btf_maps::sk_storage::SkStorage where U: core::convert::From pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::into(self) -> U @@ -145,101 +104,85 @@ impl core::borrow::BorrowMut for aya_ebpf::btf_maps::sk_storage::SkStorage pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_ebpf::btf_maps::sk_storage::SkStorage pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::from(t: T) -> T -pub struct aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl aya_ebpf::btf_maps::sk_storage::SkStorageDef -pub const fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::new() -> aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl core::marker::Freeze for aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl !core::marker::Send for aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl !core::marker::Sync for aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl core::marker::Unpin for aya_ebpf::btf_maps::sk_storage::SkStorageDef -impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorageDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorageDef where K: core::panic::unwind_safe::RefUnwindSafe, V: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::sk_storage::SkStorageDef where U: core::convert::From -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::sk_storage::SkStorageDef where U: core::convert::Into -pub type aya_ebpf::btf_maps::sk_storage::SkStorageDef::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::sk_storage::SkStorageDef where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::sk_storage::SkStorageDef::Error = >::Error -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::sk_storage::SkStorageDef where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::sk_storage::SkStorageDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::sk_storage::SkStorageDef where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::sk_storage::SkStorageDef -pub fn aya_ebpf::btf_maps::sk_storage::SkStorageDef::from(t: T) -> T -#[repr(transparent)] pub struct aya_ebpf::btf_maps::Array(_) -impl aya_ebpf::btf_maps::array::Array -pub fn aya_ebpf::btf_maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> -pub fn aya_ebpf::btf_maps::array::Array::get_ptr(&self, index: u32) -> core::option::Option<*const T> -pub fn aya_ebpf::btf_maps::array::Array::get_ptr_mut(&self, index: u32) -> core::option::Option<*mut T> -pub const fn aya_ebpf::btf_maps::array::Array::new() -> Self -pub fn aya_ebpf::btf_maps::array::Array::set(&self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya_ebpf_cty::od::c_long> -impl core::marker::Sync for aya_ebpf::btf_maps::array::Array -impl !core::marker::Freeze for aya_ebpf::btf_maps::array::Array -impl !core::marker::Send for aya_ebpf::btf_maps::array::Array -impl core::marker::Unpin for aya_ebpf::btf_maps::array::Array -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::array::Array -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::array::Array where U: core::convert::From -pub fn aya_ebpf::btf_maps::array::Array::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::array::Array where U: core::convert::Into -pub type aya_ebpf::btf_maps::array::Array::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::array::Array::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::array::Array where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::array::Array::Error = >::Error -pub fn aya_ebpf::btf_maps::array::Array::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::array::Array where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::array::Array::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::array::Array -pub fn aya_ebpf::btf_maps::array::Array::from(t: T) -> T -#[repr(transparent)] pub struct aya_ebpf::btf_maps::RingBuf(_) -impl aya_ebpf::btf_maps::ring_buf::RingBuf -pub const fn aya_ebpf::btf_maps::ring_buf::RingBuf::new() -> Self -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output_untyped(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where T: 'static -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_bytes(&self, size: usize, flags: u64) -> core::option::Option> -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_untyped(&self, flags: u64) -> core::option::Option> -impl core::marker::Sync for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::marker::Freeze for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::marker::Send for aya_ebpf::btf_maps::ring_buf::RingBuf -impl core::marker::Unpin for aya_ebpf::btf_maps::ring_buf::RingBuf -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf -impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe -impl core::convert::Into for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::From -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::into(self) -> U -impl core::convert::TryFrom for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::Into -pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = core::convert::Infallible -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::TryFrom -pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = >::Error -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for aya_ebpf::btf_maps::ring_buf::RingBuf where T: 'static + ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow(&self) -> &T -impl core::borrow::BorrowMut for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T -impl core::convert::From for aya_ebpf::btf_maps::ring_buf::RingBuf -pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::from(t: T) -> T -#[repr(transparent)] pub struct aya_ebpf::btf_maps::SkStorage(_) +#[repr(C)] pub struct aya_ebpf::btf_maps::Array +impl aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> +pub fn aya_ebpf::btf_maps::array::Array::get_ptr(&self, index: u32) -> core::option::Option<*const T> +pub fn aya_ebpf::btf_maps::array::Array::get_ptr_mut(&self, index: u32) -> core::option::Option<*mut T> +pub fn aya_ebpf::btf_maps::array::Array::set(&self, index: u32, value: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), aya_ebpf_cty::od::c_long> +impl aya_ebpf::btf_maps::array::Array +pub const fn aya_ebpf::btf_maps::array::Array::new() -> Self +impl core::default::Default for aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::array::Array +impl core::marker::Freeze for aya_ebpf::btf_maps::array::Array +impl !core::marker::Send for aya_ebpf::btf_maps::array::Array +impl core::marker::Unpin for aya_ebpf::btf_maps::array::Array +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::array::Array where T: core::panic::unwind_safe::RefUnwindSafe +impl core::convert::Into for aya_ebpf::btf_maps::array::Array where U: core::convert::From +pub fn aya_ebpf::btf_maps::array::Array::into(self) -> U +impl core::convert::TryFrom for aya_ebpf::btf_maps::array::Array where U: core::convert::Into +pub type aya_ebpf::btf_maps::array::Array::Error = core::convert::Infallible +pub fn aya_ebpf::btf_maps::array::Array::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_ebpf::btf_maps::array::Array where U: core::convert::TryFrom +pub type aya_ebpf::btf_maps::array::Array::Error = >::Error +pub fn aya_ebpf::btf_maps::array::Array::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_ebpf::btf_maps::array::Array where T: 'static + ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_ebpf::btf_maps::array::Array where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::array::Array::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_ebpf::btf_maps::array::Array +pub fn aya_ebpf::btf_maps::array::Array::from(t: T) -> T +#[repr(C)] pub struct aya_ebpf::btf_maps::RingBuf +impl aya_ebpf::btf_maps::ring_buf::RingBuf +pub const fn aya_ebpf::btf_maps::ring_buf::RingBuf::new() -> Self +impl aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::output_untyped(&self, data: impl core::borrow::Borrow, flags: u64) -> core::result::Result<(), i64> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve(&self, flags: u64) -> core::option::Option> where T: 'static +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_bytes(&self, size: usize, flags: u64) -> core::option::Option> +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::reserve_untyped(&self, flags: u64) -> core::option::Option> +impl core::default::Default for aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::marker::Freeze for aya_ebpf::btf_maps::ring_buf::RingBuf +impl !core::marker::Send for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::marker::Unpin for aya_ebpf::btf_maps::ring_buf::RingBuf +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::ring_buf::RingBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::convert::Into for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::From +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::into(self) -> U +impl core::convert::TryFrom for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::Into +pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = core::convert::Infallible +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_ebpf::btf_maps::ring_buf::RingBuf where U: core::convert::TryFrom +pub type aya_ebpf::btf_maps::ring_buf::RingBuf::Error = >::Error +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_ebpf::btf_maps::ring_buf::RingBuf where T: 'static + ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_ebpf::btf_maps::ring_buf::RingBuf where T: ?core::marker::Sized +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_ebpf::btf_maps::ring_buf::RingBuf +pub fn aya_ebpf::btf_maps::ring_buf::RingBuf::from(t: T) -> T +#[repr(C)] pub struct aya_ebpf::btf_maps::SkStorage impl aya_ebpf::btf_maps::sk_storage::SkStorage pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::delete(&self, sk: *mut aya_ebpf_bindings::x86_64::bindings::bpf_sock) -> core::result::Result<(), aya_ebpf_cty::od::c_long> pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::get_or_insert_ptr_mut(&self, ctx: &aya_ebpf::programs::sock_addr::SockAddrContext, value: core::option::Option<&mut T>) -> *mut T pub unsafe fn aya_ebpf::btf_maps::sk_storage::SkStorage::get_ptr_mut(&self, ctx: &aya_ebpf::programs::sock_addr::SockAddrContext) -> *mut T +impl aya_ebpf::btf_maps::sk_storage::SkStorage pub const fn aya_ebpf::btf_maps::sk_storage::SkStorage::new() -> Self -impl core::marker::Sync for aya_ebpf::btf_maps::sk_storage::SkStorage -impl !core::marker::Freeze for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::default::Default for aya_ebpf::btf_maps::sk_storage::SkStorage +pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::default() -> Self +impl core::marker::Sync for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::marker::Freeze for aya_ebpf::btf_maps::sk_storage::SkStorage impl !core::marker::Send for aya_ebpf::btf_maps::sk_storage::SkStorage impl core::marker::Unpin for aya_ebpf::btf_maps::sk_storage::SkStorage -impl !core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage +impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage where T: core::panic::unwind_safe::RefUnwindSafe impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::sk_storage::SkStorage where T: core::panic::unwind_safe::RefUnwindSafe impl core::convert::Into for aya_ebpf::btf_maps::sk_storage::SkStorage where U: core::convert::From pub fn aya_ebpf::btf_maps::sk_storage::SkStorage::into(self) -> U @@ -3024,7 +2967,6 @@ pub fn aya_ebpf::programs::xdp::XdpContext::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_ebpf::programs::xdp::XdpContext pub fn aya_ebpf::programs::xdp::XdpContext::from(t: T) -> T pub macro aya_ebpf::bpf_printk! -pub macro aya_ebpf::btf_map_def! pub const aya_ebpf::TASK_COMM_LEN: usize pub trait aya_ebpf::Argument: aya_ebpf::args::sealed::Argument impl aya_ebpf::Argument for T diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index 5e59c5ea2..cf3462212 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -30,7 +30,6 @@ pub aya_obj::btf::BtfError::MaximumTypeDepthReached pub aya_obj::btf::BtfError::MaximumTypeDepthReached::type_id: u32 pub aya_obj::btf::BtfError::SymbolOffsetNotFound pub aya_obj::btf::BtfError::SymbolOffsetNotFound::symbol_name: alloc::string::String -pub aya_obj::btf::BtfError::UnexpectedBtfMapWrapperLayout(aya_obj::btf::Struct) pub aya_obj::btf::BtfError::UnexpectedBtfType pub aya_obj::btf::BtfError::UnexpectedBtfType::type_id: u32 pub aya_obj::btf::BtfError::UnknownBtfType From 1fa7ee2823c4632fd4189ff75856a19c5796b764 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 27 Jan 2026 00:44:14 +0100 Subject: [PATCH 2/2] integration-test: add btf_maps libbpf compatibility tests Add integration tests to verify that btf_maps generated with the generalized btf_map_def macro are compatible with libbpf's bpf_map_def. Also add CI infrastructure for macOS cross-compilation to Linux musl, including stub headers and autoconf cache variables for libbpf-sys vendored dependencies. --- .github/workflows/ci.yml | 61 +++++++++++++++++++++ Brewfile | 5 ++ Cargo.toml | 1 + ci/bin/make | 8 +++ ci/headers/argp.h | 42 ++++++++++++++ ci/libbpf-sys.env | 6 ++ ci/macos-toolchain.env | 4 ++ clippy.sh | 16 ++++++ test/integration-ebpf/Cargo.toml | 4 ++ test/integration-ebpf/src/btf_maps_plain.rs | 29 ++++++++++ test/integration-test/Cargo.toml | 1 + test/integration-test/src/lib.rs | 1 + test/integration-test/src/tests.rs | 1 + test/integration-test/src/tests/btf_maps.rs | 31 +++++++++++ 14 files changed, 210 insertions(+) create mode 100755 ci/bin/make create mode 100644 ci/headers/argp.h create mode 100644 ci/libbpf-sys.env create mode 100644 ci/macos-toolchain.env create mode 100644 test/integration-ebpf/src/btf_maps_plain.rs create mode 100644 test/integration-test/src/tests/btf_maps.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb0d1a8c7..c6f2b0768 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,13 @@ jobs: - run: cargo +nightly fmt --all -- --check + - name: Install libbpf-rs prerequisites + run: | + set -euxo pipefail + + sudo apt update + sudo apt -y install autopoint + - run: ./clippy.sh # On the `aya-rs/aya` repository, regenerate the public API on a schedule. @@ -102,7 +109,19 @@ jobs: with: target: ${{ matrix.arch }} + - name: Install libbpf-rs prerequisites + run: | + set -euxo pipefail + + sudo apt update + sudo apt -y install autopoint + - name: Build + env: + # Fix for 32-bit ARM: Ubuntu 24.04 GCC defines _TIME_BITS=64 as a built-in, + # which requires _FILE_OFFSET_BITS=64 (glibc requirement). We must unset + # _TIME_BITS first because the built-in is seen before -D flags by libbpf-sys. + CFLAGS_armv7_unknown_linux_gnueabi: "-U_TIME_BITS -D_FILE_OFFSET_BITS=64" run: | set -euxo pipefail cargo hack build --all-targets --feature-powerset \ @@ -262,7 +281,12 @@ jobs: sudo udevadm trigger --name-match=kvm || true # kvm is not available on arm64. sudo apt update + # linux-libc-dev provides kernel UAPI headers for libbpf-sys cross-compilation. + # + # See https://github.com/libbpf/libbpf-sys/issues/137. sudo apt -y install \ + autopoint \ + linux-libc-dev \ liblzma-dev \ lynx \ musl-tools \ @@ -370,10 +394,47 @@ jobs: if: runner.os == 'Linux' && matrix.skip-local != true run: cargo xtask integration-test local + # macOS cross-compilation fixes for libbpf-sys vendored dependencies. + # + # See https://github.com/libbpf/libbpf-sys/issues/137. + - name: Set cross-compilation env for macOS + if: runner.os == 'macOS' + run: | + # Add make wrapper that overrides AR/RANLIB for zlib build. + echo "${{ github.workspace }}/ci/bin" >> $GITHUB_PATH + # Export env vars, stripping comments and quotes (shell quoting breaks GITHUB_ENV). + grep -v '^#' ci/libbpf-sys.env ci/macos-toolchain.env | grep -v '^$' | sed 's/"//g' >> $GITHUB_ENV + + # libbpf-sys cross-compilation workarounds: + # - linux-libc-dev provides kernel UAPI headers (installed above) + # - LIBBPF_SYS_EXTRA_CFLAGS adds -idirafter for cross-compile header paths + # - ac_cv_search_* variables from ci/libbpf-sys.env skip autoconf checks + # + # See https://github.com/libbpf/libbpf-sys/issues/137. - name: Run virtualized integration tests if: matrix.download-kernel-images != 'local' run: | set -euxo pipefail + + # Source cross-compilation env vars for libbpf-sys vendored dependencies. + set -a + . ci/libbpf-sys.env + if [ "$(uname -s)" = "Darwin" ]; then + . ci/macos-toolchain.env + fi + set +a + + arch=$(uname -m) + libbpf_sys_extra_cflags=(-idirafter "/usr/include/${arch}-linux-gnu" -idirafter /usr/include) + if [ "${arch}" = aarch64 ]; then + libbpf_sys_extra_cflags+=(-mno-outline-atomics) + fi + export LIBBPF_SYS_EXTRA_CFLAGS="${libbpf_sys_extra_cflags[@]}" + + # libbpf-sys forwards LIBBPF_SYS_EXTRA_CFLAGS to libbpf, but the + # vendored elfutils build ignores it and only honors CFLAGS/CPPFLAGS. + export CFLAGS='-I${{ github.workspace }}/ci/headers' + find test/.tmp -name '*.deb' -print0 | sort -Vz | xargs -t -0 \ cargo xtask integration-test vm --cache-dir test/.tmp \ --github-api-token ${{ secrets.GITHUB_TOKEN }} diff --git a/Brewfile b/Brewfile index fe52a392d..54aad4e51 100644 --- a/Brewfile +++ b/Brewfile @@ -12,6 +12,11 @@ brew "lynx" brew "pkg-config" brew "qemu" +# Required by libbpf-sys vendored dependencies. +brew "autoconf" +brew "automake" +brew "gawk" + # macOS provides only dynamic zlib. Install the static one. brew "zlib" diff --git a/Cargo.toml b/Cargo.toml index 5014a789c..e726cd48d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,7 @@ futures = { version = "0.3.28", default-features = false } glob = { version = "0.3.0", default-features = false } hashbrown = { version = "0.16.0", default-features = false } indoc = { version = "2.0", default-features = false } +libbpf-rs = { version = "0.25", default-features = false } libc = { version = "0.2.105", default-features = false } log = { version = "0.4", default-features = false } network-types = { version = "0.1.0", default-features = false } diff --git a/ci/bin/make b/ci/bin/make new file mode 100755 index 000000000..bd84722df --- /dev/null +++ b/ci/bin/make @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +set -eux + +# Wrapper to override AR/RANLIB for cross-compilation from macOS to Linux musl. +# zlib's configure sets AR=libtool on Darwin (Mach-O format, not ELF). +# See https://github.com/madler/zlib/issues/331 +exec /usr/bin/make AR=x86_64-linux-musl-ar ARFLAGS=rcs RANLIB=x86_64-linux-musl-ranlib "$@" diff --git a/ci/headers/argp.h b/ci/headers/argp.h new file mode 100644 index 000000000..1e58b3659 --- /dev/null +++ b/ci/headers/argp.h @@ -0,0 +1,42 @@ +#ifndef AYA_CI_STUB_ARGP_H +#define AYA_CI_STUB_ARGP_H + +#include + +typedef int error_t; + +struct argp_option { + const char *name; + int key; + const char *arg; + int flags; + const char *doc; + int group; +}; + +struct argp_state; + +typedef error_t (*argp_parser_t)(int key, char *arg, struct argp_state *state); + +struct argp { + const struct argp_option *options; + argp_parser_t parser; + const char *args_doc; + const char *doc; + const void *children; + void *help_filter; + const char *argp_domain; +}; + +struct argp_state { + const char *name; +}; + +#define OPTION_ARG_OPTIONAL 0x1 +#define ARGP_HELP_SEE 0x40 +#define ARGP_ERR_UNKNOWN 1 + +int argp_help(const struct argp *argp, FILE *stream, unsigned int flags, + char *name); + +#endif /* AYA_CI_STUB_ARGP_H */ diff --git a/ci/libbpf-sys.env b/ci/libbpf-sys.env new file mode 100644 index 000000000..2cb34fa0b --- /dev/null +++ b/ci/libbpf-sys.env @@ -0,0 +1,6 @@ +# Autoconf cache variables to skip configure checks for libraries unavailable +# during cross-compilation. +ac_cv_search_argp_parse="none required" +ac_cv_search__obstack_free="none required" +ac_cv_search_gzdirect="none required" +ac_cv_search_fts_close="none required" diff --git a/ci/macos-toolchain.env b/ci/macos-toolchain.env new file mode 100644 index 000000000..36808433f --- /dev/null +++ b/ci/macos-toolchain.env @@ -0,0 +1,4 @@ +# Target-specific toolchain for x86_64 musl cross-compilation on macOS. +# cc-rs checks AR_{target} before AR, so these only apply for x86_64-unknown-linux-musl. +AR_x86_64_unknown_linux_musl=x86_64-linux-musl-ar +RANLIB_x86_64_unknown_linux_musl=x86_64-linux-musl-ranlib diff --git a/clippy.sh b/clippy.sh index 9641623b2..48feb9b7a 100755 --- a/clippy.sh +++ b/clippy.sh @@ -2,6 +2,22 @@ set -eux +# macOS cross-compilation fixes for libbpf-sys vendored dependencies. +# +# PATH and CFLAGS are set here rather than in libbpf-sys.env because they +# require dynamic absolute paths (the env file only contains static values). +# +# See https://github.com/libbpf/libbpf-sys/issues/137. +if [ "$(uname -s)" = "Darwin" ]; then + script_dir=$(cd "$(dirname "$0")" && pwd) + export PATH="$script_dir/ci/bin:$PATH" + export CFLAGS="-I$script_dir/ci/headers" + set -a + . "$script_dir/ci/libbpf-sys.env" + . "$script_dir/ci/macos-toolchain.env" + set +a +fi + # `-C panic=abort` because "unwinding panics are not supported without std"; integration-ebpf # contains `#[no_std]` binaries. # diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index 33715cfb8..a9bcd75f7 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -32,6 +32,10 @@ path = "src/array.rs" name = "bpf_probe_read" path = "src/bpf_probe_read.rs" +[[bin]] +name = "btf_maps_plain" +path = "src/btf_maps_plain.rs" + [[bin]] name = "linear_data_structures" path = "src/linear_data_structures.rs" diff --git a/test/integration-ebpf/src/btf_maps_plain.rs b/test/integration-ebpf/src/btf_maps_plain.rs new file mode 100644 index 000000000..f75e60284 --- /dev/null +++ b/test/integration-ebpf/src/btf_maps_plain.rs @@ -0,0 +1,29 @@ +//! eBPF program using only btf_maps (no legacy maps). +//! +//! This program is used to test that libbpf can load BTF maps +//! produced by aya-ebpf's btf_maps module. + +#![no_std] +#![no_main] +#![expect(unused_crate_dependencies, reason = "used in other bins")] + +#[cfg(not(test))] +extern crate ebpf_panic; + +use aya_ebpf::{ + btf_maps::Array, + macros::{btf_map, uprobe}, + programs::ProbeContext, +}; + +#[btf_map] +static BTF_ARRAY: Array = Array::new(); + +#[uprobe] +fn btf_maps_plain(_ctx: ProbeContext) -> u32 { + if let Some(value) = BTF_ARRAY.get(0) { + *value as u32 + } else { + 0 + } +} diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index aed0ab90c..535cfdbe1 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -24,6 +24,7 @@ aya-obj = { path = "../../aya-obj", version = "^0.2.2", default-features = false epoll = { workspace = true } futures = { workspace = true, features = ["alloc"] } integration-common = { path = "../integration-common", features = ["user"] } +libbpf-rs = { workspace = true, features = ["static", "vendored"] } libc = { workspace = true } log = { workspace = true } nix = { workspace = true, features = ["mount", "sched"] } diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 04d87bc6e..4027c0146 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -41,6 +41,7 @@ bpf_file!( ARRAY => "array", BPF_PROBE_READ => "bpf_probe_read", + BTF_MAPS_PLAIN => "btf_maps_plain", LINEAR_DATA_STRUCTURES => "linear_data_structures", LOG => "log", MAP_TEST => "map_test", diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index 4de831aad..fdc078361 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -1,5 +1,6 @@ mod array; mod bpf_probe_read; +mod btf_maps; mod btf_relocations; mod elf; mod feature_probe; diff --git a/test/integration-test/src/tests/btf_maps.rs b/test/integration-test/src/tests/btf_maps.rs new file mode 100644 index 000000000..37f82452b --- /dev/null +++ b/test/integration-test/src/tests/btf_maps.rs @@ -0,0 +1,31 @@ +//! Test that libbpf can load BTF maps from Rust eBPF programs. +//! +//! This test verifies that the BTF metadata produced by aya-ebpf's btf_maps +//! is compatible with libbpf's loader. + +/// Test that libbpf can open and load a Rust eBPF program with btf_maps. +/// +/// This verifies that our BTF map definitions produce metadata that libbpf +/// can parse and load. +#[test_log::test] +fn libbpf_can_load_btf_maps() { + // Use libbpf-rs to open the object file. + let obj = libbpf_rs::ObjectBuilder::default() + .open_memory(crate::BTF_MAPS_PLAIN) + .expect("libbpf failed to open Rust eBPF object with btf_maps"); + + // Verify libbpf can see the BTF_ARRAY map. + + // Materialize the maps because `OpenMap::name` returns the wrong lifetime. + // + // TODO(https://github.com/libbpf/libbpf-rs/commit/9622223): remove the `collect` when this commit is released. + let maps = obj.maps().collect::>(); + let map_names: Vec<_> = maps.iter().map(|m| m.name()).collect(); + if !map_names.iter().any(|name| *name == "BTF_ARRAY") { + let display_map_names = map_names.join(std::ffi::OsStr::new(", ")); + panic!( + "libbpf should find the BTF_ARRAY map defined with btf_map macro, found: {}", + display_map_names.display() + ); + } +}