Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020 Facebook */
0003 #include <test_progs.h>
0004 #include <bpf/btf.h>
0005 #include "btf_helpers.h"
0006 
0007 static void test_split_simple() {
0008     const struct btf_type *t;
0009     struct btf *btf1, *btf2;
0010     int str_off, err;
0011 
0012     btf1 = btf__new_empty();
0013     if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
0014         return;
0015 
0016     btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
0017 
0018     btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
0019     btf__add_ptr(btf1, 1);              /* [2] ptr to int */
0020     btf__add_struct(btf1, "s1", 4);         /* [3] struct s1 { */
0021     btf__add_field(btf1, "f1", 1, 0, 0);        /*      int f1; */
0022                             /* } */
0023 
0024     VALIDATE_RAW_BTF(
0025         btf1,
0026         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0027         "[2] PTR '(anon)' type_id=1",
0028         "[3] STRUCT 's1' size=4 vlen=1\n"
0029         "\t'f1' type_id=1 bits_offset=0");
0030 
0031     ASSERT_STREQ(btf_type_c_dump(btf1), "\
0032 struct s1 {\n\
0033     int f1;\n\
0034 };\n\n", "c_dump");
0035 
0036     btf2 = btf__new_empty_split(btf1);
0037     if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
0038         goto cleanup;
0039 
0040     /* pointer size should be "inherited" from main BTF */
0041     ASSERT_EQ(btf__pointer_size(btf2), 8, "inherit_ptr_sz");
0042 
0043     str_off = btf__find_str(btf2, "int");
0044     ASSERT_NEQ(str_off, -ENOENT, "str_int_missing");
0045 
0046     t = btf__type_by_id(btf2, 1);
0047     if (!ASSERT_OK_PTR(t, "int_type"))
0048         goto cleanup;
0049     ASSERT_EQ(btf_is_int(t), true, "int_kind");
0050     ASSERT_STREQ(btf__str_by_offset(btf2, t->name_off), "int", "int_name");
0051 
0052     btf__add_struct(btf2, "s2", 16);        /* [4] struct s2 {  */
0053     btf__add_field(btf2, "f1", 6, 0, 0);        /*      struct s1 f1;   */
0054     btf__add_field(btf2, "f2", 5, 32, 0);       /*      int f2;     */
0055     btf__add_field(btf2, "f3", 2, 64, 0);       /*      int *f3;    */
0056                             /* } */
0057 
0058     /* duplicated int */
0059     btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [5] int */
0060 
0061     /* duplicated struct s1 */
0062     btf__add_struct(btf2, "s1", 4);         /* [6] struct s1 { */
0063     btf__add_field(btf2, "f1", 5, 0, 0);        /*      int f1; */
0064                             /* } */
0065 
0066     VALIDATE_RAW_BTF(
0067         btf2,
0068         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0069         "[2] PTR '(anon)' type_id=1",
0070         "[3] STRUCT 's1' size=4 vlen=1\n"
0071         "\t'f1' type_id=1 bits_offset=0",
0072         "[4] STRUCT 's2' size=16 vlen=3\n"
0073         "\t'f1' type_id=6 bits_offset=0\n"
0074         "\t'f2' type_id=5 bits_offset=32\n"
0075         "\t'f3' type_id=2 bits_offset=64",
0076         "[5] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0077         "[6] STRUCT 's1' size=4 vlen=1\n"
0078         "\t'f1' type_id=5 bits_offset=0");
0079 
0080     ASSERT_STREQ(btf_type_c_dump(btf2), "\
0081 struct s1 {\n\
0082     int f1;\n\
0083 };\n\
0084 \n\
0085 struct s1___2 {\n\
0086     int f1;\n\
0087 };\n\
0088 \n\
0089 struct s2 {\n\
0090     struct s1___2 f1;\n\
0091     int f2;\n\
0092     int *f3;\n\
0093 };\n\n", "c_dump");
0094 
0095     err = btf__dedup(btf2, NULL);
0096     if (!ASSERT_OK(err, "btf_dedup"))
0097         goto cleanup;
0098 
0099     VALIDATE_RAW_BTF(
0100         btf2,
0101         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0102         "[2] PTR '(anon)' type_id=1",
0103         "[3] STRUCT 's1' size=4 vlen=1\n"
0104         "\t'f1' type_id=1 bits_offset=0",
0105         "[4] STRUCT 's2' size=16 vlen=3\n"
0106         "\t'f1' type_id=3 bits_offset=0\n"
0107         "\t'f2' type_id=1 bits_offset=32\n"
0108         "\t'f3' type_id=2 bits_offset=64");
0109 
0110     ASSERT_STREQ(btf_type_c_dump(btf2), "\
0111 struct s1 {\n\
0112     int f1;\n\
0113 };\n\
0114 \n\
0115 struct s2 {\n\
0116     struct s1 f1;\n\
0117     int f2;\n\
0118     int *f3;\n\
0119 };\n\n", "c_dump");
0120 
0121 cleanup:
0122     btf__free(btf2);
0123     btf__free(btf1);
0124 }
0125 
0126 static void test_split_fwd_resolve() {
0127     struct btf *btf1, *btf2;
0128     int err;
0129 
0130     btf1 = btf__new_empty();
0131     if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
0132         return;
0133 
0134     btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
0135 
0136     btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
0137     btf__add_ptr(btf1, 4);              /* [2] ptr to struct s1 */
0138     btf__add_ptr(btf1, 5);              /* [3] ptr to struct s2 */
0139     btf__add_struct(btf1, "s1", 16);        /* [4] struct s1 { */
0140     btf__add_field(btf1, "f1", 2, 0, 0);        /*      struct s1 *f1; */
0141     btf__add_field(btf1, "f2", 3, 64, 0);       /*      struct s2 *f2; */
0142                             /* } */
0143     btf__add_struct(btf1, "s2", 4);         /* [5] struct s2 { */
0144     btf__add_field(btf1, "f1", 1, 0, 0);        /*      int f1; */
0145                             /* } */
0146 
0147     VALIDATE_RAW_BTF(
0148         btf1,
0149         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0150         "[2] PTR '(anon)' type_id=4",
0151         "[3] PTR '(anon)' type_id=5",
0152         "[4] STRUCT 's1' size=16 vlen=2\n"
0153         "\t'f1' type_id=2 bits_offset=0\n"
0154         "\t'f2' type_id=3 bits_offset=64",
0155         "[5] STRUCT 's2' size=4 vlen=1\n"
0156         "\t'f1' type_id=1 bits_offset=0");
0157 
0158     btf2 = btf__new_empty_split(btf1);
0159     if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
0160         goto cleanup;
0161 
0162     btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [6] int */
0163     btf__add_ptr(btf2, 10);             /* [7] ptr to struct s1 */
0164     btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);   /* [8] fwd for struct s2 */
0165     btf__add_ptr(btf2, 8);              /* [9] ptr to fwd struct s2 */
0166     btf__add_struct(btf2, "s1", 16);        /* [10] struct s1 { */
0167     btf__add_field(btf2, "f1", 7, 0, 0);        /*      struct s1 *f1; */
0168     btf__add_field(btf2, "f2", 9, 64, 0);       /*      struct s2 *f2; */
0169                             /* } */
0170 
0171     VALIDATE_RAW_BTF(
0172         btf2,
0173         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0174         "[2] PTR '(anon)' type_id=4",
0175         "[3] PTR '(anon)' type_id=5",
0176         "[4] STRUCT 's1' size=16 vlen=2\n"
0177         "\t'f1' type_id=2 bits_offset=0\n"
0178         "\t'f2' type_id=3 bits_offset=64",
0179         "[5] STRUCT 's2' size=4 vlen=1\n"
0180         "\t'f1' type_id=1 bits_offset=0",
0181         "[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0182         "[7] PTR '(anon)' type_id=10",
0183         "[8] FWD 's2' fwd_kind=struct",
0184         "[9] PTR '(anon)' type_id=8",
0185         "[10] STRUCT 's1' size=16 vlen=2\n"
0186         "\t'f1' type_id=7 bits_offset=0\n"
0187         "\t'f2' type_id=9 bits_offset=64");
0188 
0189     err = btf__dedup(btf2, NULL);
0190     if (!ASSERT_OK(err, "btf_dedup"))
0191         goto cleanup;
0192 
0193     VALIDATE_RAW_BTF(
0194         btf2,
0195         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0196         "[2] PTR '(anon)' type_id=4",
0197         "[3] PTR '(anon)' type_id=5",
0198         "[4] STRUCT 's1' size=16 vlen=2\n"
0199         "\t'f1' type_id=2 bits_offset=0\n"
0200         "\t'f2' type_id=3 bits_offset=64",
0201         "[5] STRUCT 's2' size=4 vlen=1\n"
0202         "\t'f1' type_id=1 bits_offset=0");
0203 
0204 cleanup:
0205     btf__free(btf2);
0206     btf__free(btf1);
0207 }
0208 
0209 static void test_split_struct_duped() {
0210     struct btf *btf1, *btf2;
0211     int err;
0212 
0213     btf1 = btf__new_empty();
0214     if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
0215         return;
0216 
0217     btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
0218 
0219     btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);   /* [1] int */
0220     btf__add_ptr(btf1, 5);              /* [2] ptr to struct s1 */
0221     btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT);   /* [3] fwd for struct s2 */
0222     btf__add_ptr(btf1, 3);              /* [4] ptr to fwd struct s2 */
0223     btf__add_struct(btf1, "s1", 16);        /* [5] struct s1 { */
0224     btf__add_field(btf1, "f1", 2, 0, 0);        /*      struct s1 *f1; */
0225     btf__add_field(btf1, "f2", 4, 64, 0);       /*      struct s2 *f2; */
0226                             /* } */
0227 
0228     VALIDATE_RAW_BTF(
0229         btf1,
0230         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0231         "[2] PTR '(anon)' type_id=5",
0232         "[3] FWD 's2' fwd_kind=struct",
0233         "[4] PTR '(anon)' type_id=3",
0234         "[5] STRUCT 's1' size=16 vlen=2\n"
0235         "\t'f1' type_id=2 bits_offset=0\n"
0236         "\t'f2' type_id=4 bits_offset=64");
0237 
0238     btf2 = btf__new_empty_split(btf1);
0239     if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
0240         goto cleanup;
0241 
0242     btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);   /* [6] int */
0243     btf__add_ptr(btf2, 10);             /* [7] ptr to struct s1 */
0244     btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);   /* [8] fwd for struct s2 */
0245     btf__add_ptr(btf2, 11);             /* [9] ptr to struct s2 */
0246     btf__add_struct(btf2, "s1", 16);        /* [10] struct s1 { */
0247     btf__add_field(btf2, "f1", 7, 0, 0);        /*      struct s1 *f1; */
0248     btf__add_field(btf2, "f2", 9, 64, 0);       /*      struct s2 *f2; */
0249                             /* } */
0250     btf__add_struct(btf2, "s2", 40);        /* [11] struct s2 { */
0251     btf__add_field(btf2, "f1", 7, 0, 0);        /*      struct s1 *f1;  */
0252     btf__add_field(btf2, "f2", 9, 64, 0);       /*      struct s2 *f2;  */
0253     btf__add_field(btf2, "f3", 6, 128, 0);      /*      int f3;     */
0254     btf__add_field(btf2, "f4", 10, 192, 0);     /*      struct s1 f4;   */
0255                             /* } */
0256     btf__add_ptr(btf2, 8);              /* [12] ptr to fwd struct s2 */
0257     btf__add_struct(btf2, "s3", 8);         /* [13] struct s3 { */
0258     btf__add_field(btf2, "f1", 12, 0, 0);       /*      struct s2 *f1; (fwd) */
0259                             /* } */
0260 
0261     VALIDATE_RAW_BTF(
0262         btf2,
0263         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0264         "[2] PTR '(anon)' type_id=5",
0265         "[3] FWD 's2' fwd_kind=struct",
0266         "[4] PTR '(anon)' type_id=3",
0267         "[5] STRUCT 's1' size=16 vlen=2\n"
0268         "\t'f1' type_id=2 bits_offset=0\n"
0269         "\t'f2' type_id=4 bits_offset=64",
0270         "[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0271         "[7] PTR '(anon)' type_id=10",
0272         "[8] FWD 's2' fwd_kind=struct",
0273         "[9] PTR '(anon)' type_id=11",
0274         "[10] STRUCT 's1' size=16 vlen=2\n"
0275         "\t'f1' type_id=7 bits_offset=0\n"
0276         "\t'f2' type_id=9 bits_offset=64",
0277         "[11] STRUCT 's2' size=40 vlen=4\n"
0278         "\t'f1' type_id=7 bits_offset=0\n"
0279         "\t'f2' type_id=9 bits_offset=64\n"
0280         "\t'f3' type_id=6 bits_offset=128\n"
0281         "\t'f4' type_id=10 bits_offset=192",
0282         "[12] PTR '(anon)' type_id=8",
0283         "[13] STRUCT 's3' size=8 vlen=1\n"
0284         "\t'f1' type_id=12 bits_offset=0");
0285 
0286     err = btf__dedup(btf2, NULL);
0287     if (!ASSERT_OK(err, "btf_dedup"))
0288         goto cleanup;
0289 
0290     VALIDATE_RAW_BTF(
0291         btf2,
0292         "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0293         "[2] PTR '(anon)' type_id=5",
0294         "[3] FWD 's2' fwd_kind=struct",
0295         "[4] PTR '(anon)' type_id=3",
0296         "[5] STRUCT 's1' size=16 vlen=2\n"
0297         "\t'f1' type_id=2 bits_offset=0\n"
0298         "\t'f2' type_id=4 bits_offset=64",
0299         "[6] PTR '(anon)' type_id=8",
0300         "[7] PTR '(anon)' type_id=9",
0301         "[8] STRUCT 's1' size=16 vlen=2\n"
0302         "\t'f1' type_id=6 bits_offset=0\n"
0303         "\t'f2' type_id=7 bits_offset=64",
0304         "[9] STRUCT 's2' size=40 vlen=4\n"
0305         "\t'f1' type_id=6 bits_offset=0\n"
0306         "\t'f2' type_id=7 bits_offset=64\n"
0307         "\t'f3' type_id=1 bits_offset=128\n"
0308         "\t'f4' type_id=8 bits_offset=192",
0309         "[10] STRUCT 's3' size=8 vlen=1\n"
0310         "\t'f1' type_id=7 bits_offset=0");
0311 
0312 cleanup:
0313     btf__free(btf2);
0314     btf__free(btf1);
0315 }
0316 
0317 static void btf_add_dup_struct_in_cu(struct btf *btf, int start_id)
0318 {
0319 #define ID(n) (start_id + n)
0320     btf__set_pointer_size(btf, 8); /* enforce 64-bit arch */
0321 
0322     btf__add_int(btf, "int", 4, BTF_INT_SIGNED);    /* [1] int */
0323 
0324     btf__add_struct(btf, "s", 8);                   /* [2] struct s { */
0325     btf__add_field(btf, "a", ID(3), 0, 0);          /*      struct anon a; */
0326     btf__add_field(btf, "b", ID(4), 0, 0);          /*      struct anon b; */
0327                             /* } */
0328 
0329     btf__add_struct(btf, "(anon)", 8);              /* [3] struct anon { */
0330     btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */
0331     btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */
0332                             /* } */
0333 
0334     btf__add_struct(btf, "(anon)", 8);              /* [4] struct anon { */
0335     btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */
0336     btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */
0337                             /* } */
0338 #undef ID
0339 }
0340 
0341 static void test_split_dup_struct_in_cu()
0342 {
0343     struct btf *btf1, *btf2 = NULL;
0344     int err;
0345 
0346     /* generate the base data.. */
0347     btf1 = btf__new_empty();
0348     if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
0349         return;
0350 
0351     btf_add_dup_struct_in_cu(btf1, 0);
0352 
0353     VALIDATE_RAW_BTF(
0354             btf1,
0355             "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0356             "[2] STRUCT 's' size=8 vlen=2\n"
0357             "\t'a' type_id=3 bits_offset=0\n"
0358             "\t'b' type_id=4 bits_offset=0",
0359             "[3] STRUCT '(anon)' size=8 vlen=2\n"
0360             "\t'f1' type_id=1 bits_offset=0\n"
0361             "\t'f2' type_id=1 bits_offset=32",
0362             "[4] STRUCT '(anon)' size=8 vlen=2\n"
0363             "\t'f1' type_id=1 bits_offset=0\n"
0364             "\t'f2' type_id=1 bits_offset=32");
0365 
0366     /* ..dedup them... */
0367     err = btf__dedup(btf1, NULL);
0368     if (!ASSERT_OK(err, "btf_dedup"))
0369         goto cleanup;
0370 
0371     VALIDATE_RAW_BTF(
0372             btf1,
0373             "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0374             "[2] STRUCT 's' size=8 vlen=2\n"
0375             "\t'a' type_id=3 bits_offset=0\n"
0376             "\t'b' type_id=3 bits_offset=0",
0377             "[3] STRUCT '(anon)' size=8 vlen=2\n"
0378             "\t'f1' type_id=1 bits_offset=0\n"
0379             "\t'f2' type_id=1 bits_offset=32");
0380 
0381     /* and add the same data on top of it */
0382     btf2 = btf__new_empty_split(btf1);
0383     if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
0384         goto cleanup;
0385 
0386     btf_add_dup_struct_in_cu(btf2, 3);
0387 
0388     VALIDATE_RAW_BTF(
0389             btf2,
0390             "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0391             "[2] STRUCT 's' size=8 vlen=2\n"
0392             "\t'a' type_id=3 bits_offset=0\n"
0393             "\t'b' type_id=3 bits_offset=0",
0394             "[3] STRUCT '(anon)' size=8 vlen=2\n"
0395             "\t'f1' type_id=1 bits_offset=0\n"
0396             "\t'f2' type_id=1 bits_offset=32",
0397             "[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0398             "[5] STRUCT 's' size=8 vlen=2\n"
0399             "\t'a' type_id=6 bits_offset=0\n"
0400             "\t'b' type_id=7 bits_offset=0",
0401             "[6] STRUCT '(anon)' size=8 vlen=2\n"
0402             "\t'f1' type_id=4 bits_offset=0\n"
0403             "\t'f2' type_id=4 bits_offset=32",
0404             "[7] STRUCT '(anon)' size=8 vlen=2\n"
0405             "\t'f1' type_id=4 bits_offset=0\n"
0406             "\t'f2' type_id=4 bits_offset=32");
0407 
0408     err = btf__dedup(btf2, NULL);
0409     if (!ASSERT_OK(err, "btf_dedup"))
0410         goto cleanup;
0411 
0412     /* after dedup it should match the original data */
0413     VALIDATE_RAW_BTF(
0414             btf2,
0415             "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
0416             "[2] STRUCT 's' size=8 vlen=2\n"
0417             "\t'a' type_id=3 bits_offset=0\n"
0418             "\t'b' type_id=3 bits_offset=0",
0419             "[3] STRUCT '(anon)' size=8 vlen=2\n"
0420             "\t'f1' type_id=1 bits_offset=0\n"
0421             "\t'f2' type_id=1 bits_offset=32");
0422 
0423 cleanup:
0424     btf__free(btf2);
0425     btf__free(btf1);
0426 }
0427 
0428 void test_btf_dedup_split()
0429 {
0430     if (test__start_subtest("split_simple"))
0431         test_split_simple();
0432     if (test__start_subtest("split_struct_duped"))
0433         test_split_struct_duped();
0434     if (test__start_subtest("split_fwd_resolve"))
0435         test_split_fwd_resolve();
0436     if (test__start_subtest("split_dup_struct_in_cu"))
0437         test_split_dup_struct_in_cu();
0438 }