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
18struct a_struct {
19	int x;
20};
21
22struct a_complex_struct {
23	union {
24		struct a_struct *a;
25		void *b;
26	} x;
27	volatile long y;
28};
29
30union a_union {
31	int y;
32	int z;
33};
34
35typedef struct a_struct named_struct_typedef;
36
37typedef struct { int x, y, z; } anon_struct_typedef;
38
39typedef struct {
40	int a, b, c;
41} *struct_ptr_typedef;
42
43enum an_enum {
44	AN_ENUM_VAL1 = 1,
45	AN_ENUM_VAL2 = 2,
46	AN_ENUM_VAL3 = 3,
47};
48
49typedef int int_typedef;
50
51typedef enum { TYPEDEF_ENUM_VAL1, TYPEDEF_ENUM_VAL2 } enum_typedef;
52
53typedef void *void_ptr_typedef;
54typedef int *restrict restrict_ptr_typedef;
55
56typedef int (*func_proto_typedef)(long);
57
58typedef char arr_typedef[20];
59
60struct core_reloc_type_based_output {
61	bool struct_exists;
62	bool complex_struct_exists;
63	bool union_exists;
64	bool enum_exists;
65	bool typedef_named_struct_exists;
66	bool typedef_anon_struct_exists;
67	bool typedef_struct_ptr_exists;
68	bool typedef_int_exists;
69	bool typedef_enum_exists;
70	bool typedef_void_ptr_exists;
71	bool typedef_restrict_ptr_exists;
72	bool typedef_func_proto_exists;
73	bool typedef_arr_exists;
74
75	bool struct_matches;
76	bool complex_struct_matches;
77	bool union_matches;
78	bool enum_matches;
79	bool typedef_named_struct_matches;
80	bool typedef_anon_struct_matches;
81	bool typedef_struct_ptr_matches;
82	bool typedef_int_matches;
83	bool typedef_enum_matches;
84	bool typedef_void_ptr_matches;
85	bool typedef_restrict_ptr_matches;
86	bool typedef_func_proto_matches;
87	bool typedef_arr_matches;
88
89	int struct_sz;
90	int union_sz;
91	int enum_sz;
92	int typedef_named_struct_sz;
93	int typedef_anon_struct_sz;
94	int typedef_struct_ptr_sz;
95	int typedef_int_sz;
96	int typedef_enum_sz;
97	int typedef_void_ptr_sz;
98	int typedef_func_proto_sz;
99	int typedef_arr_sz;
100};
101
102SEC("raw_tracepoint/sys_enter")
103int test_core_type_based(void *ctx)
104{
105	/* Support for the BPF_TYPE_MATCHES argument to the
106	 * __builtin_preserve_type_info builtin was added at some point during
107	 * development of clang 15 and it's what we require for this test. Part of it
108	 * could run with merely __builtin_preserve_type_info (which could be checked
109	 * separately), but we have to find an upper bound.
110	 */
111#if __has_builtin(__builtin_preserve_type_info) && __clang_major__ >= 15
112	struct core_reloc_type_based_output *out = (void *)&data.out;
113
114	out->struct_exists = bpf_core_type_exists(struct a_struct);
115	out->complex_struct_exists = bpf_core_type_exists(struct a_complex_struct);
116	out->union_exists = bpf_core_type_exists(union a_union);
117	out->enum_exists = bpf_core_type_exists(enum an_enum);
118	out->typedef_named_struct_exists = bpf_core_type_exists(named_struct_typedef);
119	out->typedef_anon_struct_exists = bpf_core_type_exists(anon_struct_typedef);
120	out->typedef_struct_ptr_exists = bpf_core_type_exists(struct_ptr_typedef);
121	out->typedef_int_exists = bpf_core_type_exists(int_typedef);
122	out->typedef_enum_exists = bpf_core_type_exists(enum_typedef);
123	out->typedef_void_ptr_exists = bpf_core_type_exists(void_ptr_typedef);
124	out->typedef_restrict_ptr_exists = bpf_core_type_exists(restrict_ptr_typedef);
125	out->typedef_func_proto_exists = bpf_core_type_exists(func_proto_typedef);
126	out->typedef_arr_exists = bpf_core_type_exists(arr_typedef);
127
128	out->struct_matches = bpf_core_type_matches(struct a_struct);
129	out->complex_struct_matches = bpf_core_type_matches(struct a_complex_struct);
130	out->union_matches = bpf_core_type_matches(union a_union);
131	out->enum_matches = bpf_core_type_matches(enum an_enum);
132	out->typedef_named_struct_matches = bpf_core_type_matches(named_struct_typedef);
133	out->typedef_anon_struct_matches = bpf_core_type_matches(anon_struct_typedef);
134	out->typedef_struct_ptr_matches = bpf_core_type_matches(struct_ptr_typedef);
135	out->typedef_int_matches = bpf_core_type_matches(int_typedef);
136	out->typedef_enum_matches = bpf_core_type_matches(enum_typedef);
137	out->typedef_void_ptr_matches = bpf_core_type_matches(void_ptr_typedef);
138	out->typedef_restrict_ptr_matches = bpf_core_type_matches(restrict_ptr_typedef);
139	out->typedef_func_proto_matches = bpf_core_type_matches(func_proto_typedef);
140	out->typedef_arr_matches = bpf_core_type_matches(arr_typedef);
141
142	out->struct_sz = bpf_core_type_size(struct a_struct);
143	out->union_sz = bpf_core_type_size(union a_union);
144	out->enum_sz = bpf_core_type_size(enum an_enum);
145	out->typedef_named_struct_sz = bpf_core_type_size(named_struct_typedef);
146	out->typedef_anon_struct_sz = bpf_core_type_size(anon_struct_typedef);
147	out->typedef_struct_ptr_sz = bpf_core_type_size(struct_ptr_typedef);
148	out->typedef_int_sz = bpf_core_type_size(int_typedef);
149	out->typedef_enum_sz = bpf_core_type_size(enum_typedef);
150	out->typedef_void_ptr_sz = bpf_core_type_size(void_ptr_typedef);
151	out->typedef_func_proto_sz = bpf_core_type_size(func_proto_typedef);
152	out->typedef_arr_sz = bpf_core_type_size(arr_typedef);
153#else
154	data.skip = true;
155#endif
156	return 0;
157}
158