Merge tag 'powerpc-5.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[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 <sys/mman.h>
5 #include <sys/syscall.h>
6
7 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
8
9 #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {     \
10         .a = 42,                                                        \
11         .b = 0xc001,                                                    \
12         .c = 0xbeef,                                                    \
13 }
14
15 #define FLAVORS_CASE_COMMON(name)                                       \
16         .case_name = #name,                                             \
17         .bpf_obj_file = "test_core_reloc_flavors.o",                    \
18         .btf_src_file = "btf__core_reloc_" #name ".o"                   \
19
20 #define FLAVORS_CASE(name) {                                            \
21         FLAVORS_CASE_COMMON(name),                                      \
22         .input = FLAVORS_DATA(core_reloc_##name),                       \
23         .input_len = sizeof(struct core_reloc_##name),                  \
24         .output = FLAVORS_DATA(core_reloc_flavors),                     \
25         .output_len = sizeof(struct core_reloc_flavors),                \
26 }
27
28 #define FLAVORS_ERR_CASE(name) {                                        \
29         FLAVORS_CASE_COMMON(name),                                      \
30         .fails = true,                                                  \
31 }
32
33 #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {     \
34         .a = { .a = { .a = 42 } },                                      \
35         .b = { .b = { .b = 0xc001 } },                                  \
36 }
37
38 #define NESTING_CASE_COMMON(name)                                       \
39         .case_name = #name,                                             \
40         .bpf_obj_file = "test_core_reloc_nesting.o",                    \
41         .btf_src_file = "btf__core_reloc_" #name ".o"
42
43 #define NESTING_CASE(name) {                                            \
44         NESTING_CASE_COMMON(name),                                      \
45         .input = NESTING_DATA(core_reloc_##name),                       \
46         .input_len = sizeof(struct core_reloc_##name),                  \
47         .output = NESTING_DATA(core_reloc_nesting),                     \
48         .output_len = sizeof(struct core_reloc_nesting)                 \
49 }
50
51 #define NESTING_ERR_CASE(name) {                                        \
52         NESTING_CASE_COMMON(name),                                      \
53         .fails = true,                                                  \
54 }
55
56 #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {      \
57         .a = { [2] = 1 },                                               \
58         .b = { [1] = { [2] = { [3] = 2 } } },                           \
59         .c = { [1] = { .c =  3 } },                                     \
60         .d = { [0] = { [0] = { .d = 4 } } },                            \
61 }
62
63 #define ARRAYS_CASE_COMMON(name)                                        \
64         .case_name = #name,                                             \
65         .bpf_obj_file = "test_core_reloc_arrays.o",                     \
66         .btf_src_file = "btf__core_reloc_" #name ".o"
67
68 #define ARRAYS_CASE(name) {                                             \
69         ARRAYS_CASE_COMMON(name),                                       \
70         .input = ARRAYS_DATA(core_reloc_##name),                        \
71         .input_len = sizeof(struct core_reloc_##name),                  \
72         .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) {        \
73                 .a2   = 1,                                              \
74                 .b123 = 2,                                              \
75                 .c1c  = 3,                                              \
76                 .d00d = 4,                                              \
77                 .f10c = 0,                                              \
78         },                                                              \
79         .output_len = sizeof(struct core_reloc_arrays_output)           \
80 }
81
82 #define ARRAYS_ERR_CASE(name) {                                         \
83         ARRAYS_CASE_COMMON(name),                                       \
84         .fails = true,                                                  \
85 }
86
87 #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {  \
88         .a = 1,                                                         \
89         .b = 2,                                                         \
90         .c = 3,                                                         \
91         .d = (void *)4,                                                 \
92         .f = (void *)5,                                                 \
93 }
94
95 #define PRIMITIVES_CASE_COMMON(name)                                    \
96         .case_name = #name,                                             \
97         .bpf_obj_file = "test_core_reloc_primitives.o",                 \
98         .btf_src_file = "btf__core_reloc_" #name ".o"
99
100 #define PRIMITIVES_CASE(name) {                                         \
101         PRIMITIVES_CASE_COMMON(name),                                   \
102         .input = PRIMITIVES_DATA(core_reloc_##name),                    \
103         .input_len = sizeof(struct core_reloc_##name),                  \
104         .output = PRIMITIVES_DATA(core_reloc_primitives),               \
105         .output_len = sizeof(struct core_reloc_primitives),             \
106 }
107
108 #define PRIMITIVES_ERR_CASE(name) {                                     \
109         PRIMITIVES_CASE_COMMON(name),                                   \
110         .fails = true,                                                  \
111 }
112
113 #define MODS_CASE(name) {                                               \
114         .case_name = #name,                                             \
115         .bpf_obj_file = "test_core_reloc_mods.o",                       \
116         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
117         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) {                \
118                 .a = 1,                                                 \
119                 .b = 2,                                                 \
120                 .c = (void *)3,                                         \
121                 .d = (void *)4,                                         \
122                 .e = { [2] = 5 },                                       \
123                 .f = { [1] = 6 },                                       \
124                 .g = { .x = 7 },                                        \
125                 .h = { .y = 8 },                                        \
126         },                                                              \
127         .input_len = sizeof(struct core_reloc_##name),                  \
128         .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) {          \
129                 .a = 1, .b = 2, .c = 3, .d = 4,                         \
130                 .e = 5, .f = 6, .g = 7, .h = 8,                         \
131         },                                                              \
132         .output_len = sizeof(struct core_reloc_mods_output),            \
133 }
134
135 #define PTR_AS_ARR_CASE(name) {                                         \
136         .case_name = #name,                                             \
137         .bpf_obj_file = "test_core_reloc_ptr_as_arr.o",                 \
138         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
139         .input = (const char *)&(struct core_reloc_##name []){          \
140                 { .a = 1 },                                             \
141                 { .a = 2 },                                             \
142                 { .a = 3 },                                             \
143         },                                                              \
144         .input_len = 3 * sizeof(struct core_reloc_##name),              \
145         .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) {           \
146                 .a = 3,                                                 \
147         },                                                              \
148         .output_len = sizeof(struct core_reloc_ptr_as_arr),             \
149 }
150
151 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {        \
152         .u8_field = 1,                                                  \
153         .s8_field = 2,                                                  \
154         .u16_field = 3,                                                 \
155         .s16_field = 4,                                                 \
156         .u32_field = 5,                                                 \
157         .s32_field = 6,                                                 \
158         .u64_field = 7,                                                 \
159         .s64_field = 8,                                                 \
160 }
161
162 #define INTS_CASE_COMMON(name)                                          \
163         .case_name = #name,                                             \
164         .bpf_obj_file = "test_core_reloc_ints.o",                       \
165         .btf_src_file = "btf__core_reloc_" #name ".o"
166
167 #define INTS_CASE(name) {                                               \
168         INTS_CASE_COMMON(name),                                         \
169         .input = INTS_DATA(core_reloc_##name),                          \
170         .input_len = sizeof(struct core_reloc_##name),                  \
171         .output = INTS_DATA(core_reloc_ints),                           \
172         .output_len = sizeof(struct core_reloc_ints),                   \
173 }
174
175 #define INTS_ERR_CASE(name) {                                           \
176         INTS_CASE_COMMON(name),                                         \
177         .fails = true,                                                  \
178 }
179
180 #define EXISTENCE_CASE_COMMON(name)                                     \
181         .case_name = #name,                                             \
182         .bpf_obj_file = "test_core_reloc_existence.o",                  \
183         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
184         .relaxed_core_relocs = true
185
186 #define EXISTENCE_ERR_CASE(name) {                                      \
187         EXISTENCE_CASE_COMMON(name),                                    \
188         .fails = true,                                                  \
189 }
190
191 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix,  name)         \
192         .case_name = test_name_prefix#name,                             \
193         .bpf_obj_file = objfile,                                        \
194         .btf_src_file = "btf__core_reloc_" #name ".o"
195
196 #define BITFIELDS_CASE(name, ...) {                                     \
197         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o",     \
198                               "direct:", name),                         \
199         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,     \
200         .input_len = sizeof(struct core_reloc_##name),                  \
201         .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)       \
202                 __VA_ARGS__,                                            \
203         .output_len = sizeof(struct core_reloc_bitfields_output),       \
204 }, {                                                                    \
205         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o",     \
206                               "probed:", name),                         \
207         .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,     \
208         .input_len = sizeof(struct core_reloc_##name),                  \
209         .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)       \
210                 __VA_ARGS__,                                            \
211         .output_len = sizeof(struct core_reloc_bitfields_output),       \
212         .direct_raw_tp = true,                                          \
213 }
214
215
216 #define BITFIELDS_ERR_CASE(name) {                                      \
217         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o",     \
218                               "probed:", name),                         \
219         .fails = true,                                                  \
220 }, {                                                                    \
221         BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o",     \
222                               "direct:", name),                         \
223         .direct_raw_tp = true,                                          \
224         .fails = true,                                                  \
225 }
226
227 #define SIZE_CASE_COMMON(name)                                          \
228         .case_name = #name,                                             \
229         .bpf_obj_file = "test_core_reloc_size.o",                       \
230         .btf_src_file = "btf__core_reloc_" #name ".o",                  \
231         .relaxed_core_relocs = true
232
233 #define SIZE_OUTPUT_DATA(type)                                          \
234         STRUCT_TO_CHAR_PTR(core_reloc_size_output) {                    \
235                 .int_sz = sizeof(((type *)0)->int_field),               \
236                 .struct_sz = sizeof(((type *)0)->struct_field),         \
237                 .union_sz = sizeof(((type *)0)->union_field),           \
238                 .arr_sz = sizeof(((type *)0)->arr_field),               \
239                 .arr_elem_sz = sizeof(((type *)0)->arr_field[0]),       \
240                 .ptr_sz = 8, /* always 8-byte pointer for BPF */        \
241                 .enum_sz = sizeof(((type *)0)->enum_field),             \
242         }
243
244 #define SIZE_CASE(name) {                                               \
245         SIZE_CASE_COMMON(name),                                         \
246         .input_len = 0,                                                 \
247         .output = SIZE_OUTPUT_DATA(struct core_reloc_##name),           \
248         .output_len = sizeof(struct core_reloc_size_output),            \
249 }
250
251 #define SIZE_ERR_CASE(name) {                                           \
252         SIZE_CASE_COMMON(name),                                         \
253         .fails = true,                                                  \
254 }
255
256 struct core_reloc_test_case {
257         const char *case_name;
258         const char *bpf_obj_file;
259         const char *btf_src_file;
260         const char *input;
261         int input_len;
262         const char *output;
263         int output_len;
264         bool fails;
265         bool relaxed_core_relocs;
266         bool direct_raw_tp;
267 };
268
269 static struct core_reloc_test_case test_cases[] = {
270         /* validate we can find kernel image and use its BTF for relocs */
271         {
272                 .case_name = "kernel",
273                 .bpf_obj_file = "test_core_reloc_kernel.o",
274                 .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */
275                 .input = "",
276                 .input_len = 0,
277                 .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
278                         .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
279                         .comm = "test_progs",
280                         .comm_len = sizeof("test_progs"),
281                 },
282                 .output_len = sizeof(struct core_reloc_kernel_output),
283         },
284
285         /* validate BPF program can use multiple flavors to match against
286          * single target BTF type
287          */
288         FLAVORS_CASE(flavors),
289
290         FLAVORS_ERR_CASE(flavors__err_wrong_name),
291
292         /* various struct/enum nesting and resolution scenarios */
293         NESTING_CASE(nesting),
294         NESTING_CASE(nesting___anon_embed),
295         NESTING_CASE(nesting___struct_union_mixup),
296         NESTING_CASE(nesting___extra_nesting),
297         NESTING_CASE(nesting___dup_compat_types),
298
299         NESTING_ERR_CASE(nesting___err_missing_field),
300         NESTING_ERR_CASE(nesting___err_array_field),
301         NESTING_ERR_CASE(nesting___err_missing_container),
302         NESTING_ERR_CASE(nesting___err_nonstruct_container),
303         NESTING_ERR_CASE(nesting___err_array_container),
304         NESTING_ERR_CASE(nesting___err_dup_incompat_types),
305         NESTING_ERR_CASE(nesting___err_partial_match_dups),
306         NESTING_ERR_CASE(nesting___err_too_deep),
307
308         /* various array access relocation scenarios */
309         ARRAYS_CASE(arrays),
310         ARRAYS_CASE(arrays___diff_arr_dim),
311         ARRAYS_CASE(arrays___diff_arr_val_sz),
312         ARRAYS_CASE(arrays___equiv_zero_sz_arr),
313         ARRAYS_CASE(arrays___fixed_arr),
314
315         ARRAYS_ERR_CASE(arrays___err_too_small),
316         ARRAYS_ERR_CASE(arrays___err_too_shallow),
317         ARRAYS_ERR_CASE(arrays___err_non_array),
318         ARRAYS_ERR_CASE(arrays___err_wrong_val_type1),
319         ARRAYS_ERR_CASE(arrays___err_wrong_val_type2),
320         ARRAYS_ERR_CASE(arrays___err_bad_zero_sz_arr),
321
322         /* enum/ptr/int handling scenarios */
323         PRIMITIVES_CASE(primitives),
324         PRIMITIVES_CASE(primitives___diff_enum_def),
325         PRIMITIVES_CASE(primitives___diff_func_proto),
326         PRIMITIVES_CASE(primitives___diff_ptr_type),
327
328         PRIMITIVES_ERR_CASE(primitives___err_non_enum),
329         PRIMITIVES_ERR_CASE(primitives___err_non_int),
330         PRIMITIVES_ERR_CASE(primitives___err_non_ptr),
331
332         /* const/volatile/restrict and typedefs scenarios */
333         MODS_CASE(mods),
334         MODS_CASE(mods___mod_swap),
335         MODS_CASE(mods___typedefs),
336
337         /* handling "ptr is an array" semantics */
338         PTR_AS_ARR_CASE(ptr_as_arr),
339         PTR_AS_ARR_CASE(ptr_as_arr___diff_sz),
340
341         /* int signedness/sizing/bitfield handling */
342         INTS_CASE(ints),
343         INTS_CASE(ints___bool),
344         INTS_CASE(ints___reverse_sign),
345
346         /* validate edge cases of capturing relocations */
347         {
348                 .case_name = "misc",
349                 .bpf_obj_file = "test_core_reloc_misc.o",
350                 .btf_src_file = "btf__core_reloc_misc.o",
351                 .input = (const char *)&(struct core_reloc_misc_extensible[]){
352                         { .a = 1 },
353                         { .a = 2 }, /* not read */
354                         { .a = 3 },
355                 },
356                 .input_len = 4 * sizeof(int),
357                 .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) {
358                         .a = 1,
359                         .b = 1,
360                         .c = 0, /* BUG in clang, should be 3 */
361                 },
362                 .output_len = sizeof(struct core_reloc_misc_output),
363         },
364
365         /* validate field existence checks */
366         {
367                 EXISTENCE_CASE_COMMON(existence),
368                 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
369                         .a = 1,
370                         .b = 2,
371                         .c = 3,
372                         .arr = { 4 },
373                         .s = { .x = 5 },
374                 },
375                 .input_len = sizeof(struct core_reloc_existence),
376                 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
377                         .a_exists = 1,
378                         .b_exists = 1,
379                         .c_exists = 1,
380                         .arr_exists = 1,
381                         .s_exists = 1,
382                         .a_value = 1,
383                         .b_value = 2,
384                         .c_value = 3,
385                         .arr_value = 4,
386                         .s_value = 5,
387                 },
388                 .output_len = sizeof(struct core_reloc_existence_output),
389         },
390         {
391                 EXISTENCE_CASE_COMMON(existence___minimal),
392                 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
393                         .a = 42,
394                 },
395                 .input_len = sizeof(struct core_reloc_existence___minimal),
396                 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
397                         .a_exists = 1,
398                         .b_exists = 0,
399                         .c_exists = 0,
400                         .arr_exists = 0,
401                         .s_exists = 0,
402                         .a_value = 42,
403                         .b_value = 0xff000002u,
404                         .c_value = 0xff000003u,
405                         .arr_value = 0xff000004u,
406                         .s_value = 0xff000005u,
407                 },
408                 .output_len = sizeof(struct core_reloc_existence_output),
409         },
410
411         EXISTENCE_ERR_CASE(existence__err_int_sz),
412         EXISTENCE_ERR_CASE(existence__err_int_type),
413         EXISTENCE_ERR_CASE(existence__err_int_kind),
414         EXISTENCE_ERR_CASE(existence__err_arr_kind),
415         EXISTENCE_ERR_CASE(existence__err_arr_value_type),
416         EXISTENCE_ERR_CASE(existence__err_struct_type),
417
418         /* bitfield relocation checks */
419         BITFIELDS_CASE(bitfields, {
420                 .ub1 = 1,
421                 .ub2 = 2,
422                 .ub7 = 96,
423                 .sb4 = -7,
424                 .sb20 = -0x76543,
425                 .u32 = 0x80000000,
426                 .s32 = -0x76543210,
427         }),
428         BITFIELDS_CASE(bitfields___bit_sz_change, {
429                 .ub1 = 6,
430                 .ub2 = 0xABCDE,
431                 .ub7 = 1,
432                 .sb4 = -1,
433                 .sb20 = -0x17654321,
434                 .u32 = 0xBEEF,
435                 .s32 = -0x3FEDCBA987654321LL,
436         }),
437         BITFIELDS_CASE(bitfields___bitfield_vs_int, {
438                 .ub1 = 0xFEDCBA9876543210LL,
439                 .ub2 = 0xA6,
440                 .ub7 = -0x7EDCBA987654321LL,
441                 .sb4 = -0x6123456789ABCDELL,
442                 .sb20 = 0xD00DLL,
443                 .u32 = -0x76543,
444                 .s32 = 0x0ADEADBEEFBADB0BLL,
445         }),
446         BITFIELDS_CASE(bitfields___just_big_enough, {
447                 .ub1 = 0xFLL,
448                 .ub2 = 0x0812345678FEDCBALL,
449         }),
450         BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield),
451
452         /* size relocation checks */
453         SIZE_CASE(size),
454         SIZE_CASE(size___diff_sz),
455 };
456
457 struct data {
458         char in[256];
459         char out[256];
460         uint64_t my_pid_tgid;
461 };
462
463 static size_t roundup_page(size_t sz)
464 {
465         long page_size = sysconf(_SC_PAGE_SIZE);
466         return (sz + page_size - 1) / page_size * page_size;
467 }
468
469 void test_core_reloc(void)
470 {
471         const size_t mmap_sz = roundup_page(sizeof(struct data));
472         struct bpf_object_load_attr load_attr = {};
473         struct core_reloc_test_case *test_case;
474         const char *tp_name, *probe_name;
475         int err, duration = 0, i, equal;
476         struct bpf_link *link = NULL;
477         struct bpf_map *data_map;
478         struct bpf_program *prog;
479         struct bpf_object *obj;
480         uint64_t my_pid_tgid;
481         struct data *data;
482         void *mmap_data = NULL;
483
484         my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32);
485
486         for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
487                 test_case = &test_cases[i];
488                 if (!test__start_subtest(test_case->case_name))
489                         continue;
490
491                 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
492                         .relaxed_core_relocs = test_case->relaxed_core_relocs,
493                 );
494
495                 obj = bpf_object__open_file(test_case->bpf_obj_file, &opts);
496                 if (CHECK(IS_ERR(obj), "obj_open", "failed to open '%s': %ld\n",
497                           test_case->bpf_obj_file, PTR_ERR(obj)))
498                         continue;
499
500                 /* for typed raw tracepoints, NULL should be specified */
501                 if (test_case->direct_raw_tp) {
502                         probe_name = "tp_btf/sys_enter";
503                         tp_name = NULL;
504                 } else {
505                         probe_name = "raw_tracepoint/sys_enter";
506                         tp_name = "sys_enter";
507                 }
508
509                 prog = bpf_object__find_program_by_title(obj, probe_name);
510                 if (CHECK(!prog, "find_probe",
511                           "prog '%s' not found\n", probe_name))
512                         goto cleanup;
513
514                 load_attr.obj = obj;
515                 load_attr.log_level = 0;
516                 load_attr.target_btf_path = test_case->btf_src_file;
517                 err = bpf_object__load_xattr(&load_attr);
518                 if (test_case->fails) {
519                         CHECK(!err, "obj_load_fail",
520                               "should fail to load prog '%s'\n", probe_name);
521                         goto cleanup;
522                 } else {
523                         if (CHECK(err, "obj_load",
524                                   "failed to load prog '%s': %d\n",
525                                   probe_name, err))
526                                 goto cleanup;
527                 }
528
529                 data_map = bpf_object__find_map_by_name(obj, "test_cor.bss");
530                 if (CHECK(!data_map, "find_data_map", "data map not found\n"))
531                         goto cleanup;
532
533                 mmap_data = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
534                                  MAP_SHARED, bpf_map__fd(data_map), 0);
535                 if (CHECK(mmap_data == MAP_FAILED, "mmap",
536                           ".bss mmap failed: %d", errno)) {
537                         mmap_data = NULL;
538                         goto cleanup;
539                 }
540                 data = mmap_data;
541
542                 memset(mmap_data, 0, sizeof(*data));
543                 memcpy(data->in, test_case->input, test_case->input_len);
544                 data->my_pid_tgid = my_pid_tgid;
545
546                 link = bpf_program__attach_raw_tracepoint(prog, tp_name);
547                 if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n",
548                           PTR_ERR(link)))
549                         goto cleanup;
550
551                 /* trigger test run */
552                 usleep(1);
553
554                 equal = memcmp(data->out, test_case->output,
555                                test_case->output_len) == 0;
556                 if (CHECK(!equal, "check_result",
557                           "input/output data don't match\n")) {
558                         int j;
559
560                         for (j = 0; j < test_case->input_len; j++) {
561                                 printf("input byte #%d: 0x%02hhx\n",
562                                        j, test_case->input[j]);
563                         }
564                         for (j = 0; j < test_case->output_len; j++) {
565                                 printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n",
566                                        j, test_case->output[j], data->out[j]);
567                         }
568                         goto cleanup;
569                 }
570
571 cleanup:
572                 if (mmap_data) {
573                         CHECK_FAIL(munmap(mmap_data, mmap_sz));
574                         mmap_data = NULL;
575                 }
576                 if (!IS_ERR_OR_NULL(link)) {
577                         bpf_link__destroy(link);
578                         link = NULL;
579                 }
580                 bpf_object__close(obj);
581         }
582 }