Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Test multi-split BTF

Extend split BTF test to cover case where we create split BTF on top of
existing split BTF and add info to it; ensure that such BTF can be
created and handled by searching within it, dumping/comparing to expected.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20250519165935.261614-3-alan.maguire@oracle.com

authored by

Alan Maguire and committed by
Andrii Nakryiko
02f5e7c1 4e29128a

+52 -6
+52 -6
tools/testing/selftests/bpf/prog_tests/btf_split.c
··· 12 12 vfprintf(ctx, fmt, args); 13 13 } 14 14 15 - void test_btf_split() { 15 + static void __test_btf_split(bool multi) 16 + { 16 17 struct btf_dump *d = NULL; 17 18 const struct btf_type *t; 18 - struct btf *btf1, *btf2; 19 + struct btf *btf1, *btf2, *btf3 = NULL; 19 20 int str_off, i, err; 20 21 21 22 btf1 = btf__new_empty(); ··· 64 63 ASSERT_EQ(btf_vlen(t), 3, "split_struct_vlen"); 65 64 ASSERT_STREQ(btf__str_by_offset(btf2, t->name_off), "s2", "split_struct_name"); 66 65 66 + if (multi) { 67 + btf3 = btf__new_empty_split(btf2); 68 + if (!ASSERT_OK_PTR(btf3, "multi_split_btf")) 69 + goto cleanup; 70 + } else { 71 + btf3 = btf2; 72 + } 73 + 74 + btf__add_union(btf3, "u1", 16); /* [5] union u1 { */ 75 + btf__add_field(btf3, "f1", 4, 0, 0); /* struct s2 f1; */ 76 + btf__add_field(btf3, "uf2", 1, 0, 0); /* int f2; */ 77 + /* } */ 78 + 79 + if (multi) { 80 + t = btf__type_by_id(btf2, 5); 81 + ASSERT_NULL(t, "multisplit_type_in_first_split"); 82 + } 83 + 84 + t = btf__type_by_id(btf3, 5); 85 + if (!ASSERT_OK_PTR(t, "split_union_type")) 86 + goto cleanup; 87 + ASSERT_EQ(btf_is_union(t), true, "split_union_kind"); 88 + ASSERT_EQ(btf_vlen(t), 2, "split_union_vlen"); 89 + ASSERT_STREQ(btf__str_by_offset(btf3, t->name_off), "u1", "split_union_name"); 90 + ASSERT_EQ(btf__type_cnt(btf3), 6, "split_type_cnt"); 91 + 92 + t = btf__type_by_id(btf3, 1); 93 + if (!ASSERT_OK_PTR(t, "split_base_type")) 94 + goto cleanup; 95 + ASSERT_EQ(btf_is_int(t), true, "split_base_int"); 96 + ASSERT_STREQ(btf__str_by_offset(btf3, t->name_off), "int", "split_base_type_name"); 97 + 67 98 /* BTF-to-C dump of split BTF */ 68 99 dump_buf_file = open_memstream(&dump_buf, &dump_buf_sz); 69 100 if (!ASSERT_OK_PTR(dump_buf_file, "dump_memstream")) 70 101 return; 71 - d = btf_dump__new(btf2, btf_dump_printf, dump_buf_file, NULL); 102 + d = btf_dump__new(btf3, btf_dump_printf, dump_buf_file, NULL); 72 103 if (!ASSERT_OK_PTR(d, "btf_dump__new")) 73 104 goto cleanup; 74 - for (i = 1; i < btf__type_cnt(btf2); i++) { 105 + for (i = 1; i < btf__type_cnt(btf3); i++) { 75 106 err = btf_dump__dump_type(d, i); 76 107 ASSERT_OK(err, "dump_type_ok"); 77 108 } ··· 112 79 ASSERT_STREQ(dump_buf, 113 80 "struct s1 {\n" 114 81 " int f1;\n" 115 - "};\n" 116 - "\n" 82 + "};\n\n" 117 83 "struct s2 {\n" 118 84 " struct s1 f1;\n" 119 85 " int f2;\n" 120 86 " int *f3;\n" 87 + "};\n\n" 88 + "union u1 {\n" 89 + " struct s2 f1;\n" 90 + " int uf2;\n" 121 91 "};\n\n", "c_dump"); 122 92 123 93 cleanup: ··· 130 94 btf_dump__free(d); 131 95 btf__free(btf1); 132 96 btf__free(btf2); 97 + if (btf2 != btf3) 98 + btf__free(btf3); 99 + } 100 + 101 + void test_btf_split(void) 102 + { 103 + if (test__start_subtest("single_split")) 104 + __test_btf_split(false); 105 + if (test__start_subtest("multi_split")) 106 + __test_btf_split(true); 133 107 }