File Index
Files and directories
Sign in
FILE

btf_dedup_split.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c C
  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
  7static 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), "\
 32struct 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), "\
 81struct s1 {\n\
 82	int f1;\n\
 83};\n\
 84\n\
 85struct s1___2 {\n\
 86	int f1;\n\
 87};\n\
 88\n\
 89struct 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), "\
111struct s1 {\n\
112	int f1;\n\
113};\n\
114\n\
115struct s2 {\n\
116	struct s1 f1;\n\
117	int f2;\n\
118	int *f3;\n\
119};\n\n", "c_dump");
120
121cleanup:
122	btf__free(btf2);
123	btf__free(btf1);
124}
125
126static 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
219cleanup:
220	btf__free(btf2);
221	btf__free(btf1);
222}
223
224static 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
327cleanup:
328	btf__free(btf2);
329	btf__free(btf1);
330}
331
332static 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
356static 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
438cleanup:
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 */
465const char *mod_funcs[] = {
466	"bpf_testmod_test_write",
467	"bpf_kfunc_call_test3",
468	"bpf_kfunc_call_test_pass_ctx"
469};
470
471static 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	}
537cleanup:
538	btf__free(btf1);
539	btf__free(vmlinux_btf);
540}
541
542void 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}
~/ Read-only file preview.