use core::{cell::UnsafeCell, mem}; use crate::{ EbpfContext, bindings::bpf_map_type::BPF_MAP_TYPE_STACK_TRACE, btf_maps::AyaBtfMapMarker, helpers::bpf_get_stackid, }; const PERF_MAX_STACK_DEPTH: usize = 127; const VALUE_SIZE: usize = mem::size_of::() * PERF_MAX_STACK_DEPTH; #[allow(dead_code)] pub struct StackTraceDef { r#type: *const [i32; BPF_MAP_TYPE_STACK_TRACE as usize], key_size: *const [i32; mem::size_of::()], value_size: *const [i32; VALUE_SIZE], max_entries: *const [i32; M], map_flags: *const [i32; F], // Anonymize the struct. _anon: AyaBtfMapMarker, } #[repr(transparent)] pub struct StackTrace(UnsafeCell>); unsafe impl Sync for StackTrace {} impl StackTrace { // Implementing `Default` makes no sense in this case. Maps are always // global variables, so they need to be instantiated with a `const` method. // The `Default::default` method is not `const`. #[allow(clippy::new_without_default)] pub const fn new() -> Self { Self(UnsafeCell::new(StackTraceDef { r#type: &[0i32; BPF_MAP_TYPE_STACK_TRACE as usize], key_size: &[0i32; mem::size_of::()], value_size: &[0i32; VALUE_SIZE], max_entries: &[0i32; M], map_flags: &[0i32; F], _anon: AyaBtfMapMarker::new(), })) } pub unsafe fn get_stackid(&self, ctx: &C, flags: u64) -> Result { let ret = unsafe { bpf_get_stackid(ctx.as_ptr(), self.0.get() as *mut _, flags) }; if ret < 0 { Err(ret) } else { Ok(ret) } } }