454 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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);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 /* keep this not a part of type the graph to test btf_dedup_resolve_fwds */147 btf__add_struct(btf1, "s3", 4); /* [6] struct s3 { */148 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */149 /* } */150 151 VALIDATE_RAW_BTF(152 btf1,153 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",154 "[2] PTR '(anon)' type_id=4",155 "[3] PTR '(anon)' type_id=5",156 "[4] STRUCT 's1' size=16 vlen=2\n"157 "\t'f1' type_id=2 bits_offset=0\n"158 "\t'f2' type_id=3 bits_offset=64",159 "[5] STRUCT 's2' size=4 vlen=1\n"160 "\t'f1' type_id=1 bits_offset=0",161 "[6] STRUCT 's3' size=4 vlen=1\n"162 "\t'f1' type_id=1 bits_offset=0");163 164 btf2 = btf__new_empty_split(btf1);165 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))166 goto cleanup;167 168 btf__add_int(btf2, "int", 4, BTF_INT_SIGNED); /* [7] int */169 btf__add_ptr(btf2, 11); /* [8] ptr to struct s1 */170 btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT); /* [9] fwd for struct s2 */171 btf__add_ptr(btf2, 9); /* [10] ptr to fwd struct s2 */172 btf__add_struct(btf2, "s1", 16); /* [11] struct s1 { */173 btf__add_field(btf2, "f1", 8, 0, 0); /* struct s1 *f1; */174 btf__add_field(btf2, "f2", 10, 64, 0); /* struct s2 *f2; */175 /* } */176 btf__add_fwd(btf2, "s3", BTF_FWD_STRUCT); /* [12] fwd for struct s3 */177 btf__add_ptr(btf2, 12); /* [13] ptr to struct s1 */178 179 VALIDATE_RAW_BTF(180 btf2,181 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",182 "[2] PTR '(anon)' type_id=4",183 "[3] PTR '(anon)' type_id=5",184 "[4] STRUCT 's1' size=16 vlen=2\n"185 "\t'f1' type_id=2 bits_offset=0\n"186 "\t'f2' type_id=3 bits_offset=64",187 "[5] STRUCT 's2' size=4 vlen=1\n"188 "\t'f1' type_id=1 bits_offset=0",189 "[6] STRUCT 's3' size=4 vlen=1\n"190 "\t'f1' type_id=1 bits_offset=0",191 "[7] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",192 "[8] PTR '(anon)' type_id=11",193 "[9] FWD 's2' fwd_kind=struct",194 "[10] PTR '(anon)' type_id=9",195 "[11] STRUCT 's1' size=16 vlen=2\n"196 "\t'f1' type_id=8 bits_offset=0\n"197 "\t'f2' type_id=10 bits_offset=64",198 "[12] FWD 's3' fwd_kind=struct",199 "[13] PTR '(anon)' type_id=12");200 201 err = btf__dedup(btf2, NULL);202 if (!ASSERT_OK(err, "btf_dedup"))203 goto cleanup;204 205 VALIDATE_RAW_BTF(206 btf2,207 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",208 "[2] PTR '(anon)' type_id=4",209 "[3] PTR '(anon)' type_id=5",210 "[4] STRUCT 's1' size=16 vlen=2\n"211 "\t'f1' type_id=2 bits_offset=0\n"212 "\t'f2' type_id=3 bits_offset=64",213 "[5] STRUCT 's2' size=4 vlen=1\n"214 "\t'f1' type_id=1 bits_offset=0",215 "[6] STRUCT 's3' size=4 vlen=1\n"216 "\t'f1' type_id=1 bits_offset=0",217 "[7] PTR '(anon)' type_id=6");218 219cleanup:220 btf__free(btf2);221 btf__free(btf1);222}223 224static void test_split_struct_duped() {225 struct btf *btf1, *btf2;226 int err;227 228 btf1 = btf__new_empty();229 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))230 return;231 232 btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */233 234 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */235 btf__add_ptr(btf1, 5); /* [2] ptr to struct s1 */236 btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT); /* [3] fwd for struct s2 */237 btf__add_ptr(btf1, 3); /* [4] ptr to fwd struct s2 */238 btf__add_struct(btf1, "s1", 16); /* [5] struct s1 { */239 btf__add_field(btf1, "f1", 2, 0, 0); /* struct s1 *f1; */240 btf__add_field(btf1, "f2", 4, 64, 0); /* struct s2 *f2; */241 /* } */242 243 VALIDATE_RAW_BTF(244 btf1,245 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",246 "[2] PTR '(anon)' type_id=5",247 "[3] FWD 's2' fwd_kind=struct",248 "[4] PTR '(anon)' type_id=3",249 "[5] STRUCT 's1' size=16 vlen=2\n"250 "\t'f1' type_id=2 bits_offset=0\n"251 "\t'f2' type_id=4 bits_offset=64");252 253 btf2 = btf__new_empty_split(btf1);254 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))255 goto cleanup;256 257 btf__add_int(btf2, "int", 4, BTF_INT_SIGNED); /* [6] int */258 btf__add_ptr(btf2, 10); /* [7] ptr to struct s1 */259 btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT); /* [8] fwd for struct s2 */260 btf__add_ptr(btf2, 11); /* [9] ptr to struct s2 */261 btf__add_struct(btf2, "s1", 16); /* [10] struct s1 { */262 btf__add_field(btf2, "f1", 7, 0, 0); /* struct s1 *f1; */263 btf__add_field(btf2, "f2", 9, 64, 0); /* struct s2 *f2; */264 /* } */265 btf__add_struct(btf2, "s2", 40); /* [11] struct s2 { */266 btf__add_field(btf2, "f1", 7, 0, 0); /* struct s1 *f1; */267 btf__add_field(btf2, "f2", 9, 64, 0); /* struct s2 *f2; */268 btf__add_field(btf2, "f3", 6, 128, 0); /* int f3; */269 btf__add_field(btf2, "f4", 10, 192, 0); /* struct s1 f4; */270 /* } */271 btf__add_ptr(btf2, 8); /* [12] ptr to fwd struct s2 */272 btf__add_struct(btf2, "s3", 8); /* [13] struct s3 { */273 btf__add_field(btf2, "f1", 12, 0, 0); /* struct s2 *f1; (fwd) */274 /* } */275 276 VALIDATE_RAW_BTF(277 btf2,278 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",279 "[2] PTR '(anon)' type_id=5",280 "[3] FWD 's2' fwd_kind=struct",281 "[4] PTR '(anon)' type_id=3",282 "[5] STRUCT 's1' size=16 vlen=2\n"283 "\t'f1' type_id=2 bits_offset=0\n"284 "\t'f2' type_id=4 bits_offset=64",285 "[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",286 "[7] PTR '(anon)' type_id=10",287 "[8] FWD 's2' fwd_kind=struct",288 "[9] PTR '(anon)' type_id=11",289 "[10] STRUCT 's1' size=16 vlen=2\n"290 "\t'f1' type_id=7 bits_offset=0\n"291 "\t'f2' type_id=9 bits_offset=64",292 "[11] STRUCT 's2' size=40 vlen=4\n"293 "\t'f1' type_id=7 bits_offset=0\n"294 "\t'f2' type_id=9 bits_offset=64\n"295 "\t'f3' type_id=6 bits_offset=128\n"296 "\t'f4' type_id=10 bits_offset=192",297 "[12] PTR '(anon)' type_id=8",298 "[13] STRUCT 's3' size=8 vlen=1\n"299 "\t'f1' type_id=12 bits_offset=0");300 301 err = btf__dedup(btf2, NULL);302 if (!ASSERT_OK(err, "btf_dedup"))303 goto cleanup;304 305 VALIDATE_RAW_BTF(306 btf2,307 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",308 "[2] PTR '(anon)' type_id=5",309 "[3] FWD 's2' fwd_kind=struct",310 "[4] PTR '(anon)' type_id=3",311 "[5] STRUCT 's1' size=16 vlen=2\n"312 "\t'f1' type_id=2 bits_offset=0\n"313 "\t'f2' type_id=4 bits_offset=64",314 "[6] PTR '(anon)' type_id=8",315 "[7] PTR '(anon)' type_id=9",316 "[8] STRUCT 's1' size=16 vlen=2\n"317 "\t'f1' type_id=6 bits_offset=0\n"318 "\t'f2' type_id=7 bits_offset=64",319 "[9] STRUCT 's2' size=40 vlen=4\n"320 "\t'f1' type_id=6 bits_offset=0\n"321 "\t'f2' type_id=7 bits_offset=64\n"322 "\t'f3' type_id=1 bits_offset=128\n"323 "\t'f4' type_id=8 bits_offset=192",324 "[10] STRUCT 's3' size=8 vlen=1\n"325 "\t'f1' type_id=7 bits_offset=0");326 327cleanup:328 btf__free(btf2);329 btf__free(btf1);330}331 332static void btf_add_dup_struct_in_cu(struct btf *btf, int start_id)333{334#define ID(n) (start_id + n)335 btf__set_pointer_size(btf, 8); /* enforce 64-bit arch */336 337 btf__add_int(btf, "int", 4, BTF_INT_SIGNED); /* [1] int */338 339 btf__add_struct(btf, "s", 8); /* [2] struct s { */340 btf__add_field(btf, "a", ID(3), 0, 0); /* struct anon a; */341 btf__add_field(btf, "b", ID(4), 0, 0); /* struct anon b; */342 /* } */343 344 btf__add_struct(btf, "(anon)", 8); /* [3] struct anon { */345 btf__add_field(btf, "f1", ID(1), 0, 0); /* int f1; */346 btf__add_field(btf, "f2", ID(1), 32, 0); /* int f2; */347 /* } */348 349 btf__add_struct(btf, "(anon)", 8); /* [4] struct anon { */350 btf__add_field(btf, "f1", ID(1), 0, 0); /* int f1; */351 btf__add_field(btf, "f2", ID(1), 32, 0); /* int f2; */352 /* } */353#undef ID354}355 356static void test_split_dup_struct_in_cu()357{358 struct btf *btf1, *btf2 = NULL;359 int err;360 361 /* generate the base data.. */362 btf1 = btf__new_empty();363 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))364 return;365 366 btf_add_dup_struct_in_cu(btf1, 0);367 368 VALIDATE_RAW_BTF(369 btf1,370 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",371 "[2] STRUCT 's' size=8 vlen=2\n"372 "\t'a' type_id=3 bits_offset=0\n"373 "\t'b' type_id=4 bits_offset=0",374 "[3] STRUCT '(anon)' size=8 vlen=2\n"375 "\t'f1' type_id=1 bits_offset=0\n"376 "\t'f2' type_id=1 bits_offset=32",377 "[4] STRUCT '(anon)' size=8 vlen=2\n"378 "\t'f1' type_id=1 bits_offset=0\n"379 "\t'f2' type_id=1 bits_offset=32");380 381 /* ..dedup them... */382 err = btf__dedup(btf1, NULL);383 if (!ASSERT_OK(err, "btf_dedup"))384 goto cleanup;385 386 VALIDATE_RAW_BTF(387 btf1,388 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",389 "[2] STRUCT 's' size=8 vlen=2\n"390 "\t'a' type_id=3 bits_offset=0\n"391 "\t'b' type_id=3 bits_offset=0",392 "[3] STRUCT '(anon)' size=8 vlen=2\n"393 "\t'f1' type_id=1 bits_offset=0\n"394 "\t'f2' type_id=1 bits_offset=32");395 396 /* and add the same data on top of it */397 btf2 = btf__new_empty_split(btf1);398 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))399 goto cleanup;400 401 btf_add_dup_struct_in_cu(btf2, 3);402 403 VALIDATE_RAW_BTF(404 btf2,405 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",406 "[2] STRUCT 's' size=8 vlen=2\n"407 "\t'a' type_id=3 bits_offset=0\n"408 "\t'b' type_id=3 bits_offset=0",409 "[3] STRUCT '(anon)' size=8 vlen=2\n"410 "\t'f1' type_id=1 bits_offset=0\n"411 "\t'f2' type_id=1 bits_offset=32",412 "[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",413 "[5] STRUCT 's' size=8 vlen=2\n"414 "\t'a' type_id=6 bits_offset=0\n"415 "\t'b' type_id=7 bits_offset=0",416 "[6] STRUCT '(anon)' size=8 vlen=2\n"417 "\t'f1' type_id=4 bits_offset=0\n"418 "\t'f2' type_id=4 bits_offset=32",419 "[7] STRUCT '(anon)' size=8 vlen=2\n"420 "\t'f1' type_id=4 bits_offset=0\n"421 "\t'f2' type_id=4 bits_offset=32");422 423 err = btf__dedup(btf2, NULL);424 if (!ASSERT_OK(err, "btf_dedup"))425 goto cleanup;426 427 /* after dedup it should match the original data */428 VALIDATE_RAW_BTF(429 btf2,430 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",431 "[2] STRUCT 's' size=8 vlen=2\n"432 "\t'a' type_id=3 bits_offset=0\n"433 "\t'b' type_id=3 bits_offset=0",434 "[3] STRUCT '(anon)' size=8 vlen=2\n"435 "\t'f1' type_id=1 bits_offset=0\n"436 "\t'f2' type_id=1 bits_offset=32");437 438cleanup:439 btf__free(btf2);440 btf__free(btf1);441}442 443void test_btf_dedup_split()444{445 if (test__start_subtest("split_simple"))446 test_split_simple();447 if (test__start_subtest("split_struct_duped"))448 test_split_struct_duped();449 if (test__start_subtest("split_fwd_resolve"))450 test_split_fwd_resolve();451 if (test__start_subtest("split_dup_struct_in_cu"))452 test_split_dup_struct_in_cu();453}454