github.com/kubeshark/ebpf@v0.9.2/btf/testdata/relocs.c (about) 1 #include "../../testdata/common.h" 2 #include "bpf_core_read.h" 3 4 enum e { 5 // clang-12 doesn't allow enum relocations with zero value. 6 // See https://reviews.llvm.org/D97659 7 ONE = 1, 8 TWO, 9 }; 10 11 typedef enum e e_t; 12 13 struct s { 14 int _1; 15 char _2; 16 }; 17 18 typedef struct s s_t; 19 20 union u { 21 int *_1; 22 char *_2; 23 }; 24 25 typedef union u u_t; 26 27 #define local_id_zero(expr) \ 28 ({ \ 29 if (bpf_core_type_id_local(expr) != 0) { \ 30 return __LINE__; \ 31 } \ 32 }) 33 34 #define local_id_not_zero(expr) \ 35 ({ \ 36 if (bpf_core_type_id_local(expr) == 0) { \ 37 return __LINE__; \ 38 } \ 39 }) 40 41 #define target_and_local_id_match(expr) \ 42 ({ \ 43 if (bpf_core_type_id_kernel(expr) != bpf_core_type_id_local(expr)) { \ 44 return __LINE__; \ 45 } \ 46 }) 47 48 __section("socket_filter/type_ids") int type_ids() { 49 local_id_not_zero(int); 50 local_id_not_zero(struct { int frob; }); 51 local_id_not_zero(enum {FRAP}); 52 local_id_not_zero(union { char bar; }); 53 54 local_id_not_zero(struct s); 55 local_id_not_zero(s_t); 56 local_id_not_zero(const s_t); 57 local_id_not_zero(volatile s_t); 58 local_id_not_zero(enum e); 59 local_id_not_zero(e_t); 60 local_id_not_zero(const e_t); 61 local_id_not_zero(volatile e_t); 62 local_id_not_zero(union u); 63 local_id_not_zero(u_t); 64 local_id_not_zero(const u_t); 65 local_id_not_zero(volatile u_t); 66 67 // Qualifiers on types crash clang. 68 target_and_local_id_match(struct s); 69 target_and_local_id_match(s_t); 70 // target_and_local_id_match(const s_t); 71 // target_and_local_id_match(volatile s_t); 72 target_and_local_id_match(enum e); 73 target_and_local_id_match(e_t); 74 // target_and_local_id_match(const e_t); 75 // target_and_local_id_match(volatile e_t); 76 target_and_local_id_match(union u); 77 target_and_local_id_match(u_t); 78 // target_and_local_id_match(const u_t); 79 // target_and_local_id_match(volatile u_t); 80 81 return 0; 82 } 83 84 #define type_exists(expr) \ 85 ({ \ 86 if (!bpf_core_type_exists(expr)) { \ 87 return __LINE__; \ 88 } \ 89 }) 90 91 #define type_size_matches(expr) \ 92 ({ \ 93 if (bpf_core_type_size(expr) != sizeof(expr)) { \ 94 return __LINE__; \ 95 } \ 96 }) 97 98 __section("socket_filter/types") int types() { 99 type_exists(struct s); 100 type_exists(s_t); 101 type_exists(const s_t); 102 type_exists(volatile s_t); 103 type_exists(enum e); 104 type_exists(e_t); 105 type_exists(const e_t); 106 type_exists(volatile e_t); 107 type_exists(union u); 108 type_exists(u_t); 109 type_exists(const u_t); 110 type_exists(volatile u_t); 111 // TODO: Check non-existence. 112 113 type_size_matches(struct s); 114 type_size_matches(s_t); 115 type_size_matches(const s_t); 116 type_size_matches(volatile s_t); 117 type_size_matches(enum e); 118 type_size_matches(e_t); 119 type_size_matches(const e_t); 120 type_size_matches(volatile e_t); 121 type_size_matches(union u); 122 type_size_matches(u_t); 123 type_size_matches(const u_t); 124 type_size_matches(volatile u_t); 125 126 return 0; 127 } 128 129 #define enum_value_exists(t, v) \ 130 ({ \ 131 if (!bpf_core_enum_value_exists(t, v)) { \ 132 return __LINE__; \ 133 } \ 134 }) 135 136 #define enum_value_matches(t, v) \ 137 ({ \ 138 if (v != bpf_core_enum_value(t, v)) { \ 139 return __LINE__; \ 140 } \ 141 }) 142 143 __section("socket_filter/enums") int enums() { 144 enum_value_exists(enum e, ONE); 145 enum_value_exists(volatile enum e, ONE); 146 enum_value_exists(const enum e, ONE); 147 enum_value_exists(e_t, TWO); 148 // TODO: Check non-existence. 149 150 enum_value_matches(enum e, TWO); 151 enum_value_matches(e_t, ONE); 152 enum_value_matches(volatile e_t, ONE); 153 enum_value_matches(const e_t, ONE); 154 155 return 0; 156 } 157 158 #define field_exists(f) \ 159 ({ \ 160 if (!bpf_core_field_exists(f)) { \ 161 return __LINE__; \ 162 } \ 163 }) 164 165 #define field_size_matches(f) \ 166 ({ \ 167 if (sizeof(f) != bpf_core_field_size(f)) { \ 168 return __LINE__; \ 169 } \ 170 }) 171 172 #define field_offset_matches(t, f) \ 173 ({ \ 174 if (__builtin_offsetof(t, f) != __builtin_preserve_field_info(((typeof(t) *)0)->f, BPF_FIELD_BYTE_OFFSET)) { \ 175 return __LINE__; \ 176 } \ 177 }) 178 179 __section("socket_filter/fields") int fields() { 180 field_exists((struct s){}._1); 181 field_exists((s_t){}._2); 182 field_exists((union u){}._1); 183 field_exists((u_t){}._2); 184 185 field_size_matches((struct s){}._1); 186 field_size_matches((s_t){}._2); 187 field_size_matches((union u){}._1); 188 field_size_matches((u_t){}._2); 189 190 field_offset_matches(struct s, _1); 191 field_offset_matches(s_t, _2); 192 field_offset_matches(union u, _1); 193 field_offset_matches(u_t, _2); 194 195 struct t { 196 union { 197 s_t s[10]; 198 }; 199 struct { 200 union u u; 201 }; 202 } bar, *barp = &bar; 203 204 field_exists(bar.s[2]._1); 205 field_exists(bar.s[1]._2); 206 field_exists(bar.u._1); 207 field_exists(bar.u._2); 208 field_exists(barp[1].u._2); 209 210 field_size_matches(bar.s[2]._1); 211 field_size_matches(bar.s[1]._2); 212 field_size_matches(bar.u._1); 213 field_size_matches(bar.u._2); 214 field_size_matches(barp[1].u._2); 215 216 field_offset_matches(struct t, s[2]._1); 217 field_offset_matches(struct t, s[1]._2); 218 field_offset_matches(struct t, u._1); 219 field_offset_matches(struct t, u._2); 220 221 return 0; 222 } 223 224 struct ambiguous { 225 int _1; 226 char _2; 227 }; 228 229 struct ambiguous___flavour { 230 char _1; 231 int _2; 232 }; 233 234 __section("socket_filter/err_ambiguous") int err_ambiguous() { 235 return bpf_core_type_id_kernel(struct ambiguous); 236 } 237 238 __section("socket_filter/err_ambiguous_flavour") int err_ambiguous_flavour() { 239 return bpf_core_type_id_kernel(struct ambiguous___flavour); 240 }