1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2020 Facebook
3
4#include <linux/bpf.h>
5#include <stdint.h>
6#include <stdbool.h>
7#include <bpf/bpf_helpers.h>
8#include <bpf/bpf_core_read.h>
9
10char _license[] SEC("license") = "GPL";
11
12struct {
13	char in[256];
14	char out[256];
15	bool skip;
16} data = {};
17
18/* some types are shared with test_core_reloc_type_based.c */
19struct a_struct {
20	int x;
21};
22
23union a_union {
24	int y;
25	int z;
26};
27
28enum an_enum {
29	AN_ENUM_VAL1 = 1,
30	AN_ENUM_VAL2 = 2,
31	AN_ENUM_VAL3 = 3,
32};
33
34typedef struct a_struct named_struct_typedef;
35
36typedef int (*func_proto_typedef)(long);
37
38typedef char arr_typedef[20];
39
40struct core_reloc_type_id_output {
41	int local_anon_struct;
42	int local_anon_union;
43	int local_anon_enum;
44	int local_anon_func_proto_ptr;
45	int local_anon_void_ptr;
46	int local_anon_arr;
47
48	int local_struct;
49	int local_union;
50	int local_enum;
51	int local_int;
52	int local_struct_typedef;
53	int local_func_proto_typedef;
54	int local_arr_typedef;
55
56	int targ_struct;
57	int targ_union;
58	int targ_enum;
59	int targ_int;
60	int targ_struct_typedef;
61	int targ_func_proto_typedef;
62	int targ_arr_typedef;
63};
64
65/* preserve types even if Clang doesn't support built-in */
66struct a_struct t1 = {};
67union a_union t2 = {};
68enum an_enum t3 = 0;
69named_struct_typedef t4 = {};
70func_proto_typedef t5 = 0;
71arr_typedef t6 = {};
72
73SEC("raw_tracepoint/sys_enter")
74int test_core_type_id(void *ctx)
75{
76	/* We use __builtin_btf_type_id() in this tests, but up until the time
77	 * __builtin_preserve_type_info() was added it contained a bug that
78	 * would make this test fail. The bug was fixed ([0]) with addition of
79	 * __builtin_preserve_type_info(), though, so that's what we are using
80	 * to detect whether this test has to be executed, however strange
81	 * that might look like.
82	 *
83	 *   [0] https://github.com/llvm/llvm-project/commit/00602ee7ef0bf6c68d690a2bd729c12b95c95c99
84	 */
85#if __has_builtin(__builtin_preserve_type_info)
86	struct core_reloc_type_id_output *out = (void *)&data.out;
87
88	out->local_anon_struct = bpf_core_type_id_local(struct { int marker_field; });
89	out->local_anon_union = bpf_core_type_id_local(union { int marker_field; });
90	out->local_anon_enum = bpf_core_type_id_local(enum { MARKER_ENUM_VAL = 123 });
91	out->local_anon_func_proto_ptr = bpf_core_type_id_local(_Bool(*)(int));
92	out->local_anon_void_ptr = bpf_core_type_id_local(void *);
93	out->local_anon_arr = bpf_core_type_id_local(_Bool[47]);
94
95	out->local_struct = bpf_core_type_id_local(struct a_struct);
96	out->local_union = bpf_core_type_id_local(union a_union);
97	out->local_enum = bpf_core_type_id_local(enum an_enum);
98	out->local_int = bpf_core_type_id_local(int);
99	out->local_struct_typedef = bpf_core_type_id_local(named_struct_typedef);
100	out->local_func_proto_typedef = bpf_core_type_id_local(func_proto_typedef);
101	out->local_arr_typedef = bpf_core_type_id_local(arr_typedef);
102
103	out->targ_struct = bpf_core_type_id_kernel(struct a_struct);
104	out->targ_union = bpf_core_type_id_kernel(union a_union);
105	out->targ_enum = bpf_core_type_id_kernel(enum an_enum);
106	out->targ_int = bpf_core_type_id_kernel(int);
107	out->targ_struct_typedef = bpf_core_type_id_kernel(named_struct_typedef);
108	out->targ_func_proto_typedef = bpf_core_type_id_kernel(func_proto_typedef);
109	out->targ_arr_typedef = bpf_core_type_id_kernel(arr_typedef);
110#else
111	data.skip = true;
112#endif
113
114	return 0;
115}
116