1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #include <test_progs.h> 4 #include <bpf/btf.h> 5 #include "test_btf_decl_tag.skel.h" 6 7 /* struct btf_type_tag_test is referenced in btf_type_tag.skel.h */ 8 struct btf_type_tag_test { 9 int **p; 10 }; 11 #include "btf_type_tag.skel.h" 12 #include "btf_type_tag_user.skel.h" 13 #include "btf_type_tag_percpu.skel.h" 14 15 static void test_btf_decl_tag(void) 16 { 17 struct test_btf_decl_tag *skel; 18 19 skel = test_btf_decl_tag__open_and_load(); 20 if (!ASSERT_OK_PTR(skel, "btf_decl_tag")) 21 return; 22 23 if (skel->rodata->skip_tests) { 24 printf("%s:SKIP: btf_decl_tag attribute not supported", __func__); 25 test__skip(); 26 } 27 28 test_btf_decl_tag__destroy(skel); 29 } 30 31 static void test_btf_type_tag(void) 32 { 33 struct btf_type_tag *skel; 34 35 skel = btf_type_tag__open_and_load(); 36 if (!ASSERT_OK_PTR(skel, "btf_type_tag")) 37 return; 38 39 if (skel->rodata->skip_tests) { 40 printf("%s:SKIP: btf_type_tag attribute not supported", __func__); 41 test__skip(); 42 } 43 44 btf_type_tag__destroy(skel); 45 } 46 47 /* loads vmlinux_btf as well as module_btf. If the caller passes NULL as 48 * module_btf, it will not load module btf. 49 * 50 * Returns 0 on success. 51 * Return -1 On error. In case of error, the loaded btf will be freed and the 52 * input parameters will be set to pointing to NULL. 53 */ 54 static int load_btfs(struct btf **vmlinux_btf, struct btf **module_btf, 55 bool needs_vmlinux_tag) 56 { 57 const char *module_name = "bpf_testmod"; 58 __s32 type_id; 59 60 if (!env.has_testmod) { 61 test__skip(); 62 return -1; 63 } 64 65 *vmlinux_btf = btf__load_vmlinux_btf(); 66 if (!ASSERT_OK_PTR(*vmlinux_btf, "could not load vmlinux BTF")) 67 return -1; 68 69 if (!needs_vmlinux_tag) 70 goto load_module_btf; 71 72 /* skip the test if the vmlinux does not have __user tags */ 73 type_id = btf__find_by_name_kind(*vmlinux_btf, "user", BTF_KIND_TYPE_TAG); 74 if (type_id <= 0) { 75 printf("%s:SKIP: btf_type_tag attribute not in vmlinux btf", __func__); 76 test__skip(); 77 goto free_vmlinux_btf; 78 } 79 80 load_module_btf: 81 /* skip loading module_btf, if not requested by caller */ 82 if (!module_btf) 83 return 0; 84 85 *module_btf = btf__load_module_btf(module_name, *vmlinux_btf); 86 if (!ASSERT_OK_PTR(*module_btf, "could not load module BTF")) 87 goto free_vmlinux_btf; 88 89 /* skip the test if the module does not have __user tags */ 90 type_id = btf__find_by_name_kind(*module_btf, "user", BTF_KIND_TYPE_TAG); 91 if (type_id <= 0) { 92 printf("%s:SKIP: btf_type_tag attribute not in %s", __func__, module_name); 93 test__skip(); 94 goto free_module_btf; 95 } 96 97 return 0; 98 99 free_module_btf: 100 btf__free(*module_btf); 101 free_vmlinux_btf: 102 btf__free(*vmlinux_btf); 103 104 *vmlinux_btf = NULL; 105 if (module_btf) 106 *module_btf = NULL; 107 return -1; 108 } 109 110 static void test_btf_type_tag_mod_user(bool load_test_user1) 111 { 112 struct btf *vmlinux_btf = NULL, *module_btf = NULL; 113 struct btf_type_tag_user *skel; 114 int err; 115 116 if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false)) 117 return; 118 119 skel = btf_type_tag_user__open(); 120 if (!ASSERT_OK_PTR(skel, "btf_type_tag_user")) 121 goto cleanup; 122 123 bpf_program__set_autoload(skel->progs.test_sys_getsockname, false); 124 if (load_test_user1) 125 bpf_program__set_autoload(skel->progs.test_user2, false); 126 else 127 bpf_program__set_autoload(skel->progs.test_user1, false); 128 129 err = btf_type_tag_user__load(skel); 130 ASSERT_ERR(err, "btf_type_tag_user"); 131 132 btf_type_tag_user__destroy(skel); 133 134 cleanup: 135 btf__free(module_btf); 136 btf__free(vmlinux_btf); 137 } 138 139 static void test_btf_type_tag_vmlinux_user(void) 140 { 141 struct btf_type_tag_user *skel; 142 struct btf *vmlinux_btf = NULL; 143 int err; 144 145 if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true)) 146 return; 147 148 skel = btf_type_tag_user__open(); 149 if (!ASSERT_OK_PTR(skel, "btf_type_tag_user")) 150 goto cleanup; 151 152 bpf_program__set_autoload(skel->progs.test_user2, false); 153 bpf_program__set_autoload(skel->progs.test_user1, false); 154 155 err = btf_type_tag_user__load(skel); 156 ASSERT_ERR(err, "btf_type_tag_user"); 157 158 btf_type_tag_user__destroy(skel); 159 160 cleanup: 161 btf__free(vmlinux_btf); 162 } 163 164 static void test_btf_type_tag_mod_percpu(bool load_test_percpu1) 165 { 166 struct btf *vmlinux_btf, *module_btf; 167 struct btf_type_tag_percpu *skel; 168 int err; 169 170 if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false)) 171 return; 172 173 skel = btf_type_tag_percpu__open(); 174 if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu")) 175 goto cleanup; 176 177 bpf_program__set_autoload(skel->progs.test_percpu_load, false); 178 bpf_program__set_autoload(skel->progs.test_percpu_helper, false); 179 if (load_test_percpu1) 180 bpf_program__set_autoload(skel->progs.test_percpu2, false); 181 else 182 bpf_program__set_autoload(skel->progs.test_percpu1, false); 183 184 err = btf_type_tag_percpu__load(skel); 185 ASSERT_ERR(err, "btf_type_tag_percpu"); 186 187 btf_type_tag_percpu__destroy(skel); 188 189 cleanup: 190 btf__free(module_btf); 191 btf__free(vmlinux_btf); 192 } 193 194 static void test_btf_type_tag_vmlinux_percpu(bool load_test) 195 { 196 struct btf_type_tag_percpu *skel; 197 struct btf *vmlinux_btf = NULL; 198 int err; 199 200 if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true)) 201 return; 202 203 skel = btf_type_tag_percpu__open(); 204 if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu")) 205 goto cleanup; 206 207 bpf_program__set_autoload(skel->progs.test_percpu2, false); 208 bpf_program__set_autoload(skel->progs.test_percpu1, false); 209 if (load_test) { 210 bpf_program__set_autoload(skel->progs.test_percpu_helper, false); 211 212 err = btf_type_tag_percpu__load(skel); 213 ASSERT_ERR(err, "btf_type_tag_percpu_load"); 214 } else { 215 bpf_program__set_autoload(skel->progs.test_percpu_load, false); 216 217 err = btf_type_tag_percpu__load(skel); 218 ASSERT_OK(err, "btf_type_tag_percpu_helper"); 219 } 220 221 btf_type_tag_percpu__destroy(skel); 222 223 cleanup: 224 btf__free(vmlinux_btf); 225 } 226 227 void test_btf_tag(void) 228 { 229 if (test__start_subtest("btf_decl_tag")) 230 test_btf_decl_tag(); 231 if (test__start_subtest("btf_type_tag")) 232 test_btf_type_tag(); 233 234 if (test__start_subtest("btf_type_tag_user_mod1")) 235 test_btf_type_tag_mod_user(true); 236 if (test__start_subtest("btf_type_tag_user_mod2")) 237 test_btf_type_tag_mod_user(false); 238 if (test__start_subtest("btf_type_tag_sys_user_vmlinux")) 239 test_btf_type_tag_vmlinux_user(); 240 241 if (test__start_subtest("btf_type_tag_percpu_mod1")) 242 test_btf_type_tag_mod_percpu(true); 243 if (test__start_subtest("btf_type_tag_percpu_mod2")) 244 test_btf_type_tag_mod_percpu(false); 245 if (test__start_subtest("btf_type_tag_percpu_vmlinux_load")) 246 test_btf_type_tag_vmlinux_percpu(true); 247 if (test__start_subtest("btf_type_tag_percpu_vmlinux_helper")) 248 test_btf_type_tag_vmlinux_percpu(false); 249 } 250