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 /* Ensure module split BTF dedup worked correctly; when dedup fails badly 444 * core kernel types are in split BTF also, so ensure that references to 445 * such types point at base - not split - BTF. 446 * 447 * bpf_testmod_test_write() has multiple core kernel type parameters; 448 * 449 * ssize_t 450 * bpf_testmod_test_write(struct file *file, struct kobject *kobj, 451 * struct bin_attribute *bin_attr, 452 * char *buf, loff_t off, size_t len); 453 * 454 * Ensure each of the FUNC_PROTO params is a core kernel type. 455 * 456 * Do the same for 457 * 458 * __bpf_kfunc struct sock *bpf_kfunc_call_test3(struct sock *sk); 459 * 460 * ...and 461 * 462 * __bpf_kfunc void bpf_kfunc_call_test_pass_ctx(struct __sk_buff *skb); 463 * 464 */ 465 const char *mod_funcs[] = { 466 "bpf_testmod_test_write", 467 "bpf_kfunc_call_test3", 468 "bpf_kfunc_call_test_pass_ctx" 469 }; 470 471 static void test_split_module(void) 472 { 473 struct btf *vmlinux_btf, *btf1 = NULL; 474 int i, nr_base_types; 475 476 vmlinux_btf = btf__load_vmlinux_btf(); 477 if (!ASSERT_OK_PTR(vmlinux_btf, "vmlinux_btf")) 478 return; 479 nr_base_types = btf__type_cnt(vmlinux_btf); 480 if (!ASSERT_GT(nr_base_types, 0, "nr_base_types")) 481 goto cleanup; 482 483 btf1 = btf__parse_split("/sys/kernel/btf/bpf_testmod", vmlinux_btf); 484 if (!ASSERT_OK_PTR(btf1, "split_btf")) 485 return; 486 487 for (i = 0; i < ARRAY_SIZE(mod_funcs); i++) { 488 const struct btf_param *p; 489 const struct btf_type *t; 490 __u16 vlen; 491 __u32 id; 492 int j; 493 494 id = btf__find_by_name_kind(btf1, mod_funcs[i], BTF_KIND_FUNC); 495 if (!ASSERT_GE(id, nr_base_types, "func_id")) 496 goto cleanup; 497 t = btf__type_by_id(btf1, id); 498 if (!ASSERT_OK_PTR(t, "func_id_type")) 499 goto cleanup; 500 t = btf__type_by_id(btf1, t->type); 501 if (!ASSERT_OK_PTR(t, "func_proto_id_type")) 502 goto cleanup; 503 if (!ASSERT_EQ(btf_is_func_proto(t), true, "is_func_proto")) 504 goto cleanup; 505 vlen = btf_vlen(t); 506 507 for (j = 0, p = btf_params(t); j < vlen; j++, p++) { 508 /* bpf_testmod uses resilient split BTF, so any 509 * reference types will be added to split BTF and their 510 * associated targets will be base BTF types; for example 511 * for a "struct sock *" the PTR will be in split BTF 512 * while the "struct sock" will be in base. 513 * 514 * In some cases like loff_t we have to resolve 515 * multiple typedefs hence the while() loop below. 516 * 517 * Note that resilient split BTF generation depends 518 * on pahole version, so we do not assert that 519 * reference types are in split BTF, as if pahole 520 * does not support resilient split BTF they will 521 * also be base BTF types. 522 */ 523 id = p->type; 524 do { 525 t = btf__type_by_id(btf1, id); 526 if (!ASSERT_OK_PTR(t, "param_ref_type")) 527 goto cleanup; 528 if (!btf_is_mod(t) && !btf_is_ptr(t) && !btf_is_typedef(t)) 529 break; 530 id = t->type; 531 } while (true); 532 533 if (!ASSERT_LT(id, nr_base_types, "verify_base_type")) 534 goto cleanup; 535 } 536 } 537 cleanup: 538 btf__free(btf1); 539 btf__free(vmlinux_btf); 540 } 541 542 void test_btf_dedup_split() 543 { 544 if (test__start_subtest("split_simple")) 545 test_split_simple(); 546 if (test__start_subtest("split_struct_duped")) 547 test_split_struct_duped(); 548 if (test__start_subtest("split_fwd_resolve")) 549 test_split_fwd_resolve(); 550 if (test__start_subtest("split_dup_struct_in_cu")) 551 test_split_dup_struct_in_cu(); 552 if (test__start_subtest("split_module")) 553 test_split_module(); 554 } 555