linux/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Facebook */
   3#include <test_progs.h>
   4#include <bpf/btf.h>
   5#include "btf_helpers.h"
   6
   7static void test_split_simple() {
   8        const struct btf_type *t;
   9        struct btf *btf1, *btf2;
  10        int str_off, err;
  11
  12        btf1 = btf__new_empty();
  13        if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
  14                return;
  15
  16        btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
  17
  18        btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
  19        btf__add_ptr(btf1, 1);                          /* [2] ptr to int */
  20        btf__add_struct(btf1, "s1", 4);                 /* [3] struct s1 { */
  21        btf__add_field(btf1, "f1", 1, 0, 0);            /*      int f1; */
  22                                                        /* } */
  23
  24        VALIDATE_RAW_BTF(
  25                btf1,
  26                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
  27                "[2] PTR '(anon)' type_id=1",
  28                "[3] STRUCT 's1' size=4 vlen=1\n"
  29                "\t'f1' type_id=1 bits_offset=0");
  30
  31        ASSERT_STREQ(btf_type_c_dump(btf1), "\
  32struct s1 {\n\
  33        int f1;\n\
  34};\n\n", "c_dump");
  35
  36        btf2 = btf__new_empty_split(btf1);
  37        if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
  38                goto cleanup;
  39
  40        /* pointer size should be "inherited" from main BTF */
  41        ASSERT_EQ(btf__pointer_size(btf2), 8, "inherit_ptr_sz");
  42
  43        str_off = btf__find_str(btf2, "int");
  44        ASSERT_NEQ(str_off, -ENOENT, "str_int_missing");
  45
  46        t = btf__type_by_id(btf2, 1);
  47        if (!ASSERT_OK_PTR(t, "int_type"))
  48                goto cleanup;
  49        ASSERT_EQ(btf_is_int(t), true, "int_kind");
  50        ASSERT_STREQ(btf__str_by_offset(btf2, t->name_off), "int", "int_name");
  51
  52        btf__add_struct(btf2, "s2", 16);                /* [4] struct s2 {      */
  53        btf__add_field(btf2, "f1", 6, 0, 0);            /*      struct s1 f1;   */
  54        btf__add_field(btf2, "f2", 5, 32, 0);           /*      int f2;         */
  55        btf__add_field(btf2, "f3", 2, 64, 0);           /*      int *f3;        */
  56                                                        /* } */
  57
  58        /* duplicated int */
  59        btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [5] int */
  60
  61        /* duplicated struct s1 */
  62        btf__add_struct(btf2, "s1", 4);                 /* [6] struct s1 { */
  63        btf__add_field(btf2, "f1", 5, 0, 0);            /*      int f1; */
  64                                                        /* } */
  65
  66        VALIDATE_RAW_BTF(
  67                btf2,
  68                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
  69                "[2] PTR '(anon)' type_id=1",
  70                "[3] STRUCT 's1' size=4 vlen=1\n"
  71                "\t'f1' type_id=1 bits_offset=0",
  72                "[4] STRUCT 's2' size=16 vlen=3\n"
  73                "\t'f1' type_id=6 bits_offset=0\n"
  74                "\t'f2' type_id=5 bits_offset=32\n"
  75                "\t'f3' type_id=2 bits_offset=64",
  76                "[5] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
  77                "[6] STRUCT 's1' size=4 vlen=1\n"
  78                "\t'f1' type_id=5 bits_offset=0");
  79
  80        ASSERT_STREQ(btf_type_c_dump(btf2), "\
  81struct s1 {\n\
  82        int f1;\n\
  83};\n\
  84\n\
  85struct s1___2 {\n\
  86        int f1;\n\
  87};\n\
  88\n\
  89struct s2 {\n\
  90        struct s1___2 f1;\n\
  91        int f2;\n\
  92        int *f3;\n\
  93};\n\n", "c_dump");
  94
  95        err = btf__dedup(btf2, NULL, NULL);
  96        if (!ASSERT_OK(err, "btf_dedup"))
  97                goto cleanup;
  98
  99        VALIDATE_RAW_BTF(
 100                btf2,
 101                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 102                "[2] PTR '(anon)' type_id=1",
 103                "[3] STRUCT 's1' size=4 vlen=1\n"
 104                "\t'f1' type_id=1 bits_offset=0",
 105                "[4] STRUCT 's2' size=16 vlen=3\n"
 106                "\t'f1' type_id=3 bits_offset=0\n"
 107                "\t'f2' type_id=1 bits_offset=32\n"
 108                "\t'f3' type_id=2 bits_offset=64");
 109
 110        ASSERT_STREQ(btf_type_c_dump(btf2), "\
 111struct s1 {\n\
 112        int f1;\n\
 113};\n\
 114\n\
 115struct s2 {\n\
 116        struct s1 f1;\n\
 117        int f2;\n\
 118        int *f3;\n\
 119};\n\n", "c_dump");
 120
 121cleanup:
 122        btf__free(btf2);
 123        btf__free(btf1);
 124}
 125
 126static void test_split_fwd_resolve() {
 127        struct btf *btf1, *btf2;
 128        int err;
 129
 130        btf1 = btf__new_empty();
 131        if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
 132                return;
 133
 134        btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
 135
 136        btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
 137        btf__add_ptr(btf1, 4);                          /* [2] ptr to struct s1 */
 138        btf__add_ptr(btf1, 5);                          /* [3] ptr to struct s2 */
 139        btf__add_struct(btf1, "s1", 16);                /* [4] struct s1 { */
 140        btf__add_field(btf1, "f1", 2, 0, 0);            /*      struct s1 *f1; */
 141        btf__add_field(btf1, "f2", 3, 64, 0);           /*      struct s2 *f2; */
 142                                                        /* } */
 143        btf__add_struct(btf1, "s2", 4);                 /* [5] struct s2 { */
 144        btf__add_field(btf1, "f1", 1, 0, 0);            /*      int f1; */
 145                                                        /* } */
 146
 147        VALIDATE_RAW_BTF(
 148                btf1,
 149                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 150                "[2] PTR '(anon)' type_id=4",
 151                "[3] PTR '(anon)' type_id=5",
 152                "[4] STRUCT 's1' size=16 vlen=2\n"
 153                "\t'f1' type_id=2 bits_offset=0\n"
 154                "\t'f2' type_id=3 bits_offset=64",
 155                "[5] STRUCT 's2' size=4 vlen=1\n"
 156                "\t'f1' type_id=1 bits_offset=0");
 157
 158        btf2 = btf__new_empty_split(btf1);
 159        if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
 160                goto cleanup;
 161
 162        btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [6] int */
 163        btf__add_ptr(btf2, 10);                         /* [7] ptr to struct s1 */
 164        btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);       /* [8] fwd for struct s2 */
 165        btf__add_ptr(btf2, 8);                          /* [9] ptr to fwd struct s2 */
 166        btf__add_struct(btf2, "s1", 16);                /* [10] struct s1 { */
 167        btf__add_field(btf2, "f1", 7, 0, 0);            /*      struct s1 *f1; */
 168        btf__add_field(btf2, "f2", 9, 64, 0);           /*      struct s2 *f2; */
 169                                                        /* } */
 170
 171        VALIDATE_RAW_BTF(
 172                btf2,
 173                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 174                "[2] PTR '(anon)' type_id=4",
 175                "[3] PTR '(anon)' type_id=5",
 176                "[4] STRUCT 's1' size=16 vlen=2\n"
 177                "\t'f1' type_id=2 bits_offset=0\n"
 178                "\t'f2' type_id=3 bits_offset=64",
 179                "[5] STRUCT 's2' size=4 vlen=1\n"
 180                "\t'f1' type_id=1 bits_offset=0",
 181                "[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 182                "[7] PTR '(anon)' type_id=10",
 183                "[8] FWD 's2' fwd_kind=struct",
 184                "[9] PTR '(anon)' type_id=8",
 185                "[10] STRUCT 's1' size=16 vlen=2\n"
 186                "\t'f1' type_id=7 bits_offset=0\n"
 187                "\t'f2' type_id=9 bits_offset=64");
 188
 189        err = btf__dedup(btf2, NULL, NULL);
 190        if (!ASSERT_OK(err, "btf_dedup"))
 191                goto cleanup;
 192
 193        VALIDATE_RAW_BTF(
 194                btf2,
 195                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 196                "[2] PTR '(anon)' type_id=4",
 197                "[3] PTR '(anon)' type_id=5",
 198                "[4] STRUCT 's1' size=16 vlen=2\n"
 199                "\t'f1' type_id=2 bits_offset=0\n"
 200                "\t'f2' type_id=3 bits_offset=64",
 201                "[5] STRUCT 's2' size=4 vlen=1\n"
 202                "\t'f1' type_id=1 bits_offset=0");
 203
 204cleanup:
 205        btf__free(btf2);
 206        btf__free(btf1);
 207}
 208
 209static void test_split_struct_duped() {
 210        struct btf *btf1, *btf2;
 211        int err;
 212
 213        btf1 = btf__new_empty();
 214        if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
 215                return;
 216
 217        btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
 218
 219        btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
 220        btf__add_ptr(btf1, 5);                          /* [2] ptr to struct s1 */
 221        btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT);       /* [3] fwd for struct s2 */
 222        btf__add_ptr(btf1, 3);                          /* [4] ptr to fwd struct s2 */
 223        btf__add_struct(btf1, "s1", 16);                /* [5] struct s1 { */
 224        btf__add_field(btf1, "f1", 2, 0, 0);            /*      struct s1 *f1; */
 225        btf__add_field(btf1, "f2", 4, 64, 0);           /*      struct s2 *f2; */
 226                                                        /* } */
 227
 228        VALIDATE_RAW_BTF(
 229                btf1,
 230                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 231                "[2] PTR '(anon)' type_id=5",
 232                "[3] FWD 's2' fwd_kind=struct",
 233                "[4] PTR '(anon)' type_id=3",
 234                "[5] STRUCT 's1' size=16 vlen=2\n"
 235                "\t'f1' type_id=2 bits_offset=0\n"
 236                "\t'f2' type_id=4 bits_offset=64");
 237
 238        btf2 = btf__new_empty_split(btf1);
 239        if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
 240                goto cleanup;
 241
 242        btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [6] int */
 243        btf__add_ptr(btf2, 10);                         /* [7] ptr to struct s1 */
 244        btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);       /* [8] fwd for struct s2 */
 245        btf__add_ptr(btf2, 11);                         /* [9] ptr to struct s2 */
 246        btf__add_struct(btf2, "s1", 16);                /* [10] struct s1 { */
 247        btf__add_field(btf2, "f1", 7, 0, 0);            /*      struct s1 *f1; */
 248        btf__add_field(btf2, "f2", 9, 64, 0);           /*      struct s2 *f2; */
 249                                                        /* } */
 250        btf__add_struct(btf2, "s2", 40);                /* [11] struct s2 {     */
 251        btf__add_field(btf2, "f1", 7, 0, 0);            /*      struct s1 *f1;  */
 252        btf__add_field(btf2, "f2", 9, 64, 0);           /*      struct s2 *f2;  */
 253        btf__add_field(btf2, "f3", 6, 128, 0);          /*      int f3;         */
 254        btf__add_field(btf2, "f4", 10, 192, 0);         /*      struct s1 f4;   */
 255                                                        /* } */
 256        btf__add_ptr(btf2, 8);                          /* [12] ptr to fwd struct s2 */
 257        btf__add_struct(btf2, "s3", 8);                 /* [13] struct s3 { */
 258        btf__add_field(btf2, "f1", 12, 0, 0);           /*      struct s2 *f1; (fwd) */
 259                                                        /* } */
 260
 261        VALIDATE_RAW_BTF(
 262                btf2,
 263                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 264                "[2] PTR '(anon)' type_id=5",
 265                "[3] FWD 's2' fwd_kind=struct",
 266                "[4] PTR '(anon)' type_id=3",
 267                "[5] STRUCT 's1' size=16 vlen=2\n"
 268                "\t'f1' type_id=2 bits_offset=0\n"
 269                "\t'f2' type_id=4 bits_offset=64",
 270                "[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 271                "[7] PTR '(anon)' type_id=10",
 272                "[8] FWD 's2' fwd_kind=struct",
 273                "[9] PTR '(anon)' type_id=11",
 274                "[10] STRUCT 's1' size=16 vlen=2\n"
 275                "\t'f1' type_id=7 bits_offset=0\n"
 276                "\t'f2' type_id=9 bits_offset=64",
 277                "[11] STRUCT 's2' size=40 vlen=4\n"
 278                "\t'f1' type_id=7 bits_offset=0\n"
 279                "\t'f2' type_id=9 bits_offset=64\n"
 280                "\t'f3' type_id=6 bits_offset=128\n"
 281                "\t'f4' type_id=10 bits_offset=192",
 282                "[12] PTR '(anon)' type_id=8",
 283                "[13] STRUCT 's3' size=8 vlen=1\n"
 284                "\t'f1' type_id=12 bits_offset=0");
 285
 286        err = btf__dedup(btf2, NULL, NULL);
 287        if (!ASSERT_OK(err, "btf_dedup"))
 288                goto cleanup;
 289
 290        VALIDATE_RAW_BTF(
 291                btf2,
 292                "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
 293                "[2] PTR '(anon)' type_id=5",
 294                "[3] FWD 's2' fwd_kind=struct",
 295                "[4] PTR '(anon)' type_id=3",
 296                "[5] STRUCT 's1' size=16 vlen=2\n"
 297                "\t'f1' type_id=2 bits_offset=0\n"
 298                "\t'f2' type_id=4 bits_offset=64",
 299                "[6] PTR '(anon)' type_id=8",
 300                "[7] PTR '(anon)' type_id=9",
 301                "[8] STRUCT 's1' size=16 vlen=2\n"
 302                "\t'f1' type_id=6 bits_offset=0\n"
 303                "\t'f2' type_id=7 bits_offset=64",
 304                "[9] STRUCT 's2' size=40 vlen=4\n"
 305                "\t'f1' type_id=6 bits_offset=0\n"
 306                "\t'f2' type_id=7 bits_offset=64\n"
 307                "\t'f3' type_id=1 bits_offset=128\n"
 308                "\t'f4' type_id=8 bits_offset=192",
 309                "[10] STRUCT 's3' size=8 vlen=1\n"
 310                "\t'f1' type_id=7 bits_offset=0");
 311
 312cleanup:
 313        btf__free(btf2);
 314        btf__free(btf1);
 315}
 316
 317void test_btf_dedup_split()
 318{
 319        if (test__start_subtest("split_simple"))
 320                test_split_simple();
 321        if (test__start_subtest("split_struct_duped"))
 322                test_split_struct_duped();
 323        if (test__start_subtest("split_fwd_resolve"))
 324                test_split_fwd_resolve();
 325}
 326