selftests/bpf: Add stacktrace test for uprobe[_multi] programs Adding stacktrace test for uprobe[_multi] probes. Signed-off-by: Jiri Olsa <jolsa@kernel.org>
diff --git a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c index ba464e4..43c6a1b 100644 --- a/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c +++ b/tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
@@ -176,6 +176,62 @@ static void test_stacktrace_map_tracing(bool exit) stacktrace_map__destroy(skel); } +noinline void stacktrace_map_uprobe_trigger(void) +{ + asm volatile (""); +} + +static void test_stacktrace_map_uprobe(bool retprobe) +{ + LIBBPF_OPTS(bpf_uprobe_opts, opts, + .retprobe = retprobe, + .func_name = "stacktrace_map_uprobe_trigger", + ); + LIBBPF_OPTS(bpf_test_run_opts, topts); + struct stacktrace_map *skel; + + skel = stacktrace_map__open_and_load(); + if (!ASSERT_OK_PTR(skel, "stacktrace_map__open_and_load")) + return; + + skel->links.uprobe_test = bpf_program__attach_uprobe_opts(skel->progs.uprobe_test, + -1 /* pid */, "/proc/self/exe", 0 /* offset */, + &opts); + if (!ASSERT_OK_PTR(skel->links.uprobe_test, "bpf_program__attach_uprobe_opts")) + goto cleanup; + + stacktrace_map_uprobe_trigger(); + check_stackmap(skel); + +cleanup: + stacktrace_map__destroy(skel); +} + +static void test_stacktrace_map_uprobe_multi(bool retprobe) +{ + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts, + .retprobe = retprobe + ); + struct stacktrace_map *skel; + + skel = stacktrace_map__open_and_load(); + if (!ASSERT_OK_PTR(skel, "stacktrace_map__open_and_load")) + return; + + skel->links.uprobe_multi_test = bpf_program__attach_uprobe_multi(skel->progs.uprobe_multi_test, + -1 /* pid */, "/proc/self/exe", + "stacktrace_map_uprobe_trigger", + &opts); + if (!ASSERT_OK_PTR(skel->links.uprobe_multi_test, "bpf_program__attach_uprobe_multi")) + goto cleanup; + + stacktrace_map_uprobe_trigger(); + check_stackmap(skel); + +cleanup: + stacktrace_map__destroy(skel); +} + void test_stacktrace_map(void) { if (test__start_subtest("tp")) @@ -194,4 +250,12 @@ void test_stacktrace_map(void) test_stacktrace_map_tracing(false); if (test__start_subtest("fexit")) test_stacktrace_map_tracing(true); + if (test__start_subtest("uprobe")) + test_stacktrace_map_uprobe(false); + if (test__start_subtest("uretprobe")) + test_stacktrace_map_uprobe(true); + if (test__start_subtest("uprobe_multi")) + test_stacktrace_map_uprobe_multi(false); + if (test__start_subtest("uretprobe_multi")) + test_stacktrace_map_uprobe_multi(true); }
diff --git a/tools/testing/selftests/bpf/progs/stacktrace_map.c b/tools/testing/selftests/bpf/progs/stacktrace_map.c index 37f598c..130fd63 100644 --- a/tools/testing/selftests/bpf/progs/stacktrace_map.c +++ b/tools/testing/selftests/bpf/progs/stacktrace_map.c
@@ -62,7 +62,7 @@ struct sched_switch_args { }; __u32 stack_id; -static inline void test_stackmap(void *ctx, int skip) +static inline void test_stackmap_flags(void *ctx, __u64 flags) { __u32 max_len = PERF_MAX_STACK_DEPTH * sizeof(__u64); __u32 key = 0, val = 0, *value_p; @@ -73,16 +73,28 @@ static inline void test_stackmap(void *ctx, int skip) return; /* skip if non-zero *value_p */ /* The size of stackmap and stackid_hmap should be the same */ - key = bpf_get_stackid(ctx, &stackmap, (u64) skip); + key = bpf_get_stackid(ctx, &stackmap, flags); if ((int)key >= 0) { stack_id = key; bpf_map_update_elem(&stackid_hmap, &key, &val, 0); stack_p = bpf_map_lookup_elem(&stack_amap, &key); if (stack_p) - bpf_get_stack(ctx, stack_p, max_len, (u64) skip); + bpf_get_stack(ctx, stack_p, max_len, flags); } } +static inline void test_stackmap(void *ctx, int skip) +{ + test_stackmap_flags(ctx, (__u64) skip); +} + +static inline void test_stackmap_user(void *ctx, int skip) +{ + __u64 flags = (__u64) skip | BPF_F_USER_STACK; + + test_stackmap_flags(ctx, flags); +} + /* * No tests in here, just to trigger 'bpf_fentry_test*' * through tracing test_run. @@ -141,4 +153,18 @@ int BPF_PROG(fexit) return 0; } +SEC("uprobe.multi") +int uprobe_multi_test(struct pt_regs *ctx) +{ + test_stackmap_user(ctx, 0); + return 0; +} + +SEC("uprobe") +int uprobe_test(struct pt_regs *ctx) +{ + test_stackmap_user(ctx, 0); + return 0; +} + char _license[] SEC("license") = "GPL";