btf_dedup_split.c (13551B)
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); 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); 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); 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 317static void btf_add_dup_struct_in_cu(struct btf *btf, int start_id) 318{ 319#define ID(n) (start_id + n) 320 btf__set_pointer_size(btf, 8); /* enforce 64-bit arch */ 321 322 btf__add_int(btf, "int", 4, BTF_INT_SIGNED); /* [1] int */ 323 324 btf__add_struct(btf, "s", 8); /* [2] struct s { */ 325 btf__add_field(btf, "a", ID(3), 0, 0); /* struct anon a; */ 326 btf__add_field(btf, "b", ID(4), 0, 0); /* struct anon b; */ 327 /* } */ 328 329 btf__add_struct(btf, "(anon)", 8); /* [3] struct anon { */ 330 btf__add_field(btf, "f1", ID(1), 0, 0); /* int f1; */ 331 btf__add_field(btf, "f2", ID(1), 32, 0); /* int f2; */ 332 /* } */ 333 334 btf__add_struct(btf, "(anon)", 8); /* [4] struct anon { */ 335 btf__add_field(btf, "f1", ID(1), 0, 0); /* int f1; */ 336 btf__add_field(btf, "f2", ID(1), 32, 0); /* int f2; */ 337 /* } */ 338#undef ID 339} 340 341static void test_split_dup_struct_in_cu() 342{ 343 struct btf *btf1, *btf2 = NULL; 344 int err; 345 346 /* generate the base data.. */ 347 btf1 = btf__new_empty(); 348 if (!ASSERT_OK_PTR(btf1, "empty_main_btf")) 349 return; 350 351 btf_add_dup_struct_in_cu(btf1, 0); 352 353 VALIDATE_RAW_BTF( 354 btf1, 355 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", 356 "[2] STRUCT 's' size=8 vlen=2\n" 357 "\t'a' type_id=3 bits_offset=0\n" 358 "\t'b' type_id=4 bits_offset=0", 359 "[3] STRUCT '(anon)' size=8 vlen=2\n" 360 "\t'f1' type_id=1 bits_offset=0\n" 361 "\t'f2' type_id=1 bits_offset=32", 362 "[4] STRUCT '(anon)' size=8 vlen=2\n" 363 "\t'f1' type_id=1 bits_offset=0\n" 364 "\t'f2' type_id=1 bits_offset=32"); 365 366 /* ..dedup them... */ 367 err = btf__dedup(btf1, NULL); 368 if (!ASSERT_OK(err, "btf_dedup")) 369 goto cleanup; 370 371 VALIDATE_RAW_BTF( 372 btf1, 373 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", 374 "[2] STRUCT 's' size=8 vlen=2\n" 375 "\t'a' type_id=3 bits_offset=0\n" 376 "\t'b' type_id=3 bits_offset=0", 377 "[3] 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 /* and add the same data on top of it */ 382 btf2 = btf__new_empty_split(btf1); 383 if (!ASSERT_OK_PTR(btf2, "empty_split_btf")) 384 goto cleanup; 385 386 btf_add_dup_struct_in_cu(btf2, 3); 387 388 VALIDATE_RAW_BTF( 389 btf2, 390 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", 391 "[2] STRUCT 's' size=8 vlen=2\n" 392 "\t'a' type_id=3 bits_offset=0\n" 393 "\t'b' type_id=3 bits_offset=0", 394 "[3] STRUCT '(anon)' size=8 vlen=2\n" 395 "\t'f1' type_id=1 bits_offset=0\n" 396 "\t'f2' type_id=1 bits_offset=32", 397 "[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", 398 "[5] STRUCT 's' size=8 vlen=2\n" 399 "\t'a' type_id=6 bits_offset=0\n" 400 "\t'b' type_id=7 bits_offset=0", 401 "[6] STRUCT '(anon)' size=8 vlen=2\n" 402 "\t'f1' type_id=4 bits_offset=0\n" 403 "\t'f2' type_id=4 bits_offset=32", 404 "[7] STRUCT '(anon)' size=8 vlen=2\n" 405 "\t'f1' type_id=4 bits_offset=0\n" 406 "\t'f2' type_id=4 bits_offset=32"); 407 408 err = btf__dedup(btf2, NULL); 409 if (!ASSERT_OK(err, "btf_dedup")) 410 goto cleanup; 411 412 /* after dedup it should match the original data */ 413 VALIDATE_RAW_BTF( 414 btf2, 415 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED", 416 "[2] STRUCT 's' size=8 vlen=2\n" 417 "\t'a' type_id=3 bits_offset=0\n" 418 "\t'b' type_id=3 bits_offset=0", 419 "[3] STRUCT '(anon)' size=8 vlen=2\n" 420 "\t'f1' type_id=1 bits_offset=0\n" 421 "\t'f2' type_id=1 bits_offset=32"); 422 423cleanup: 424 btf__free(btf2); 425 btf__free(btf1); 426} 427 428void test_btf_dedup_split() 429{ 430 if (test__start_subtest("split_simple")) 431 test_split_simple(); 432 if (test__start_subtest("split_struct_duped")) 433 test_split_struct_duped(); 434 if (test__start_subtest("split_fwd_resolve")) 435 test_split_fwd_resolve(); 436 if (test__start_subtest("split_dup_struct_in_cu")) 437 test_split_dup_struct_in_cu(); 438}