[X86] Don't emit R_X86_64_[REX_]GOTPCRELX for a GOT load with an offset
authorFangrui Song <i@maskray.me>
Mon, 30 Nov 2020 16:27:30 +0000 (08:27 -0800)
committerFangrui Song <i@maskray.me>
Mon, 30 Nov 2020 16:27:31 +0000 (08:27 -0800)
commit25c8fbb3d92fd8321af59bb370e901f0e229b1c9
tree2089c59397490864e82b2c3896533e8f014af08e
parentcbbd7021f176d1344fb4d71d492ccc6017f98151
[X86] Don't emit R_X86_64_[REX_]GOTPCRELX for a GOT load with an offset

clang may produce `movl x@GOTPCREL+4(%rip), %eax` when loading the high
32 bits of the address of a global variable in -fpic/-fpie mode.

If assembled by GNU as, the fixup emits R_X86_64_GOTPCRELX with an addend != -4.
The instruction loads from the GOT entry with an offset and thus it is incorrect
to relax the instruction.

This patch does not emit a relaxable relocation for a GOT load with an offset
because R_X86_64_[REX_]GOTPCRELX do not make sense for instructions which cannot
be relaxed.  The result is good enough for LLD to work. GNU ld relaxes
mov+GOTPCREL as well, but it suppresses the relaxation if addend != -4.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D92114
llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
llvm/test/MC/ELF/got-relaxed-rex.s
llvm/test/MC/X86/gotpcrelx.s