1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "progs/core_reloc_types.h"
5 #include <sys/syscall.h>
8 static int duration = 0;
10 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
12 #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
18 #define FLAVORS_CASE_COMMON(name) \
20 .bpf_obj_file = "test_core_reloc_flavors.o", \
21 .btf_src_file = "btf__core_reloc_" #name ".o" \
23 #define FLAVORS_CASE(name) { \
24 FLAVORS_CASE_COMMON(name), \
25 .input = FLAVORS_DATA(core_reloc_##name), \
26 .input_len = sizeof(struct core_reloc_##name), \
27 .output = FLAVORS_DATA(core_reloc_flavors), \
28 .output_len = sizeof(struct core_reloc_flavors), \
31 #define FLAVORS_ERR_CASE(name) { \
32 FLAVORS_CASE_COMMON(name), \
36 #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
37 .a = { .a = { .a = 42 } }, \
38 .b = { .b = { .b = 0xc001 } }, \
41 #define NESTING_CASE_COMMON(name) \
43 .bpf_obj_file = "test_core_reloc_nesting.o", \
44 .btf_src_file = "btf__core_reloc_" #name ".o"
46 #define NESTING_CASE(name) { \
47 NESTING_CASE_COMMON(name), \
48 .input = NESTING_DATA(core_reloc_##name), \
49 .input_len = sizeof(struct core_reloc_##name), \
50 .output = NESTING_DATA(core_reloc_nesting), \
51 .output_len = sizeof(struct core_reloc_nesting) \
54 #define NESTING_ERR_CASE(name) { \
55 NESTING_CASE_COMMON(name), \
59 #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
61 .b = { [1] = { [2] = { [3] = 2 } } }, \
62 .c = { [1] = { .c = 3 } }, \
63 .d = { [0] = { [0] = { .d = 4 } } }, \
66 #define ARRAYS_CASE_COMMON(name) \
68 .bpf_obj_file = "test_core_reloc_arrays.o", \
69 .btf_src_file = "btf__core_reloc_" #name ".o"
71 #define ARRAYS_CASE(name) { \
72 ARRAYS_CASE_COMMON(name), \
73 .input = ARRAYS_DATA(core_reloc_##name), \
74 .input_len = sizeof(struct core_reloc_##name), \
75 .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) { \
82 .output_len = sizeof(struct core_reloc_arrays_output) \
85 #define ARRAYS_ERR_CASE(name) { \
86 ARRAYS_CASE_COMMON(name), \
90 #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
98 #define PRIMITIVES_CASE_COMMON(name) \
100 .bpf_obj_file = "test_core_reloc_primitives.o", \
101 .btf_src_file = "btf__core_reloc_" #name ".o"
103 #define PRIMITIVES_CASE(name) { \
104 PRIMITIVES_CASE_COMMON(name), \
105 .input = PRIMITIVES_DATA(core_reloc_##name), \
106 .input_len = sizeof(struct core_reloc_##name), \
107 .output = PRIMITIVES_DATA(core_reloc_primitives), \
108 .output_len = sizeof(struct core_reloc_primitives), \
111 #define PRIMITIVES_ERR_CASE(name) { \
112 PRIMITIVES_CASE_COMMON(name), \
116 #define MODS_CASE(name) { \
117 .case_name = #name, \
118 .bpf_obj_file = "test_core_reloc_mods.o", \
119 .btf_src_file = "btf__core_reloc_" #name ".o", \
120 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) { \
130 .input_len = sizeof(struct core_reloc_##name), \
131 .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) { \
132 .a = 1, .b = 2, .c = 3, .d = 4, \
133 .e = 5, .f = 6, .g = 7, .h = 8, \
135 .output_len = sizeof(struct core_reloc_mods_output), \
138 #define PTR_AS_ARR_CASE(name) { \
139 .case_name = #name, \
140 .bpf_obj_file = "test_core_reloc_ptr_as_arr.o", \
141 .btf_src_file = "btf__core_reloc_" #name ".o", \
142 .input = (const char *)&(struct core_reloc_##name []){ \
147 .input_len = 3 * sizeof(struct core_reloc_##name), \
148 .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) { \
151 .output_len = sizeof(struct core_reloc_ptr_as_arr), \
154 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
165 #define INTS_CASE_COMMON(name) \
166 .case_name = #name, \
167 .bpf_obj_file = "test_core_reloc_ints.o", \
168 .btf_src_file = "btf__core_reloc_" #name ".o"
170 #define INTS_CASE(name) { \
171 INTS_CASE_COMMON(name), \
172 .input = INTS_DATA(core_reloc_##name), \
173 .input_len = sizeof(struct core_reloc_##name), \
174 .output = INTS_DATA(core_reloc_ints), \
175 .output_len = sizeof(struct core_reloc_ints), \
178 #define INTS_ERR_CASE(name) { \
179 INTS_CASE_COMMON(name), \
183 #define FIELD_EXISTS_CASE_COMMON(name) \
184 .case_name = #name, \
185 .bpf_obj_file = "test_core_reloc_existence.o", \
186 .btf_src_file = "btf__core_reloc_" #name ".o" \
188 #define FIELD_EXISTS_ERR_CASE(name) { \
189 FIELD_EXISTS_CASE_COMMON(name), \
193 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \
194 .case_name = test_name_prefix#name, \
195 .bpf_obj_file = objfile, \
196 .btf_src_file = "btf__core_reloc_" #name ".o"
198 #define BITFIELDS_CASE(name, ...) { \
199 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
201 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \
202 .input_len = sizeof(struct core_reloc_##name), \
203 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
205 .output_len = sizeof(struct core_reloc_bitfields_output), \
207 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
209 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \
210 .input_len = sizeof(struct core_reloc_##name), \
211 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
213 .output_len = sizeof(struct core_reloc_bitfields_output), \
214 .direct_raw_tp = true, \
218 #define BITFIELDS_ERR_CASE(name) { \
219 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
223 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
225 .direct_raw_tp = true, \
229 #define SIZE_CASE_COMMON(name) \
230 .case_name = #name, \
231 .bpf_obj_file = "test_core_reloc_size.o", \
232 .btf_src_file = "btf__core_reloc_" #name ".o", \
233 .relaxed_core_relocs = true
235 #define SIZE_OUTPUT_DATA(type) \
236 STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \
237 .int_sz = sizeof(((type *)0)->int_field), \
238 .struct_sz = sizeof(((type *)0)->struct_field), \
239 .union_sz = sizeof(((type *)0)->union_field), \
240 .arr_sz = sizeof(((type *)0)->arr_field), \
241 .arr_elem_sz = sizeof(((type *)0)->arr_field[0]), \
242 .ptr_sz = 8, /* always 8-byte pointer for BPF */ \
243 .enum_sz = sizeof(((type *)0)->enum_field), \
246 #define SIZE_CASE(name) { \
247 SIZE_CASE_COMMON(name), \
249 .output = SIZE_OUTPUT_DATA(struct core_reloc_##name), \
250 .output_len = sizeof(struct core_reloc_size_output), \
253 #define SIZE_ERR_CASE(name) { \
254 SIZE_CASE_COMMON(name), \
258 #define TYPE_BASED_CASE_COMMON(name) \
259 .case_name = #name, \
260 .bpf_obj_file = "test_core_reloc_type_based.o", \
261 .btf_src_file = "btf__core_reloc_" #name ".o" \
263 #define TYPE_BASED_CASE(name, ...) { \
264 TYPE_BASED_CASE_COMMON(name), \
265 .output = STRUCT_TO_CHAR_PTR(core_reloc_type_based_output) \
267 .output_len = sizeof(struct core_reloc_type_based_output), \
270 #define TYPE_BASED_ERR_CASE(name) { \
271 TYPE_BASED_CASE_COMMON(name), \
275 #define TYPE_ID_CASE_COMMON(name) \
276 .case_name = #name, \
277 .bpf_obj_file = "test_core_reloc_type_id.o", \
278 .btf_src_file = "btf__core_reloc_" #name ".o" \
280 #define TYPE_ID_CASE(name, setup_fn) { \
281 TYPE_ID_CASE_COMMON(name), \
282 .output = STRUCT_TO_CHAR_PTR(core_reloc_type_id_output) {}, \
283 .output_len = sizeof(struct core_reloc_type_id_output), \
287 #define TYPE_ID_ERR_CASE(name) { \
288 TYPE_ID_CASE_COMMON(name), \
292 struct core_reloc_test_case;
294 typedef int (*setup_test_fn)(struct core_reloc_test_case *test);
296 struct core_reloc_test_case {
297 const char *case_name;
298 const char *bpf_obj_file;
299 const char *btf_src_file;
305 bool relaxed_core_relocs;
310 static int find_btf_type(const struct btf *btf, const char *name, __u32 kind)
314 id = btf__find_by_name_kind(btf, name, kind);
315 if (CHECK(id <= 0, "find_type_id", "failed to find '%s', kind %d: %d\n", name, kind, id))
321 static int setup_type_id_case_local(struct core_reloc_test_case *test)
323 struct core_reloc_type_id_output *exp = (void *)test->output;
324 struct btf *local_btf = btf__parse(test->bpf_obj_file, NULL);
325 struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
326 const struct btf_type *t;
330 if (CHECK(IS_ERR(local_btf), "local_btf", "failed: %ld\n", PTR_ERR(local_btf)) ||
331 CHECK(IS_ERR(targ_btf), "targ_btf", "failed: %ld\n", PTR_ERR(targ_btf))) {
332 btf__free(local_btf);
337 exp->local_anon_struct = -1;
338 exp->local_anon_union = -1;
339 exp->local_anon_enum = -1;
340 exp->local_anon_func_proto_ptr = -1;
341 exp->local_anon_void_ptr = -1;
342 exp->local_anon_arr = -1;
344 for (i = 1; i <= btf__get_nr_types(local_btf); i++)
346 t = btf__type_by_id(local_btf, i);
347 /* we are interested only in anonymous types */
351 if (btf_is_struct(t) && btf_vlen(t) &&
352 (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
353 strcmp(name, "marker_field") == 0) {
354 exp->local_anon_struct = i;
355 } else if (btf_is_union(t) && btf_vlen(t) &&
356 (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
357 strcmp(name, "marker_field") == 0) {
358 exp->local_anon_union = i;
359 } else if (btf_is_enum(t) && btf_vlen(t) &&
360 (name = btf__name_by_offset(local_btf, btf_enum(t)[0].name_off)) &&
361 strcmp(name, "MARKER_ENUM_VAL") == 0) {
362 exp->local_anon_enum = i;
363 } else if (btf_is_ptr(t) && (t = btf__type_by_id(local_btf, t->type))) {
364 if (btf_is_func_proto(t) && (t = btf__type_by_id(local_btf, t->type)) &&
365 btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
366 strcmp(name, "_Bool") == 0) {
367 /* ptr -> func_proto -> _Bool */
368 exp->local_anon_func_proto_ptr = i;
369 } else if (btf_is_void(t)) {
371 exp->local_anon_void_ptr = i;
373 } else if (btf_is_array(t) && (t = btf__type_by_id(local_btf, btf_array(t)->type)) &&
374 btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
375 strcmp(name, "_Bool") == 0) {
377 exp->local_anon_arr = i;
381 exp->local_struct = find_btf_type(local_btf, "a_struct", BTF_KIND_STRUCT);
382 exp->local_union = find_btf_type(local_btf, "a_union", BTF_KIND_UNION);
383 exp->local_enum = find_btf_type(local_btf, "an_enum", BTF_KIND_ENUM);
384 exp->local_int = find_btf_type(local_btf, "int", BTF_KIND_INT);
385 exp->local_struct_typedef = find_btf_type(local_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
386 exp->local_func_proto_typedef = find_btf_type(local_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
387 exp->local_arr_typedef = find_btf_type(local_btf, "arr_typedef", BTF_KIND_TYPEDEF);
389 btf__free(local_btf);
394 static int setup_type_id_case_success(struct core_reloc_test_case *test) {
395 struct core_reloc_type_id_output *exp = (void *)test->output;
396 struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
399 err = setup_type_id_case_local(test);
403 targ_btf = btf__parse(test->btf_src_file, NULL);
405 exp->targ_struct = find_btf_type(targ_btf, "a_struct", BTF_KIND_STRUCT);
406 exp->targ_union = find_btf_type(targ_btf, "a_union", BTF_KIND_UNION);
407 exp->targ_enum = find_btf_type(targ_btf, "an_enum", BTF_KIND_ENUM);
408 exp->targ_int = find_btf_type(targ_btf, "int", BTF_KIND_INT);
409 exp->targ_struct_typedef = find_btf_type(targ_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
410 exp->targ_func_proto_typedef = find_btf_type(targ_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
411 exp->targ_arr_typedef = find_btf_type(targ_btf, "arr_typedef", BTF_KIND_TYPEDEF);
417 static int setup_type_id_case_failure(struct core_reloc_test_case *test)
419 struct core_reloc_type_id_output *exp = (void *)test->output;
422 err = setup_type_id_case_local(test);
426 exp->targ_struct = 0;
430 exp->targ_struct_typedef = 0;
431 exp->targ_func_proto_typedef = 0;
432 exp->targ_arr_typedef = 0;
437 static struct core_reloc_test_case test_cases[] = {
438 /* validate we can find kernel image and use its BTF for relocs */
440 .case_name = "kernel",
441 .bpf_obj_file = "test_core_reloc_kernel.o",
442 .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */
445 .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
446 .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
447 .comm = "test_progs",
448 .comm_len = sizeof("test_progs"),
450 .output_len = sizeof(struct core_reloc_kernel_output),
453 /* validate BPF program can use multiple flavors to match against
454 * single target BTF type
456 FLAVORS_CASE(flavors),
458 FLAVORS_ERR_CASE(flavors__err_wrong_name),
460 /* various struct/enum nesting and resolution scenarios */
461 NESTING_CASE(nesting),
462 NESTING_CASE(nesting___anon_embed),
463 NESTING_CASE(nesting___struct_union_mixup),
464 NESTING_CASE(nesting___extra_nesting),
465 NESTING_CASE(nesting___dup_compat_types),
467 NESTING_ERR_CASE(nesting___err_missing_field),
468 NESTING_ERR_CASE(nesting___err_array_field),
469 NESTING_ERR_CASE(nesting___err_missing_container),
470 NESTING_ERR_CASE(nesting___err_nonstruct_container),
471 NESTING_ERR_CASE(nesting___err_array_container),
472 NESTING_ERR_CASE(nesting___err_dup_incompat_types),
473 NESTING_ERR_CASE(nesting___err_partial_match_dups),
474 NESTING_ERR_CASE(nesting___err_too_deep),
476 /* various array access relocation scenarios */
478 ARRAYS_CASE(arrays___diff_arr_dim),
479 ARRAYS_CASE(arrays___diff_arr_val_sz),
480 ARRAYS_CASE(arrays___equiv_zero_sz_arr),
481 ARRAYS_CASE(arrays___fixed_arr),
483 ARRAYS_ERR_CASE(arrays___err_too_small),
484 ARRAYS_ERR_CASE(arrays___err_too_shallow),
485 ARRAYS_ERR_CASE(arrays___err_non_array),
486 ARRAYS_ERR_CASE(arrays___err_wrong_val_type1),
487 ARRAYS_ERR_CASE(arrays___err_wrong_val_type2),
488 ARRAYS_ERR_CASE(arrays___err_bad_zero_sz_arr),
490 /* enum/ptr/int handling scenarios */
491 PRIMITIVES_CASE(primitives),
492 PRIMITIVES_CASE(primitives___diff_enum_def),
493 PRIMITIVES_CASE(primitives___diff_func_proto),
494 PRIMITIVES_CASE(primitives___diff_ptr_type),
496 PRIMITIVES_ERR_CASE(primitives___err_non_enum),
497 PRIMITIVES_ERR_CASE(primitives___err_non_int),
498 PRIMITIVES_ERR_CASE(primitives___err_non_ptr),
500 /* const/volatile/restrict and typedefs scenarios */
502 MODS_CASE(mods___mod_swap),
503 MODS_CASE(mods___typedefs),
505 /* handling "ptr is an array" semantics */
506 PTR_AS_ARR_CASE(ptr_as_arr),
507 PTR_AS_ARR_CASE(ptr_as_arr___diff_sz),
509 /* int signedness/sizing/bitfield handling */
511 INTS_CASE(ints___bool),
512 INTS_CASE(ints___reverse_sign),
514 /* validate edge cases of capturing relocations */
517 .bpf_obj_file = "test_core_reloc_misc.o",
518 .btf_src_file = "btf__core_reloc_misc.o",
519 .input = (const char *)&(struct core_reloc_misc_extensible[]){
521 { .a = 2 }, /* not read */
524 .input_len = 4 * sizeof(int),
525 .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) {
528 .c = 0, /* BUG in clang, should be 3 */
530 .output_len = sizeof(struct core_reloc_misc_output),
533 /* validate field existence checks */
535 FIELD_EXISTS_CASE_COMMON(existence),
536 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
543 .input_len = sizeof(struct core_reloc_existence),
544 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
556 .output_len = sizeof(struct core_reloc_existence_output),
559 FIELD_EXISTS_CASE_COMMON(existence___minimal),
560 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
563 .input_len = sizeof(struct core_reloc_existence___minimal),
564 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
571 .b_value = 0xff000002u,
572 .c_value = 0xff000003u,
573 .arr_value = 0xff000004u,
574 .s_value = 0xff000005u,
576 .output_len = sizeof(struct core_reloc_existence_output),
579 FIELD_EXISTS_ERR_CASE(existence__err_int_sz),
580 FIELD_EXISTS_ERR_CASE(existence__err_int_type),
581 FIELD_EXISTS_ERR_CASE(existence__err_int_kind),
582 FIELD_EXISTS_ERR_CASE(existence__err_arr_kind),
583 FIELD_EXISTS_ERR_CASE(existence__err_arr_value_type),
584 FIELD_EXISTS_ERR_CASE(existence__err_struct_type),
586 /* bitfield relocation checks */
587 BITFIELDS_CASE(bitfields, {
596 BITFIELDS_CASE(bitfields___bit_sz_change, {
603 .s32 = -0x3FEDCBA987654321LL,
605 BITFIELDS_CASE(bitfields___bitfield_vs_int, {
606 .ub1 = 0xFEDCBA9876543210LL,
608 .ub7 = -0x7EDCBA987654321LL,
609 .sb4 = -0x6123456789ABCDELL,
612 .s32 = 0x0ADEADBEEFBADB0BLL,
614 BITFIELDS_CASE(bitfields___just_big_enough, {
616 .ub2 = 0x0812345678FEDCBALL,
618 BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield),
620 /* size relocation checks */
622 SIZE_CASE(size___diff_sz),
623 SIZE_ERR_CASE(size___err_ambiguous),
625 /* validate type existence and size relocations */
626 TYPE_BASED_CASE(type_based, {
630 .typedef_named_struct_exists = 1,
631 .typedef_anon_struct_exists = 1,
632 .typedef_struct_ptr_exists = 1,
633 .typedef_int_exists = 1,
634 .typedef_enum_exists = 1,
635 .typedef_void_ptr_exists = 1,
636 .typedef_func_proto_exists = 1,
637 .typedef_arr_exists = 1,
638 .struct_sz = sizeof(struct a_struct),
639 .union_sz = sizeof(union a_union),
640 .enum_sz = sizeof(enum an_enum),
641 .typedef_named_struct_sz = sizeof(named_struct_typedef),
642 .typedef_anon_struct_sz = sizeof(anon_struct_typedef),
643 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef),
644 .typedef_int_sz = sizeof(int_typedef),
645 .typedef_enum_sz = sizeof(enum_typedef),
646 .typedef_void_ptr_sz = sizeof(void_ptr_typedef),
647 .typedef_func_proto_sz = sizeof(func_proto_typedef),
648 .typedef_arr_sz = sizeof(arr_typedef),
650 TYPE_BASED_CASE(type_based___all_missing, {
653 TYPE_BASED_CASE(type_based___diff_sz, {
657 .typedef_named_struct_exists = 1,
658 .typedef_anon_struct_exists = 1,
659 .typedef_struct_ptr_exists = 1,
660 .typedef_int_exists = 1,
661 .typedef_enum_exists = 1,
662 .typedef_void_ptr_exists = 1,
663 .typedef_func_proto_exists = 1,
664 .typedef_arr_exists = 1,
665 .struct_sz = sizeof(struct a_struct___diff_sz),
666 .union_sz = sizeof(union a_union___diff_sz),
667 .enum_sz = sizeof(enum an_enum___diff_sz),
668 .typedef_named_struct_sz = sizeof(named_struct_typedef___diff_sz),
669 .typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff_sz),
670 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff_sz),
671 .typedef_int_sz = sizeof(int_typedef___diff_sz),
672 .typedef_enum_sz = sizeof(enum_typedef___diff_sz),
673 .typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff_sz),
674 .typedef_func_proto_sz = sizeof(func_proto_typedef___diff_sz),
675 .typedef_arr_sz = sizeof(arr_typedef___diff_sz),
677 TYPE_BASED_CASE(type_based___incompat, {
679 .enum_sz = sizeof(enum an_enum),
681 TYPE_BASED_CASE(type_based___fn_wrong_args, {
683 .struct_sz = sizeof(struct a_struct),
686 /* BTF_TYPE_ID_LOCAL/BTF_TYPE_ID_TARGET tests */
687 TYPE_ID_CASE(type_id, setup_type_id_case_success),
688 TYPE_ID_CASE(type_id___missing_targets, setup_type_id_case_failure),
695 uint64_t my_pid_tgid;
698 static size_t roundup_page(size_t sz)
700 long page_size = sysconf(_SC_PAGE_SIZE);
701 return (sz + page_size - 1) / page_size * page_size;
704 void test_core_reloc(void)
706 const size_t mmap_sz = roundup_page(sizeof(struct data));
707 struct bpf_object_load_attr load_attr = {};
708 struct core_reloc_test_case *test_case;
709 const char *tp_name, *probe_name;
711 struct bpf_link *link = NULL;
712 struct bpf_map *data_map;
713 struct bpf_program *prog;
714 struct bpf_object *obj;
715 uint64_t my_pid_tgid;
717 void *mmap_data = NULL;
719 my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32);
721 for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
722 test_case = &test_cases[i];
723 if (!test__start_subtest(test_case->case_name))
726 if (test_case->setup) {
727 err = test_case->setup(test_case);
728 if (CHECK(err, "test_setup", "test #%d setup failed: %d\n", i, err))
732 obj = bpf_object__open_file(test_case->bpf_obj_file, NULL);
733 if (CHECK(IS_ERR(obj), "obj_open", "failed to open '%s': %ld\n",
734 test_case->bpf_obj_file, PTR_ERR(obj)))
737 /* for typed raw tracepoints, NULL should be specified */
738 if (test_case->direct_raw_tp) {
739 probe_name = "tp_btf/sys_enter";
742 probe_name = "raw_tracepoint/sys_enter";
743 tp_name = "sys_enter";
746 prog = bpf_object__find_program_by_title(obj, probe_name);
747 if (CHECK(!prog, "find_probe",
748 "prog '%s' not found\n", probe_name))
752 load_attr.log_level = 0;
753 load_attr.target_btf_path = test_case->btf_src_file;
754 err = bpf_object__load_xattr(&load_attr);
756 if (!test_case->fails)
757 CHECK(false, "obj_load", "failed to load prog '%s': %d\n", probe_name, err);
761 data_map = bpf_object__find_map_by_name(obj, "test_cor.bss");
762 if (CHECK(!data_map, "find_data_map", "data map not found\n"))
765 mmap_data = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
766 MAP_SHARED, bpf_map__fd(data_map), 0);
767 if (CHECK(mmap_data == MAP_FAILED, "mmap",
768 ".bss mmap failed: %d", errno)) {
774 memset(mmap_data, 0, sizeof(*data));
775 memcpy(data->in, test_case->input, test_case->input_len);
776 data->my_pid_tgid = my_pid_tgid;
778 link = bpf_program__attach_raw_tracepoint(prog, tp_name);
779 if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n",
783 /* trigger test run */
791 if (test_case->fails) {
792 CHECK(false, "obj_load_fail", "should fail to load prog '%s'\n", probe_name);
796 equal = memcmp(data->out, test_case->output,
797 test_case->output_len) == 0;
798 if (CHECK(!equal, "check_result",
799 "input/output data don't match\n")) {
802 for (j = 0; j < test_case->input_len; j++) {
803 printf("input byte #%d: 0x%02hhx\n",
804 j, test_case->input[j]);
806 for (j = 0; j < test_case->output_len; j++) {
807 printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n",
808 j, test_case->output[j], data->out[j]);
815 CHECK_FAIL(munmap(mmap_data, mmap_sz));
818 if (!IS_ERR_OR_NULL(link)) {
819 bpf_link__destroy(link);
822 bpf_object__close(obj);