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" ) |
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 | |