https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106834
Bug ID: 106834 Summary: GCC creates R_X86_64_GOTOFF64 for 4-bytes immediate Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: rui314 at gmail dot com Target Milestone: --- I think I found a GCC bug. Here is how to reproduce the issue: ``` $ cat foo.c #include <stdio.h> extern char _GLOBAL_OFFSET_TABLE_[]; int main() { printf("%lx", (unsigned long)_GLOBAL_OFFSET_TABLE_); } $ gcc-12 -c -fPIC foo.c $ gcc -o foo foo.o $ ./foo Illegal instruction (core dumped) ``` The resulting executable crashes with an illegal instruction because the linker overwrites instructions with an immediate. Take a look at the following objdump output: ``` $ objdump -dr foo.o foo.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0: f3 0f 1e fa endbr64 4: 55 push %rbp 5: 48 89 e5 mov %rsp,%rbp 8: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # f <main+0xf> b: R_X86_64_GOTOFF64 _GLOBAL_OFFSET_TABLE_-0x4 f: 48 89 c6 mov %rax,%rsi 12: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 19 <main+0x19> 15: R_X86_64_PC32 .rodata-0x4 19: 48 89 c7 mov %rax,%rdi 1c: b8 00 00 00 00 mov $0x0,%eax 21: e8 00 00 00 00 call 26 <main+0x26> 22: R_X86_64_PLT32 printf-0x4 26: b8 00 00 00 00 mov $0x0,%eax 2b: 5d pop %rbp 2c: c3 ret ``` At offset 0xb, there's a relocation of type R_X86_64_GOTOFF64. GOTOFF64 makes the linker to write a 8-bytes offset to a given symbol. However, the instruction for that relocation is just `mov` and not `movabs`, so the subsequent 4-bytes are accidentally overwrote byt eh linker.