[llvm] f04d92a - [X86] Produce R_X86_64_GOTPCRELX for test/binop instructions (MOV32rm/TEST32rm/...) when -Wa, -mrelax-relocations=yes is enabled
Stephan Bergmann via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 2 01:13:00 PST 2020
On 26/10/2020 23:07, Stephan Bergmann wrote:
> On 25/10/2020 00:14, Fangrui Song via llvm-commits wrote:
>>
>> Author: Fangrui Song
>> Date: 2020-10-24T15:14:17-07:00
>> New Revision: f04d92af94a8d763e91ae38fe35319e426dc466c
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/f04d92af94a8d763e91ae38fe35319e426dc466c
>>
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/f04d92af94a8d763e91ae38fe35319e426dc466c.diff
>>
>>
>> LOG: [X86] Produce R_X86_64_GOTPCRELX for test/binop instructions
>> (MOV32rm/TEST32rm/...) when -Wa,-mrelax-relocations=yes is enabled
>>
>> We have been producing R_X86_64_REX_GOTPCRELX (MOV64rm/TEST64rm/...) and
>> R_X86_64_GOTPCRELX for CALL64m/JMP64m without the REX prefix since
>> 2016 (to be
>> consistent with GNU as), but not for MOV32rm/TEST32rm/...
>>
>> Added:
>> llvm/test/MC/X86/gotpcrelx.s
>>
>> Modified:
>> llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
>> llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
>> llvm/test/MC/ELF/got.s
>>
>> Removed:
>> llvm/test/MC/ELF/got-relaxed.s
>
> At least on Linux x86-64 in combination with lld, this causes
> miscompilation when an expression like
>
> ((long) otherfunction) >> 32
>
> computing the upper 32 bits of a function's address is emitted as
>
> movl otherfunction at GOTPCREL+4(%rip), %eax
>
> which lld then optimizes as
>
> lea otherfunction+4(%rip), %eax
>
> computing the lower 32 bits of the function's address + 4.
>
> The simplest reproducer I came up with is
>
>> $ cat test.c
>> void otherfunction(void);
>> int __attribute__ ((visibility("default"))) test1(void) { return
>> (long) otherfunction; }
>> int __attribute__ ((visibility("default"))) test2(void) { return
>> ((long) otherfunction) >> 32; }
>>
>> $ cat otherfunction.c
>> void otherfunction(void) {}
>>
>> $ cat main.c
>> #include <stdio.h>
>> int test1(void);
>> int test2(void);
>> int main() {
>> printf("%08X %08X\n", test1(), test2());
>> return 0;
>> }
>>
>> $ llvm/inst/bin/clang -fpic -fvisibility=hidden -O -c test.c
>> $ objdump -dr test.o | grep -F -A3 '<test'
>> 0000000000000000 <test1>:
>> 0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 6
>> <test1+0x6>
>> 2: R_X86_64_GOTPCRELX otherfunction-0x4
>> 6: c3 retq
>> 7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
>> --
>> 0000000000000010 <test2>:
>> 10: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 16
>> <test2+0x6>
>> 12: R_X86_64_GOTPCRELX otherfunction
>> 16: c3 retq
>>
>> $ llvm/inst/bin/clang -fpic -fvisibility=hidden -c otherfunction.c
>>
>> $ llvm/inst/bin/clang -fuse-ld=lld
>> --ld-path=/home/sbergman/llvm/inst/bin/ld.lld -shared test.o
>> otherfunction.o -o libtest.so
>> $ objdump -dR libtest.so | grep -F -A3 '<test'
>> 00000000000015d0 <test1>:
>> 15d0: 8d 05 1a 00 00 00 lea 0x1a(%rip),%eax
>> # 15f0 <otherfunction>
>> 15d6: c3 retq
>> 15d7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
>> --
>> 00000000000015e0 <test2>:
>> 15e0: 8d 05 0e 00 00 00 lea 0xe(%rip),%eax #
>> 15f4 <otherfunction+0x4>
>> 15e6: c3 retq
>> 15e7: cc int3
>>
>> $ llvm/inst/bin/clang main.c libtest.so
>> $ LD_LIBRARY_PATH=. ./a.out
>> 602065F0 602065F4
>
> where using R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL in test2
> causes the second value printed out to be (first value + 4) instead of
> some 00007F55 or similar.
Any update on this? Shall we revert
<https://github.com/llvm/llvm-project/commit/f04d92af94a8d763e91ae38fe35319e426dc466c>
"[X86] Produce R_X86_64_GOTPCRELX for test/binop instructions
(MOV32rm/TEST32rm/...) when -Wa,-mrelax-relocations=yes is enabled" for now?
More information about the llvm-commits
mailing list