xref: /linux/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1232338faSAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2232338faSAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3232338faSAndrii Nakryiko #include <test_progs.h>
4232338faSAndrii Nakryiko #include <bpf/btf.h>
5232338faSAndrii Nakryiko #include "btf_helpers.h"
6232338faSAndrii Nakryiko 
test_split_simple()7232338faSAndrii Nakryiko static void test_split_simple() {
8232338faSAndrii Nakryiko 	const struct btf_type *t;
9232338faSAndrii Nakryiko 	struct btf *btf1, *btf2;
10232338faSAndrii Nakryiko 	int str_off, err;
11232338faSAndrii Nakryiko 
12232338faSAndrii Nakryiko 	btf1 = btf__new_empty();
13232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
14232338faSAndrii Nakryiko 		return;
15232338faSAndrii Nakryiko 
16232338faSAndrii Nakryiko 	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
17232338faSAndrii Nakryiko 
18232338faSAndrii Nakryiko 	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */
19232338faSAndrii Nakryiko 	btf__add_ptr(btf1, 1);				/* [2] ptr to int */
20232338faSAndrii Nakryiko 	btf__add_struct(btf1, "s1", 4);			/* [3] struct s1 { */
21232338faSAndrii Nakryiko 	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */
22232338faSAndrii Nakryiko 							/* } */
23232338faSAndrii Nakryiko 
24232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
25232338faSAndrii Nakryiko 		btf1,
26232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
27232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=1",
28232338faSAndrii Nakryiko 		"[3] STRUCT 's1' size=4 vlen=1\n"
29232338faSAndrii Nakryiko 		"\t'f1' type_id=1 bits_offset=0");
30232338faSAndrii Nakryiko 
31232338faSAndrii Nakryiko 	ASSERT_STREQ(btf_type_c_dump(btf1), "\
32232338faSAndrii Nakryiko struct s1 {\n\
33232338faSAndrii Nakryiko 	int f1;\n\
34232338faSAndrii Nakryiko };\n\n", "c_dump");
35232338faSAndrii Nakryiko 
36232338faSAndrii Nakryiko 	btf2 = btf__new_empty_split(btf1);
37232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
38232338faSAndrii Nakryiko 		goto cleanup;
39232338faSAndrii Nakryiko 
40232338faSAndrii Nakryiko 	/* pointer size should be "inherited" from main BTF */
41232338faSAndrii Nakryiko 	ASSERT_EQ(btf__pointer_size(btf2), 8, "inherit_ptr_sz");
42232338faSAndrii Nakryiko 
43232338faSAndrii Nakryiko 	str_off = btf__find_str(btf2, "int");
44232338faSAndrii Nakryiko 	ASSERT_NEQ(str_off, -ENOENT, "str_int_missing");
45232338faSAndrii Nakryiko 
46232338faSAndrii Nakryiko 	t = btf__type_by_id(btf2, 1);
47232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(t, "int_type"))
48232338faSAndrii Nakryiko 		goto cleanup;
49232338faSAndrii Nakryiko 	ASSERT_EQ(btf_is_int(t), true, "int_kind");
50232338faSAndrii Nakryiko 	ASSERT_STREQ(btf__str_by_offset(btf2, t->name_off), "int", "int_name");
51232338faSAndrii Nakryiko 
52232338faSAndrii Nakryiko 	btf__add_struct(btf2, "s2", 16);		/* [4] struct s2 {	*/
53232338faSAndrii Nakryiko 	btf__add_field(btf2, "f1", 6, 0, 0);		/*      struct s1 f1;	*/
54232338faSAndrii Nakryiko 	btf__add_field(btf2, "f2", 5, 32, 0);		/*      int f2;		*/
55232338faSAndrii Nakryiko 	btf__add_field(btf2, "f3", 2, 64, 0);		/*      int *f3;	*/
56232338faSAndrii Nakryiko 							/* } */
57232338faSAndrii Nakryiko 
58232338faSAndrii Nakryiko 	/* duplicated int */
59232338faSAndrii Nakryiko 	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [5] int */
60232338faSAndrii Nakryiko 
61232338faSAndrii Nakryiko 	/* duplicated struct s1 */
62232338faSAndrii Nakryiko 	btf__add_struct(btf2, "s1", 4);			/* [6] struct s1 { */
63232338faSAndrii Nakryiko 	btf__add_field(btf2, "f1", 5, 0, 0);		/*      int f1; */
64232338faSAndrii Nakryiko 							/* } */
65232338faSAndrii Nakryiko 
66232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
67232338faSAndrii Nakryiko 		btf2,
68232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
69232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=1",
70232338faSAndrii Nakryiko 		"[3] STRUCT 's1' size=4 vlen=1\n"
71232338faSAndrii Nakryiko 		"\t'f1' type_id=1 bits_offset=0",
72232338faSAndrii Nakryiko 		"[4] STRUCT 's2' size=16 vlen=3\n"
73232338faSAndrii Nakryiko 		"\t'f1' type_id=6 bits_offset=0\n"
74232338faSAndrii Nakryiko 		"\t'f2' type_id=5 bits_offset=32\n"
75232338faSAndrii Nakryiko 		"\t'f3' type_id=2 bits_offset=64",
76232338faSAndrii Nakryiko 		"[5] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
77232338faSAndrii Nakryiko 		"[6] STRUCT 's1' size=4 vlen=1\n"
78232338faSAndrii Nakryiko 		"\t'f1' type_id=5 bits_offset=0");
79232338faSAndrii Nakryiko 
80232338faSAndrii Nakryiko 	ASSERT_STREQ(btf_type_c_dump(btf2), "\
81232338faSAndrii Nakryiko struct s1 {\n\
82232338faSAndrii Nakryiko 	int f1;\n\
83232338faSAndrii Nakryiko };\n\
84232338faSAndrii Nakryiko \n\
85232338faSAndrii Nakryiko struct s1___2 {\n\
86232338faSAndrii Nakryiko 	int f1;\n\
87232338faSAndrii Nakryiko };\n\
88232338faSAndrii Nakryiko \n\
89232338faSAndrii Nakryiko struct s2 {\n\
90232338faSAndrii Nakryiko 	struct s1___2 f1;\n\
91232338faSAndrii Nakryiko 	int f2;\n\
92232338faSAndrii Nakryiko 	int *f3;\n\
93232338faSAndrii Nakryiko };\n\n", "c_dump");
94232338faSAndrii Nakryiko 
95957d350aSAndrii Nakryiko 	err = btf__dedup(btf2, NULL);
96232338faSAndrii Nakryiko 	if (!ASSERT_OK(err, "btf_dedup"))
97232338faSAndrii Nakryiko 		goto cleanup;
98232338faSAndrii Nakryiko 
99232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
100232338faSAndrii Nakryiko 		btf2,
101232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
102232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=1",
103232338faSAndrii Nakryiko 		"[3] STRUCT 's1' size=4 vlen=1\n"
104232338faSAndrii Nakryiko 		"\t'f1' type_id=1 bits_offset=0",
105232338faSAndrii Nakryiko 		"[4] STRUCT 's2' size=16 vlen=3\n"
106232338faSAndrii Nakryiko 		"\t'f1' type_id=3 bits_offset=0\n"
107232338faSAndrii Nakryiko 		"\t'f2' type_id=1 bits_offset=32\n"
108232338faSAndrii Nakryiko 		"\t'f3' type_id=2 bits_offset=64");
109232338faSAndrii Nakryiko 
110232338faSAndrii Nakryiko 	ASSERT_STREQ(btf_type_c_dump(btf2), "\
111232338faSAndrii Nakryiko struct s1 {\n\
112232338faSAndrii Nakryiko 	int f1;\n\
113232338faSAndrii Nakryiko };\n\
114232338faSAndrii Nakryiko \n\
115232338faSAndrii Nakryiko struct s2 {\n\
116232338faSAndrii Nakryiko 	struct s1 f1;\n\
117232338faSAndrii Nakryiko 	int f2;\n\
118232338faSAndrii Nakryiko 	int *f3;\n\
119232338faSAndrii Nakryiko };\n\n", "c_dump");
120232338faSAndrii Nakryiko 
121232338faSAndrii Nakryiko cleanup:
122232338faSAndrii Nakryiko 	btf__free(btf2);
123232338faSAndrii Nakryiko 	btf__free(btf1);
124232338faSAndrii Nakryiko }
125232338faSAndrii Nakryiko 
test_split_fwd_resolve()126232338faSAndrii Nakryiko static void test_split_fwd_resolve() {
127232338faSAndrii Nakryiko 	struct btf *btf1, *btf2;
128232338faSAndrii Nakryiko 	int err;
129232338faSAndrii Nakryiko 
130232338faSAndrii Nakryiko 	btf1 = btf__new_empty();
131232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
132232338faSAndrii Nakryiko 		return;
133232338faSAndrii Nakryiko 
134232338faSAndrii Nakryiko 	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
135232338faSAndrii Nakryiko 
136232338faSAndrii Nakryiko 	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */
137232338faSAndrii Nakryiko 	btf__add_ptr(btf1, 4);				/* [2] ptr to struct s1 */
138232338faSAndrii Nakryiko 	btf__add_ptr(btf1, 5);				/* [3] ptr to struct s2 */
139232338faSAndrii Nakryiko 	btf__add_struct(btf1, "s1", 16);		/* [4] struct s1 { */
140232338faSAndrii Nakryiko 	btf__add_field(btf1, "f1", 2, 0, 0);		/*      struct s1 *f1; */
141232338faSAndrii Nakryiko 	btf__add_field(btf1, "f2", 3, 64, 0);		/*      struct s2 *f2; */
142232338faSAndrii Nakryiko 							/* } */
143232338faSAndrii Nakryiko 	btf__add_struct(btf1, "s2", 4);			/* [5] struct s2 { */
144232338faSAndrii Nakryiko 	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */
145232338faSAndrii Nakryiko 							/* } */
146*99e18fadSEduard Zingerman 	/* keep this not a part of type the graph to test btf_dedup_resolve_fwds */
147*99e18fadSEduard Zingerman 	btf__add_struct(btf1, "s3", 4);                 /* [6] struct s3 { */
148*99e18fadSEduard Zingerman 	btf__add_field(btf1, "f1", 1, 0, 0);		/*      int f1; */
149*99e18fadSEduard Zingerman 							/* } */
150232338faSAndrii Nakryiko 
151232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
152232338faSAndrii Nakryiko 		btf1,
153232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
154232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=4",
155232338faSAndrii Nakryiko 		"[3] PTR '(anon)' type_id=5",
156232338faSAndrii Nakryiko 		"[4] STRUCT 's1' size=16 vlen=2\n"
157232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
158232338faSAndrii Nakryiko 		"\t'f2' type_id=3 bits_offset=64",
159232338faSAndrii Nakryiko 		"[5] STRUCT 's2' size=4 vlen=1\n"
160*99e18fadSEduard Zingerman 		"\t'f1' type_id=1 bits_offset=0",
161*99e18fadSEduard Zingerman 		"[6] STRUCT 's3' size=4 vlen=1\n"
162232338faSAndrii Nakryiko 		"\t'f1' type_id=1 bits_offset=0");
163232338faSAndrii Nakryiko 
164232338faSAndrii Nakryiko 	btf2 = btf__new_empty_split(btf1);
165232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
166232338faSAndrii Nakryiko 		goto cleanup;
167232338faSAndrii Nakryiko 
168*99e18fadSEduard Zingerman 	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [7] int */
169*99e18fadSEduard Zingerman 	btf__add_ptr(btf2, 11);				/* [8] ptr to struct s1 */
170*99e18fadSEduard Zingerman 	btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);	/* [9] fwd for struct s2 */
171*99e18fadSEduard Zingerman 	btf__add_ptr(btf2, 9);				/* [10] ptr to fwd struct s2 */
172*99e18fadSEduard Zingerman 	btf__add_struct(btf2, "s1", 16);		/* [11] struct s1 { */
173*99e18fadSEduard Zingerman 	btf__add_field(btf2, "f1", 8, 0, 0);		/*      struct s1 *f1; */
174*99e18fadSEduard Zingerman 	btf__add_field(btf2, "f2", 10, 64, 0);		/*      struct s2 *f2; */
175232338faSAndrii Nakryiko 							/* } */
176*99e18fadSEduard Zingerman 	btf__add_fwd(btf2, "s3", BTF_FWD_STRUCT);	/* [12] fwd for struct s3 */
177*99e18fadSEduard Zingerman 	btf__add_ptr(btf2, 12);				/* [13] ptr to struct s1 */
178232338faSAndrii Nakryiko 
179232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
180232338faSAndrii Nakryiko 		btf2,
181232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
182232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=4",
183232338faSAndrii Nakryiko 		"[3] PTR '(anon)' type_id=5",
184232338faSAndrii Nakryiko 		"[4] STRUCT 's1' size=16 vlen=2\n"
185232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
186232338faSAndrii Nakryiko 		"\t'f2' type_id=3 bits_offset=64",
187232338faSAndrii Nakryiko 		"[5] STRUCT 's2' size=4 vlen=1\n"
188232338faSAndrii Nakryiko 		"\t'f1' type_id=1 bits_offset=0",
189*99e18fadSEduard Zingerman 		"[6] STRUCT 's3' size=4 vlen=1\n"
190*99e18fadSEduard Zingerman 		"\t'f1' type_id=1 bits_offset=0",
191*99e18fadSEduard Zingerman 		"[7] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
192*99e18fadSEduard Zingerman 		"[8] PTR '(anon)' type_id=11",
193*99e18fadSEduard Zingerman 		"[9] FWD 's2' fwd_kind=struct",
194*99e18fadSEduard Zingerman 		"[10] PTR '(anon)' type_id=9",
195*99e18fadSEduard Zingerman 		"[11] STRUCT 's1' size=16 vlen=2\n"
196*99e18fadSEduard Zingerman 		"\t'f1' type_id=8 bits_offset=0\n"
197*99e18fadSEduard Zingerman 		"\t'f2' type_id=10 bits_offset=64",
198*99e18fadSEduard Zingerman 		"[12] FWD 's3' fwd_kind=struct",
199*99e18fadSEduard Zingerman 		"[13] PTR '(anon)' type_id=12");
200232338faSAndrii Nakryiko 
201957d350aSAndrii Nakryiko 	err = btf__dedup(btf2, NULL);
202232338faSAndrii Nakryiko 	if (!ASSERT_OK(err, "btf_dedup"))
203232338faSAndrii Nakryiko 		goto cleanup;
204232338faSAndrii Nakryiko 
205232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
206232338faSAndrii Nakryiko 		btf2,
207232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
208232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=4",
209232338faSAndrii Nakryiko 		"[3] PTR '(anon)' type_id=5",
210232338faSAndrii Nakryiko 		"[4] STRUCT 's1' size=16 vlen=2\n"
211232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
212232338faSAndrii Nakryiko 		"\t'f2' type_id=3 bits_offset=64",
213232338faSAndrii Nakryiko 		"[5] STRUCT 's2' size=4 vlen=1\n"
214*99e18fadSEduard Zingerman 		"\t'f1' type_id=1 bits_offset=0",
215*99e18fadSEduard Zingerman 		"[6] STRUCT 's3' size=4 vlen=1\n"
216*99e18fadSEduard Zingerman 		"\t'f1' type_id=1 bits_offset=0",
217*99e18fadSEduard Zingerman 		"[7] PTR '(anon)' type_id=6");
218232338faSAndrii Nakryiko 
219232338faSAndrii Nakryiko cleanup:
220232338faSAndrii Nakryiko 	btf__free(btf2);
221232338faSAndrii Nakryiko 	btf__free(btf1);
222232338faSAndrii Nakryiko }
223232338faSAndrii Nakryiko 
test_split_struct_duped()224232338faSAndrii Nakryiko static void test_split_struct_duped() {
225232338faSAndrii Nakryiko 	struct btf *btf1, *btf2;
226232338faSAndrii Nakryiko 	int err;
227232338faSAndrii Nakryiko 
228232338faSAndrii Nakryiko 	btf1 = btf__new_empty();
229232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
230232338faSAndrii Nakryiko 		return;
231232338faSAndrii Nakryiko 
232232338faSAndrii Nakryiko 	btf__set_pointer_size(btf1, 8); /* enforce 64-bit arch */
233232338faSAndrii Nakryiko 
234232338faSAndrii Nakryiko 	btf__add_int(btf1, "int", 4, BTF_INT_SIGNED);	/* [1] int */
235232338faSAndrii Nakryiko 	btf__add_ptr(btf1, 5);				/* [2] ptr to struct s1 */
236232338faSAndrii Nakryiko 	btf__add_fwd(btf1, "s2", BTF_FWD_STRUCT);	/* [3] fwd for struct s2 */
237232338faSAndrii Nakryiko 	btf__add_ptr(btf1, 3);				/* [4] ptr to fwd struct s2 */
238232338faSAndrii Nakryiko 	btf__add_struct(btf1, "s1", 16);		/* [5] struct s1 { */
239232338faSAndrii Nakryiko 	btf__add_field(btf1, "f1", 2, 0, 0);		/*      struct s1 *f1; */
240232338faSAndrii Nakryiko 	btf__add_field(btf1, "f2", 4, 64, 0);		/*      struct s2 *f2; */
241232338faSAndrii Nakryiko 							/* } */
242232338faSAndrii Nakryiko 
243232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
244232338faSAndrii Nakryiko 		btf1,
245232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
246232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=5",
247232338faSAndrii Nakryiko 		"[3] FWD 's2' fwd_kind=struct",
248232338faSAndrii Nakryiko 		"[4] PTR '(anon)' type_id=3",
249232338faSAndrii Nakryiko 		"[5] STRUCT 's1' size=16 vlen=2\n"
250232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
251232338faSAndrii Nakryiko 		"\t'f2' type_id=4 bits_offset=64");
252232338faSAndrii Nakryiko 
253232338faSAndrii Nakryiko 	btf2 = btf__new_empty_split(btf1);
254232338faSAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
255232338faSAndrii Nakryiko 		goto cleanup;
256232338faSAndrii Nakryiko 
257232338faSAndrii Nakryiko 	btf__add_int(btf2, "int", 4, BTF_INT_SIGNED);	/* [6] int */
258232338faSAndrii Nakryiko 	btf__add_ptr(btf2, 10);				/* [7] ptr to struct s1 */
259232338faSAndrii Nakryiko 	btf__add_fwd(btf2, "s2", BTF_FWD_STRUCT);	/* [8] fwd for struct s2 */
260232338faSAndrii Nakryiko 	btf__add_ptr(btf2, 11);				/* [9] ptr to struct s2 */
261232338faSAndrii Nakryiko 	btf__add_struct(btf2, "s1", 16);		/* [10] struct s1 { */
262232338faSAndrii Nakryiko 	btf__add_field(btf2, "f1", 7, 0, 0);		/*      struct s1 *f1; */
263232338faSAndrii Nakryiko 	btf__add_field(btf2, "f2", 9, 64, 0);		/*      struct s2 *f2; */
264232338faSAndrii Nakryiko 							/* } */
265232338faSAndrii Nakryiko 	btf__add_struct(btf2, "s2", 40);		/* [11] struct s2 {	*/
266232338faSAndrii Nakryiko 	btf__add_field(btf2, "f1", 7, 0, 0);		/*      struct s1 *f1;	*/
267232338faSAndrii Nakryiko 	btf__add_field(btf2, "f2", 9, 64, 0);		/*      struct s2 *f2;	*/
268232338faSAndrii Nakryiko 	btf__add_field(btf2, "f3", 6, 128, 0);		/*      int f3;		*/
269232338faSAndrii Nakryiko 	btf__add_field(btf2, "f4", 10, 192, 0);		/*      struct s1 f4;	*/
270232338faSAndrii Nakryiko 							/* } */
271232338faSAndrii Nakryiko 	btf__add_ptr(btf2, 8);				/* [12] ptr to fwd struct s2 */
272232338faSAndrii Nakryiko 	btf__add_struct(btf2, "s3", 8);			/* [13] struct s3 { */
273232338faSAndrii Nakryiko 	btf__add_field(btf2, "f1", 12, 0, 0);		/*      struct s2 *f1; (fwd) */
274232338faSAndrii Nakryiko 							/* } */
275232338faSAndrii Nakryiko 
276232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
277232338faSAndrii Nakryiko 		btf2,
278232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
279232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=5",
280232338faSAndrii Nakryiko 		"[3] FWD 's2' fwd_kind=struct",
281232338faSAndrii Nakryiko 		"[4] PTR '(anon)' type_id=3",
282232338faSAndrii Nakryiko 		"[5] STRUCT 's1' size=16 vlen=2\n"
283232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
284232338faSAndrii Nakryiko 		"\t'f2' type_id=4 bits_offset=64",
285232338faSAndrii Nakryiko 		"[6] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
286232338faSAndrii Nakryiko 		"[7] PTR '(anon)' type_id=10",
287232338faSAndrii Nakryiko 		"[8] FWD 's2' fwd_kind=struct",
288232338faSAndrii Nakryiko 		"[9] PTR '(anon)' type_id=11",
289232338faSAndrii Nakryiko 		"[10] STRUCT 's1' size=16 vlen=2\n"
290232338faSAndrii Nakryiko 		"\t'f1' type_id=7 bits_offset=0\n"
291232338faSAndrii Nakryiko 		"\t'f2' type_id=9 bits_offset=64",
292232338faSAndrii Nakryiko 		"[11] STRUCT 's2' size=40 vlen=4\n"
293232338faSAndrii Nakryiko 		"\t'f1' type_id=7 bits_offset=0\n"
294232338faSAndrii Nakryiko 		"\t'f2' type_id=9 bits_offset=64\n"
295232338faSAndrii Nakryiko 		"\t'f3' type_id=6 bits_offset=128\n"
296232338faSAndrii Nakryiko 		"\t'f4' type_id=10 bits_offset=192",
297232338faSAndrii Nakryiko 		"[12] PTR '(anon)' type_id=8",
298232338faSAndrii Nakryiko 		"[13] STRUCT 's3' size=8 vlen=1\n"
299232338faSAndrii Nakryiko 		"\t'f1' type_id=12 bits_offset=0");
300232338faSAndrii Nakryiko 
301957d350aSAndrii Nakryiko 	err = btf__dedup(btf2, NULL);
302232338faSAndrii Nakryiko 	if (!ASSERT_OK(err, "btf_dedup"))
303232338faSAndrii Nakryiko 		goto cleanup;
304232338faSAndrii Nakryiko 
305232338faSAndrii Nakryiko 	VALIDATE_RAW_BTF(
306232338faSAndrii Nakryiko 		btf2,
307232338faSAndrii Nakryiko 		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
308232338faSAndrii Nakryiko 		"[2] PTR '(anon)' type_id=5",
309232338faSAndrii Nakryiko 		"[3] FWD 's2' fwd_kind=struct",
310232338faSAndrii Nakryiko 		"[4] PTR '(anon)' type_id=3",
311232338faSAndrii Nakryiko 		"[5] STRUCT 's1' size=16 vlen=2\n"
312232338faSAndrii Nakryiko 		"\t'f1' type_id=2 bits_offset=0\n"
313232338faSAndrii Nakryiko 		"\t'f2' type_id=4 bits_offset=64",
314232338faSAndrii Nakryiko 		"[6] PTR '(anon)' type_id=8",
315232338faSAndrii Nakryiko 		"[7] PTR '(anon)' type_id=9",
316232338faSAndrii Nakryiko 		"[8] STRUCT 's1' size=16 vlen=2\n"
317232338faSAndrii Nakryiko 		"\t'f1' type_id=6 bits_offset=0\n"
318232338faSAndrii Nakryiko 		"\t'f2' type_id=7 bits_offset=64",
319232338faSAndrii Nakryiko 		"[9] STRUCT 's2' size=40 vlen=4\n"
320232338faSAndrii Nakryiko 		"\t'f1' type_id=6 bits_offset=0\n"
321232338faSAndrii Nakryiko 		"\t'f2' type_id=7 bits_offset=64\n"
322232338faSAndrii Nakryiko 		"\t'f3' type_id=1 bits_offset=128\n"
323232338faSAndrii Nakryiko 		"\t'f4' type_id=8 bits_offset=192",
324232338faSAndrii Nakryiko 		"[10] STRUCT 's3' size=8 vlen=1\n"
325232338faSAndrii Nakryiko 		"\t'f1' type_id=7 bits_offset=0");
326232338faSAndrii Nakryiko 
327232338faSAndrii Nakryiko cleanup:
328232338faSAndrii Nakryiko 	btf__free(btf2);
329232338faSAndrii Nakryiko 	btf__free(btf1);
330232338faSAndrii Nakryiko }
331232338faSAndrii Nakryiko 
btf_add_dup_struct_in_cu(struct btf * btf,int start_id)3329a49afe6SJiri Olsa static void btf_add_dup_struct_in_cu(struct btf *btf, int start_id)
3339a49afe6SJiri Olsa {
3349a49afe6SJiri Olsa #define ID(n) (start_id + n)
3359a49afe6SJiri Olsa 	btf__set_pointer_size(btf, 8); /* enforce 64-bit arch */
3369a49afe6SJiri Olsa 
3379a49afe6SJiri Olsa 	btf__add_int(btf, "int", 4, BTF_INT_SIGNED);    /* [1] int */
3389a49afe6SJiri Olsa 
3399a49afe6SJiri Olsa 	btf__add_struct(btf, "s", 8);                   /* [2] struct s { */
3409a49afe6SJiri Olsa 	btf__add_field(btf, "a", ID(3), 0, 0);          /*      struct anon a; */
3419a49afe6SJiri Olsa 	btf__add_field(btf, "b", ID(4), 0, 0);          /*      struct anon b; */
3429a49afe6SJiri Olsa 							/* } */
3439a49afe6SJiri Olsa 
3449a49afe6SJiri Olsa 	btf__add_struct(btf, "(anon)", 8);              /* [3] struct anon { */
3459a49afe6SJiri Olsa 	btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */
3469a49afe6SJiri Olsa 	btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */
3479a49afe6SJiri Olsa 							/* } */
3489a49afe6SJiri Olsa 
3499a49afe6SJiri Olsa 	btf__add_struct(btf, "(anon)", 8);              /* [4] struct anon { */
3509a49afe6SJiri Olsa 	btf__add_field(btf, "f1", ID(1), 0, 0);         /*      int f1; */
3519a49afe6SJiri Olsa 	btf__add_field(btf, "f2", ID(1), 32, 0);        /*      int f2; */
3529a49afe6SJiri Olsa 							/* } */
3539a49afe6SJiri Olsa #undef ID
3549a49afe6SJiri Olsa }
3559a49afe6SJiri Olsa 
test_split_dup_struct_in_cu()3569a49afe6SJiri Olsa static void test_split_dup_struct_in_cu()
3579a49afe6SJiri Olsa {
358b540358eSYonghong Song 	struct btf *btf1, *btf2 = NULL;
3599a49afe6SJiri Olsa 	int err;
3609a49afe6SJiri Olsa 
3619a49afe6SJiri Olsa 	/* generate the base data.. */
3629a49afe6SJiri Olsa 	btf1 = btf__new_empty();
3639a49afe6SJiri Olsa 	if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
3649a49afe6SJiri Olsa 		return;
3659a49afe6SJiri Olsa 
3669a49afe6SJiri Olsa 	btf_add_dup_struct_in_cu(btf1, 0);
3679a49afe6SJiri Olsa 
3689a49afe6SJiri Olsa 	VALIDATE_RAW_BTF(
3699a49afe6SJiri Olsa 			btf1,
3709a49afe6SJiri Olsa 			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
3719a49afe6SJiri Olsa 			"[2] STRUCT 's' size=8 vlen=2\n"
3729a49afe6SJiri Olsa 			"\t'a' type_id=3 bits_offset=0\n"
3739a49afe6SJiri Olsa 			"\t'b' type_id=4 bits_offset=0",
3749a49afe6SJiri Olsa 			"[3] STRUCT '(anon)' size=8 vlen=2\n"
3759a49afe6SJiri Olsa 			"\t'f1' type_id=1 bits_offset=0\n"
3769a49afe6SJiri Olsa 			"\t'f2' type_id=1 bits_offset=32",
3779a49afe6SJiri Olsa 			"[4] STRUCT '(anon)' size=8 vlen=2\n"
3789a49afe6SJiri Olsa 			"\t'f1' type_id=1 bits_offset=0\n"
3799a49afe6SJiri Olsa 			"\t'f2' type_id=1 bits_offset=32");
3809a49afe6SJiri Olsa 
3819a49afe6SJiri Olsa 	/* ..dedup them... */
382045b233aSAndrii Nakryiko 	err = btf__dedup(btf1, NULL);
3839a49afe6SJiri Olsa 	if (!ASSERT_OK(err, "btf_dedup"))
3849a49afe6SJiri Olsa 		goto cleanup;
3859a49afe6SJiri Olsa 
3869a49afe6SJiri Olsa 	VALIDATE_RAW_BTF(
3879a49afe6SJiri Olsa 			btf1,
3889a49afe6SJiri Olsa 			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
3899a49afe6SJiri Olsa 			"[2] STRUCT 's' size=8 vlen=2\n"
3909a49afe6SJiri Olsa 			"\t'a' type_id=3 bits_offset=0\n"
3919a49afe6SJiri Olsa 			"\t'b' type_id=3 bits_offset=0",
3929a49afe6SJiri Olsa 			"[3] STRUCT '(anon)' size=8 vlen=2\n"
3939a49afe6SJiri Olsa 			"\t'f1' type_id=1 bits_offset=0\n"
3949a49afe6SJiri Olsa 			"\t'f2' type_id=1 bits_offset=32");
3959a49afe6SJiri Olsa 
3969a49afe6SJiri Olsa 	/* and add the same data on top of it */
3979a49afe6SJiri Olsa 	btf2 = btf__new_empty_split(btf1);
3989a49afe6SJiri Olsa 	if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
3999a49afe6SJiri Olsa 		goto cleanup;
4009a49afe6SJiri Olsa 
4019a49afe6SJiri Olsa 	btf_add_dup_struct_in_cu(btf2, 3);
4029a49afe6SJiri Olsa 
4039a49afe6SJiri Olsa 	VALIDATE_RAW_BTF(
4049a49afe6SJiri Olsa 			btf2,
4059a49afe6SJiri Olsa 			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
4069a49afe6SJiri Olsa 			"[2] STRUCT 's' size=8 vlen=2\n"
4079a49afe6SJiri Olsa 			"\t'a' type_id=3 bits_offset=0\n"
4089a49afe6SJiri Olsa 			"\t'b' type_id=3 bits_offset=0",
4099a49afe6SJiri Olsa 			"[3] STRUCT '(anon)' size=8 vlen=2\n"
4109a49afe6SJiri Olsa 			"\t'f1' type_id=1 bits_offset=0\n"
4119a49afe6SJiri Olsa 			"\t'f2' type_id=1 bits_offset=32",
4129a49afe6SJiri Olsa 			"[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
4139a49afe6SJiri Olsa 			"[5] STRUCT 's' size=8 vlen=2\n"
4149a49afe6SJiri Olsa 			"\t'a' type_id=6 bits_offset=0\n"
4159a49afe6SJiri Olsa 			"\t'b' type_id=7 bits_offset=0",
4169a49afe6SJiri Olsa 			"[6] STRUCT '(anon)' size=8 vlen=2\n"
4179a49afe6SJiri Olsa 			"\t'f1' type_id=4 bits_offset=0\n"
4189a49afe6SJiri Olsa 			"\t'f2' type_id=4 bits_offset=32",
4199a49afe6SJiri Olsa 			"[7] STRUCT '(anon)' size=8 vlen=2\n"
4209a49afe6SJiri Olsa 			"\t'f1' type_id=4 bits_offset=0\n"
4219a49afe6SJiri Olsa 			"\t'f2' type_id=4 bits_offset=32");
4229a49afe6SJiri Olsa 
423045b233aSAndrii Nakryiko 	err = btf__dedup(btf2, NULL);
4249a49afe6SJiri Olsa 	if (!ASSERT_OK(err, "btf_dedup"))
4259a49afe6SJiri Olsa 		goto cleanup;
4269a49afe6SJiri Olsa 
4279a49afe6SJiri Olsa 	/* after dedup it should match the original data */
4289a49afe6SJiri Olsa 	VALIDATE_RAW_BTF(
4299a49afe6SJiri Olsa 			btf2,
4309a49afe6SJiri Olsa 			"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
4319a49afe6SJiri Olsa 			"[2] STRUCT 's' size=8 vlen=2\n"
4329a49afe6SJiri Olsa 			"\t'a' type_id=3 bits_offset=0\n"
4339a49afe6SJiri Olsa 			"\t'b' type_id=3 bits_offset=0",
4349a49afe6SJiri Olsa 			"[3] STRUCT '(anon)' size=8 vlen=2\n"
4359a49afe6SJiri Olsa 			"\t'f1' type_id=1 bits_offset=0\n"
4369a49afe6SJiri Olsa 			"\t'f2' type_id=1 bits_offset=32");
4379a49afe6SJiri Olsa 
4389a49afe6SJiri Olsa cleanup:
4399a49afe6SJiri Olsa 	btf__free(btf2);
4409a49afe6SJiri Olsa 	btf__free(btf1);
4419a49afe6SJiri Olsa }
4429a49afe6SJiri Olsa 
test_btf_dedup_split()443232338faSAndrii Nakryiko void test_btf_dedup_split()
444232338faSAndrii Nakryiko {
445232338faSAndrii Nakryiko 	if (test__start_subtest("split_simple"))
446232338faSAndrii Nakryiko 		test_split_simple();
447232338faSAndrii Nakryiko 	if (test__start_subtest("split_struct_duped"))
448232338faSAndrii Nakryiko 		test_split_struct_duped();
449232338faSAndrii Nakryiko 	if (test__start_subtest("split_fwd_resolve"))
450232338faSAndrii Nakryiko 		test_split_fwd_resolve();
4519a49afe6SJiri Olsa 	if (test__start_subtest("split_dup_struct_in_cu"))
4529a49afe6SJiri Olsa 		test_split_dup_struct_in_cu();
453232338faSAndrii Nakryiko }
454