selftests/bpf: Add type-match checks to type-based tests
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / prog_tests / core_reloc.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "progs/core_reloc_types.h"
4 #include "bpf_testmod/bpf_testmod.h"
5 #include <linux/limits.h>
6 #include <sys/mman.h>
7 #include <sys/syscall.h>
8 #include <bpf/btf.h>
9
10 static int duration = 0;
11
12 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
13
14 #define MODULES_CASE(name, pg_name, tp_name) {                          \
15         .case_name = name,                                              \
16         .bpf_obj_file = "test_core_reloc_module.o",                     \
17         .btf_src_file = NULL, /* find in kernel module BTFs */          \
18         .input = "",                                                    \
19         .input_len = 0,                                                 \
20         .output = STRUCT_TO_CHAR_PTR(core_reloc_module_output) {        \
21                 .read_ctx_sz = sizeof(struct bpf_testmod_test_read_ctx),\
22                 .read_ctx_exists = true,                                \
23                 .buf_exists = true,                                     \
24                 .len_exists = true,                                     \
25                 .off_exists = true,                                     \
26                 .len = 123,                                             \
27                 .off = 0,                                               \
28                 .comm = "test_progs",                                   \
29                 .comm_len = sizeof("test_progs"),                       \
30         },                                                              \
31         .output_len = sizeof(struct core_reloc_module_output),          \
32         .prog_name = pg_name,                                           \
33         .raw_tp_name = tp_name,                                         \
34         .trigger = __trigger_module_test_read,                          \
35         .needs_testmod = true,                                          \
36 }
37
38 #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {     \
39         .a = 42,                                                        \
40         .b = 0xc001,                                                    \
41         .c = 0xbeef,                                                    \
42 }
43
44 #define FLAVORS_CASE_COMMON(name)                                       \
45         .case_name = #name,                                             \
46         .bpf_obj_file = "test_core_reloc_flavors.o",                    \
47         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
48         .raw_tp_name = "sys_enter",                                     \
49         .prog_name = "test_core_flavors"                                \
50
51 #define FLAVORS_CASE(name) {                                            \
52         FLAVORS_CASE_COMMON(name),                                      \
53         .input = FLAVORS_DATA(core_reloc_##name),                       \
54         .input_len = sizeof(struct core_reloc_##name),                  \
55         .output = FLAVORS_DATA(core_reloc_flavors),                     \
56         .output_len = sizeof(struct core_reloc_flavors),                \
57 }
58
59 #define FLAVORS_ERR_CASE(name) {                                        \
60         FLAVORS_CASE_COMMON(name),                                      \
61         .fails = true,                                                  \
62 }
63
64 #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {     \
65         .a = { .a = { .a = 42 } },                                      \
66         .b = { .b = { .b = 0xc001 } },                                  \
67 }
68
69 #define NESTING_CASE_COMMON(name)                                       \
70         .case_name = #name,                                             \
71         .bpf_obj_file = "test_core_reloc_nesting.o",                    \
72         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
73         .raw_tp_name = "sys_enter",                                     \
74         .prog_name = "test_core_nesting"                                \
75
76 #define NESTING_CASE(name) {                                            \
77         NESTING_CASE_COMMON(name),                                      \
78         .input = NESTING_DATA(core_reloc_##name),                       \
79         .input_len = sizeof(struct core_reloc_##name),                  \
80         .output = NESTING_DATA(core_reloc_nesting),                     \
81         .output_len = sizeof(struct core_reloc_nesting)                 \
82 }
83
84 #define NESTING_ERR_CASE(name) {                                        \
85         NESTING_CASE_COMMON(name),                                      \
86         .fails = true,                                                  \
87         .run_btfgen_fails = true,                                                       \
88 }
89
90 #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {      \
91         .a = { [2] = 1 },                                               \
92         .b = { [1] = { [2] = { [3] = 2 } } },                           \
93         .c = { [1] = { .c =  3 } },                                     \
94         .d = { [0] = { [0] = { .d = 4 } } },                            \
95 }
96
97 #define ARRAYS_CASE_COMMON(name)                                        \
98         .case_name = #name,                                             \
99         .bpf_obj_file = "test_core_reloc_arrays.o",                     \
100         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
101         .raw_tp_name = "sys_enter",                                     \
102         .prog_name = "test_core_arrays"                                 \
103
104 #define ARRAYS_CASE(name) {                                             \
105         ARRAYS_CASE_COMMON(name),                                       \
106         .input = ARRAYS_DATA(core_reloc_##name),                        \
107         .input_len = sizeof(struct core_reloc_##name),                  \
108         .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) {        \
109                 .a2   = 1,                                              \
110                 .b123 = 2,                                              \
111                 .c1c  = 3,                                              \
112                 .d00d = 4,                                              \
113                 .f10c = 0,                                              \
114         },                                                              \
115         .output_len = sizeof(struct core_reloc_arrays_output)           \
116 }
117
118 #define ARRAYS_ERR_CASE(name) {                                         \
119         ARRAYS_CASE_COMMON(name),                                       \
120         .fails = true,                                                  \
121 }
122
123 #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {  \
124         .a = 1,                                                         \
125         .b = 2,                                                         \
126         .c = 3,                                                         \
127         .d = (void *)4,                                                 \
128         .f = (void *)5,                                                 \
129 }
130
131 #define PRIMITIVES_CASE_COMMON(name)                                    \
132         .case_name = #name,                                             \
133         .bpf_obj_file = "test_core_reloc_primitives.o",                 \
134         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
135         .raw_tp_name = "sys_enter",                                     \
136         .prog_name = "test_core_primitives"                             \
137
138 #define PRIMITIVES_CASE(name) {                                         \
139         PRIMITIVES_CASE_COMMON(name),                                   \
140         .input = PRIMITIVES_DATA(core_reloc_##name),                    \
141         .input_len = sizeof(struct core_reloc_##name),                  \
142         .output = PRIMITIVES_DATA(core_reloc_primitives),               \
143         .output_len = sizeof(struct core_reloc_primitives),             \
144 }
145
146 #define PRIMITIVES_ERR_CASE(name) {                                     \
147         PRIMITIVES_CASE_COMMON(name),                                   \
148         .fails = true,                                                  \
149 }
150
151 #define MODS_CASE(name) {                                               \
152         .case_name = #name,                                             \
153         .bpf_obj_file = "test_core_reloc_mods.o",                       \
154         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
155         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) {                \
156                 .a = 1,                                                 \
157                 .b = 2,                                                 \
158                 .c = (void *)3,                                         \
159                 .d = (void *)4,                                         \
160                 .e = { [2] = 5 },                                       \
161                 .f = { [1] = 6 },                                       \
162                 .g = { .x = 7 },                                        \
163                 .h = { .y = 8 },                                        \
164         },                                                              \
165         .input_len = sizeof(struct core_reloc_##name),                  \
166         .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) {          \
167                 .a = 1, .b = 2, .c = 3, .d = 4,                         \
168                 .e = 5, .f = 6, .g = 7, .h = 8,                         \
169         },                                                              \
170         .output_len = sizeof(struct core_reloc_mods_output),            \
171         .raw_tp_name = "sys_enter",                                     \
172         .prog_name = "test_core_mods",                                  \
173 }
174
175 #define PTR_AS_ARR_CASE(name) {                                         \
176         .case_name = #name,                                             \
177         .bpf_obj_file = "test_core_reloc_ptr_as_arr.o",                 \
178         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
179         .input = (const char *)&(struct core_reloc_##name []){          \
180                 { .a = 1 },                                             \
181                 { .a = 2 },                                             \
182                 { .a = 3 },                                             \
183         },                                                              \
184         .input_len = 3 * sizeof(struct core_reloc_##name),              \
185         .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) {           \
186                 .a = 3,                                                 \
187         },                                                              \
188         .output_len = sizeof(struct core_reloc_ptr_as_arr),             \
189         .raw_tp_name = "sys_enter",                                     \
190         .prog_name = "test_core_ptr_as_arr",                            \
191 }
192
193 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {        \
194         .u8_field = 1,                                                  \
195         .s8_field = 2,                                                  \
196         .u16_field = 3,                                                 \
197         .s16_field = 4,                                                 \
198         .u32_field = 5,                                                 \
199         .s32_field = 6,                                                 \
200         .u64_field = 7,                                                 \
201         .s64_field = 8,                                                 \
202 }
203
204 #define INTS_CASE_COMMON(name)                                          \
205         .case_name = #name,                                             \
206         .bpf_obj_file = "test_core_reloc_ints.o",                       \
207         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
208         .raw_tp_name = "sys_enter",                                     \
209         .prog_name = "test_core_ints"
210
211 #define INTS_CASE(name) {                                               \
212         INTS_CASE_COMMON(name),                                         \
213         .input = INTS_DATA(core_reloc_##name),                          \
214         .input_len = sizeof(struct core_reloc_##name),                  \
215         .output = INTS_DATA(core_reloc_ints),                           \
216         .output_len = sizeof(struct core_reloc_ints),                   \
217 }
218
219 #define INTS_ERR_CASE(name) {                                           \
220         INTS_CASE_COMMON(name),                                         \
221         .fails = true,                                                  \
222 }
223
224 #define FIELD_EXISTS_CASE_COMMON(name)                                  \
225         .case_name = #name,                                             \
226         .bpf_obj_file = "test_core_reloc_existence.o",                  \
227         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
228         .raw_tp_name = "sys_enter",                                     \
229         .prog_name = "test_core_existence"
230
231 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix,  name)         \
232         .case_name = test_name_prefix#name,                             \
233         .bpf_obj_file = objfile,                                        \
234         .btf_src_file = "btf__core_reloc_" #name ".o"
235
236 #define BITFIELDS_CASE(name, ...) {                                     \
237         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o",     \
238                               "probed:", name),                         \
239         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,     \
240         .input_len = sizeof(struct core_reloc_##name),                  \
241         .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)       \
242                 __VA_ARGS__,                                            \
243         .output_len = sizeof(struct core_reloc_bitfields_output),       \
244         .raw_tp_name = "sys_enter",                                     \
245         .prog_name = "test_core_bitfields",                             \
246 }, {                                                                    \
247         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o",     \
248                               "direct:", name),                         \
249         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,     \
250         .input_len = sizeof(struct core_reloc_##name),                  \
251         .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)       \
252                 __VA_ARGS__,                                            \
253         .output_len = sizeof(struct core_reloc_bitfields_output),       \
254         .prog_name = "test_core_bitfields_direct",                      \
255 }
256
257
258 #define BITFIELDS_ERR_CASE(name) {                                      \
259         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o",     \
260                               "probed:", name),                         \
261         .fails = true,                                                  \
262         .run_btfgen_fails = true,                                                       \
263         .raw_tp_name = "sys_enter",                                     \
264         .prog_name = "test_core_bitfields",                             \
265 }, {                                                                    \
266         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o",     \
267                               "direct:", name),                         \
268         .fails = true,                                                  \
269         .run_btfgen_fails = true,                                                       \
270         .prog_name = "test_core_bitfields_direct",                      \
271 }
272
273 #define SIZE_CASE_COMMON(name)                                          \
274         .case_name = #name,                                             \
275         .bpf_obj_file = "test_core_reloc_size.o",                       \
276         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
277         .raw_tp_name = "sys_enter",                                     \
278         .prog_name = "test_core_size"
279
280 #define SIZE_OUTPUT_DATA(type)                                          \
281         STRUCT_TO_CHAR_PTR(core_reloc_size_output) {                    \
282                 .int_sz = sizeof(((type *)0)->int_field),               \
283                 .int_off = offsetof(type, int_field),                   \
284                 .struct_sz = sizeof(((type *)0)->struct_field),         \
285                 .struct_off = offsetof(type, struct_field),             \
286                 .union_sz = sizeof(((type *)0)->union_field),           \
287                 .union_off = offsetof(type, union_field),               \
288                 .arr_sz = sizeof(((type *)0)->arr_field),               \
289                 .arr_off = offsetof(type, arr_field),                   \
290                 .arr_elem_sz = sizeof(((type *)0)->arr_field[1]),       \
291                 .arr_elem_off = offsetof(type, arr_field[1]),           \
292                 .ptr_sz = 8, /* always 8-byte pointer for BPF */        \
293                 .ptr_off = offsetof(type, ptr_field),                   \
294                 .enum_sz = sizeof(((type *)0)->enum_field),             \
295                 .enum_off = offsetof(type, enum_field),                 \
296                 .float_sz = sizeof(((type *)0)->float_field),           \
297                 .float_off = offsetof(type, float_field),               \
298         }
299
300 #define SIZE_CASE(name) {                                               \
301         SIZE_CASE_COMMON(name),                                         \
302         .input_len = 0,                                                 \
303         .output = SIZE_OUTPUT_DATA(struct core_reloc_##name),           \
304         .output_len = sizeof(struct core_reloc_size_output),            \
305 }
306
307 #define SIZE_ERR_CASE(name) {                                           \
308         SIZE_CASE_COMMON(name),                                         \
309         .fails = true,                                                  \
310         .run_btfgen_fails = true,                                                       \
311 }
312
313 #define TYPE_BASED_CASE_COMMON(name)                                    \
314         .case_name = #name,                                             \
315         .bpf_obj_file = "test_core_reloc_type_based.o",                 \
316         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
317         .raw_tp_name = "sys_enter",                                     \
318         .prog_name = "test_core_type_based"
319
320 #define TYPE_BASED_CASE(name, ...) {                                    \
321         TYPE_BASED_CASE_COMMON(name),                                   \
322         .output = STRUCT_TO_CHAR_PTR(core_reloc_type_based_output)      \
323                         __VA_ARGS__,                                    \
324         .output_len = sizeof(struct core_reloc_type_based_output),      \
325 }
326
327 #define TYPE_BASED_ERR_CASE(name) {                                     \
328         TYPE_BASED_CASE_COMMON(name),                                   \
329         .fails = true,                                                  \
330 }
331
332 #define TYPE_ID_CASE_COMMON(name)                                       \
333         .case_name = #name,                                             \
334         .bpf_obj_file = "test_core_reloc_type_id.o",                    \
335         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
336         .raw_tp_name = "sys_enter",                                     \
337         .prog_name = "test_core_type_id"
338
339 #define TYPE_ID_CASE(name, setup_fn) {                                  \
340         TYPE_ID_CASE_COMMON(name),                                      \
341         .output = STRUCT_TO_CHAR_PTR(core_reloc_type_id_output) {},     \
342         .output_len = sizeof(struct core_reloc_type_id_output),         \
343         .setup = setup_fn,                                              \
344 }
345
346 #define TYPE_ID_ERR_CASE(name) {                                        \
347         TYPE_ID_CASE_COMMON(name),                                      \
348         .fails = true,                                                  \
349 }
350
351 #define ENUMVAL_CASE_COMMON(name)                                       \
352         .case_name = #name,                                             \
353         .bpf_obj_file = "test_core_reloc_enumval.o",                    \
354         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
355         .raw_tp_name = "sys_enter",                                     \
356         .prog_name = "test_core_enumval"
357
358 #define ENUMVAL_CASE(name, ...) {                                       \
359         ENUMVAL_CASE_COMMON(name),                                      \
360         .output = STRUCT_TO_CHAR_PTR(core_reloc_enumval_output)         \
361                         __VA_ARGS__,                                    \
362         .output_len = sizeof(struct core_reloc_enumval_output),         \
363 }
364
365 #define ENUMVAL_ERR_CASE(name) {                                        \
366         ENUMVAL_CASE_COMMON(name),                                      \
367         .fails = true,                                                  \
368 }
369
370 #define ENUM64VAL_CASE_COMMON(name)                                     \
371         .case_name = #name,                                             \
372         .bpf_obj_file = "test_core_reloc_enum64val.o",                  \
373         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
374         .raw_tp_name = "sys_enter",                                     \
375         .prog_name = "test_core_enum64val"
376
377 #define ENUM64VAL_CASE(name, ...) {                                     \
378         ENUM64VAL_CASE_COMMON(name),                                    \
379         .output = STRUCT_TO_CHAR_PTR(core_reloc_enum64val_output)       \
380                         __VA_ARGS__,                                    \
381         .output_len = sizeof(struct core_reloc_enum64val_output),       \
382 }
383
384 #define ENUM64VAL_ERR_CASE(name) {                                      \
385         ENUM64VAL_CASE_COMMON(name),                                    \
386         .fails = true,                                                  \
387 }
388
389 struct core_reloc_test_case;
390
391 typedef int (*setup_test_fn)(struct core_reloc_test_case *test);
392 typedef int (*trigger_test_fn)(const struct core_reloc_test_case *test);
393
394 struct core_reloc_test_case {
395         const char *case_name;
396         const char *bpf_obj_file;
397         const char *btf_src_file;
398         const char *input;
399         int input_len;
400         const char *output;
401         int output_len;
402         bool fails;
403         bool run_btfgen_fails;
404         bool needs_testmod;
405         bool relaxed_core_relocs;
406         const char *prog_name;
407         const char *raw_tp_name;
408         setup_test_fn setup;
409         trigger_test_fn trigger;
410 };
411
412 static int find_btf_type(const struct btf *btf, const char *name, __u32 kind)
413 {
414         int id;
415
416         id = btf__find_by_name_kind(btf, name, kind);
417         if (CHECK(id <= 0, "find_type_id", "failed to find '%s', kind %d: %d\n", name, kind, id))
418                 return -1;
419
420         return id;
421 }
422
423 static int setup_type_id_case_local(struct core_reloc_test_case *test)
424 {
425         struct core_reloc_type_id_output *exp = (void *)test->output;
426         struct btf *local_btf = btf__parse(test->bpf_obj_file, NULL);
427         struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
428         const struct btf_type *t;
429         const char *name;
430         int i;
431
432         if (!ASSERT_OK_PTR(local_btf, "local_btf") || !ASSERT_OK_PTR(targ_btf, "targ_btf")) {
433                 btf__free(local_btf);
434                 btf__free(targ_btf);
435                 return -EINVAL;
436         }
437
438         exp->local_anon_struct = -1;
439         exp->local_anon_union = -1;
440         exp->local_anon_enum = -1;
441         exp->local_anon_func_proto_ptr = -1;
442         exp->local_anon_void_ptr = -1;
443         exp->local_anon_arr = -1;
444
445         for (i = 1; i < btf__type_cnt(local_btf); i++)
446         {
447                 t = btf__type_by_id(local_btf, i);
448                 /* we are interested only in anonymous types */
449                 if (t->name_off)
450                         continue;
451
452                 if (btf_is_struct(t) && btf_vlen(t) &&
453                     (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
454                     strcmp(name, "marker_field") == 0) {
455                         exp->local_anon_struct = i;
456                 } else if (btf_is_union(t) && btf_vlen(t) &&
457                          (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
458                          strcmp(name, "marker_field") == 0) {
459                         exp->local_anon_union = i;
460                 } else if (btf_is_enum(t) && btf_vlen(t) &&
461                          (name = btf__name_by_offset(local_btf, btf_enum(t)[0].name_off)) &&
462                          strcmp(name, "MARKER_ENUM_VAL") == 0) {
463                         exp->local_anon_enum = i;
464                 } else if (btf_is_ptr(t) && (t = btf__type_by_id(local_btf, t->type))) {
465                         if (btf_is_func_proto(t) && (t = btf__type_by_id(local_btf, t->type)) &&
466                             btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
467                             strcmp(name, "_Bool") == 0) {
468                                 /* ptr -> func_proto -> _Bool */
469                                 exp->local_anon_func_proto_ptr = i;
470                         } else if (btf_is_void(t)) {
471                                 /* ptr -> void */
472                                 exp->local_anon_void_ptr = i;
473                         }
474                 } else if (btf_is_array(t) && (t = btf__type_by_id(local_btf, btf_array(t)->type)) &&
475                            btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
476                            strcmp(name, "_Bool") == 0) {
477                         /* _Bool[] */
478                         exp->local_anon_arr = i;
479                 }
480         }
481
482         exp->local_struct = find_btf_type(local_btf, "a_struct", BTF_KIND_STRUCT);
483         exp->local_union = find_btf_type(local_btf, "a_union", BTF_KIND_UNION);
484         exp->local_enum = find_btf_type(local_btf, "an_enum", BTF_KIND_ENUM);
485         exp->local_int = find_btf_type(local_btf, "int", BTF_KIND_INT);
486         exp->local_struct_typedef = find_btf_type(local_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
487         exp->local_func_proto_typedef = find_btf_type(local_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
488         exp->local_arr_typedef = find_btf_type(local_btf, "arr_typedef", BTF_KIND_TYPEDEF);
489
490         btf__free(local_btf);
491         btf__free(targ_btf);
492         return 0;
493 }
494
495 static int setup_type_id_case_success(struct core_reloc_test_case *test) {
496         struct core_reloc_type_id_output *exp = (void *)test->output;
497         struct btf *targ_btf;
498         int err;
499
500         err = setup_type_id_case_local(test);
501         if (err)
502                 return err;
503
504         targ_btf = btf__parse(test->btf_src_file, NULL);
505
506         exp->targ_struct = find_btf_type(targ_btf, "a_struct", BTF_KIND_STRUCT);
507         exp->targ_union = find_btf_type(targ_btf, "a_union", BTF_KIND_UNION);
508         exp->targ_enum = find_btf_type(targ_btf, "an_enum", BTF_KIND_ENUM);
509         exp->targ_int = find_btf_type(targ_btf, "int", BTF_KIND_INT);
510         exp->targ_struct_typedef = find_btf_type(targ_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
511         exp->targ_func_proto_typedef = find_btf_type(targ_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
512         exp->targ_arr_typedef = find_btf_type(targ_btf, "arr_typedef", BTF_KIND_TYPEDEF);
513
514         btf__free(targ_btf);
515         return 0;
516 }
517
518 static int setup_type_id_case_failure(struct core_reloc_test_case *test)
519 {
520         struct core_reloc_type_id_output *exp = (void *)test->output;
521         int err;
522
523         err = setup_type_id_case_local(test);
524         if (err)
525                 return err;
526
527         exp->targ_struct = 0;
528         exp->targ_union = 0;
529         exp->targ_enum = 0;
530         exp->targ_int = 0;
531         exp->targ_struct_typedef = 0;
532         exp->targ_func_proto_typedef = 0;
533         exp->targ_arr_typedef = 0;
534
535         return 0;
536 }
537
538 static int __trigger_module_test_read(const struct core_reloc_test_case *test)
539 {
540         struct core_reloc_module_output *exp = (void *)test->output;
541
542         trigger_module_test_read(exp->len);
543         return 0;
544 }
545
546 static const struct core_reloc_test_case test_cases[] = {
547         /* validate we can find kernel image and use its BTF for relocs */
548         {
549                 .case_name = "kernel",
550                 .bpf_obj_file = "test_core_reloc_kernel.o",
551                 .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */
552                 .input = "",
553                 .input_len = 0,
554                 .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
555                         .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
556                         .comm = "test_progs",
557                         .comm_len = sizeof("test_progs"),
558                 },
559                 .output_len = sizeof(struct core_reloc_kernel_output),
560                 .raw_tp_name = "sys_enter",
561                 .prog_name = "test_core_kernel",
562         },
563
564         /* validate we can find kernel module BTF types for relocs/attach */
565         MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
566         MODULES_CASE("module_direct", "test_core_module_direct", NULL),
567
568         /* validate BPF program can use multiple flavors to match against
569          * single target BTF type
570          */
571         FLAVORS_CASE(flavors),
572
573         FLAVORS_ERR_CASE(flavors__err_wrong_name),
574
575         /* various struct/enum nesting and resolution scenarios */
576         NESTING_CASE(nesting),
577         NESTING_CASE(nesting___anon_embed),
578         NESTING_CASE(nesting___struct_union_mixup),
579         NESTING_CASE(nesting___extra_nesting),
580         NESTING_CASE(nesting___dup_compat_types),
581
582         NESTING_ERR_CASE(nesting___err_missing_field),
583         NESTING_ERR_CASE(nesting___err_array_field),
584         NESTING_ERR_CASE(nesting___err_missing_container),
585         NESTING_ERR_CASE(nesting___err_nonstruct_container),
586         NESTING_ERR_CASE(nesting___err_array_container),
587         NESTING_ERR_CASE(nesting___err_dup_incompat_types),
588         NESTING_ERR_CASE(nesting___err_partial_match_dups),
589         NESTING_ERR_CASE(nesting___err_too_deep),
590
591         /* various array access relocation scenarios */
592         ARRAYS_CASE(arrays),
593         ARRAYS_CASE(arrays___diff_arr_dim),
594         ARRAYS_CASE(arrays___diff_arr_val_sz),
595         ARRAYS_CASE(arrays___equiv_zero_sz_arr),
596         ARRAYS_CASE(arrays___fixed_arr),
597
598         ARRAYS_ERR_CASE(arrays___err_too_small),
599         ARRAYS_ERR_CASE(arrays___err_too_shallow),
600         ARRAYS_ERR_CASE(arrays___err_non_array),
601         ARRAYS_ERR_CASE(arrays___err_wrong_val_type),
602         ARRAYS_ERR_CASE(arrays___err_bad_zero_sz_arr),
603
604         /* enum/ptr/int handling scenarios */
605         PRIMITIVES_CASE(primitives),
606         PRIMITIVES_CASE(primitives___diff_enum_def),
607         PRIMITIVES_CASE(primitives___diff_func_proto),
608         PRIMITIVES_CASE(primitives___diff_ptr_type),
609
610         PRIMITIVES_ERR_CASE(primitives___err_non_enum),
611         PRIMITIVES_ERR_CASE(primitives___err_non_int),
612         PRIMITIVES_ERR_CASE(primitives___err_non_ptr),
613
614         /* const/volatile/restrict and typedefs scenarios */
615         MODS_CASE(mods),
616         MODS_CASE(mods___mod_swap),
617         MODS_CASE(mods___typedefs),
618
619         /* handling "ptr is an array" semantics */
620         PTR_AS_ARR_CASE(ptr_as_arr),
621         PTR_AS_ARR_CASE(ptr_as_arr___diff_sz),
622
623         /* int signedness/sizing/bitfield handling */
624         INTS_CASE(ints),
625         INTS_CASE(ints___bool),
626         INTS_CASE(ints___reverse_sign),
627
628         /* validate edge cases of capturing relocations */
629         {
630                 .case_name = "misc",
631                 .bpf_obj_file = "test_core_reloc_misc.o",
632                 .btf_src_file = "btf__core_reloc_misc.o",
633                 .input = (const char *)&(struct core_reloc_misc_extensible[]){
634                         { .a = 1 },
635                         { .a = 2 }, /* not read */
636                         { .a = 3 },
637                 },
638                 .input_len = 4 * sizeof(int),
639                 .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) {
640                         .a = 1,
641                         .b = 1,
642                         .c = 0, /* BUG in clang, should be 3 */
643                 },
644                 .output_len = sizeof(struct core_reloc_misc_output),
645                 .raw_tp_name = "sys_enter",
646                 .prog_name = "test_core_misc",
647         },
648
649         /* validate field existence checks */
650         {
651                 FIELD_EXISTS_CASE_COMMON(existence),
652                 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
653                         .a = 1,
654                         .b = 2,
655                         .c = 3,
656                         .arr = { 4 },
657                         .s = { .x = 5 },
658                 },
659                 .input_len = sizeof(struct core_reloc_existence),
660                 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
661                         .a_exists = 1,
662                         .b_exists = 1,
663                         .c_exists = 1,
664                         .arr_exists = 1,
665                         .s_exists = 1,
666                         .a_value = 1,
667                         .b_value = 2,
668                         .c_value = 3,
669                         .arr_value = 4,
670                         .s_value = 5,
671                 },
672                 .output_len = sizeof(struct core_reloc_existence_output),
673         },
674         {
675                 FIELD_EXISTS_CASE_COMMON(existence___minimal),
676                 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
677                         .a = 42,
678                 },
679                 .input_len = sizeof(struct core_reloc_existence___minimal),
680                 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
681                         .a_exists = 1,
682                         .b_exists = 0,
683                         .c_exists = 0,
684                         .arr_exists = 0,
685                         .s_exists = 0,
686                         .a_value = 42,
687                         .b_value = 0xff000002u,
688                         .c_value = 0xff000003u,
689                         .arr_value = 0xff000004u,
690                         .s_value = 0xff000005u,
691                 },
692                 .output_len = sizeof(struct core_reloc_existence_output),
693         },
694         {
695                 FIELD_EXISTS_CASE_COMMON(existence___wrong_field_defs),
696                 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___wrong_field_defs) {
697                 },
698                 .input_len = sizeof(struct core_reloc_existence___wrong_field_defs),
699                 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
700                         .a_exists = 0,
701                         .b_exists = 0,
702                         .c_exists = 0,
703                         .arr_exists = 0,
704                         .s_exists = 0,
705                         .a_value = 0xff000001u,
706                         .b_value = 0xff000002u,
707                         .c_value = 0xff000003u,
708                         .arr_value = 0xff000004u,
709                         .s_value = 0xff000005u,
710                 },
711                 .output_len = sizeof(struct core_reloc_existence_output),
712         },
713
714         /* bitfield relocation checks */
715         BITFIELDS_CASE(bitfields, {
716                 .ub1 = 1,
717                 .ub2 = 2,
718                 .ub7 = 96,
719                 .sb4 = -7,
720                 .sb20 = -0x76543,
721                 .u32 = 0x80000000,
722                 .s32 = -0x76543210,
723         }),
724         BITFIELDS_CASE(bitfields___bit_sz_change, {
725                 .ub1 = 6,
726                 .ub2 = 0xABCDE,
727                 .ub7 = 1,
728                 .sb4 = -1,
729                 .sb20 = -0x17654321,
730                 .u32 = 0xBEEF,
731                 .s32 = -0x3FEDCBA987654321LL,
732         }),
733         BITFIELDS_CASE(bitfields___bitfield_vs_int, {
734                 .ub1 = 0xFEDCBA9876543210LL,
735                 .ub2 = 0xA6,
736                 .ub7 = -0x7EDCBA987654321LL,
737                 .sb4 = -0x6123456789ABCDELL,
738                 .sb20 = 0xD00DLL,
739                 .u32 = -0x76543,
740                 .s32 = 0x0ADEADBEEFBADB0BLL,
741         }),
742         BITFIELDS_CASE(bitfields___just_big_enough, {
743                 .ub1 = 0xFLL,
744                 .ub2 = 0x0812345678FEDCBALL,
745         }),
746         BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield),
747
748         /* field size and offset relocation checks */
749         SIZE_CASE(size),
750         SIZE_CASE(size___diff_sz),
751         SIZE_CASE(size___diff_offs),
752         SIZE_ERR_CASE(size___err_ambiguous),
753
754         /* validate type existence, match, and size relocations */
755         TYPE_BASED_CASE(type_based, {
756                 .struct_exists = 1,
757                 .union_exists = 1,
758                 .enum_exists = 1,
759                 .typedef_named_struct_exists = 1,
760                 .typedef_anon_struct_exists = 1,
761                 .typedef_struct_ptr_exists = 1,
762                 .typedef_int_exists = 1,
763                 .typedef_enum_exists = 1,
764                 .typedef_void_ptr_exists = 1,
765                 .typedef_func_proto_exists = 1,
766                 .typedef_arr_exists = 1,
767
768                 .struct_matches = 1,
769                 .union_matches = 1,
770                 .enum_matches = 1,
771                 .typedef_named_struct_matches = 1,
772                 .typedef_anon_struct_matches = 1,
773                 .typedef_struct_ptr_matches = 1,
774                 .typedef_int_matches = 1,
775                 .typedef_enum_matches = 1,
776                 .typedef_void_ptr_matches = 1,
777                 .typedef_func_proto_matches = 1,
778                 .typedef_arr_matches = 1,
779
780                 .struct_sz = sizeof(struct a_struct),
781                 .union_sz = sizeof(union a_union),
782                 .enum_sz = sizeof(enum an_enum),
783                 .typedef_named_struct_sz = sizeof(named_struct_typedef),
784                 .typedef_anon_struct_sz = sizeof(anon_struct_typedef),
785                 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef),
786                 .typedef_int_sz = sizeof(int_typedef),
787                 .typedef_enum_sz = sizeof(enum_typedef),
788                 .typedef_void_ptr_sz = sizeof(void_ptr_typedef),
789                 .typedef_func_proto_sz = sizeof(func_proto_typedef),
790                 .typedef_arr_sz = sizeof(arr_typedef),
791         }),
792         TYPE_BASED_CASE(type_based___all_missing, {
793                 /* all zeros */
794         }),
795         TYPE_BASED_CASE(type_based___diff_sz, {
796                 .struct_exists = 1,
797                 .union_exists = 1,
798                 .enum_exists = 1,
799                 .typedef_named_struct_exists = 1,
800                 .typedef_anon_struct_exists = 1,
801                 .typedef_struct_ptr_exists = 1,
802                 .typedef_int_exists = 1,
803                 .typedef_enum_exists = 1,
804                 .typedef_void_ptr_exists = 1,
805                 .typedef_func_proto_exists = 1,
806                 .typedef_arr_exists = 1,
807
808                 .struct_matches = 0,
809                 .union_matches = 0,
810                 .enum_matches = 0,
811                 .typedef_named_struct_matches = 0,
812                 .typedef_anon_struct_matches = 0,
813                 .typedef_struct_ptr_matches = 1,
814                 .typedef_int_matches = 0,
815                 .typedef_enum_matches = 0,
816                 .typedef_void_ptr_matches = 1,
817                 .typedef_func_proto_matches = 0,
818                 .typedef_arr_matches = 0,
819
820                 .struct_sz = sizeof(struct a_struct___diff_sz),
821                 .union_sz = sizeof(union a_union___diff_sz),
822                 .enum_sz = sizeof(enum an_enum___diff_sz),
823                 .typedef_named_struct_sz = sizeof(named_struct_typedef___diff_sz),
824                 .typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff_sz),
825                 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff_sz),
826                 .typedef_int_sz = sizeof(int_typedef___diff_sz),
827                 .typedef_enum_sz = sizeof(enum_typedef___diff_sz),
828                 .typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff_sz),
829                 .typedef_func_proto_sz = sizeof(func_proto_typedef___diff_sz),
830                 .typedef_arr_sz = sizeof(arr_typedef___diff_sz),
831         }),
832         TYPE_BASED_CASE(type_based___incompat, {
833                 .enum_exists = 1,
834                 .enum_matches = 1,
835                 .enum_sz = sizeof(enum an_enum),
836         }),
837         TYPE_BASED_CASE(type_based___fn_wrong_args, {
838                 .struct_exists = 1,
839                 .struct_matches = 1,
840                 .struct_sz = sizeof(struct a_struct),
841         }),
842
843         /* BTF_TYPE_ID_LOCAL/BTF_TYPE_ID_TARGET tests */
844         TYPE_ID_CASE(type_id, setup_type_id_case_success),
845         TYPE_ID_CASE(type_id___missing_targets, setup_type_id_case_failure),
846
847         /* Enumerator value existence and value relocations */
848         ENUMVAL_CASE(enumval, {
849                 .named_val1_exists = true,
850                 .named_val2_exists = true,
851                 .named_val3_exists = true,
852                 .anon_val1_exists = true,
853                 .anon_val2_exists = true,
854                 .anon_val3_exists = true,
855                 .named_val1 = 1,
856                 .named_val2 = 2,
857                 .anon_val1 = 0x10,
858                 .anon_val2 = 0x20,
859         }),
860         ENUMVAL_CASE(enumval___diff, {
861                 .named_val1_exists = true,
862                 .named_val2_exists = true,
863                 .named_val3_exists = true,
864                 .anon_val1_exists = true,
865                 .anon_val2_exists = true,
866                 .anon_val3_exists = true,
867                 .named_val1 = 101,
868                 .named_val2 = 202,
869                 .anon_val1 = 0x11,
870                 .anon_val2 = 0x22,
871         }),
872         ENUMVAL_CASE(enumval___val3_missing, {
873                 .named_val1_exists = true,
874                 .named_val2_exists = true,
875                 .named_val3_exists = false,
876                 .anon_val1_exists = true,
877                 .anon_val2_exists = true,
878                 .anon_val3_exists = false,
879                 .named_val1 = 111,
880                 .named_val2 = 222,
881                 .anon_val1 = 0x111,
882                 .anon_val2 = 0x222,
883         }),
884         ENUMVAL_ERR_CASE(enumval___err_missing),
885
886         /* 64bit enumerator value existence and value relocations */
887         ENUM64VAL_CASE(enum64val, {
888                 .unsigned_val1_exists = true,
889                 .unsigned_val2_exists = true,
890                 .unsigned_val3_exists = true,
891                 .signed_val1_exists = true,
892                 .signed_val2_exists = true,
893                 .signed_val3_exists = true,
894                 .unsigned_val1 = 0x1ffffffffULL,
895                 .unsigned_val2 = 0x2,
896                 .signed_val1 = 0x1ffffffffLL,
897                 .signed_val2 = -2,
898         }),
899         ENUM64VAL_CASE(enum64val___diff, {
900                 .unsigned_val1_exists = true,
901                 .unsigned_val2_exists = true,
902                 .unsigned_val3_exists = true,
903                 .signed_val1_exists = true,
904                 .signed_val2_exists = true,
905                 .signed_val3_exists = true,
906                 .unsigned_val1 = 0x101ffffffffULL,
907                 .unsigned_val2 = 0x202ffffffffULL,
908                 .signed_val1 = -101,
909                 .signed_val2 = -202,
910         }),
911         ENUM64VAL_CASE(enum64val___val3_missing, {
912                 .unsigned_val1_exists = true,
913                 .unsigned_val2_exists = true,
914                 .unsigned_val3_exists = false,
915                 .signed_val1_exists = true,
916                 .signed_val2_exists = true,
917                 .signed_val3_exists = false,
918                 .unsigned_val1 = 0x111ffffffffULL,
919                 .unsigned_val2 = 0x222,
920                 .signed_val1 = 0x111ffffffffLL,
921                 .signed_val2 = -222,
922         }),
923         ENUM64VAL_ERR_CASE(enum64val___err_missing),
924 };
925
926 struct data {
927         char in[256];
928         char out[256];
929         bool skip;
930         uint64_t my_pid_tgid;
931 };
932
933 static size_t roundup_page(size_t sz)
934 {
935         long page_size = sysconf(_SC_PAGE_SIZE);
936         return (sz + page_size - 1) / page_size * page_size;
937 }
938
939 static int run_btfgen(const char *src_btf, const char *dst_btf, const char *objpath)
940 {
941         char command[4096];
942         int n;
943
944         n = snprintf(command, sizeof(command),
945                      "./bpftool gen min_core_btf %s %s %s",
946                      src_btf, dst_btf, objpath);
947         if (n < 0 || n >= sizeof(command))
948                 return -1;
949
950         return system(command);
951 }
952
953 static void run_core_reloc_tests(bool use_btfgen)
954 {
955         const size_t mmap_sz = roundup_page(sizeof(struct data));
956         DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts);
957         struct core_reloc_test_case *test_case, test_case_copy;
958         const char *tp_name, *probe_name;
959         int err, i, equal, fd;
960         struct bpf_link *link = NULL;
961         struct bpf_map *data_map;
962         struct bpf_program *prog;
963         struct bpf_object *obj;
964         uint64_t my_pid_tgid;
965         struct data *data;
966         void *mmap_data = NULL;
967
968         my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32);
969
970         for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
971                 char btf_file[] = "/tmp/core_reloc.btf.XXXXXX";
972
973                 test_case_copy = test_cases[i];
974                 test_case = &test_case_copy;
975
976                 if (!test__start_subtest(test_case->case_name))
977                         continue;
978
979                 if (test_case->needs_testmod && !env.has_testmod) {
980                         test__skip();
981                         continue;
982                 }
983
984                 /* generate a "minimal" BTF file and use it as source */
985                 if (use_btfgen) {
986
987                         if (!test_case->btf_src_file || test_case->run_btfgen_fails) {
988                                 test__skip();
989                                 continue;
990                         }
991
992                         fd = mkstemp(btf_file);
993                         if (!ASSERT_GE(fd, 0, "btf_tmp"))
994                                 continue;
995                         close(fd); /* we only need the path */
996                         err = run_btfgen(test_case->btf_src_file, btf_file,
997                                          test_case->bpf_obj_file);
998                         if (!ASSERT_OK(err, "run_btfgen"))
999                                 continue;
1000
1001                         test_case->btf_src_file = btf_file;
1002                 }
1003
1004                 if (test_case->setup) {
1005                         err = test_case->setup(test_case);
1006                         if (CHECK(err, "test_setup", "test #%d setup failed: %d\n", i, err))
1007                                 continue;
1008                 }
1009
1010                 if (test_case->btf_src_file) {
1011                         err = access(test_case->btf_src_file, R_OK);
1012                         if (!ASSERT_OK(err, "btf_src_file"))
1013                                 continue;
1014                 }
1015
1016                 open_opts.btf_custom_path = test_case->btf_src_file;
1017                 obj = bpf_object__open_file(test_case->bpf_obj_file, &open_opts);
1018                 if (!ASSERT_OK_PTR(obj, "obj_open"))
1019                         goto cleanup;
1020
1021                 probe_name = test_case->prog_name;
1022                 tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
1023                 prog = bpf_object__find_program_by_name(obj, probe_name);
1024                 if (CHECK(!prog, "find_probe",
1025                           "prog '%s' not found\n", probe_name))
1026                         goto cleanup;
1027
1028                 err = bpf_object__load(obj);
1029                 if (err) {
1030                         if (!test_case->fails)
1031                                 ASSERT_OK(err, "obj_load");
1032                         goto cleanup;
1033                 }
1034
1035                 data_map = bpf_object__find_map_by_name(obj, ".bss");
1036                 if (CHECK(!data_map, "find_data_map", "data map not found\n"))
1037                         goto cleanup;
1038
1039                 mmap_data = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
1040                                  MAP_SHARED, bpf_map__fd(data_map), 0);
1041                 if (CHECK(mmap_data == MAP_FAILED, "mmap",
1042                           ".bss mmap failed: %d", errno)) {
1043                         mmap_data = NULL;
1044                         goto cleanup;
1045                 }
1046                 data = mmap_data;
1047
1048                 memset(mmap_data, 0, sizeof(*data));
1049                 if (test_case->input_len)
1050                         memcpy(data->in, test_case->input, test_case->input_len);
1051                 data->my_pid_tgid = my_pid_tgid;
1052
1053                 link = bpf_program__attach_raw_tracepoint(prog, tp_name);
1054                 if (!ASSERT_OK_PTR(link, "attach_raw_tp"))
1055                         goto cleanup;
1056
1057                 /* trigger test run */
1058                 if (test_case->trigger) {
1059                         if (!ASSERT_OK(test_case->trigger(test_case), "test_trigger"))
1060                                 goto cleanup;
1061                 } else {
1062                         usleep(1);
1063                 }
1064
1065                 if (data->skip) {
1066                         test__skip();
1067                         goto cleanup;
1068                 }
1069
1070                 if (!ASSERT_FALSE(test_case->fails, "obj_load_should_fail"))
1071                         goto cleanup;
1072
1073                 equal = memcmp(data->out, test_case->output,
1074                                test_case->output_len) == 0;
1075                 if (CHECK(!equal, "check_result",
1076                           "input/output data don't match\n")) {
1077                         int j;
1078
1079                         for (j = 0; j < test_case->input_len; j++) {
1080                                 printf("input byte #%d: 0x%02hhx\n",
1081                                        j, test_case->input[j]);
1082                         }
1083                         for (j = 0; j < test_case->output_len; j++) {
1084                                 printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n",
1085                                        j, test_case->output[j], data->out[j]);
1086                         }
1087                         goto cleanup;
1088                 }
1089
1090 cleanup:
1091                 if (mmap_data) {
1092                         CHECK_FAIL(munmap(mmap_data, mmap_sz));
1093                         mmap_data = NULL;
1094                 }
1095                 if (use_btfgen)
1096                         remove(test_case->btf_src_file);
1097                 bpf_link__destroy(link);
1098                 link = NULL;
1099                 bpf_object__close(obj);
1100         }
1101 }
1102
1103 void test_core_reloc(void)
1104 {
1105         run_core_reloc_tests(false);
1106 }
1107
1108 void test_core_reloc_btfgen(void)
1109 {
1110         run_core_reloc_tests(true);
1111 }