github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/testdata/relocs.c (about) 1 #include "../../testdata/common.h" 2 #include "bpf_core_read.h" 3 4 enum e { 5 ZERO = 0, 6 ONE, 7 TWO, 8 }; 9 10 enum e64 { 11 LARGE = 0x1ffffffff, 12 }; 13 14 typedef enum e e_t; 15 16 struct s { 17 int _1; 18 char _2; 19 unsigned int _3; 20 }; 21 22 typedef struct s s_t; 23 24 union u { 25 int *_1; 26 char *_2; 27 unsigned int *_3; 28 }; 29 30 typedef union u u_t; 31 32 #define local_id_not_zero(expr) \ 33 ({ \ 34 if (bpf_core_type_id_local(expr) == 0) { \ 35 return __LINE__; \ 36 } \ 37 }) 38 39 #define target_and_local_id_dont_match(expr) \ 40 ({ \ 41 if (bpf_core_type_id_kernel(expr) == bpf_core_type_id_local(expr)) { \ 42 return __LINE__; \ 43 } \ 44 }) 45 46 __section("socket/type_ids") int type_ids() { 47 local_id_not_zero(int); 48 local_id_not_zero(struct { int frob; }); 49 local_id_not_zero(enum {FRAP}); 50 local_id_not_zero(union { char bar; }); 51 52 local_id_not_zero(struct s); 53 local_id_not_zero(s_t); 54 local_id_not_zero(const s_t); 55 local_id_not_zero(volatile s_t); 56 local_id_not_zero(enum e); 57 local_id_not_zero(e_t); 58 local_id_not_zero(const e_t); 59 local_id_not_zero(volatile e_t); 60 local_id_not_zero(union u); 61 local_id_not_zero(u_t); 62 local_id_not_zero(const u_t); 63 local_id_not_zero(volatile u_t); 64 65 // In this context, target is the BTF generated by clang. local is 66 // generated on the fly by the library. There is a low chance that 67 // the order on both is the same, so we assert this to make sure that 68 // CO-RE uses the IDs from the dynamic BTF. 69 // Qualifiers on types crash clang. 70 target_and_local_id_dont_match(struct s); 71 target_and_local_id_dont_match(s_t); 72 // target_and_local_id_dont_match(const s_t); 73 // target_and_local_id_dont_match(volatile s_t); 74 target_and_local_id_dont_match(enum e); 75 target_and_local_id_dont_match(e_t); 76 // target_and_local_id_dont_match(const e_t); 77 // target_and_local_id_dont_match(volatile e_t); 78 target_and_local_id_dont_match(union u); 79 target_and_local_id_dont_match(u_t); 80 // target_and_local_id_dont_match(const u_t); 81 // target_and_local_id_dont_match(volatile u_t); 82 83 return 0; 84 } 85 86 #define type_exists(expr) \ 87 ({ \ 88 if (!bpf_core_type_exists(expr)) { \ 89 return __LINE__; \ 90 } \ 91 }) 92 93 #define type_size_matches(expr) \ 94 ({ \ 95 if (bpf_core_type_size(expr) != sizeof(expr)) { \ 96 return __LINE__; \ 97 } \ 98 }) 99 100 #define type_matches(expr) \ 101 ({ \ 102 if (!bpf_core_type_matches(expr)) { \ 103 return __LINE__; \ 104 } \ 105 }) 106 107 __section("socket/types") int types() { 108 type_exists(struct s); 109 type_exists(s_t); 110 type_exists(const s_t); 111 type_exists(volatile s_t); 112 type_exists(enum e); 113 type_exists(e_t); 114 type_exists(const e_t); 115 type_exists(volatile e_t); 116 type_exists(union u); 117 type_exists(u_t); 118 type_exists(const u_t); 119 type_exists(volatile u_t); 120 // TODO: Check non-existence. 121 122 type_size_matches(struct s); 123 type_size_matches(s_t); 124 type_size_matches(const s_t); 125 type_size_matches(volatile s_t); 126 type_size_matches(enum e); 127 type_size_matches(e_t); 128 type_size_matches(const e_t); 129 type_size_matches(volatile e_t); 130 type_size_matches(union u); 131 type_size_matches(u_t); 132 type_size_matches(const u_t); 133 type_size_matches(volatile u_t); 134 135 type_matches(struct s); 136 type_matches(s_t); 137 type_matches(const s_t); 138 type_matches(volatile s_t); 139 type_matches(enum e); 140 type_matches(e_t); 141 type_matches(const e_t); 142 type_matches(volatile e_t); 143 type_matches(union u); 144 type_matches(u_t); 145 type_matches(const u_t); 146 type_matches(volatile u_t); 147 148 return 0; 149 } 150 151 #define enum_value_exists(t, v) \ 152 ({ \ 153 if (!bpf_core_enum_value_exists(t, v)) { \ 154 return __LINE__; \ 155 } \ 156 }) 157 158 #define enum_value_matches(t, v) \ 159 ({ \ 160 if (v != bpf_core_enum_value(t, v)) { \ 161 return __LINE__; \ 162 } \ 163 }) 164 165 __section("socket/enums") int enums() { 166 enum_value_exists(enum e, ONE); 167 enum_value_exists(volatile enum e, ONE); 168 enum_value_exists(const enum e, ONE); 169 enum_value_exists(e_t, TWO); 170 enum_value_exists(enum e64, LARGE); 171 // TODO: Check non-existence. 172 173 enum_value_matches(enum e, ZERO); 174 enum_value_matches(enum e, TWO); 175 enum_value_matches(e_t, ONE); 176 enum_value_matches(volatile e_t, ONE); 177 enum_value_matches(const e_t, ONE); 178 enum_value_matches(enum e64, LARGE); 179 180 return 0; 181 } 182 183 #define field_exists(f) \ 184 ({ \ 185 if (!bpf_core_field_exists(f)) { \ 186 return __LINE__; \ 187 } \ 188 }) 189 190 #define field_size_matches(f) \ 191 ({ \ 192 if (sizeof(f) != bpf_core_field_size(f)) { \ 193 return __LINE__; \ 194 } \ 195 }) 196 197 #define field_offset_matches(t, f) \ 198 ({ \ 199 if (__builtin_offsetof(t, f) != __builtin_preserve_field_info(((typeof(t) *)0)->f, BPF_FIELD_BYTE_OFFSET)) { \ 200 return __LINE__; \ 201 } \ 202 }) 203 204 #define field_is_signed(f) \ 205 ({ \ 206 if (!__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \ 207 return __LINE__; \ 208 } \ 209 }) 210 211 #define field_is_unsigned(f) \ 212 ({ \ 213 if (__builtin_preserve_field_info(f, BPF_FIELD_SIGNED)) { \ 214 return __LINE__; \ 215 } \ 216 }) 217 218 __section("socket/fields") int fields() { 219 field_exists((struct s){}._1); 220 field_exists((s_t){}._2); 221 field_exists((union u){}._1); 222 field_exists((u_t){}._2); 223 224 field_is_signed((struct s){}._1); 225 field_is_unsigned((struct s){}._3); 226 // unions crash clang-14. 227 // field_is_signed((union u){}._1); 228 // field_is_unsigned((union u){}._3); 229 230 field_size_matches((struct s){}._1); 231 field_size_matches((s_t){}._2); 232 field_size_matches((union u){}._1); 233 field_size_matches((u_t){}._2); 234 235 field_offset_matches(struct s, _1); 236 field_offset_matches(s_t, _2); 237 field_offset_matches(union u, _1); 238 field_offset_matches(u_t, _2); 239 240 struct t { 241 union { 242 s_t s[10]; 243 }; 244 struct { 245 union u u; 246 }; 247 } bar, *barp = &bar; 248 249 field_exists(bar.s[2]._1); 250 field_exists(bar.s[1]._2); 251 field_exists(bar.u._1); 252 field_exists(bar.u._2); 253 field_exists(barp[1].u._2); 254 255 field_is_signed(bar.s[2]._1); 256 field_is_unsigned(bar.s[2]._3); 257 // unions crash clang-14. 258 // field_is_signed(bar.u._1); 259 // field_is_signed(bar.u._3); 260 261 field_size_matches(bar.s[2]._1); 262 field_size_matches(bar.s[1]._2); 263 field_size_matches(bar.u._1); 264 field_size_matches(bar.u._2); 265 field_size_matches(barp[1].u._2); 266 267 field_offset_matches(struct t, s[2]._1); 268 field_offset_matches(struct t, s[1]._2); 269 field_offset_matches(struct t, u._1); 270 field_offset_matches(struct t, u._2); 271 272 return 0; 273 } 274 275 struct ambiguous { 276 int _1; 277 char _2; 278 }; 279 280 struct ambiguous___flavour { 281 char _1; 282 int _2; 283 }; 284 285 __section("socket/err_ambiguous") int err_ambiguous() { 286 return bpf_core_type_id_kernel(struct ambiguous); 287 } 288 289 __section("socket/err_ambiguous_flavour") int err_ambiguous_flavour() { 290 return bpf_core_type_id_kernel(struct ambiguous___flavour); 291 }