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
test_btf_decl_tag(void)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
test_btf_type_tag(void)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 */
load_btfs(struct btf ** vmlinux_btf,struct btf ** module_btf,bool needs_vmlinux_tag)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
test_btf_type_tag_mod_user(bool load_test_user1)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
test_btf_type_tag_vmlinux_user(void)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
test_btf_type_tag_mod_percpu(bool load_test_percpu1)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
test_btf_type_tag_vmlinux_percpu(bool load_test)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
test_btf_tag(void)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