1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use aya_ebpf_bindings::bindings::{BPF_F_STACK_BUILD_ID, PERF_MAX_STACK_DEPTH};
use crate::btf_maps::btf_map_def;
btf_map_def!(
/// A BTF-compatible BPF stack-trace map.
///
/// Stores hashed stack traces keyed by a `u32` stack ID, where each value
/// is a fixed-depth array of return addresses. Populate a stack trace by
/// calling [`StackIdContext::get_stackid`][get-stackid] from a tracing
/// program; read the resulting trace from user space via
/// `aya::maps::StackTraceMap`.
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 4.6.
///
/// # Flag restrictions
///
/// `BPF_F_STACK_BUILD_ID` switches the kernel element layout to
/// `struct bpf_stack_build_id` (32 bytes), which this type does not
/// model. Calling [`StackIdContext::get_stackid`][get-stackid] on a
/// monomorphisation that sets the flag fails to compile, and loading
/// such a map for reading through `aya::maps::StackTraceMap` is
/// rejected at load time.
///
/// # Example
///
/// ```rust
/// use aya_ebpf::{btf_maps::StackTrace, macros::btf_map};
///
/// #[btf_map]
/// static STACK_TRACES: StackTrace<1024> = StackTrace::new();
/// ```
///
/// [get-stackid]: crate::programs::tracing::StackIdContext::get_stackid
pub struct StackTrace<;
const MAX_ENTRIES: usize,
const FLAGS: usize = 0,
const DEPTH: usize = { PERF_MAX_STACK_DEPTH as usize },
>,
map_type: BPF_MAP_TYPE_STACK_TRACE,
max_entries: MAX_ENTRIES,
map_flags: FLAGS,
key_type: u32,
value_type: [u64; DEPTH],
);
impl<const MAX_ENTRIES: usize, const FLAGS: usize, const DEPTH: usize>
StackTrace<MAX_ENTRIES, FLAGS, DEPTH>
{
// `const _: ()` is forbidden in a generic impl; a named associated
// const is lazy without reference, hence `let () = Self::_CHECK` in
// the `StackTraceMap::as_ptr` impl below.
const _CHECK: () = {
assert!(DEPTH > 0, "stack trace DEPTH must be greater than zero.");
assert!(
MAX_ENTRIES > 0,
"stack trace max_entries must be greater than zero.",
);
assert!(
FLAGS & BPF_F_STACK_BUILD_ID as usize == 0,
"BPF_F_STACK_BUILD_ID is not supported by StackTrace.",
);
};
}
impl<const MAX_ENTRIES: usize, const FLAGS: usize, const DEPTH: usize>
crate::programs::tracing::sealed::StackTraceMap for StackTrace<MAX_ENTRIES, FLAGS, DEPTH>
{
fn as_ptr(&self) -> *mut core::ffi::c_void {
let () = Self::_CHECK;
self.as_ptr()
}
}