https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94391
--- Comment #9 from H.J. Lu <hjl.tools at gmail dot com> --- (In reply to Fangrui Song from comment #5) > 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. Your are using the incorrect user code. Please use --- extern unsigned long _binary_a_c_size; unsigned long foo() { return _binary_a_c_size; } --- GCC and ld handle it correctly.