The previous two commits added libbpf support for BPF objects containing multiple programs sharing the same instructions using the compiler `__attribute__((alias("...")))`. This adds tests for such objects. The tests check that different kinds of relocations (namely for global vars, maps, subprogs, and CO-RE) are correctly performed in both the original and the aliasing BPF program and that both programs hit when the target event occurs. Signed-off-by: Viktor Malik <vmalik@xxxxxxxxxx> --- .../selftests/bpf/prog_tests/fentry_alias.c | 41 +++++++++ .../selftests/bpf/progs/fentry_alias.c | 83 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/fentry_alias.c create mode 100644 tools/testing/selftests/bpf/progs/fentry_alias.c diff --git a/tools/testing/selftests/bpf/prog_tests/fentry_alias.c b/tools/testing/selftests/bpf/prog_tests/fentry_alias.c new file mode 100644 index 000000000000..6b9c6895b374 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/fentry_alias.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <test_progs.h> +#include "fentry_alias.skel.h" + +void test_fentry_alias(void) +{ + struct fentry_alias *fentry_skel = NULL; + int err, prog_fd; + __u64 key = 0, val; + + LIBBPF_OPTS(bpf_test_run_opts, opts); + + fentry_skel = fentry_alias__open_and_load(); + if (!ASSERT_OK_PTR(fentry_skel, "fentry_skel_load")) + goto cleanup; + + err = fentry_alias__attach(fentry_skel); + if (!ASSERT_OK(err, "fentry_attach")) + goto cleanup; + + fentry_skel->bss->real_pid = getpid(); + + prog_fd = bpf_program__fd(fentry_skel->progs.test1); + err = bpf_prog_test_run_opts(prog_fd, &opts); + + ASSERT_EQ(fentry_skel->bss->test1_hit_cnt, 2, + "fentry_alias_test1_result"); + + err = bpf_map__lookup_elem(fentry_skel->maps.map, &key, sizeof(key), + &val, sizeof(val), 0); + ASSERT_OK(err, "hashmap lookup"); + ASSERT_EQ(val, 2, "fentry_alias_test2_result"); + + ASSERT_EQ(fentry_skel->bss->test3_hit_cnt, 2, + "fentry_alias_test3_result"); + + ASSERT_EQ(fentry_skel->bss->test4_hit_cnt, 2, + "fentry_alias_test4_result"); +cleanup: + fentry_alias__destroy(fentry_skel); +} diff --git a/tools/testing/selftests/bpf/progs/fentry_alias.c b/tools/testing/selftests/bpf/progs/fentry_alias.c new file mode 100644 index 000000000000..5d7b492c7f95 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/fentry_alias.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include <bpf/bpf_core_read.h> + +char _license[] SEC("license") = "GPL"; + +struct task_struct { + int tgid; +} __attribute__((preserve_access_index)); + +int real_pid = 0; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u64); + __type(value, __u64); +} map SEC(".maps"); + +/* test1 - glob var relocations */ +__u64 test1_hit_cnt = 0; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(test1, int a) +{ + test1_hit_cnt++; + return 0; +} + +int test1_alias(int a) __attribute__((alias("test1"))); + +/* test2 - map relocations */ +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(test2, int a) +{ + __u64 key = 0, *value, new_value; + + value = bpf_map_lookup_elem(&map, &key); + new_value = value ? *value + 1 : 1; + bpf_map_update_elem(&map, &key, &new_value, 0); + return 0; +} + +int test2_alias(int a) __attribute__((alias("test2"))); + +/* test3 - subprog relocations */ +__u64 test3_hit_cnt = 0; + +static __noinline void test3_subprog(void) +{ + test3_hit_cnt++; +} + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(test3, int a) +{ + test3_subprog(); + return 0; +} + +int test3_alias(int a) __attribute__((alias("test3"))); + +/* test4 - CO-RE relocations */ +__u64 test4_hit_cnt = 0; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(test4, int a) +{ + struct task_struct *task; + int pid; + + task = (void *)bpf_get_current_task(); + pid = BPF_CORE_READ(task, tgid); + + if (pid == real_pid) + test4_hit_cnt++; + + return 0; +} + +int test4_alias(int a) __attribute__((alias("test4"))); -- 2.46.0