linux/tools/testing/selftests/bpf/prog_tests/core_autosize.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Facebook */
   3
   4#include <test_progs.h>
   5#include <bpf/btf.h>
   6
   7/* real layout and sizes according to test's (32-bit) BTF
   8 * needs to be defined before skeleton is included */
   9struct test_struct___real {
  10        unsigned int ptr; /* can't use `void *`, it is always 8 byte in BPF target */
  11        unsigned int val2;
  12        unsigned long long val1;
  13        unsigned short val3;
  14        unsigned char val4;
  15        unsigned char _pad;
  16};
  17
  18#include "test_core_autosize.skel.h"
  19
  20static int duration = 0;
  21
  22static struct {
  23        unsigned long long ptr_samesized;
  24        unsigned long long val1_samesized;
  25        unsigned long long val2_samesized;
  26        unsigned long long val3_samesized;
  27        unsigned long long val4_samesized;
  28        struct test_struct___real output_samesized;
  29
  30        unsigned long long ptr_downsized;
  31        unsigned long long val1_downsized;
  32        unsigned long long val2_downsized;
  33        unsigned long long val3_downsized;
  34        unsigned long long val4_downsized;
  35        struct test_struct___real output_downsized;
  36
  37        unsigned long long ptr_probed;
  38        unsigned long long val1_probed;
  39        unsigned long long val2_probed;
  40        unsigned long long val3_probed;
  41        unsigned long long val4_probed;
  42
  43        unsigned long long ptr_signed;
  44        unsigned long long val1_signed;
  45        unsigned long long val2_signed;
  46        unsigned long long val3_signed;
  47        unsigned long long val4_signed;
  48        struct test_struct___real output_signed;
  49} out;
  50
  51void test_core_autosize(void)
  52{
  53        char btf_file[] = "/tmp/core_autosize.btf.XXXXXX";
  54        int err, fd = -1, zero = 0;
  55        int char_id, short_id, int_id, long_long_id, void_ptr_id, id;
  56        DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts);
  57        struct test_core_autosize* skel = NULL;
  58        struct bpf_program *prog;
  59        struct bpf_map *bss_map;
  60        struct btf *btf = NULL;
  61        size_t written;
  62        const void *raw_data;
  63        __u32 raw_sz;
  64        FILE *f = NULL;
  65
  66        btf = btf__new_empty();
  67        if (!ASSERT_OK_PTR(btf, "empty_btf"))
  68                return;
  69        /* Emit the following struct with 32-bit pointer size:
  70         *
  71         * struct test_struct {
  72         *     void *ptr;
  73         *     unsigned long val2;
  74         *     unsigned long long val1;
  75         *     unsigned short val3;
  76         *     unsigned char val4;
  77         *     char: 8;
  78         * };
  79         *
  80         * This struct is going to be used as the "kernel BTF" for this test.
  81         * It's equivalent memory-layout-wise to test_struct__real above.
  82         */
  83
  84        /* force 32-bit pointer size */
  85        btf__set_pointer_size(btf, 4);
  86
  87        char_id = btf__add_int(btf, "unsigned char", 1, 0);
  88        ASSERT_EQ(char_id, 1, "char_id");
  89        short_id = btf__add_int(btf, "unsigned short", 2, 0);
  90        ASSERT_EQ(short_id, 2, "short_id");
  91        /* "long unsigned int" of 4 byte size tells BTF that sizeof(void *) == 4 */
  92        int_id = btf__add_int(btf, "long unsigned int", 4, 0);
  93        ASSERT_EQ(int_id, 3, "int_id");
  94        long_long_id = btf__add_int(btf, "unsigned long long", 8, 0);
  95        ASSERT_EQ(long_long_id, 4, "long_long_id");
  96        void_ptr_id = btf__add_ptr(btf, 0);
  97        ASSERT_EQ(void_ptr_id, 5, "void_ptr_id");
  98
  99        id = btf__add_struct(btf, "test_struct", 20 /* bytes */);
 100        ASSERT_EQ(id, 6, "struct_id");
 101        err = btf__add_field(btf, "ptr", void_ptr_id, 0, 0);
 102        err = err ?: btf__add_field(btf, "val2", int_id, 32, 0);
 103        err = err ?: btf__add_field(btf, "val1", long_long_id, 64, 0);
 104        err = err ?: btf__add_field(btf, "val3", short_id, 128, 0);
 105        err = err ?: btf__add_field(btf, "val4", char_id, 144, 0);
 106        ASSERT_OK(err, "struct_fields");
 107
 108        fd = mkstemp(btf_file);
 109        if (CHECK(fd < 0, "btf_tmp", "failed to create file: %d\n", fd))
 110                goto cleanup;
 111        f = fdopen(fd, "w");
 112        if (!ASSERT_OK_PTR(f, "btf_fdopen"))
 113                goto cleanup;
 114
 115        raw_data = btf__get_raw_data(btf, &raw_sz);
 116        if (!ASSERT_OK_PTR(raw_data, "raw_data"))
 117                goto cleanup;
 118        written = fwrite(raw_data, 1, raw_sz, f);
 119        if (CHECK(written != raw_sz, "btf_write", "written: %zu, errno: %d\n", written, errno))
 120                goto cleanup;
 121        fflush(f);
 122        fclose(f);
 123        f = NULL;
 124        close(fd);
 125        fd = -1;
 126
 127        /* open and load BPF program with custom BTF as the kernel BTF */
 128        open_opts.btf_custom_path = btf_file;
 129        skel = test_core_autosize__open_opts(&open_opts);
 130        if (!ASSERT_OK_PTR(skel, "skel_open"))
 131                goto cleanup;
 132
 133        /* disable handle_signed() for now */
 134        prog = bpf_object__find_program_by_name(skel->obj, "handle_signed");
 135        if (!ASSERT_OK_PTR(prog, "prog_find"))
 136                goto cleanup;
 137        bpf_program__set_autoload(prog, false);
 138
 139        err = bpf_object__load(skel->obj);
 140        if (!ASSERT_OK(err, "prog_load"))
 141                goto cleanup;
 142
 143        prog = bpf_object__find_program_by_name(skel->obj, "handle_samesize");
 144        if (!ASSERT_OK_PTR(prog, "prog_find"))
 145                goto cleanup;
 146        skel->links.handle_samesize = bpf_program__attach(prog);
 147        if (!ASSERT_OK_PTR(skel->links.handle_samesize, "prog_attach"))
 148                goto cleanup;
 149
 150        prog = bpf_object__find_program_by_name(skel->obj, "handle_downsize");
 151        if (!ASSERT_OK_PTR(prog, "prog_find"))
 152                goto cleanup;
 153        skel->links.handle_downsize = bpf_program__attach(prog);
 154        if (!ASSERT_OK_PTR(skel->links.handle_downsize, "prog_attach"))
 155                goto cleanup;
 156
 157        prog = bpf_object__find_program_by_name(skel->obj, "handle_probed");
 158        if (!ASSERT_OK_PTR(prog, "prog_find"))
 159                goto cleanup;
 160        skel->links.handle_probed = bpf_program__attach(prog);
 161        if (!ASSERT_OK_PTR(skel->links.handle_probed, "prog_attach"))
 162                goto cleanup;
 163
 164        usleep(1);
 165
 166        bss_map = bpf_object__find_map_by_name(skel->obj, "test_cor.bss");
 167        if (!ASSERT_OK_PTR(bss_map, "bss_map_find"))
 168                goto cleanup;
 169
 170        err = bpf_map_lookup_elem(bpf_map__fd(bss_map), &zero, (void *)&out);
 171        if (!ASSERT_OK(err, "bss_lookup"))
 172                goto cleanup;
 173
 174        ASSERT_EQ(out.ptr_samesized, 0x01020304, "ptr_samesized");
 175        ASSERT_EQ(out.val1_samesized, 0x1020304050607080, "val1_samesized");
 176        ASSERT_EQ(out.val2_samesized, 0x0a0b0c0d, "val2_samesized");
 177        ASSERT_EQ(out.val3_samesized, 0xfeed, "val3_samesized");
 178        ASSERT_EQ(out.val4_samesized, 0xb9, "val4_samesized");
 179        ASSERT_EQ(out.output_samesized.ptr, 0x01020304, "ptr_samesized");
 180        ASSERT_EQ(out.output_samesized.val1, 0x1020304050607080, "val1_samesized");
 181        ASSERT_EQ(out.output_samesized.val2, 0x0a0b0c0d, "val2_samesized");
 182        ASSERT_EQ(out.output_samesized.val3, 0xfeed, "val3_samesized");
 183        ASSERT_EQ(out.output_samesized.val4, 0xb9, "val4_samesized");
 184
 185        ASSERT_EQ(out.ptr_downsized, 0x01020304, "ptr_downsized");
 186        ASSERT_EQ(out.val1_downsized, 0x1020304050607080, "val1_downsized");
 187        ASSERT_EQ(out.val2_downsized, 0x0a0b0c0d, "val2_downsized");
 188        ASSERT_EQ(out.val3_downsized, 0xfeed, "val3_downsized");
 189        ASSERT_EQ(out.val4_downsized, 0xb9, "val4_downsized");
 190        ASSERT_EQ(out.output_downsized.ptr, 0x01020304, "ptr_downsized");
 191        ASSERT_EQ(out.output_downsized.val1, 0x1020304050607080, "val1_downsized");
 192        ASSERT_EQ(out.output_downsized.val2, 0x0a0b0c0d, "val2_downsized");
 193        ASSERT_EQ(out.output_downsized.val3, 0xfeed, "val3_downsized");
 194        ASSERT_EQ(out.output_downsized.val4, 0xb9, "val4_downsized");
 195
 196        ASSERT_EQ(out.ptr_probed, 0x01020304, "ptr_probed");
 197        ASSERT_EQ(out.val1_probed, 0x1020304050607080, "val1_probed");
 198        ASSERT_EQ(out.val2_probed, 0x0a0b0c0d, "val2_probed");
 199        ASSERT_EQ(out.val3_probed, 0xfeed, "val3_probed");
 200        ASSERT_EQ(out.val4_probed, 0xb9, "val4_probed");
 201
 202        test_core_autosize__destroy(skel);
 203        skel = NULL;
 204
 205        /* now re-load with handle_signed() enabled, it should fail loading */
 206        open_opts.btf_custom_path = btf_file;
 207        skel = test_core_autosize__open_opts(&open_opts);
 208        if (!ASSERT_OK_PTR(skel, "skel_open"))
 209                goto cleanup;
 210
 211        err = test_core_autosize__load(skel);
 212        if (!ASSERT_ERR(err, "skel_load"))
 213                goto cleanup;
 214
 215cleanup:
 216        if (f)
 217                fclose(f);
 218        if (fd >= 0)
 219                close(fd);
 220        remove(btf_file);
 221        btf__free(btf);
 222        test_core_autosize__destroy(skel);
 223}
 224