| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (c) 2021 Facebook */ |
| #include <test_progs.h> |
| #include <bpf/btf.h> |
| #include "test_btf_decl_tag.skel.h" |
| |
| /* struct btf_type_tag_test is referenced in btf_type_tag.skel.h */ |
| struct btf_type_tag_test { |
| int **p; |
| }; |
| #include "btf_type_tag.skel.h" |
| #include "btf_type_tag_user.skel.h" |
| #include "btf_type_tag_percpu.skel.h" |
| |
| static void test_btf_decl_tag(void) |
| { |
| struct test_btf_decl_tag *skel; |
| |
| skel = test_btf_decl_tag__open_and_load(); |
| if (!ASSERT_OK_PTR(skel, "btf_decl_tag")) |
| return; |
| |
| if (skel->rodata->skip_tests) { |
| printf("%s:SKIP: btf_decl_tag attribute not supported", __func__); |
| test__skip(); |
| } |
| |
| test_btf_decl_tag__destroy(skel); |
| } |
| |
| static void test_btf_type_tag(void) |
| { |
| struct btf_type_tag *skel; |
| |
| skel = btf_type_tag__open_and_load(); |
| if (!ASSERT_OK_PTR(skel, "btf_type_tag")) |
| return; |
| |
| if (skel->rodata->skip_tests) { |
| printf("%s:SKIP: btf_type_tag attribute not supported", __func__); |
| test__skip(); |
| } |
| |
| btf_type_tag__destroy(skel); |
| } |
| |
| /* loads vmlinux_btf as well as module_btf. If the caller passes NULL as |
| * module_btf, it will not load module btf. |
| * |
| * Returns 0 on success. |
| * Return -1 On error. In case of error, the loaded btf will be freed and the |
| * input parameters will be set to pointing to NULL. |
| */ |
| static int load_btfs(struct btf **vmlinux_btf, struct btf **module_btf, |
| bool needs_vmlinux_tag) |
| { |
| const char *module_name = "bpf_testmod"; |
| __s32 type_id; |
| |
| if (!env.has_testmod) { |
| test__skip(); |
| return -1; |
| } |
| |
| *vmlinux_btf = btf__load_vmlinux_btf(); |
| if (!ASSERT_OK_PTR(*vmlinux_btf, "could not load vmlinux BTF")) |
| return -1; |
| |
| if (!needs_vmlinux_tag) |
| goto load_module_btf; |
| |
| /* skip the test if the vmlinux does not have __user tags */ |
| type_id = btf__find_by_name_kind(*vmlinux_btf, "user", BTF_KIND_TYPE_TAG); |
| if (type_id <= 0) { |
| printf("%s:SKIP: btf_type_tag attribute not in vmlinux btf", __func__); |
| test__skip(); |
| goto free_vmlinux_btf; |
| } |
| |
| load_module_btf: |
| /* skip loading module_btf, if not requested by caller */ |
| if (!module_btf) |
| return 0; |
| |
| *module_btf = btf__load_module_btf(module_name, *vmlinux_btf); |
| if (!ASSERT_OK_PTR(*module_btf, "could not load module BTF")) |
| goto free_vmlinux_btf; |
| |
| /* skip the test if the module does not have __user tags */ |
| type_id = btf__find_by_name_kind(*module_btf, "user", BTF_KIND_TYPE_TAG); |
| if (type_id <= 0) { |
| printf("%s:SKIP: btf_type_tag attribute not in %s", __func__, module_name); |
| test__skip(); |
| goto free_module_btf; |
| } |
| |
| return 0; |
| |
| free_module_btf: |
| btf__free(*module_btf); |
| free_vmlinux_btf: |
| btf__free(*vmlinux_btf); |
| |
| *vmlinux_btf = NULL; |
| if (module_btf) |
| *module_btf = NULL; |
| return -1; |
| } |
| |
| static void test_btf_type_tag_mod_user(bool load_test_user1) |
| { |
| struct btf *vmlinux_btf = NULL, *module_btf = NULL; |
| struct btf_type_tag_user *skel; |
| int err; |
| |
| if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false)) |
| return; |
| |
| skel = btf_type_tag_user__open(); |
| if (!ASSERT_OK_PTR(skel, "btf_type_tag_user")) |
| goto cleanup; |
| |
| bpf_program__set_autoload(skel->progs.test_sys_getsockname, false); |
| if (load_test_user1) |
| bpf_program__set_autoload(skel->progs.test_user2, false); |
| else |
| bpf_program__set_autoload(skel->progs.test_user1, false); |
| |
| err = btf_type_tag_user__load(skel); |
| ASSERT_ERR(err, "btf_type_tag_user"); |
| |
| btf_type_tag_user__destroy(skel); |
| |
| cleanup: |
| btf__free(module_btf); |
| btf__free(vmlinux_btf); |
| } |
| |
| static void test_btf_type_tag_vmlinux_user(void) |
| { |
| struct btf_type_tag_user *skel; |
| struct btf *vmlinux_btf = NULL; |
| int err; |
| |
| if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true)) |
| return; |
| |
| skel = btf_type_tag_user__open(); |
| if (!ASSERT_OK_PTR(skel, "btf_type_tag_user")) |
| goto cleanup; |
| |
| bpf_program__set_autoload(skel->progs.test_user2, false); |
| bpf_program__set_autoload(skel->progs.test_user1, false); |
| |
| err = btf_type_tag_user__load(skel); |
| ASSERT_ERR(err, "btf_type_tag_user"); |
| |
| btf_type_tag_user__destroy(skel); |
| |
| cleanup: |
| btf__free(vmlinux_btf); |
| } |
| |
| static void test_btf_type_tag_mod_percpu(bool load_test_percpu1) |
| { |
| struct btf *vmlinux_btf, *module_btf; |
| struct btf_type_tag_percpu *skel; |
| int err; |
| |
| if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false)) |
| return; |
| |
| skel = btf_type_tag_percpu__open(); |
| if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu")) |
| goto cleanup; |
| |
| bpf_program__set_autoload(skel->progs.test_percpu_load, false); |
| bpf_program__set_autoload(skel->progs.test_percpu_helper, false); |
| if (load_test_percpu1) |
| bpf_program__set_autoload(skel->progs.test_percpu2, false); |
| else |
| bpf_program__set_autoload(skel->progs.test_percpu1, false); |
| |
| err = btf_type_tag_percpu__load(skel); |
| ASSERT_ERR(err, "btf_type_tag_percpu"); |
| |
| btf_type_tag_percpu__destroy(skel); |
| |
| cleanup: |
| btf__free(module_btf); |
| btf__free(vmlinux_btf); |
| } |
| |
| static void test_btf_type_tag_vmlinux_percpu(bool load_test) |
| { |
| struct btf_type_tag_percpu *skel; |
| struct btf *vmlinux_btf = NULL; |
| int err; |
| |
| if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true)) |
| return; |
| |
| skel = btf_type_tag_percpu__open(); |
| if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu")) |
| goto cleanup; |
| |
| bpf_program__set_autoload(skel->progs.test_percpu2, false); |
| bpf_program__set_autoload(skel->progs.test_percpu1, false); |
| if (load_test) { |
| bpf_program__set_autoload(skel->progs.test_percpu_helper, false); |
| |
| err = btf_type_tag_percpu__load(skel); |
| ASSERT_ERR(err, "btf_type_tag_percpu_load"); |
| } else { |
| bpf_program__set_autoload(skel->progs.test_percpu_load, false); |
| |
| err = btf_type_tag_percpu__load(skel); |
| ASSERT_OK(err, "btf_type_tag_percpu_helper"); |
| } |
| |
| btf_type_tag_percpu__destroy(skel); |
| |
| cleanup: |
| btf__free(vmlinux_btf); |
| } |
| |
| void test_btf_tag(void) |
| { |
| if (test__start_subtest("btf_decl_tag")) |
| test_btf_decl_tag(); |
| if (test__start_subtest("btf_type_tag")) |
| test_btf_type_tag(); |
| |
| if (test__start_subtest("btf_type_tag_user_mod1")) |
| test_btf_type_tag_mod_user(true); |
| if (test__start_subtest("btf_type_tag_user_mod2")) |
| test_btf_type_tag_mod_user(false); |
| if (test__start_subtest("btf_type_tag_sys_user_vmlinux")) |
| test_btf_type_tag_vmlinux_user(); |
| |
| if (test__start_subtest("btf_type_tag_percpu_mod1")) |
| test_btf_type_tag_mod_percpu(true); |
| if (test__start_subtest("btf_type_tag_percpu_mod2")) |
| test_btf_type_tag_mod_percpu(false); |
| if (test__start_subtest("btf_type_tag_percpu_vmlinux_load")) |
| test_btf_type_tag_vmlinux_percpu(true); |
| if (test__start_subtest("btf_type_tag_percpu_vmlinux_helper")) |
| test_btf_type_tag_vmlinux_percpu(false); |
| } |