1888d83b9SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2888d83b9SAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3888d83b9SAndrii Nakryiko 
4888d83b9SAndrii Nakryiko #include <test_progs.h>
5888d83b9SAndrii Nakryiko #include <bpf/btf.h>
6888d83b9SAndrii Nakryiko 
7888d83b9SAndrii Nakryiko /* real layout and sizes according to test's (32-bit) BTF
8888d83b9SAndrii Nakryiko  * needs to be defined before skeleton is included */
9888d83b9SAndrii Nakryiko struct test_struct___real {
10888d83b9SAndrii Nakryiko 	unsigned int ptr; /* can't use `void *`, it is always 8 byte in BPF target */
11888d83b9SAndrii Nakryiko 	unsigned int val2;
12888d83b9SAndrii Nakryiko 	unsigned long long val1;
13888d83b9SAndrii Nakryiko 	unsigned short val3;
14888d83b9SAndrii Nakryiko 	unsigned char val4;
15888d83b9SAndrii Nakryiko 	unsigned char _pad;
16888d83b9SAndrii Nakryiko };
17888d83b9SAndrii Nakryiko 
18888d83b9SAndrii Nakryiko #include "test_core_autosize.skel.h"
19888d83b9SAndrii Nakryiko 
20888d83b9SAndrii Nakryiko static int duration = 0;
21888d83b9SAndrii Nakryiko 
22888d83b9SAndrii Nakryiko static struct {
23888d83b9SAndrii Nakryiko 	unsigned long long ptr_samesized;
24888d83b9SAndrii Nakryiko 	unsigned long long val1_samesized;
25888d83b9SAndrii Nakryiko 	unsigned long long val2_samesized;
26888d83b9SAndrii Nakryiko 	unsigned long long val3_samesized;
27888d83b9SAndrii Nakryiko 	unsigned long long val4_samesized;
28888d83b9SAndrii Nakryiko 	struct test_struct___real output_samesized;
29888d83b9SAndrii Nakryiko 
30888d83b9SAndrii Nakryiko 	unsigned long long ptr_downsized;
31888d83b9SAndrii Nakryiko 	unsigned long long val1_downsized;
32888d83b9SAndrii Nakryiko 	unsigned long long val2_downsized;
33888d83b9SAndrii Nakryiko 	unsigned long long val3_downsized;
34888d83b9SAndrii Nakryiko 	unsigned long long val4_downsized;
35888d83b9SAndrii Nakryiko 	struct test_struct___real output_downsized;
36888d83b9SAndrii Nakryiko 
37888d83b9SAndrii Nakryiko 	unsigned long long ptr_probed;
38888d83b9SAndrii Nakryiko 	unsigned long long val1_probed;
39888d83b9SAndrii Nakryiko 	unsigned long long val2_probed;
40888d83b9SAndrii Nakryiko 	unsigned long long val3_probed;
41888d83b9SAndrii Nakryiko 	unsigned long long val4_probed;
42888d83b9SAndrii Nakryiko 
43888d83b9SAndrii Nakryiko 	unsigned long long ptr_signed;
44888d83b9SAndrii Nakryiko 	unsigned long long val1_signed;
45888d83b9SAndrii Nakryiko 	unsigned long long val2_signed;
46888d83b9SAndrii Nakryiko 	unsigned long long val3_signed;
47888d83b9SAndrii Nakryiko 	unsigned long long val4_signed;
48888d83b9SAndrii Nakryiko 	struct test_struct___real output_signed;
49888d83b9SAndrii Nakryiko } out;
50888d83b9SAndrii Nakryiko 
test_core_autosize(void)51888d83b9SAndrii Nakryiko void test_core_autosize(void)
52888d83b9SAndrii Nakryiko {
53888d83b9SAndrii Nakryiko 	char btf_file[] = "/tmp/core_autosize.btf.XXXXXX";
54888d83b9SAndrii Nakryiko 	int err, fd = -1, zero = 0;
55888d83b9SAndrii Nakryiko 	int char_id, short_id, int_id, long_long_id, void_ptr_id, id;
56f0b7d119SShuyi Cheng 	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts);
57888d83b9SAndrii Nakryiko 	struct test_core_autosize* skel = NULL;
58888d83b9SAndrii Nakryiko 	struct bpf_program *prog;
59888d83b9SAndrii Nakryiko 	struct bpf_map *bss_map;
60888d83b9SAndrii Nakryiko 	struct btf *btf = NULL;
61888d83b9SAndrii Nakryiko 	size_t written;
62888d83b9SAndrii Nakryiko 	const void *raw_data;
63888d83b9SAndrii Nakryiko 	__u32 raw_sz;
64888d83b9SAndrii Nakryiko 	FILE *f = NULL;
65888d83b9SAndrii Nakryiko 
66888d83b9SAndrii Nakryiko 	btf = btf__new_empty();
67888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(btf, "empty_btf"))
68888d83b9SAndrii Nakryiko 		return;
69888d83b9SAndrii Nakryiko 	/* Emit the following struct with 32-bit pointer size:
70888d83b9SAndrii Nakryiko 	 *
71888d83b9SAndrii Nakryiko 	 * struct test_struct {
72888d83b9SAndrii Nakryiko 	 *     void *ptr;
73888d83b9SAndrii Nakryiko 	 *     unsigned long val2;
74888d83b9SAndrii Nakryiko 	 *     unsigned long long val1;
75888d83b9SAndrii Nakryiko 	 *     unsigned short val3;
76888d83b9SAndrii Nakryiko 	 *     unsigned char val4;
77888d83b9SAndrii Nakryiko 	 *     char: 8;
78888d83b9SAndrii Nakryiko 	 * };
79888d83b9SAndrii Nakryiko 	 *
80888d83b9SAndrii Nakryiko 	 * This struct is going to be used as the "kernel BTF" for this test.
81888d83b9SAndrii Nakryiko 	 * It's equivalent memory-layout-wise to test_struct__real above.
82888d83b9SAndrii Nakryiko 	 */
83888d83b9SAndrii Nakryiko 
84888d83b9SAndrii Nakryiko 	/* force 32-bit pointer size */
85888d83b9SAndrii Nakryiko 	btf__set_pointer_size(btf, 4);
86888d83b9SAndrii Nakryiko 
87888d83b9SAndrii Nakryiko 	char_id = btf__add_int(btf, "unsigned char", 1, 0);
88888d83b9SAndrii Nakryiko 	ASSERT_EQ(char_id, 1, "char_id");
89888d83b9SAndrii Nakryiko 	short_id = btf__add_int(btf, "unsigned short", 2, 0);
90888d83b9SAndrii Nakryiko 	ASSERT_EQ(short_id, 2, "short_id");
91888d83b9SAndrii Nakryiko 	/* "long unsigned int" of 4 byte size tells BTF that sizeof(void *) == 4 */
92888d83b9SAndrii Nakryiko 	int_id = btf__add_int(btf, "long unsigned int", 4, 0);
93888d83b9SAndrii Nakryiko 	ASSERT_EQ(int_id, 3, "int_id");
94888d83b9SAndrii Nakryiko 	long_long_id = btf__add_int(btf, "unsigned long long", 8, 0);
95888d83b9SAndrii Nakryiko 	ASSERT_EQ(long_long_id, 4, "long_long_id");
96888d83b9SAndrii Nakryiko 	void_ptr_id = btf__add_ptr(btf, 0);
97888d83b9SAndrii Nakryiko 	ASSERT_EQ(void_ptr_id, 5, "void_ptr_id");
98888d83b9SAndrii Nakryiko 
99888d83b9SAndrii Nakryiko 	id = btf__add_struct(btf, "test_struct", 20 /* bytes */);
100888d83b9SAndrii Nakryiko 	ASSERT_EQ(id, 6, "struct_id");
101888d83b9SAndrii Nakryiko 	err = btf__add_field(btf, "ptr", void_ptr_id, 0, 0);
102888d83b9SAndrii Nakryiko 	err = err ?: btf__add_field(btf, "val2", int_id, 32, 0);
103888d83b9SAndrii Nakryiko 	err = err ?: btf__add_field(btf, "val1", long_long_id, 64, 0);
104888d83b9SAndrii Nakryiko 	err = err ?: btf__add_field(btf, "val3", short_id, 128, 0);
105888d83b9SAndrii Nakryiko 	err = err ?: btf__add_field(btf, "val4", char_id, 144, 0);
106888d83b9SAndrii Nakryiko 	ASSERT_OK(err, "struct_fields");
107888d83b9SAndrii Nakryiko 
108888d83b9SAndrii Nakryiko 	fd = mkstemp(btf_file);
109888d83b9SAndrii Nakryiko 	if (CHECK(fd < 0, "btf_tmp", "failed to create file: %d\n", fd))
110888d83b9SAndrii Nakryiko 		goto cleanup;
111888d83b9SAndrii Nakryiko 	f = fdopen(fd, "w");
112888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(f, "btf_fdopen"))
113888d83b9SAndrii Nakryiko 		goto cleanup;
114888d83b9SAndrii Nakryiko 
115487ef148SHengqi Chen 	raw_data = btf__raw_data(btf, &raw_sz);
116888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(raw_data, "raw_data"))
117888d83b9SAndrii Nakryiko 		goto cleanup;
118888d83b9SAndrii Nakryiko 	written = fwrite(raw_data, 1, raw_sz, f);
119888d83b9SAndrii Nakryiko 	if (CHECK(written != raw_sz, "btf_write", "written: %zu, errno: %d\n", written, errno))
120888d83b9SAndrii Nakryiko 		goto cleanup;
121888d83b9SAndrii Nakryiko 	fflush(f);
122888d83b9SAndrii Nakryiko 	fclose(f);
123888d83b9SAndrii Nakryiko 	f = NULL;
124888d83b9SAndrii Nakryiko 	close(fd);
125888d83b9SAndrii Nakryiko 	fd = -1;
126888d83b9SAndrii Nakryiko 
127888d83b9SAndrii Nakryiko 	/* open and load BPF program with custom BTF as the kernel BTF */
128f0b7d119SShuyi Cheng 	open_opts.btf_custom_path = btf_file;
129f0b7d119SShuyi Cheng 	skel = test_core_autosize__open_opts(&open_opts);
130888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
131f0b7d119SShuyi Cheng 		goto cleanup;
132888d83b9SAndrii Nakryiko 
133888d83b9SAndrii Nakryiko 	/* disable handle_signed() for now */
134888d83b9SAndrii Nakryiko 	prog = bpf_object__find_program_by_name(skel->obj, "handle_signed");
135888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(prog, "prog_find"))
136888d83b9SAndrii Nakryiko 		goto cleanup;
137888d83b9SAndrii Nakryiko 	bpf_program__set_autoload(prog, false);
138888d83b9SAndrii Nakryiko 
139f0b7d119SShuyi Cheng 	err = bpf_object__load(skel->obj);
140888d83b9SAndrii Nakryiko 	if (!ASSERT_OK(err, "prog_load"))
141888d83b9SAndrii Nakryiko 		goto cleanup;
142888d83b9SAndrii Nakryiko 
143888d83b9SAndrii Nakryiko 	prog = bpf_object__find_program_by_name(skel->obj, "handle_samesize");
144888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(prog, "prog_find"))
145888d83b9SAndrii Nakryiko 		goto cleanup;
146888d83b9SAndrii Nakryiko 	skel->links.handle_samesize = bpf_program__attach(prog);
147888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel->links.handle_samesize, "prog_attach"))
148888d83b9SAndrii Nakryiko 		goto cleanup;
149888d83b9SAndrii Nakryiko 
150888d83b9SAndrii Nakryiko 	prog = bpf_object__find_program_by_name(skel->obj, "handle_downsize");
151888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(prog, "prog_find"))
152888d83b9SAndrii Nakryiko 		goto cleanup;
153888d83b9SAndrii Nakryiko 	skel->links.handle_downsize = bpf_program__attach(prog);
154888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel->links.handle_downsize, "prog_attach"))
155888d83b9SAndrii Nakryiko 		goto cleanup;
156888d83b9SAndrii Nakryiko 
157888d83b9SAndrii Nakryiko 	prog = bpf_object__find_program_by_name(skel->obj, "handle_probed");
158888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(prog, "prog_find"))
159888d83b9SAndrii Nakryiko 		goto cleanup;
160888d83b9SAndrii Nakryiko 	skel->links.handle_probed = bpf_program__attach(prog);
161888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel->links.handle_probed, "prog_attach"))
162888d83b9SAndrii Nakryiko 		goto cleanup;
163888d83b9SAndrii Nakryiko 
164888d83b9SAndrii Nakryiko 	usleep(1);
165888d83b9SAndrii Nakryiko 
1664f2511e1SAndrii Nakryiko 	bss_map = bpf_object__find_map_by_name(skel->obj, ".bss");
167888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(bss_map, "bss_map_find"))
168888d83b9SAndrii Nakryiko 		goto cleanup;
169888d83b9SAndrii Nakryiko 
170*b2531d4bSAndrii Nakryiko 	err = bpf_map__lookup_elem(bss_map, &zero, sizeof(zero), &out, sizeof(out), 0);
171888d83b9SAndrii Nakryiko 	if (!ASSERT_OK(err, "bss_lookup"))
172888d83b9SAndrii Nakryiko 		goto cleanup;
173888d83b9SAndrii Nakryiko 
174888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.ptr_samesized, 0x01020304, "ptr_samesized");
175888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val1_samesized, 0x1020304050607080, "val1_samesized");
176888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val2_samesized, 0x0a0b0c0d, "val2_samesized");
177888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val3_samesized, 0xfeed, "val3_samesized");
178888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val4_samesized, 0xb9, "val4_samesized");
179888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_samesized.ptr, 0x01020304, "ptr_samesized");
180888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_samesized.val1, 0x1020304050607080, "val1_samesized");
181888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_samesized.val2, 0x0a0b0c0d, "val2_samesized");
182888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_samesized.val3, 0xfeed, "val3_samesized");
183888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_samesized.val4, 0xb9, "val4_samesized");
184888d83b9SAndrii Nakryiko 
185888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.ptr_downsized, 0x01020304, "ptr_downsized");
186888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val1_downsized, 0x1020304050607080, "val1_downsized");
187888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val2_downsized, 0x0a0b0c0d, "val2_downsized");
188888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val3_downsized, 0xfeed, "val3_downsized");
189888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val4_downsized, 0xb9, "val4_downsized");
190888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_downsized.ptr, 0x01020304, "ptr_downsized");
191888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_downsized.val1, 0x1020304050607080, "val1_downsized");
192888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_downsized.val2, 0x0a0b0c0d, "val2_downsized");
193888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_downsized.val3, 0xfeed, "val3_downsized");
194888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.output_downsized.val4, 0xb9, "val4_downsized");
195888d83b9SAndrii Nakryiko 
196888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.ptr_probed, 0x01020304, "ptr_probed");
197888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val1_probed, 0x1020304050607080, "val1_probed");
198888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val2_probed, 0x0a0b0c0d, "val2_probed");
199888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val3_probed, 0xfeed, "val3_probed");
200888d83b9SAndrii Nakryiko 	ASSERT_EQ(out.val4_probed, 0xb9, "val4_probed");
201888d83b9SAndrii Nakryiko 
202888d83b9SAndrii Nakryiko 	test_core_autosize__destroy(skel);
203888d83b9SAndrii Nakryiko 	skel = NULL;
204888d83b9SAndrii Nakryiko 
205888d83b9SAndrii Nakryiko 	/* now re-load with handle_signed() enabled, it should fail loading */
206f0b7d119SShuyi Cheng 	open_opts.btf_custom_path = btf_file;
207f0b7d119SShuyi Cheng 	skel = test_core_autosize__open_opts(&open_opts);
208888d83b9SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
209f0b7d119SShuyi Cheng 		goto cleanup;
210888d83b9SAndrii Nakryiko 
211f0b7d119SShuyi Cheng 	err = test_core_autosize__load(skel);
212f0b7d119SShuyi Cheng 	if (!ASSERT_ERR(err, "skel_load"))
213888d83b9SAndrii Nakryiko 		goto cleanup;
214888d83b9SAndrii Nakryiko 
215888d83b9SAndrii Nakryiko cleanup:
216888d83b9SAndrii Nakryiko 	if (f)
217888d83b9SAndrii Nakryiko 		fclose(f);
218888d83b9SAndrii Nakryiko 	if (fd >= 0)
219888d83b9SAndrii Nakryiko 		close(fd);
220888d83b9SAndrii Nakryiko 	remove(btf_file);
221888d83b9SAndrii Nakryiko 	btf__free(btf);
222888d83b9SAndrii Nakryiko 	test_core_autosize__destroy(skel);
223888d83b9SAndrii Nakryiko }
224