Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  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, 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
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
204cleanup:
205	btf__free(btf2);
206	btf__free(btf1);
207}
208
209static 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
312cleanup:
313	btf__free(btf2);
314	btf__free(btf1);
315}
316
317void 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}