[hjl@gnu-tgl-3 tmp]$ cat 32.s .text movl $_GLOBAL_OFFSET_TABLE_, %eax .data .long _GLOBAL_OFFSET_TABLE_ [hjl@gnu-tgl-3 tmp]$ gcc -c 32.s -m32 [hjl@gnu-tgl-3 tmp]$ readelf -r 32.o Relocation section '.rel.text' at offset 0xa0 contains 1 entry: Offset Info Type Sym.Value Sym. Name 00000001 0000010a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_ Relocation section '.rel.data' at offset 0xa8 contains 1 entry: Offset Info Type Sym.Value Sym. Name 00000000 0000010a R_386_GOTPC 00000000 _GLOBAL_OFFSET_TABLE_ [hjl@gnu-tgl-3 tmp]$ R_386_32 should be used. [hjl@gnu-tgl-3 tmp]$ cat 64.s .text movl $_GLOBAL_OFFSET_TABLE_, %eax movq _GLOBAL_OFFSET_TABLE_@GOTPCREL(%rip), %rax .data .quad _GLOBAL_OFFSET_TABLE_ [hjl@gnu-tgl-3 tmp]$ gcc -c 64.s [hjl@gnu-tgl-3 tmp]$ readelf -rW 64.o Relocation section '.rela.text' at offset 0xd0 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000001 000000010000001a R_X86_64_GOTPC32 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 1 0000000000000008 0000000100000019 R_X86_64_GOTOFF64 0000000000000000 _GLOBAL_OFFSET_TABLE_ - 4 Relocation section '.rela.data' at offset 0x100 contains 1 entry: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000000 000000010000001d R_X86_64_GOTPC64 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 0 [hjl@gnu-tgl-3 tmp]$ Relocations should be [hjl@gnu-tgl-3 tmp]$ readelf -rW 64x.o Relocation section '.rela.text' at offset 0xe8 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000001 000000010000000a R_X86_64_32 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 0 0000000000000008 000000010000002a R_X86_64_REX_GOTPCRELX 0000000000000000 _GLOBAL_OFFSET_TABLE_ - 4 Relocation section '.rela.data' at offset 0x118 contains 1 entry: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000000 0000000100000001 R_X86_64_64 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 0 [hjl@gnu-tgl-3 tmp]$
GCC generates call __x86.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx to load the address of _GLOBAL_OFFSET_TABLE_ into EBX with R_386_GOTPC relocation.
We can't change _GLOBAL_OFFSET_TABLE_ nor _GLOBAL_OFFSET_TABLE_(%rip). _GLOBAL_OFFSET_TABLE_ generates GOTPC32 relocation. _GLOBAL_OFFSET_TABLE_(%rip) generates GOTPC32 relocation which is the same as PC32 since symbol is GOT. But we should handle _GLOBAL_OFFSET_TABLE_@GOTPCREL(%rip). i386_displacement first generates BFD_RELOC_X86_64_GOTPCREL for symbol@GOTPCREL(%rip). Then i386_finalize_displacement changes it to BFD_RELOC_32_PCREL. Before i386_validate_fix changes BFD_RELOC_32_PCREL back to BFD_RELOC_X86_64_GOTPCREL, output_disp changes BFD_RELOC_32_PCREL to BFD_RELOC_X86_64_GOTPC32 because symbol == _GLOBAL_OFFSET_TABLE_.
commit d6ab8113e32876e3d8ca06ad090d3160d51c8e16 Author: Jan Beulich <jbeulich@novell.com> Date: Fri Jun 17 08:03:59 2005 +0000 has (output_disp): Do GOTPC conversion also for BFD_RELOC_X86_64_32S and BFD_RELOC_32_PCREL. Use BFD_RELOC_X86_64_GOTPC32 instead of aborting. Remove || reloc_type == BFD_RELOC_32_PCREL) seems to work.
If that also allows _GLOBAL_OFFSET_TABLE_-. to work as expected, perhaps that's the way to go. It's been a long time, but I expect that form of expression was what I had in mind when adding the check for BFD_RELOC_32_PCREL. What I'm unsure about is whether _GLOBAL_OFFSET_TABLE_@GOTPCREL is actually a legitimate construct. We're way to lax with (not) rejecting invalid <symbol>@<reloc> constructs anyway, so us not currently rejecting this means about nothing.