https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184
Bug ID: 84184 Summary: gcc generates wrong relocations with negative offsets in struct arrays (but not integral arrays) Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: slyfox at inbox dot ru Target Milestone: --- Created attachment 43327 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43327&action=edit reloc-bug.c It's a trimmed-down version of linux kernel miscompilation on ia64: https://bugs.gentoo.org/518130 Minimal reproducer: // cat reloc-bug.c #include <stdio.h> typedef unsigned long long u64; struct s { u64 a; }; struct s glo_s[] = { { 100, }, // glo_s_middle_hidden: // ; Injected as LDFLAGS="-Wl,--defsym=glo_s_middle=glo_s+8 -Wl,--defsym=glo_s_middle_hidden=glo_s+8" { 700, }, { 800, }, }; extern char glo_s_middle_hidden[] __attribute__((visibility("hidden"))); static u64 __attribute__((noinline)) val_s_hidden(void) { const struct s * m = (const struct s *)glo_s_middle_hidden; return m[-1].a; } int main() { printf ("val/hidden = %lld\n", val_s_hidden()); } + ia64-unknown-linux-gnu-gcc-7.2.0 -c -O2 reloc-bug.c -o reloc-bug.o + ia64-unknown-linux-gnu-gcc-7.2.0 -O2 reloc-bug.o -o reloc-bug -Wl,--defsym=glo_s_middle=glo_s+8 -Wl,--defsym=glo_s_middle_hidden=glo_s+8 + ./reloc-bug ./mk.sh: line 12: 12418 Segmentation fault ./reloc-bug Note a few things: Note 1: it's not trivial to write the code in standard C. I had to synthesise symbol with --defsym. I tried a few targets where this sample crashes instead of returning 100: # fails CC=sparc64-unknown-linux-gnu-gcc CC=ia64-unknown-linux-gnu-gcc CC=alpha-unknown-linux-gnu-gcc # works CC=sparc-unknown-linux-gnu-gcc CC=x86_64-pc-linux-gnu-gcc CC=aarch64-unknown-linux-gnu-gcc CC=armv5tel-softfloat-linux-gnueabi-gcc CC=hppa-unknown-linux-gnu-gcc CC=hppa2.0-unknown-linux-gnu-gcc CC=m68k-unknown-linux-gnu-gcc CC=mips-unknown-linux-gnu-gcc CC=nios2-unknown-linux-gnu-gcc CC=powerpc-unknown-linux-gnu-gcc CC=powerpc64-unknown-linux-gnu-gcc CC=powerpc64le-unknown-linux-gnu-gcc CC=s390x-unknown-linux-gnu-gcc CC=sh4-unknown-linux-gnu-gcc Note 2: If we change struct s { u64 a; }; struct s glo_s[] = { to u64 glo_s[] = { gcc will generate correct code.