0001
0002
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);
0017
0018 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);
0019 btf__add_ptr(btf1, 1);
0020 btf__add_struct(btf1, "s1", 4);
0021 btf__add_field(btf1, "f1", 1, 0, 0);
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
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);
0053 btf__add_field(btf2, "f1", 6, 0, 0);
0054 btf__add_field(btf2, "f2", 5, 32, 0);
0055 btf__add_field(btf2, "f3", 2, 64, 0);
0056
0057
0058
0059 btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);
0060
0061
0062 btf__add_struct(btf2, "s1", 4);
0063 btf__add_field(btf2, "f1", 5, 0, 0);
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);
0135
0136 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);
0137 btf__add_ptr(btf1, 4);
0138 btf__add_ptr(btf1, 5);
0139 btf__add_struct(btf1, "s1", 16);
0140 btf__add_field(btf1, "f1", 2, 0, 0);
0141 btf__add_field(btf1, "f2", 3, 64, 0);
0142
0143 btf__add_struct(btf1, "s2", 4);
0144 btf__add_field(btf1, "f1", 1, 0, 0);
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);
0163 btf__add_ptr(btf2, 10);
0164 btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);
0165 btf__add_ptr(btf2, 8);
0166 btf__add_struct(btf2, "s1", 16);
0167 btf__add_field(btf2, "f1", 7, 0, 0);
0168 btf__add_field(btf2, "f2", 9, 64, 0);
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);
0218
0219 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);
0220 btf__add_ptr(btf1, 5);
0221 btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT);
0222 btf__add_ptr(btf1, 3);
0223 btf__add_struct(btf1, "s1", 16);
0224 btf__add_field(btf1, "f1", 2, 0, 0);
0225 btf__add_field(btf1, "f2", 4, 64, 0);
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);
0243 btf__add_ptr(btf2, 10);
0244 btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);
0245 btf__add_ptr(btf2, 11);
0246 btf__add_struct(btf2, "s1", 16);
0247 btf__add_field(btf2, "f1", 7, 0, 0);
0248 btf__add_field(btf2, "f2", 9, 64, 0);
0249
0250 btf__add_struct(btf2, "s2", 40);
0251 btf__add_field(btf2, "f1", 7, 0, 0);
0252 btf__add_field(btf2, "f2", 9, 64, 0);
0253 btf__add_field(btf2, "f3", 6, 128, 0);
0254 btf__add_field(btf2, "f4", 10, 192, 0);
0255
0256 btf__add_ptr(btf2, 8);
0257 btf__add_struct(btf2, "s3", 8);
0258 btf__add_field(btf2, "f1", 12, 0, 0);
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);
0321
0322 btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
0323
0324 btf__add_struct(btf, "s", 8);
0325 btf__add_field(btf, "a", ID(3), 0, 0);
0326 btf__add_field(btf, "b", ID(4), 0, 0);
0327
0328
0329 btf__add_struct(btf, "(anon)", 8);
0330 btf__add_field(btf, "f1", ID(1), 0, 0);
0331 btf__add_field(btf, "f2", ID(1), 32, 0);
0332
0333
0334 btf__add_struct(btf, "(anon)", 8);
0335 btf__add_field(btf, "f1", ID(1), 0, 0);
0336 btf__add_field(btf, "f2", ID(1), 32, 0);
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
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
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
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
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 }