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.

Reply via email to