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 7 static 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), "\ 32 struct 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), "\ 81 struct s1 {\n\ 82 int f1;\n\ 83 };\n\ 84 \n\ 85 struct s1___2 {\n\ 86 int f1;\n\ 87 };\n\ 88 \n\ 89 struct 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), "\ 111 struct s1 {\n\ 112 int f1;\n\ 113 };\n\ 114 \n\ 115 struct s2 {\n\ 116 struct s1 f1;\n\ 117 int f2;\n\ 118 int *f3;\n\ 119 };\n\n", "c_dump"); 120 121 cleanup: 122 btf__free(btf2); 123 btf__free(btf1); 124 } 125 126 static 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 219 cleanup: 220 btf__free(btf2); 221 btf__free(btf1); 222 } 223 224 static 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 327 cleanup: 328 btf__free(btf2); 329 btf__free(btf1); 330 } 331 332 static 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 ID 354 } 355 356 static 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 438 cleanup: 439 btf__free(btf2); 440 btf__free(btf1); 441 } 442 443 void 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