Skip to content

Commit 08c8140

Browse files
Donglin PengKernel Patches Daemon
authored andcommitted
selftests/bpf: Add test cases for btf__permute functionality
This patch introduces test cases for the btf__permute function to ensure it works correctly with both base BTF and split BTF scenarios. The test suite includes: - test_permute_base: Validates permutation on base BTF - test_permute_split: Tests permutation on split BTF - test_permute_drop_base: Validates type dropping on base BTF - test_permute_drop_split: Tests type dropping on split BTF Cc: Eduard Zingerman <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Alan Maguire <[email protected]> Cc: Song Liu <[email protected]> Cc: Xiaoqin Zhang <[email protected]> Signed-off-by: Donglin Peng <[email protected]> Signed-off-by: Donglin Peng <[email protected]> Acked-by: Eduard Zingerman <[email protected]>
1 parent eb7abe5 commit 08c8140

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2025 Xiaomi */
3+
4+
#include <test_progs.h>
5+
#include <bpf/btf.h>
6+
#include "btf_helpers.h"
7+
8+
/* Ensure btf__permute work as expected with base_btf */
9+
static void test_permute_base(void)
10+
{
11+
struct btf *btf;
12+
__u32 permute_ids[6];
13+
int err;
14+
15+
btf = btf__new_empty();
16+
if (!ASSERT_OK_PTR(btf, "empty_main_btf"))
17+
return;
18+
19+
btf__add_int(btf, "int", 4, BTF_INT_SIGNED); /* [1] int */
20+
btf__add_ptr(btf, 1); /* [2] ptr to int */
21+
btf__add_struct(btf, "s1", 4); /* [3] struct s1 { */
22+
btf__add_field(btf, "m", 1, 0, 0); /* int m; */
23+
/* } */
24+
btf__add_struct(btf, "s2", 4); /* [4] struct s2 { */
25+
btf__add_field(btf, "m", 1, 0, 0); /* int m; */
26+
/* } */
27+
btf__add_func_proto(btf, 1); /* [5] int (*)(int *p); */
28+
btf__add_func_param(btf, "p", 2);
29+
btf__add_func(btf, "f", BTF_FUNC_STATIC, 5); /* [6] int f(int *p); */
30+
31+
VALIDATE_RAW_BTF(
32+
btf,
33+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
34+
"[2] PTR '(anon)' type_id=1",
35+
"[3] STRUCT 's1' size=4 vlen=1\n"
36+
"\t'm' type_id=1 bits_offset=0",
37+
"[4] STRUCT 's2' size=4 vlen=1\n"
38+
"\t'm' type_id=1 bits_offset=0",
39+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
40+
"\t'p' type_id=2",
41+
"[6] FUNC 'f' type_id=5 linkage=static");
42+
43+
permute_ids[0] = 4; /* struct s2 */
44+
permute_ids[1] = 3; /* struct s1 */
45+
permute_ids[2] = 5; /* int (*)(int *p) */
46+
permute_ids[3] = 1; /* int */
47+
permute_ids[4] = 6; /* int f(int *p) */
48+
permute_ids[5] = 2; /* ptr to int */
49+
err = btf__permute(btf, permute_ids, ARRAY_SIZE(permute_ids), NULL);
50+
if (!ASSERT_OK(err, "btf__permute_base"))
51+
goto done;
52+
53+
VALIDATE_RAW_BTF(
54+
btf,
55+
"[1] STRUCT 's2' size=4 vlen=1\n"
56+
"\t'm' type_id=4 bits_offset=0",
57+
"[2] STRUCT 's1' size=4 vlen=1\n"
58+
"\t'm' type_id=4 bits_offset=0",
59+
"[3] FUNC_PROTO '(anon)' ret_type_id=4 vlen=1\n"
60+
"\t'p' type_id=6",
61+
"[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
62+
"[5] FUNC 'f' type_id=3 linkage=static",
63+
"[6] PTR '(anon)' type_id=4");
64+
65+
done:
66+
btf__free(btf);
67+
}
68+
69+
/* Ensure btf__permute work as expected with split_btf */
70+
static void test_permute_split(void)
71+
{
72+
struct btf *split_btf = NULL, *base_btf = NULL;
73+
__u32 permute_ids[4];
74+
int err;
75+
76+
base_btf = btf__new_empty();
77+
if (!ASSERT_OK_PTR(base_btf, "empty_main_btf"))
78+
return;
79+
80+
btf__add_int(base_btf, "int", 4, BTF_INT_SIGNED); /* [1] int */
81+
btf__add_ptr(base_btf, 1); /* [2] ptr to int */
82+
VALIDATE_RAW_BTF(
83+
base_btf,
84+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
85+
"[2] PTR '(anon)' type_id=1");
86+
split_btf = btf__new_empty_split(base_btf);
87+
if (!ASSERT_OK_PTR(split_btf, "empty_split_btf"))
88+
goto cleanup;
89+
btf__add_struct(split_btf, "s1", 4); /* [3] struct s1 { */
90+
btf__add_field(split_btf, "m", 1, 0, 0); /* int m; */
91+
/* } */
92+
btf__add_struct(split_btf, "s2", 4); /* [4] struct s2 { */
93+
btf__add_field(split_btf, "m", 1, 0, 0); /* int m; */
94+
/* } */
95+
btf__add_func_proto(split_btf, 1); /* [5] int (*)(int p); */
96+
btf__add_func_param(split_btf, "p", 2);
97+
btf__add_func(split_btf, "f", BTF_FUNC_STATIC, 5); /* [6] int f(int *p); */
98+
99+
VALIDATE_RAW_BTF(
100+
split_btf,
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'm' type_id=1 bits_offset=0",
105+
"[4] STRUCT 's2' size=4 vlen=1\n"
106+
"\t'm' type_id=1 bits_offset=0",
107+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
108+
"\t'p' type_id=2",
109+
"[6] FUNC 'f' type_id=5 linkage=static");
110+
111+
permute_ids[0] = 6; /* int f(int *p) */
112+
permute_ids[1] = 3; /* struct s1 */
113+
permute_ids[2] = 5; /* int (*)(int *p) */
114+
permute_ids[3] = 4; /* struct s2 */
115+
err = btf__permute(split_btf, permute_ids, ARRAY_SIZE(permute_ids), NULL);
116+
if (!ASSERT_OK(err, "btf__permute_split"))
117+
goto cleanup;
118+
119+
VALIDATE_RAW_BTF(
120+
split_btf,
121+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
122+
"[2] PTR '(anon)' type_id=1",
123+
"[3] FUNC 'f' type_id=5 linkage=static",
124+
"[4] STRUCT 's1' size=4 vlen=1\n"
125+
"\t'm' type_id=1 bits_offset=0",
126+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
127+
"\t'p' type_id=2",
128+
"[6] STRUCT 's2' size=4 vlen=1\n"
129+
"\t'm' type_id=1 bits_offset=0");
130+
131+
cleanup:
132+
btf__free(split_btf);
133+
btf__free(base_btf);
134+
}
135+
136+
/* Verify btf__permute function drops types correctly with base_btf */
137+
static void test_permute_drop_base(void)
138+
{
139+
struct btf *btf;
140+
__u32 permute_ids[6];
141+
int err;
142+
143+
btf = btf__new_empty();
144+
if (!ASSERT_OK_PTR(btf, "empty_main_btf"))
145+
return;
146+
147+
btf__add_int(btf, "int", 4, BTF_INT_SIGNED); /* [1] int */
148+
btf__add_ptr(btf, 1); /* [2] ptr to int */
149+
btf__add_struct(btf, "s1", 4); /* [3] struct s1 { */
150+
btf__add_field(btf, "m", 1, 0, 0); /* int m; */
151+
/* } */
152+
btf__add_struct(btf, "s2", 4); /* [4] struct s2 { */
153+
btf__add_field(btf, "m", 1, 0, 0); /* int m; */
154+
/* } */
155+
btf__add_func_proto(btf, 1); /* [5] int (*)(int *p); */
156+
btf__add_func_param(btf, "p", 2);
157+
btf__add_func(btf, "f", BTF_FUNC_STATIC, 5); /* [6] int f(int *p); */
158+
159+
VALIDATE_RAW_BTF(
160+
btf,
161+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
162+
"[2] PTR '(anon)' type_id=1",
163+
"[3] STRUCT 's1' size=4 vlen=1\n"
164+
"\t'm' type_id=1 bits_offset=0",
165+
"[4] STRUCT 's2' size=4 vlen=1\n"
166+
"\t'm' type_id=1 bits_offset=0",
167+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
168+
"\t'p' type_id=2",
169+
"[6] FUNC 'f' type_id=5 linkage=static");
170+
171+
permute_ids[0] = 4; /* struct s2 */
172+
permute_ids[1] = 2; /* ptr to int */
173+
permute_ids[2] = 5; /* int (*)(int *p) */
174+
permute_ids[3] = 1; /* int */
175+
err = btf__permute(btf, permute_ids, 4, NULL);
176+
if (!ASSERT_OK(err, "btf__permute_drop_base"))
177+
goto done;
178+
179+
VALIDATE_RAW_BTF(
180+
btf,
181+
"[1] STRUCT 's2' size=4 vlen=1\n"
182+
"\t'm' type_id=4 bits_offset=0",
183+
"[2] PTR '(anon)' type_id=4",
184+
"[3] FUNC_PROTO '(anon)' ret_type_id=4 vlen=1\n"
185+
"\t'p' type_id=2",
186+
"[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED");
187+
188+
permute_ids[0] = 4; /* struct s2 */
189+
permute_ids[1] = 5; /* int (*)(int *p) */
190+
permute_ids[2] = 1; /* int */
191+
err = btf__permute(btf, permute_ids, 3, NULL);
192+
if (!ASSERT_ERR(err, "btf__permute_drop_base_fail"))
193+
goto done;
194+
195+
done:
196+
btf__free(btf);
197+
}
198+
199+
/* Verify btf__permute function drops types correctly with split_btf */
200+
static void test_permute_drop_split(void)
201+
{
202+
struct btf *split_btf = NULL, *base_btf = NULL;
203+
__u32 permute_ids[4];
204+
int err;
205+
206+
base_btf = btf__new_empty();
207+
if (!ASSERT_OK_PTR(base_btf, "empty_main_btf"))
208+
return;
209+
210+
btf__add_int(base_btf, "int", 4, BTF_INT_SIGNED); /* [1] int */
211+
btf__add_ptr(base_btf, 1); /* [2] ptr to int */
212+
VALIDATE_RAW_BTF(
213+
base_btf,
214+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
215+
"[2] PTR '(anon)' type_id=1");
216+
split_btf = btf__new_empty_split(base_btf);
217+
if (!ASSERT_OK_PTR(split_btf, "empty_split_btf"))
218+
goto cleanup;
219+
btf__add_struct(split_btf, "s1", 4); /* [3] struct s1 { */
220+
btf__add_field(split_btf, "m", 1, 0, 0); /* int m; */
221+
/* } */
222+
btf__add_struct(split_btf, "s2", 4); /* [4] struct s2 { */
223+
btf__add_field(split_btf, "m", 1, 0, 0); /* int m; */
224+
/* } */
225+
btf__add_func_proto(split_btf, 1); /* [5] int (*)(int p); */
226+
btf__add_func_param(split_btf, "p", 2);
227+
btf__add_func(split_btf, "f", BTF_FUNC_STATIC, 5); /* [6] int f(int *p); */
228+
229+
VALIDATE_RAW_BTF(
230+
split_btf,
231+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
232+
"[2] PTR '(anon)' type_id=1",
233+
"[3] STRUCT 's1' size=4 vlen=1\n"
234+
"\t'm' type_id=1 bits_offset=0",
235+
"[4] STRUCT 's2' size=4 vlen=1\n"
236+
"\t'm' type_id=1 bits_offset=0",
237+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
238+
"\t'p' type_id=2",
239+
"[6] FUNC 'f' type_id=5 linkage=static");
240+
241+
permute_ids[0] = 6; /* int f(int *p) */
242+
permute_ids[1] = 3; /* struct s1 */
243+
permute_ids[2] = 5; /* int (*)(int *p) */
244+
err = btf__permute(split_btf, permute_ids, 3, NULL);
245+
if (!ASSERT_OK(err, "btf__permute_drop_split"))
246+
goto cleanup;
247+
248+
VALIDATE_RAW_BTF(
249+
split_btf,
250+
"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
251+
"[2] PTR '(anon)' type_id=1",
252+
"[3] FUNC 'f' type_id=5 linkage=static",
253+
"[4] STRUCT 's1' size=4 vlen=1\n"
254+
"\t'm' type_id=1 bits_offset=0",
255+
"[5] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1\n"
256+
"\t'p' type_id=2");
257+
258+
permute_ids[0] = 6; /* int f(int *p) */
259+
permute_ids[1] = 3; /* struct s1 */
260+
err = btf__permute(split_btf, permute_ids, 2, NULL);
261+
if (!ASSERT_ERR(err, "btf__permute_drop_split_fail"))
262+
goto cleanup;
263+
264+
cleanup:
265+
btf__free(split_btf);
266+
btf__free(base_btf);
267+
}
268+
269+
void test_btf_permute(void)
270+
{
271+
if (test__start_subtest("permute_base"))
272+
test_permute_base();
273+
if (test__start_subtest("permute_split"))
274+
test_permute_split();
275+
if (test__start_subtest("permute_drop_base"))
276+
test_permute_drop_base();
277+
if (test__start_subtest("permute_drop_split"))
278+
test_permute_drop_split();
279+
}

0 commit comments

Comments
 (0)