diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-10-11 16:48:36 +0000 |
|---|---|---|
| committer | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-10-12 10:43:54 +0200 |
| commit | 5f8cf2e471769374ddcfcbe2eb8c977d652de156 (patch) | |
| tree | 961ff370b8ca1d799d3daaf464718a07c4c827ae | |
| parent | 87bfa22937000db29a9a09ec826ab7227eaf9e8c (diff) | |
selftests/bpf: Test tracing_multi link with BTF ids of the same address
The stub of a syscall without arguments is an alias of its __do_sys_
function. Find such pair where both have BTF ids. Which ones do depends
on the compiler, so don't hard code the names. Check that each id can be
attached and that the attach of both in one link fails with -EINVAL.
With CONFIG_DEBUG_INFO_BTF_INLINE vmlinux BTF has 26 names with more
than one BTF_KIND_FUNC:
[117318] FUNC 'hash' type_id=76715 linkage=static
[117319] FUNC 'hash' type_id=76722 linkage=static
[117320] FUNC 'hash' type_id=76789 linkage=static
while there is one 'hash' in kallsyms. tracing_multi_bench_attach skips
the names that are not unique in kallsyms only and passes all three ids
to the kernel. Take the first id of the name.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/bpf/20261011164836.2233874-3-alexei.starovoitov@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
| -rw-r--r-- | tools/testing/selftests/bpf/prog_tests/tracing_multi.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c index 0aa9532a05cf..cc727011f3a2 100644 --- a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c +++ b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c @@ -662,6 +662,97 @@ cleanup: free(ids2); } +/* + * Find two BTF ids that resolve to the same address. The stub of a syscall + * without arguments is an alias of its __do_sys_ function. + */ +static bool get_same_addr_ids(__u32 *ids) +{ + const char *prefix = "__x64_sys_"; + __u32 nr, type_id; + bool found = false; + struct btf *btf; + char alias[128]; + + btf = btf__load_vmlinux_btf(); + if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf")) + return false; + + nr = btf__type_cnt(btf); + for (type_id = 1; type_id < nr && !found; type_id++) { + const struct btf_type *type = btf__type_by_id(btf, type_id); + const char *str; + long addr; + __s32 id; + + if (!btf_is_func(type)) + continue; + + str = btf__name_by_offset(btf, type->name_off); + if (!str || strncmp(str, prefix, strlen(prefix))) + continue; + + snprintf(alias, sizeof(alias), "__do_sys_%s", str + strlen(prefix)); + id = btf__find_by_name_kind(btf, alias, BTF_KIND_FUNC); + if (id <= 0) + continue; + + addr = ksym_get_addr(str); + if (!addr || addr != ksym_get_addr(alias)) + continue; + + ids[0] = type_id; + ids[1] = id; + found = true; + } + + btf__free(btf); + return found; +} + +static void test_attach_same_addr(void) +{ + LIBBPF_OPTS(bpf_tracing_multi_opts, opts); + struct tracing_multi_fail *skel; + struct bpf_link *link; + __u32 ids[2]; + int i; + + if (!ASSERT_OK(load_kallsyms(), "load_kallsyms")) + return; + + if (!get_same_addr_ids(ids)) { + test__skip(); + return; + } + + skel = tracing_multi_fail__open_and_load(); + if (!ASSERT_OK_PTR(skel, "tracing_multi_fail__open_and_load")) + return; + + /* Each id attaches fine on its own.. */ + for (i = 0; i < 2; i++) { + opts.ids = &ids[i]; + opts.cnt = 1; + + link = bpf_program__attach_tracing_multi(skel->progs.test_fentry, NULL, &opts); + if (!ASSERT_OK_PTR(link, "attach_single")) + goto cleanup; + bpf_link__destroy(link); + } + + /* ..but there's only one call site, so not both of them. */ + opts.ids = ids; + opts.cnt = 2; + + link = bpf_program__attach_tracing_multi(skel->progs.test_fentry, NULL, &opts); + if (!ASSERT_EQ(libbpf_get_error(link), -EINVAL, "attach_same_addr")) + bpf_link__destroy(link); + +cleanup: + tracing_multi_fail__destroy(skel); +} + void serial_test_tracing_multi_bench_attach(void) { LIBBPF_OPTS(bpf_tracing_multi_opts, opts); @@ -748,6 +839,12 @@ void serial_test_tracing_multi_bench_attach(void) if (!btf_type_is_traceable_func(btf, type)) continue; + /* + * BTF can have more functions of the same name and they all + * resolve to the same address, take just the first one. + */ + tdelete(&str, &root, compare); + err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1); if (err) goto cleanup; @@ -1023,6 +1120,8 @@ void test_tracing_multi_test(void) test_session(); if (test__start_subtest("attach_api_fails")) test_attach_api_fails(); + if (test__start_subtest("attach_same_addr")) + test_attach_same_addr(); RUN_TESTS(tracing_multi_verifier); if (test__start_subtest("fentry_after_multi")) test_fentry_after_multi(); |
