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 
test_split_simple()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 
test_split_fwd_resolve()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 
test_split_struct_duped()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 
btf_add_dup_struct_in_cu(struct btf * btf,int start_id)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 
test_split_dup_struct_in_cu()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 
test_split_module(void)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 
test_btf_dedup_split()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