1 // SPDX-License-Identifier: GPL-2.0
4 #include "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.
50 typedef __u64 raw_stack_trace_t
[2 * MAX_STACK_RAWTP
];
52 __uint(type
, BPF_MAP_TYPE_PERCPU_ARRAY
);
53 __uint(max_entries
, 1);
55 __type(value
, raw_stack_trace_t
);
56 } rawdata_map
SEC(".maps");
58 SEC("tracepoint/raw_syscalls/sys_enter")
59 int bpf_prog1(void *ctx
)
61 int max_len
, max_buildid_len
, usize
, ksize
, total_size
;
62 struct stack_trace_t
*data
;
66 data
= bpf_map_lookup_elem(&stackdata_map
, &key
);
70 max_len
= MAX_STACK_RAWTP
* sizeof(__u64
);
71 max_buildid_len
= MAX_STACK_RAWTP
* sizeof(struct bpf_stack_build_id
);
72 data
->pid
= bpf_get_current_pid_tgid();
73 data
->kern_stack_size
= bpf_get_stack(ctx
, data
->kern_stack
,
75 data
->user_stack_size
= bpf_get_stack(ctx
, data
->user_stack
, max_len
,
77 data
->user_stack_buildid_size
= bpf_get_stack(
78 ctx
, data
->user_stack_buildid
, max_buildid_len
,
79 BPF_F_USER_STACK
| BPF_F_USER_BUILD_ID
);
80 bpf_perf_event_output(ctx
, &perfmap
, 0, data
, sizeof(*data
));
82 /* write both kernel and user stacks to the same buffer */
83 raw_data
= bpf_map_lookup_elem(&rawdata_map
, &key
);
87 usize
= bpf_get_stack(ctx
, raw_data
, max_len
, BPF_F_USER_STACK
);
91 ksize
= bpf_get_stack(ctx
, raw_data
+ usize
, max_len
- usize
, 0);
95 total_size
= usize
+ ksize
;
96 if (total_size
> 0 && total_size
<= max_len
)
97 bpf_perf_event_output(ctx
, &perfmap
, 0, raw_data
, total_size
);
102 char _license
[] SEC("license") = "GPL";
103 __u32 _version
SEC("version") = 1; /* ignored by tracepoints, required by libbpf.a */