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.

Reply via email to