https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107844
--- Comment #1 from David Faust <david.faust at oracle dot com> --- Looks like this is a result of the combination of how the bpf_core_field_exists macro is defined and some sort of optimization(?) happening in the C frontend. Consider: struct S { unsigned short x; char c[12]; }; int foo () { int has_c = bpf_core_field_exists (struct S, c); return has_c; } The bpf_core_field_exists macro expands to: int has_c = __builtin_preserve_field_info((((typeof(struct S) *)0)->c), BPF_RELO_FIELD_EXISTS); For some reason, for array members specifically, this construction results in the tree for the parameter when resolving the builtin being simply: (gdb) pt param <integer_cst 0x7ffff7531b88 type <pointer_type 0x7ffff741bc78> constant 2> i.e. a pointer to 0x2, the offset of 'c' in a 'struct S' mapped at 0x0. For non-array members, 'param' is some kind of <component_ref> as I'd expect. This gives us two problems: a) We cannot distinguish an array member from a non-member constant-value pointer. b) We cannot correctly compute information for the CO-RE relocation. For example, in this case BPF_RELO_FIELD_BYTE_SIZE will be calculated as 8 (size of pointer), not 12 (size of the array). I'm not sure how to resolve this and support the existing helper macros in the kernel/libbpf. Might need some change in the C frontend, or to somehow pass more information to the target_resolve_overloaded_builtin hook...