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, 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 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, 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 204 cleanup: 205 btf__free(btf2); 206 btf__free(btf1); 207 } 208 209 static 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, 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 312 cleanup: 313 btf__free(btf2); 314 btf__free(btf1); 315 } 316 317 void test_btf_dedup_split() 318 { 319 if (test__start_subtest("split_simple")) 320 test_split_simple(); 321 if (test__start_subtest("split_struct_duped")) 322 test_split_struct_duped(); 323 if (test__start_subtest("split_fwd_resolve")) 324 test_split_fwd_resolve(); 325 } 326