linux/tools/testing/selftests/bpf/prog_tests/core_reloc.c
<<
>>
Prefs
   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
 256struct 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
 269static 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
 457struct data {
 458        char in[256];
 459        char out[256];
 460        uint64_t my_pid_tgid;
 461};
 462
 463static 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
 469void 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
 571cleanup:
 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}
 583