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 
10 char _license[] SEC("license") = "GPL";
11 
12 struct {
13 	char in[256];
14 	char out[256];
15 	bool skip;
16 } data = {};
17 
18 struct a_struct {
19 	int x;
20 };
21 
22 struct a_complex_struct {
23 	union {
24 		struct a_struct *a;
25 		void *b;
26 	} x;
27 	volatile long y;
28 };
29 
30 union a_union {
31 	int y;
32 	int z;
33 };
34 
35 typedef struct a_struct named_struct_typedef;
36 
37 typedef struct { int x, y, z; } anon_struct_typedef;
38 
39 typedef struct {
40 	int a, b, c;
41 } *struct_ptr_typedef;
42 
43 enum an_enum {
44 	AN_ENUM_VAL1 = 1,
45 	AN_ENUM_VAL2 = 2,
46 	AN_ENUM_VAL3 = 3,
47 };
48 
49 typedef int int_typedef;
50 
51 typedef enum { TYPEDEF_ENUM_VAL1, TYPEDEF_ENUM_VAL2 } enum_typedef;
52 
53 typedef void *void_ptr_typedef;
54 typedef int *restrict restrict_ptr_typedef;
55 
56 typedef int (*func_proto_typedef)(long);
57 
58 typedef char arr_typedef[20];
59 
60 struct 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 
102 SEC("raw_tracepoint/sys_enter")
test_core_type_based(void * ctx)103 int 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