1 // SPDX-License-Identifier: GPL-2.0
4 #include <bpf/bpf_helpers.h>
6 /* Permit pretty deep stack traces */
7 #define MAX_STACK_RAWTP 100
12 int user_stack_buildid_size
;
13 __u64 kern_stack
[MAX_STACK_RAWTP
];
14 __u64 user_stack
[MAX_STACK_RAWTP
];
15 struct bpf_stack_build_id user_stack_buildid
[MAX_STACK_RAWTP
];
19 __uint(type
, BPF_MAP_TYPE_PERF_EVENT_ARRAY
);
20 __uint(max_entries
, 2);
21 __uint(key_size
, sizeof(int));
22 __uint(value_size
, sizeof(__u32
));
23 } perfmap
SEC(".maps");
26 __uint(type
, BPF_MAP_TYPE_PERCPU_ARRAY
);
27 __uint(max_entries
, 1);
29 __type(value
, struct stack_trace_t
);
30 } stackdata_map
SEC(".maps");
32 /* Allocate per-cpu space twice the needed. For the code below
33 * usize = bpf_get_stack(ctx, raw_data, max_len, BPF_F_USER_STACK);
36 * ksize = bpf_get_stack(ctx, raw_data + usize, max_len - usize, 0);
38 * If we have value_size = MAX_STACK_RAWTP * sizeof(__u64),
39 * verifier will complain that access "raw_data + usize"
40 * with size "max_len - usize" may be out of bound.
41 * The maximum "raw_data + usize" is "raw_data + max_len"
42 * and the maximum "max_len - usize" is "max_len", verifier
43 * concludes that the maximum buffer access range is
44 * "raw_data[0...max_len * 2 - 1]" and hence reject the program.
46 * Doubling the to-be-used max buffer size can fix this verifier
47 * issue and avoid complicated C programming massaging.
48 * This is an acceptable workaround since there is one entry here.
51 __uint(type
, BPF_MAP_TYPE_PERCPU_ARRAY
);
52 __uint(max_entries
, 1);
54 __type(value
, __u64
[2 * MAX_STACK_RAWTP
]);
55 } rawdata_map
SEC(".maps");
57 SEC("raw_tracepoint/sys_enter")
58 int bpf_prog1(void *ctx
)
60 int max_len
, max_buildid_len
, usize
, ksize
, total_size
;
61 struct stack_trace_t
*data
;
65 data
= bpf_map_lookup_elem(&stackdata_map
, &key
);
69 max_len
= MAX_STACK_RAWTP
* sizeof(__u64
);
70 max_buildid_len
= MAX_STACK_RAWTP
* sizeof(struct bpf_stack_build_id
);
71 data
->pid
= bpf_get_current_pid_tgid();
72 data
->kern_stack_size
= bpf_get_stack(ctx
, data
->kern_stack
,
74 data
->user_stack_size
= bpf_get_stack(ctx
, data
->user_stack
, max_len
,
76 data
->user_stack_buildid_size
= bpf_get_stack(
77 ctx
, data
->user_stack_buildid
, max_buildid_len
,
78 BPF_F_USER_STACK
| BPF_F_USER_BUILD_ID
);
79 bpf_perf_event_output(ctx
, &perfmap
, 0, data
, sizeof(*data
));
81 /* write both kernel and user stacks to the same buffer */
82 raw_data
= bpf_map_lookup_elem(&rawdata_map
, &key
);
86 usize
= bpf_get_stack(ctx
, raw_data
, max_len
, BPF_F_USER_STACK
);
90 ksize
= bpf_get_stack(ctx
, raw_data
+ usize
, max_len
- usize
, 0);
94 total_size
= usize
+ ksize
;
95 if (total_size
> 0 && total_size
<= max_len
)
96 bpf_perf_event_output(ctx
, &perfmap
, 0, raw_data
, total_size
);
101 char _license
[] SEC("license") = "GPL";