Loading...
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2024, Oracle and/or its affiliates. */
3
4#include <test_progs.h>
5#include <bpf/btf.h>
6#include "btf_helpers.h"
7
8/* Fabricate base, split BTF with references to base types needed; then create
9 * split BTF with distilled base BTF and ensure expectations are met:
10 * - only referenced base types from split BTF are present
11 * - struct/union/enum are represented as empty unless anonymous, when they
12 * are represented in full in split BTF
13 */
14static void test_distilled_base(void)
15{
16 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
17
18 btf1 = btf__new_empty();
19 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
20 return;
21
22 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
23 btf__add_ptr(btf1, 1); /* [2] ptr to int */
24 btf__add_struct(btf1, "s1", 8); /* [3] struct s1 { */
25 btf__add_field(btf1, "f1", 2, 0, 0); /* int *f1; */
26 /* } */
27 btf__add_struct(btf1, "", 12); /* [4] struct { */
28 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
29 btf__add_field(btf1, "f2", 3, 32, 0); /* struct s1 f2; */
30 /* } */
31 btf__add_int(btf1, "unsigned int", 4, 0); /* [5] unsigned int */
32 btf__add_union(btf1, "u1", 12); /* [6] union u1 { */
33 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
34 btf__add_field(btf1, "f2", 2, 0, 0); /* int *f2; */
35 /* } */
36 btf__add_union(btf1, "", 4); /* [7] union { */
37 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
38 /* } */
39 btf__add_enum(btf1, "e1", 4); /* [8] enum e1 { */
40 btf__add_enum_value(btf1, "v1", 1); /* v1 = 1; */
41 /* } */
42 btf__add_enum(btf1, "", 4); /* [9] enum { */
43 btf__add_enum_value(btf1, "av1", 2); /* av1 = 2; */
44 /* } */
45 btf__add_enum64(btf1, "e641", 8, true); /* [10] enum64 { */
46 btf__add_enum64_value(btf1, "v1", 1024); /* v1 = 1024; */
47 /* } */
48 btf__add_enum64(btf1, "", 8, true); /* [11] enum64 { */
49 btf__add_enum64_value(btf1, "v1", 1025); /* v1 = 1025; */
50 /* } */
51 btf__add_struct(btf1, "unneeded", 4); /* [12] struct unneeded { */
52 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
53 /* } */
54 btf__add_struct(btf1, "embedded", 4); /* [13] struct embedded { */
55 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
56 /* } */
57 btf__add_func_proto(btf1, 1); /* [14] int (*)(int *p1); */
58 btf__add_func_param(btf1, "p1", 1);
59
60 btf__add_array(btf1, 1, 1, 3); /* [15] int [3]; */
61
62 btf__add_struct(btf1, "from_proto", 4); /* [16] struct from_proto { */
63 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
64 /* } */
65 btf__add_union(btf1, "u1", 4); /* [17] union u1 { */
66 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
67 /* } */
68 VALIDATE_RAW_BTF(
69 btf1,
70 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
71 "[2] PTR '(anon)' type_id=1",
72 "[3] STRUCT 's1' size=8 vlen=1\n"
73 "\t'f1' type_id=2 bits_offset=0",
74 "[4] STRUCT '(anon)' size=12 vlen=2\n"
75 "\t'f1' type_id=1 bits_offset=0\n"
76 "\t'f2' type_id=3 bits_offset=32",
77 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
78 "[6] UNION 'u1' size=12 vlen=2\n"
79 "\t'f1' type_id=1 bits_offset=0\n"
80 "\t'f2' type_id=2 bits_offset=0",
81 "[7] UNION '(anon)' size=4 vlen=1\n"
82 "\t'f1' type_id=1 bits_offset=0",
83 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
84 "\t'v1' val=1",
85 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
86 "\t'av1' val=2",
87 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
88 "\t'v1' val=1024",
89 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
90 "\t'v1' val=1025",
91 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
92 "\t'f1' type_id=1 bits_offset=0",
93 "[13] STRUCT 'embedded' size=4 vlen=1\n"
94 "\t'f1' type_id=1 bits_offset=0",
95 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
96 "\t'p1' type_id=1",
97 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
98 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
99 "\t'f1' type_id=1 bits_offset=0",
100 "[17] UNION 'u1' size=4 vlen=1\n"
101 "\t'f1' type_id=1 bits_offset=0");
102
103 btf2 = btf__new_empty_split(btf1);
104 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
105 goto cleanup;
106
107 btf__add_ptr(btf2, 3); /* [18] ptr to struct s1 */
108 /* add ptr to struct anon */
109 btf__add_ptr(btf2, 4); /* [19] ptr to struct (anon) */
110 btf__add_const(btf2, 6); /* [20] const union u1 */
111 btf__add_restrict(btf2, 7); /* [21] restrict union (anon) */
112 btf__add_volatile(btf2, 8); /* [22] volatile enum e1 */
113 btf__add_typedef(btf2, "et", 9); /* [23] typedef enum (anon) */
114 btf__add_const(btf2, 10); /* [24] const enum64 e641 */
115 btf__add_ptr(btf2, 11); /* [25] restrict enum64 (anon) */
116 btf__add_struct(btf2, "with_embedded", 4); /* [26] struct with_embedded { */
117 btf__add_field(btf2, "f1", 13, 0, 0); /* struct embedded f1; */
118 /* } */
119 btf__add_func(btf2, "fn", BTF_FUNC_STATIC, 14); /* [27] int fn(int p1); */
120 btf__add_typedef(btf2, "arraytype", 15); /* [28] typedef int[3] foo; */
121 btf__add_func_proto(btf2, 1); /* [29] int (*)(struct from proto p1); */
122 btf__add_func_param(btf2, "p1", 16);
123
124 VALIDATE_RAW_BTF(
125 btf2,
126 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
127 "[2] PTR '(anon)' type_id=1",
128 "[3] STRUCT 's1' size=8 vlen=1\n"
129 "\t'f1' type_id=2 bits_offset=0",
130 "[4] STRUCT '(anon)' size=12 vlen=2\n"
131 "\t'f1' type_id=1 bits_offset=0\n"
132 "\t'f2' type_id=3 bits_offset=32",
133 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
134 "[6] UNION 'u1' size=12 vlen=2\n"
135 "\t'f1' type_id=1 bits_offset=0\n"
136 "\t'f2' type_id=2 bits_offset=0",
137 "[7] UNION '(anon)' size=4 vlen=1\n"
138 "\t'f1' type_id=1 bits_offset=0",
139 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
140 "\t'v1' val=1",
141 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
142 "\t'av1' val=2",
143 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
144 "\t'v1' val=1024",
145 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
146 "\t'v1' val=1025",
147 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
148 "\t'f1' type_id=1 bits_offset=0",
149 "[13] STRUCT 'embedded' size=4 vlen=1\n"
150 "\t'f1' type_id=1 bits_offset=0",
151 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
152 "\t'p1' type_id=1",
153 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
154 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
155 "\t'f1' type_id=1 bits_offset=0",
156 "[17] UNION 'u1' size=4 vlen=1\n"
157 "\t'f1' type_id=1 bits_offset=0",
158 "[18] PTR '(anon)' type_id=3",
159 "[19] PTR '(anon)' type_id=4",
160 "[20] CONST '(anon)' type_id=6",
161 "[21] RESTRICT '(anon)' type_id=7",
162 "[22] VOLATILE '(anon)' type_id=8",
163 "[23] TYPEDEF 'et' type_id=9",
164 "[24] CONST '(anon)' type_id=10",
165 "[25] PTR '(anon)' type_id=11",
166 "[26] STRUCT 'with_embedded' size=4 vlen=1\n"
167 "\t'f1' type_id=13 bits_offset=0",
168 "[27] FUNC 'fn' type_id=14 linkage=static",
169 "[28] TYPEDEF 'arraytype' type_id=15",
170 "[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
171 "\t'p1' type_id=16");
172
173 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
174 "distilled_base") ||
175 !ASSERT_OK_PTR(btf3, "distilled_base") ||
176 !ASSERT_OK_PTR(btf4, "distilled_split") ||
177 !ASSERT_EQ(8, btf__type_cnt(btf3), "distilled_base_type_cnt"))
178 goto cleanup;
179
180 VALIDATE_RAW_BTF(
181 btf4,
182 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
183 "[2] STRUCT 's1' size=8 vlen=0",
184 "[3] UNION 'u1' size=12 vlen=0",
185 "[4] ENUM 'e1' encoding=UNSIGNED size=4 vlen=0",
186 "[5] ENUM 'e641' encoding=UNSIGNED size=8 vlen=0",
187 "[6] STRUCT 'embedded' size=4 vlen=0",
188 "[7] STRUCT 'from_proto' size=4 vlen=0",
189 /* split BTF; these types should match split BTF above from 17-28, with
190 * updated type id references
191 */
192 "[8] PTR '(anon)' type_id=2",
193 "[9] PTR '(anon)' type_id=20",
194 "[10] CONST '(anon)' type_id=3",
195 "[11] RESTRICT '(anon)' type_id=21",
196 "[12] VOLATILE '(anon)' type_id=4",
197 "[13] TYPEDEF 'et' type_id=22",
198 "[14] CONST '(anon)' type_id=5",
199 "[15] PTR '(anon)' type_id=23",
200 "[16] STRUCT 'with_embedded' size=4 vlen=1\n"
201 "\t'f1' type_id=6 bits_offset=0",
202 "[17] FUNC 'fn' type_id=24 linkage=static",
203 "[18] TYPEDEF 'arraytype' type_id=25",
204 "[19] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
205 "\t'p1' type_id=7",
206 /* split BTF types added from original base BTF below */
207 "[20] STRUCT '(anon)' size=12 vlen=2\n"
208 "\t'f1' type_id=1 bits_offset=0\n"
209 "\t'f2' type_id=2 bits_offset=32",
210 "[21] UNION '(anon)' size=4 vlen=1\n"
211 "\t'f1' type_id=1 bits_offset=0",
212 "[22] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
213 "\t'av1' val=2",
214 "[23] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
215 "\t'v1' val=1025",
216 "[24] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
217 "\t'p1' type_id=1",
218 "[25] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");
219
220 if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))
221 goto cleanup;
222
223 VALIDATE_RAW_BTF(
224 btf4,
225 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
226 "[2] PTR '(anon)' type_id=1",
227 "[3] STRUCT 's1' size=8 vlen=1\n"
228 "\t'f1' type_id=2 bits_offset=0",
229 "[4] STRUCT '(anon)' size=12 vlen=2\n"
230 "\t'f1' type_id=1 bits_offset=0\n"
231 "\t'f2' type_id=3 bits_offset=32",
232 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
233 "[6] UNION 'u1' size=12 vlen=2\n"
234 "\t'f1' type_id=1 bits_offset=0\n"
235 "\t'f2' type_id=2 bits_offset=0",
236 "[7] UNION '(anon)' size=4 vlen=1\n"
237 "\t'f1' type_id=1 bits_offset=0",
238 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
239 "\t'v1' val=1",
240 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
241 "\t'av1' val=2",
242 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
243 "\t'v1' val=1024",
244 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
245 "\t'v1' val=1025",
246 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
247 "\t'f1' type_id=1 bits_offset=0",
248 "[13] STRUCT 'embedded' size=4 vlen=1\n"
249 "\t'f1' type_id=1 bits_offset=0",
250 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
251 "\t'p1' type_id=1",
252 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
253 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
254 "\t'f1' type_id=1 bits_offset=0",
255 "[17] UNION 'u1' size=4 vlen=1\n"
256 "\t'f1' type_id=1 bits_offset=0",
257 "[18] PTR '(anon)' type_id=3",
258 "[19] PTR '(anon)' type_id=30",
259 "[20] CONST '(anon)' type_id=6",
260 "[21] RESTRICT '(anon)' type_id=31",
261 "[22] VOLATILE '(anon)' type_id=8",
262 "[23] TYPEDEF 'et' type_id=32",
263 "[24] CONST '(anon)' type_id=10",
264 "[25] PTR '(anon)' type_id=33",
265 "[26] STRUCT 'with_embedded' size=4 vlen=1\n"
266 "\t'f1' type_id=13 bits_offset=0",
267 "[27] FUNC 'fn' type_id=34 linkage=static",
268 "[28] TYPEDEF 'arraytype' type_id=35",
269 "[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
270 "\t'p1' type_id=16",
271 /* below here are (duplicate) anon base types added by distill
272 * process to split BTF.
273 */
274 "[30] STRUCT '(anon)' size=12 vlen=2\n"
275 "\t'f1' type_id=1 bits_offset=0\n"
276 "\t'f2' type_id=3 bits_offset=32",
277 "[31] UNION '(anon)' size=4 vlen=1\n"
278 "\t'f1' type_id=1 bits_offset=0",
279 "[32] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
280 "\t'av1' val=2",
281 "[33] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
282 "\t'v1' val=1025",
283 "[34] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
284 "\t'p1' type_id=1",
285 "[35] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");
286
287cleanup:
288 btf__free(btf4);
289 btf__free(btf3);
290 btf__free(btf2);
291 btf__free(btf1);
292}
293
294/* ensure we can cope with multiple types with the same name in
295 * distilled base BTF. In this case because sizes are different,
296 * we can still disambiguate them.
297 */
298static void test_distilled_base_multi(void)
299{
300 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
301
302 btf1 = btf__new_empty();
303 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
304 return;
305 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
306 btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
307 VALIDATE_RAW_BTF(
308 btf1,
309 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
310 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
311 btf2 = btf__new_empty_split(btf1);
312 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
313 goto cleanup;
314 btf__add_ptr(btf2, 1);
315 btf__add_const(btf2, 2);
316 VALIDATE_RAW_BTF(
317 btf2,
318 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
319 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
320 "[3] PTR '(anon)' type_id=1",
321 "[4] CONST '(anon)' type_id=2");
322 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
323 "distilled_base") ||
324 !ASSERT_OK_PTR(btf3, "distilled_base") ||
325 !ASSERT_OK_PTR(btf4, "distilled_split") ||
326 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
327 goto cleanup;
328 VALIDATE_RAW_BTF(
329 btf3,
330 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
331 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
332 if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))
333 goto cleanup;
334
335 VALIDATE_RAW_BTF(
336 btf4,
337 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
338 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
339 "[3] PTR '(anon)' type_id=1",
340 "[4] CONST '(anon)' type_id=2");
341
342cleanup:
343 btf__free(btf4);
344 btf__free(btf3);
345 btf__free(btf2);
346 btf__free(btf1);
347}
348
349/* If a needed type is not present in the base BTF we wish to relocate
350 * with, btf__relocate() should error our.
351 */
352static void test_distilled_base_missing_err(void)
353{
354 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
355
356 btf1 = btf__new_empty();
357 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
358 return;
359 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
360 btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
361 VALIDATE_RAW_BTF(
362 btf1,
363 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
364 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
365 btf2 = btf__new_empty_split(btf1);
366 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
367 goto cleanup;
368 btf__add_ptr(btf2, 1);
369 btf__add_const(btf2, 2);
370 VALIDATE_RAW_BTF(
371 btf2,
372 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
373 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
374 "[3] PTR '(anon)' type_id=1",
375 "[4] CONST '(anon)' type_id=2");
376 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
377 "distilled_base") ||
378 !ASSERT_OK_PTR(btf3, "distilled_base") ||
379 !ASSERT_OK_PTR(btf4, "distilled_split") ||
380 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
381 goto cleanup;
382 VALIDATE_RAW_BTF(
383 btf3,
384 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
385 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
386 btf5 = btf__new_empty();
387 if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))
388 goto cleanup;
389 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
390 VALIDATE_RAW_BTF(
391 btf5,
392 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
393 ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
394
395cleanup:
396 btf__free(btf5);
397 btf__free(btf4);
398 btf__free(btf3);
399 btf__free(btf2);
400 btf__free(btf1);
401}
402
403/* With 2 types of same size in distilled base BTF, relocation should
404 * fail as we have no means to choose between them.
405 */
406static void test_distilled_base_multi_err(void)
407{
408 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
409
410 btf1 = btf__new_empty();
411 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
412 return;
413 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
414 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [2] int */
415 VALIDATE_RAW_BTF(
416 btf1,
417 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
418 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
419 btf2 = btf__new_empty_split(btf1);
420 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
421 goto cleanup;
422 btf__add_ptr(btf2, 1);
423 btf__add_const(btf2, 2);
424 VALIDATE_RAW_BTF(
425 btf2,
426 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
427 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
428 "[3] PTR '(anon)' type_id=1",
429 "[4] CONST '(anon)' type_id=2");
430 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
431 "distilled_base") ||
432 !ASSERT_OK_PTR(btf3, "distilled_base") ||
433 !ASSERT_OK_PTR(btf4, "distilled_split") ||
434 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
435 goto cleanup;
436 VALIDATE_RAW_BTF(
437 btf3,
438 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
439 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
440 ASSERT_EQ(btf__relocate(btf4, btf1), -EINVAL, "relocate_split");
441cleanup:
442 btf__free(btf4);
443 btf__free(btf3);
444 btf__free(btf2);
445 btf__free(btf1);
446}
447
448/* With 2 types of same size in base BTF, relocation should
449 * fail as we have no means to choose between them.
450 */
451static void test_distilled_base_multi_err2(void)
452{
453 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
454
455 btf1 = btf__new_empty();
456 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
457 return;
458 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
459 VALIDATE_RAW_BTF(
460 btf1,
461 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
462 btf2 = btf__new_empty_split(btf1);
463 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
464 goto cleanup;
465 btf__add_ptr(btf2, 1);
466 VALIDATE_RAW_BTF(
467 btf2,
468 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
469 "[2] PTR '(anon)' type_id=1");
470 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
471 "distilled_base") ||
472 !ASSERT_OK_PTR(btf3, "distilled_base") ||
473 !ASSERT_OK_PTR(btf4, "distilled_split") ||
474 !ASSERT_EQ(2, btf__type_cnt(btf3), "distilled_base_type_cnt"))
475 goto cleanup;
476 VALIDATE_RAW_BTF(
477 btf3,
478 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
479 btf5 = btf__new_empty();
480 if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))
481 goto cleanup;
482 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
483 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [2] int */
484 VALIDATE_RAW_BTF(
485 btf5,
486 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
487 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
488 ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
489cleanup:
490 btf__free(btf5);
491 btf__free(btf4);
492 btf__free(btf3);
493 btf__free(btf2);
494 btf__free(btf1);
495}
496
497/* create split reference BTF from vmlinux + split BTF with a few type references;
498 * ensure the resultant split reference BTF is as expected, containing only types
499 * needed to disambiguate references from split BTF.
500 */
501static void test_distilled_base_vmlinux(void)
502{
503 struct btf *split_btf = NULL, *vmlinux_btf = btf__load_vmlinux_btf();
504 struct btf *split_dist = NULL, *base_dist = NULL;
505 __s32 int_id, myint_id;
506
507 if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux"))
508 return;
509 int_id = btf__find_by_name_kind(vmlinux_btf, "int", BTF_KIND_INT);
510 if (!ASSERT_GT(int_id, 0, "find_int"))
511 goto cleanup;
512 split_btf = btf__new_empty_split(vmlinux_btf);
513 if (!ASSERT_OK_PTR(split_btf, "new_split"))
514 goto cleanup;
515 myint_id = btf__add_typedef(split_btf, "myint", int_id);
516 btf__add_ptr(split_btf, myint_id);
517
518 if (!ASSERT_EQ(btf__distill_base(split_btf, &base_dist, &split_dist), 0,
519 "distill_vmlinux_base"))
520 goto cleanup;
521
522 if (!ASSERT_OK_PTR(split_dist, "split_distilled") ||
523 !ASSERT_OK_PTR(base_dist, "base_dist"))
524 goto cleanup;
525 VALIDATE_RAW_BTF(
526 split_dist,
527 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
528 "[2] TYPEDEF 'myint' type_id=1",
529 "[3] PTR '(anon)' type_id=2");
530
531cleanup:
532 btf__free(split_dist);
533 btf__free(base_dist);
534 btf__free(split_btf);
535 btf__free(vmlinux_btf);
536}
537
538/* Split and new base BTFs should inherit endianness from source BTF. */
539static void test_distilled_endianness(void)
540{
541 struct btf *base = NULL, *split = NULL, *new_base = NULL, *new_split = NULL;
542 struct btf *new_base1 = NULL, *new_split1 = NULL;
543 enum btf_endianness inverse_endianness;
544 const void *raw_data;
545 __u32 size;
546
547 base = btf__new_empty();
548 if (!ASSERT_OK_PTR(base, "empty_main_btf"))
549 return;
550 inverse_endianness = btf__endianness(base) == BTF_LITTLE_ENDIAN ? BTF_BIG_ENDIAN
551 : BTF_LITTLE_ENDIAN;
552 btf__set_endianness(base, inverse_endianness);
553 btf__add_int(base, "int", 4, BTF_INT_SIGNED); /* [1] int */
554 VALIDATE_RAW_BTF(
555 base,
556 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
557 split = btf__new_empty_split(base);
558 if (!ASSERT_OK_PTR(split, "empty_split_btf"))
559 goto cleanup;
560 btf__add_ptr(split, 1);
561 VALIDATE_RAW_BTF(
562 split,
563 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
564 "[2] PTR '(anon)' type_id=1");
565 if (!ASSERT_EQ(0, btf__distill_base(split, &new_base, &new_split),
566 "distilled_base") ||
567 !ASSERT_OK_PTR(new_base, "distilled_base") ||
568 !ASSERT_OK_PTR(new_split, "distilled_split") ||
569 !ASSERT_EQ(2, btf__type_cnt(new_base), "distilled_base_type_cnt"))
570 goto cleanup;
571 VALIDATE_RAW_BTF(
572 new_split,
573 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
574 "[2] PTR '(anon)' type_id=1");
575
576 raw_data = btf__raw_data(new_base, &size);
577 if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #1"))
578 goto cleanup;
579 new_base1 = btf__new(raw_data, size);
580 if (!ASSERT_OK_PTR(new_base1, "new_base1 = btf__new()"))
581 goto cleanup;
582 raw_data = btf__raw_data(new_split, &size);
583 if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #2"))
584 goto cleanup;
585 new_split1 = btf__new_split(raw_data, size, new_base1);
586 if (!ASSERT_OK_PTR(new_split1, "new_split1 = btf__new()"))
587 goto cleanup;
588
589 ASSERT_EQ(btf__endianness(new_base1), inverse_endianness, "new_base1 endianness");
590 ASSERT_EQ(btf__endianness(new_split1), inverse_endianness, "new_split1 endianness");
591 VALIDATE_RAW_BTF(
592 new_split1,
593 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
594 "[2] PTR '(anon)' type_id=1");
595cleanup:
596 btf__free(new_split1);
597 btf__free(new_base1);
598 btf__free(new_split);
599 btf__free(new_base);
600 btf__free(split);
601 btf__free(base);
602}
603
604void test_btf_distill(void)
605{
606 if (test__start_subtest("distilled_base"))
607 test_distilled_base();
608 if (test__start_subtest("distilled_base_multi"))
609 test_distilled_base_multi();
610 if (test__start_subtest("distilled_base_missing_err"))
611 test_distilled_base_missing_err();
612 if (test__start_subtest("distilled_base_multi_err"))
613 test_distilled_base_multi_err();
614 if (test__start_subtest("distilled_base_multi_err2"))
615 test_distilled_base_multi_err2();
616 if (test__start_subtest("distilled_base_vmlinux"))
617 test_distilled_base_vmlinux();
618 if (test__start_subtest("distilled_endianness"))
619 test_distilled_endianness();
620}
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2024, Oracle and/or its affiliates. */
3
4#include <test_progs.h>
5#include <bpf/btf.h>
6#include "btf_helpers.h"
7
8/* Fabricate base, split BTF with references to base types needed; then create
9 * split BTF with distilled base BTF and ensure expectations are met:
10 * - only referenced base types from split BTF are present
11 * - struct/union/enum are represented as empty unless anonymous, when they
12 * are represented in full in split BTF
13 */
14static void test_distilled_base(void)
15{
16 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
17
18 btf1 = btf__new_empty();
19 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
20 return;
21
22 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
23 btf__add_ptr(btf1, 1); /* [2] ptr to int */
24 btf__add_struct(btf1, "s1", 8); /* [3] struct s1 { */
25 btf__add_field(btf1, "f1", 2, 0, 0); /* int *f1; */
26 /* } */
27 btf__add_struct(btf1, "", 12); /* [4] struct { */
28 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
29 btf__add_field(btf1, "f2", 3, 32, 0); /* struct s1 f2; */
30 /* } */
31 btf__add_int(btf1, "unsigned int", 4, 0); /* [5] unsigned int */
32 btf__add_union(btf1, "u1", 12); /* [6] union u1 { */
33 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
34 btf__add_field(btf1, "f2", 2, 0, 0); /* int *f2; */
35 /* } */
36 btf__add_union(btf1, "", 4); /* [7] union { */
37 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
38 /* } */
39 btf__add_enum(btf1, "e1", 4); /* [8] enum e1 { */
40 btf__add_enum_value(btf1, "v1", 1); /* v1 = 1; */
41 /* } */
42 btf__add_enum(btf1, "", 4); /* [9] enum { */
43 btf__add_enum_value(btf1, "av1", 2); /* av1 = 2; */
44 /* } */
45 btf__add_enum64(btf1, "e641", 8, true); /* [10] enum64 { */
46 btf__add_enum64_value(btf1, "v1", 1024); /* v1 = 1024; */
47 /* } */
48 btf__add_enum64(btf1, "", 8, true); /* [11] enum64 { */
49 btf__add_enum64_value(btf1, "v1", 1025); /* v1 = 1025; */
50 /* } */
51 btf__add_struct(btf1, "unneeded", 4); /* [12] struct unneeded { */
52 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
53 /* } */
54 btf__add_struct(btf1, "embedded", 4); /* [13] struct embedded { */
55 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
56 /* } */
57 btf__add_func_proto(btf1, 1); /* [14] int (*)(int *p1); */
58 btf__add_func_param(btf1, "p1", 1);
59
60 btf__add_array(btf1, 1, 1, 3); /* [15] int [3]; */
61
62 btf__add_struct(btf1, "from_proto", 4); /* [16] struct from_proto { */
63 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
64 /* } */
65 btf__add_union(btf1, "u1", 4); /* [17] union u1 { */
66 btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
67 /* } */
68 VALIDATE_RAW_BTF(
69 btf1,
70 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
71 "[2] PTR '(anon)' type_id=1",
72 "[3] STRUCT 's1' size=8 vlen=1\n"
73 "\t'f1' type_id=2 bits_offset=0",
74 "[4] STRUCT '(anon)' size=12 vlen=2\n"
75 "\t'f1' type_id=1 bits_offset=0\n"
76 "\t'f2' type_id=3 bits_offset=32",
77 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
78 "[6] UNION 'u1' size=12 vlen=2\n"
79 "\t'f1' type_id=1 bits_offset=0\n"
80 "\t'f2' type_id=2 bits_offset=0",
81 "[7] UNION '(anon)' size=4 vlen=1\n"
82 "\t'f1' type_id=1 bits_offset=0",
83 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
84 "\t'v1' val=1",
85 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
86 "\t'av1' val=2",
87 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
88 "\t'v1' val=1024",
89 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
90 "\t'v1' val=1025",
91 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
92 "\t'f1' type_id=1 bits_offset=0",
93 "[13] STRUCT 'embedded' size=4 vlen=1\n"
94 "\t'f1' type_id=1 bits_offset=0",
95 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
96 "\t'p1' type_id=1",
97 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
98 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
99 "\t'f1' type_id=1 bits_offset=0",
100 "[17] UNION 'u1' size=4 vlen=1\n"
101 "\t'f1' type_id=1 bits_offset=0");
102
103 btf2 = btf__new_empty_split(btf1);
104 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
105 goto cleanup;
106
107 btf__add_ptr(btf2, 3); /* [18] ptr to struct s1 */
108 /* add ptr to struct anon */
109 btf__add_ptr(btf2, 4); /* [19] ptr to struct (anon) */
110 btf__add_const(btf2, 6); /* [20] const union u1 */
111 btf__add_restrict(btf2, 7); /* [21] restrict union (anon) */
112 btf__add_volatile(btf2, 8); /* [22] volatile enum e1 */
113 btf__add_typedef(btf2, "et", 9); /* [23] typedef enum (anon) */
114 btf__add_const(btf2, 10); /* [24] const enum64 e641 */
115 btf__add_ptr(btf2, 11); /* [25] restrict enum64 (anon) */
116 btf__add_struct(btf2, "with_embedded", 4); /* [26] struct with_embedded { */
117 btf__add_field(btf2, "f1", 13, 0, 0); /* struct embedded f1; */
118 /* } */
119 btf__add_func(btf2, "fn", BTF_FUNC_STATIC, 14); /* [27] int fn(int p1); */
120 btf__add_typedef(btf2, "arraytype", 15); /* [28] typedef int[3] foo; */
121 btf__add_func_proto(btf2, 1); /* [29] int (*)(struct from proto p1); */
122 btf__add_func_param(btf2, "p1", 16);
123
124 VALIDATE_RAW_BTF(
125 btf2,
126 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
127 "[2] PTR '(anon)' type_id=1",
128 "[3] STRUCT 's1' size=8 vlen=1\n"
129 "\t'f1' type_id=2 bits_offset=0",
130 "[4] STRUCT '(anon)' size=12 vlen=2\n"
131 "\t'f1' type_id=1 bits_offset=0\n"
132 "\t'f2' type_id=3 bits_offset=32",
133 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
134 "[6] UNION 'u1' size=12 vlen=2\n"
135 "\t'f1' type_id=1 bits_offset=0\n"
136 "\t'f2' type_id=2 bits_offset=0",
137 "[7] UNION '(anon)' size=4 vlen=1\n"
138 "\t'f1' type_id=1 bits_offset=0",
139 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
140 "\t'v1' val=1",
141 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
142 "\t'av1' val=2",
143 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
144 "\t'v1' val=1024",
145 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
146 "\t'v1' val=1025",
147 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
148 "\t'f1' type_id=1 bits_offset=0",
149 "[13] STRUCT 'embedded' size=4 vlen=1\n"
150 "\t'f1' type_id=1 bits_offset=0",
151 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
152 "\t'p1' type_id=1",
153 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
154 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
155 "\t'f1' type_id=1 bits_offset=0",
156 "[17] UNION 'u1' size=4 vlen=1\n"
157 "\t'f1' type_id=1 bits_offset=0",
158 "[18] PTR '(anon)' type_id=3",
159 "[19] PTR '(anon)' type_id=4",
160 "[20] CONST '(anon)' type_id=6",
161 "[21] RESTRICT '(anon)' type_id=7",
162 "[22] VOLATILE '(anon)' type_id=8",
163 "[23] TYPEDEF 'et' type_id=9",
164 "[24] CONST '(anon)' type_id=10",
165 "[25] PTR '(anon)' type_id=11",
166 "[26] STRUCT 'with_embedded' size=4 vlen=1\n"
167 "\t'f1' type_id=13 bits_offset=0",
168 "[27] FUNC 'fn' type_id=14 linkage=static",
169 "[28] TYPEDEF 'arraytype' type_id=15",
170 "[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
171 "\t'p1' type_id=16");
172
173 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
174 "distilled_base") ||
175 !ASSERT_OK_PTR(btf3, "distilled_base") ||
176 !ASSERT_OK_PTR(btf4, "distilled_split") ||
177 !ASSERT_EQ(8, btf__type_cnt(btf3), "distilled_base_type_cnt"))
178 goto cleanup;
179
180 VALIDATE_RAW_BTF(
181 btf4,
182 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
183 "[2] STRUCT 's1' size=8 vlen=0",
184 "[3] UNION 'u1' size=12 vlen=0",
185 "[4] ENUM 'e1' encoding=UNSIGNED size=4 vlen=0",
186 "[5] ENUM 'e641' encoding=UNSIGNED size=8 vlen=0",
187 "[6] STRUCT 'embedded' size=4 vlen=0",
188 "[7] STRUCT 'from_proto' size=4 vlen=0",
189 /* split BTF; these types should match split BTF above from 17-28, with
190 * updated type id references
191 */
192 "[8] PTR '(anon)' type_id=2",
193 "[9] PTR '(anon)' type_id=20",
194 "[10] CONST '(anon)' type_id=3",
195 "[11] RESTRICT '(anon)' type_id=21",
196 "[12] VOLATILE '(anon)' type_id=4",
197 "[13] TYPEDEF 'et' type_id=22",
198 "[14] CONST '(anon)' type_id=5",
199 "[15] PTR '(anon)' type_id=23",
200 "[16] STRUCT 'with_embedded' size=4 vlen=1\n"
201 "\t'f1' type_id=6 bits_offset=0",
202 "[17] FUNC 'fn' type_id=24 linkage=static",
203 "[18] TYPEDEF 'arraytype' type_id=25",
204 "[19] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
205 "\t'p1' type_id=7",
206 /* split BTF types added from original base BTF below */
207 "[20] STRUCT '(anon)' size=12 vlen=2\n"
208 "\t'f1' type_id=1 bits_offset=0\n"
209 "\t'f2' type_id=2 bits_offset=32",
210 "[21] UNION '(anon)' size=4 vlen=1\n"
211 "\t'f1' type_id=1 bits_offset=0",
212 "[22] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
213 "\t'av1' val=2",
214 "[23] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
215 "\t'v1' val=1025",
216 "[24] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
217 "\t'p1' type_id=1",
218 "[25] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");
219
220 if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))
221 goto cleanup;
222
223 VALIDATE_RAW_BTF(
224 btf4,
225 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
226 "[2] PTR '(anon)' type_id=1",
227 "[3] STRUCT 's1' size=8 vlen=1\n"
228 "\t'f1' type_id=2 bits_offset=0",
229 "[4] STRUCT '(anon)' size=12 vlen=2\n"
230 "\t'f1' type_id=1 bits_offset=0\n"
231 "\t'f2' type_id=3 bits_offset=32",
232 "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
233 "[6] UNION 'u1' size=12 vlen=2\n"
234 "\t'f1' type_id=1 bits_offset=0\n"
235 "\t'f2' type_id=2 bits_offset=0",
236 "[7] UNION '(anon)' size=4 vlen=1\n"
237 "\t'f1' type_id=1 bits_offset=0",
238 "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
239 "\t'v1' val=1",
240 "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
241 "\t'av1' val=2",
242 "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
243 "\t'v1' val=1024",
244 "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
245 "\t'v1' val=1025",
246 "[12] STRUCT 'unneeded' size=4 vlen=1\n"
247 "\t'f1' type_id=1 bits_offset=0",
248 "[13] STRUCT 'embedded' size=4 vlen=1\n"
249 "\t'f1' type_id=1 bits_offset=0",
250 "[14] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
251 "\t'p1' type_id=1",
252 "[15] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3",
253 "[16] STRUCT 'from_proto' size=4 vlen=1\n"
254 "\t'f1' type_id=1 bits_offset=0",
255 "[17] UNION 'u1' size=4 vlen=1\n"
256 "\t'f1' type_id=1 bits_offset=0",
257 "[18] PTR '(anon)' type_id=3",
258 "[19] PTR '(anon)' type_id=30",
259 "[20] CONST '(anon)' type_id=6",
260 "[21] RESTRICT '(anon)' type_id=31",
261 "[22] VOLATILE '(anon)' type_id=8",
262 "[23] TYPEDEF 'et' type_id=32",
263 "[24] CONST '(anon)' type_id=10",
264 "[25] PTR '(anon)' type_id=33",
265 "[26] STRUCT 'with_embedded' size=4 vlen=1\n"
266 "\t'f1' type_id=13 bits_offset=0",
267 "[27] FUNC 'fn' type_id=34 linkage=static",
268 "[28] TYPEDEF 'arraytype' type_id=35",
269 "[29] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
270 "\t'p1' type_id=16",
271 /* below here are (duplicate) anon base types added by distill
272 * process to split BTF.
273 */
274 "[30] STRUCT '(anon)' size=12 vlen=2\n"
275 "\t'f1' type_id=1 bits_offset=0\n"
276 "\t'f2' type_id=3 bits_offset=32",
277 "[31] UNION '(anon)' size=4 vlen=1\n"
278 "\t'f1' type_id=1 bits_offset=0",
279 "[32] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
280 "\t'av1' val=2",
281 "[33] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
282 "\t'v1' val=1025",
283 "[34] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
284 "\t'p1' type_id=1",
285 "[35] ARRAY '(anon)' type_id=1 index_type_id=1 nr_elems=3");
286
287cleanup:
288 btf__free(btf4);
289 btf__free(btf3);
290 btf__free(btf2);
291 btf__free(btf1);
292}
293
294/* ensure we can cope with multiple types with the same name in
295 * distilled base BTF. In this case because sizes are different,
296 * we can still disambiguate them.
297 */
298static void test_distilled_base_multi(void)
299{
300 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
301
302 btf1 = btf__new_empty();
303 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
304 return;
305 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
306 btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
307 VALIDATE_RAW_BTF(
308 btf1,
309 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
310 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
311 btf2 = btf__new_empty_split(btf1);
312 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
313 goto cleanup;
314 btf__add_ptr(btf2, 1);
315 btf__add_const(btf2, 2);
316 VALIDATE_RAW_BTF(
317 btf2,
318 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
319 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
320 "[3] PTR '(anon)' type_id=1",
321 "[4] CONST '(anon)' type_id=2");
322 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
323 "distilled_base") ||
324 !ASSERT_OK_PTR(btf3, "distilled_base") ||
325 !ASSERT_OK_PTR(btf4, "distilled_split") ||
326 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
327 goto cleanup;
328 VALIDATE_RAW_BTF(
329 btf3,
330 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
331 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
332 if (!ASSERT_EQ(btf__relocate(btf4, btf1), 0, "relocate_split"))
333 goto cleanup;
334
335 VALIDATE_RAW_BTF(
336 btf4,
337 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
338 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
339 "[3] PTR '(anon)' type_id=1",
340 "[4] CONST '(anon)' type_id=2");
341
342cleanup:
343 btf__free(btf4);
344 btf__free(btf3);
345 btf__free(btf2);
346 btf__free(btf1);
347}
348
349/* If a needed type is not present in the base BTF we wish to relocate
350 * with, btf__relocate() should error our.
351 */
352static void test_distilled_base_missing_err(void)
353{
354 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
355
356 btf1 = btf__new_empty();
357 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
358 return;
359 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
360 btf__add_int(btf1, "int", 8, BTF_INT_SIGNED); /* [2] int */
361 VALIDATE_RAW_BTF(
362 btf1,
363 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
364 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
365 btf2 = btf__new_empty_split(btf1);
366 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
367 goto cleanup;
368 btf__add_ptr(btf2, 1);
369 btf__add_const(btf2, 2);
370 VALIDATE_RAW_BTF(
371 btf2,
372 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
373 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED",
374 "[3] PTR '(anon)' type_id=1",
375 "[4] CONST '(anon)' type_id=2");
376 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
377 "distilled_base") ||
378 !ASSERT_OK_PTR(btf3, "distilled_base") ||
379 !ASSERT_OK_PTR(btf4, "distilled_split") ||
380 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
381 goto cleanup;
382 VALIDATE_RAW_BTF(
383 btf3,
384 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
385 "[2] INT 'int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED");
386 btf5 = btf__new_empty();
387 if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))
388 goto cleanup;
389 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
390 VALIDATE_RAW_BTF(
391 btf5,
392 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
393 ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
394
395cleanup:
396 btf__free(btf5);
397 btf__free(btf4);
398 btf__free(btf3);
399 btf__free(btf2);
400 btf__free(btf1);
401}
402
403/* With 2 types of same size in distilled base BTF, relocation should
404 * fail as we have no means to choose between them.
405 */
406static void test_distilled_base_multi_err(void)
407{
408 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
409
410 btf1 = btf__new_empty();
411 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
412 return;
413 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
414 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [2] int */
415 VALIDATE_RAW_BTF(
416 btf1,
417 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
418 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
419 btf2 = btf__new_empty_split(btf1);
420 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
421 goto cleanup;
422 btf__add_ptr(btf2, 1);
423 btf__add_const(btf2, 2);
424 VALIDATE_RAW_BTF(
425 btf2,
426 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
427 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
428 "[3] PTR '(anon)' type_id=1",
429 "[4] CONST '(anon)' type_id=2");
430 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
431 "distilled_base") ||
432 !ASSERT_OK_PTR(btf3, "distilled_base") ||
433 !ASSERT_OK_PTR(btf4, "distilled_split") ||
434 !ASSERT_EQ(3, btf__type_cnt(btf3), "distilled_base_type_cnt"))
435 goto cleanup;
436 VALIDATE_RAW_BTF(
437 btf3,
438 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
439 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
440 ASSERT_EQ(btf__relocate(btf4, btf1), -EINVAL, "relocate_split");
441cleanup:
442 btf__free(btf4);
443 btf__free(btf3);
444 btf__free(btf2);
445 btf__free(btf1);
446}
447
448/* With 2 types of same size in base BTF, relocation should
449 * fail as we have no means to choose between them.
450 */
451static void test_distilled_base_multi_err2(void)
452{
453 struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = NULL;
454
455 btf1 = btf__new_empty();
456 if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
457 return;
458 btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
459 VALIDATE_RAW_BTF(
460 btf1,
461 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
462 btf2 = btf__new_empty_split(btf1);
463 if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
464 goto cleanup;
465 btf__add_ptr(btf2, 1);
466 VALIDATE_RAW_BTF(
467 btf2,
468 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
469 "[2] PTR '(anon)' type_id=1");
470 if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
471 "distilled_base") ||
472 !ASSERT_OK_PTR(btf3, "distilled_base") ||
473 !ASSERT_OK_PTR(btf4, "distilled_split") ||
474 !ASSERT_EQ(2, btf__type_cnt(btf3), "distilled_base_type_cnt"))
475 goto cleanup;
476 VALIDATE_RAW_BTF(
477 btf3,
478 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
479 btf5 = btf__new_empty();
480 if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))
481 goto cleanup;
482 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [1] int */
483 btf__add_int(btf5, "int", 4, BTF_INT_SIGNED); /* [2] int */
484 VALIDATE_RAW_BTF(
485 btf5,
486 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
487 "[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
488 ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
489cleanup:
490 btf__free(btf5);
491 btf__free(btf4);
492 btf__free(btf3);
493 btf__free(btf2);
494 btf__free(btf1);
495}
496
497/* create split reference BTF from vmlinux + split BTF with a few type references;
498 * ensure the resultant split reference BTF is as expected, containing only types
499 * needed to disambiguate references from split BTF.
500 */
501static void test_distilled_base_vmlinux(void)
502{
503 struct btf *split_btf = NULL, *vmlinux_btf = btf__load_vmlinux_btf();
504 struct btf *split_dist = NULL, *base_dist = NULL;
505 __s32 int_id, myint_id;
506
507 if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux"))
508 return;
509 int_id = btf__find_by_name_kind(vmlinux_btf, "int", BTF_KIND_INT);
510 if (!ASSERT_GT(int_id, 0, "find_int"))
511 goto cleanup;
512 split_btf = btf__new_empty_split(vmlinux_btf);
513 if (!ASSERT_OK_PTR(split_btf, "new_split"))
514 goto cleanup;
515 myint_id = btf__add_typedef(split_btf, "myint", int_id);
516 btf__add_ptr(split_btf, myint_id);
517
518 if (!ASSERT_EQ(btf__distill_base(split_btf, &base_dist, &split_dist), 0,
519 "distill_vmlinux_base"))
520 goto cleanup;
521
522 if (!ASSERT_OK_PTR(split_dist, "split_distilled") ||
523 !ASSERT_OK_PTR(base_dist, "base_dist"))
524 goto cleanup;
525 VALIDATE_RAW_BTF(
526 split_dist,
527 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
528 "[2] TYPEDEF 'myint' type_id=1",
529 "[3] PTR '(anon)' type_id=2");
530
531cleanup:
532 btf__free(split_dist);
533 btf__free(base_dist);
534 btf__free(split_btf);
535 btf__free(vmlinux_btf);
536}
537
538/* Split and new base BTFs should inherit endianness from source BTF. */
539static void test_distilled_endianness(void)
540{
541 struct btf *base = NULL, *split = NULL, *new_base = NULL, *new_split = NULL;
542 struct btf *new_base1 = NULL, *new_split1 = NULL;
543 enum btf_endianness inverse_endianness;
544 const void *raw_data;
545 __u32 size;
546
547 base = btf__new_empty();
548 if (!ASSERT_OK_PTR(base, "empty_main_btf"))
549 return;
550 inverse_endianness = btf__endianness(base) == BTF_LITTLE_ENDIAN ? BTF_BIG_ENDIAN
551 : BTF_LITTLE_ENDIAN;
552 btf__set_endianness(base, inverse_endianness);
553 btf__add_int(base, "int", 4, BTF_INT_SIGNED); /* [1] int */
554 VALIDATE_RAW_BTF(
555 base,
556 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
557 split = btf__new_empty_split(base);
558 if (!ASSERT_OK_PTR(split, "empty_split_btf"))
559 goto cleanup;
560 btf__add_ptr(split, 1);
561 VALIDATE_RAW_BTF(
562 split,
563 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
564 "[2] PTR '(anon)' type_id=1");
565 if (!ASSERT_EQ(0, btf__distill_base(split, &new_base, &new_split),
566 "distilled_base") ||
567 !ASSERT_OK_PTR(new_base, "distilled_base") ||
568 !ASSERT_OK_PTR(new_split, "distilled_split") ||
569 !ASSERT_EQ(2, btf__type_cnt(new_base), "distilled_base_type_cnt"))
570 goto cleanup;
571 VALIDATE_RAW_BTF(
572 new_split,
573 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
574 "[2] PTR '(anon)' type_id=1");
575
576 raw_data = btf__raw_data(new_base, &size);
577 if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #1"))
578 goto cleanup;
579 new_base1 = btf__new(raw_data, size);
580 if (!ASSERT_OK_PTR(new_base1, "new_base1 = btf__new()"))
581 goto cleanup;
582 raw_data = btf__raw_data(new_split, &size);
583 if (!ASSERT_OK_PTR(raw_data, "btf__raw_data #2"))
584 goto cleanup;
585 new_split1 = btf__new_split(raw_data, size, new_base1);
586 if (!ASSERT_OK_PTR(new_split1, "new_split1 = btf__new()"))
587 goto cleanup;
588
589 ASSERT_EQ(btf__endianness(new_base1), inverse_endianness, "new_base1 endianness");
590 ASSERT_EQ(btf__endianness(new_split1), inverse_endianness, "new_split1 endianness");
591 VALIDATE_RAW_BTF(
592 new_split1,
593 "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
594 "[2] PTR '(anon)' type_id=1");
595cleanup:
596 btf__free(new_split1);
597 btf__free(new_base1);
598 btf__free(new_split);
599 btf__free(new_base);
600 btf__free(split);
601 btf__free(base);
602}
603
604void test_btf_distill(void)
605{
606 if (test__start_subtest("distilled_base"))
607 test_distilled_base();
608 if (test__start_subtest("distilled_base_multi"))
609 test_distilled_base_multi();
610 if (test__start_subtest("distilled_base_missing_err"))
611 test_distilled_base_missing_err();
612 if (test__start_subtest("distilled_base_multi_err"))
613 test_distilled_base_multi_err();
614 if (test__start_subtest("distilled_base_multi_err2"))
615 test_distilled_base_multi_err2();
616 if (test__start_subtest("distilled_base_vmlinux"))
617 test_distilled_base_vmlinux();
618 if (test__start_subtest("distilled_endianness"))
619 test_distilled_endianness();
620}