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}