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
443void test_btf_dedup_split()
444{
445	if (test__start_subtest("split_simple"))
446		test_split_simple();
447	if (test__start_subtest("split_struct_duped"))
448		test_split_struct_duped();
449	if (test__start_subtest("split_fwd_resolve"))
450		test_split_fwd_resolve();
451	if (test__start_subtest("split_dup_struct_in_cu"))
452		test_split_dup_struct_in_cu();
453}
454