https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94391
Fangrui Song <i at maskray dot me> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |i at maskray dot me --- Comment #5 from Fangrui Song <i at maskray dot me> --- This bug exposes several problems: * GNU ld does not reject a PC-relative relocation referencing a SHN_ABS symbol * GCC should not produce R_X86_64_PC32 referencing an external symbol in -fpie mode. % gcc -fuse-ld=lld -nostdlib -fpie -pie a.c % objdump -dr a.o ... 0000000000000000 <foo>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # b <foo+0xb> 7: R_X86_64_PC32 _binary_a_c_size-0x4 b: 5d pop %rbp c: c3 retq % gcc -fuse-ld=bfd -nostdlib -fpie -pie a.c b.o -o a /usr/bin/ld.bfd: warning: cannot find entry symbol _start; defaulting to 0000000000001000 % objdump -dr a ... 0000000000001000 <foo>: 1000: 55 push %rbp 1001: 48 89 e5 mov %rsp,%rbp 1004: 48 8d 05 39 f0 ff ff lea -0xfc7(%rip),%rax # 44 <_binary_a_c_size> 100b: 5d pop %rbp 100c: c3 retq It is incorrect to reference a non-preemptible symbol with a PC relative relocation in a -pie link. GNU ld allows it but the code can be incorrect at runtime. lea -0xfc7(%rip),%rax # loads 44 to %rax only if the load base is 0. Due to ASLR (-pie), this is simply not true. lld correctly rejects the relocation. To fix this, I had a write-up last year: https://gcc.gnu.org/legacy-ml/gcc/2019-05/msg00215.html We should change the configure-time HAVE_LD_PIE_COPYRELOC to an option, probably -f(no-)direct-access-extern In clang, HAVE_LD_PIE_COPYRELOC is a compile-time option: -mpie-copy-relocations. But I think we should improve the option name. At the very least, we can also let -fno-pic code reference an external symbol with GOT to avoid copy relocations. -f(no-)direct-access-extern may be a candidate.