Bug 19609 - [2.26 Regression] Load defined symbol in non-PIC link are wrongly optimized
Summary: [2.26 Regression] Load defined symbol in non-PIC link are wrongly optimized
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.26
: P2 normal
Target Milestone: 2.27
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-02-11 11:04 UTC by H.J. Lu
Modified: 2021-02-04 14:08 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2016-02-11 11:04:31 UTC
[hjl@gnu-6 weakundef-1]$ cat x.c
extern void bar (void) __attribute__((weak));

void *
_start (void)
{
  return bar;
}
[hjl@gnu-6 weakundef-1]$ make
gcc -O2 -fPIC   -c -o x.o x.c
ld  -o x x.o
objdump -dw x

x:     file format elf64-x86-64


Disassembly of section .text:

00000000004000f0 <_start>:
  4000f0:	48 8b 05 31 00 20 00 	mov    0x200031(%rip),%rax        # 600128 <_start+0x200038>
  4000f7:	c3                   	retq   
[hjl@gnu-6 weakundef-1]$ 

Since the address of bar won't change at run-time, mov should be optimized
to lea.
Comment 1 H.J. Lu 2016-02-12 14:52:16 UTC
We should also convert

mov	bar@GOTPCREL(%rip), %rcx

to

mov	$bar, %ecx

if bar is defined below 4GB for non-PIC link.
Comment 2 H.J. Lu 2016-02-12 17:55:06 UTC
[hjl@gnu-6 pr19609]$ cat y.S
	.comm pad,0x30000000,8
	.comm foo,8,8
	.text
	.globl  _start	
	.type	_start, @function
_start:
#ifdef __x86_64__
	cmpq	foo@GOTPCREL(%rip), %rax
#else
	cmpl	foo@GOT(%edx), %eax
#endif
	.size	_start, .-_start
[hjl@gnu-6 pr19609]$ make  LD=./ld-2.25 y
gcc -B./ -Wa,-mrelax-relocations=no   -c -o y.o y.S
./ld-2.25 -Ttext=0x70000000  -o y y.o
[hjl@gnu-6 pr19609]$ objdump -d y

y:     file format elf64-x86-64


Disassembly of section .text:

0000000070000000 <_start>:
    70000000:	48 3b 05 01 00 20 00 	cmp    0x200001(%rip),%rax        # 70200008 <_start+0x200008>
[hjl@gnu-6 pr19609]$ rm y.o
[hjl@gnu-6 pr19609]$ make LD=ld
gcc -B./    -c -o x.o x.S
ld  -o x x.o
gcc -B./    -c -o y.o y.S
ld -Ttext=0x70000000  -o y y.o
y.o: In function `_start':
(.text+0x3): relocation truncated to fit: R_X86_64_32S against symbol `foo' defined in COMMON section in y.o
Makefile:24: recipe for target 'y' failed
make: *** [y] Error 1
[hjl@gnu-6 pr19609]$
Comment 3 Sourceware Commits 2016-02-26 17:42:04 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bae420ef26f4331415b0503141c5931318025906

commit bae420ef26f4331415b0503141c5931318025906
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Feb 26 09:38:08 2016 -0800

    Optimize x86 GOT32X/GOTPCRELX relocations
    
    R_386_GOT32X, R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX relocations
    retrieve the symbol address via its GOT slot.  If the symbol address is
    known at the link-time, we can use it directly by changing instruction
    encoding.  Indirect branch can only be converted to PC relative direct
    branch.  MOV can be changed to LEA or encoded differently with signed
    address.  The subset of binary operations can be encoded only with
    signed address.
    
    If undefined weak symbol is resolved to zero link-time, we can use it
    as address.  Zero addresss can't used with PC relative direct branch
    when PIC is true since the current PC is unknown.  In 64-bit, 32-bit
    relocation for PC relatiave direct branch to zero may also overflow.
    
    If this optimization causes relocation overflow, --no-relax can be used
    to work around it.
    
    bfd/
    
    	PR ld/19609
    	* elf32-i386.c (elf_i386_convert_load): Convert to R_386_32 for
    	load with locally bound symbols if PIC is false or there is no
    	base register.  Optimize branch to 0 if PIC is false.
    	(elf_i386_relocate_section): Don't generate dynamic relocations
    	against undefined weak symbols if PIC is false.
    	* elf64-x86-64.c (elf_x86_64_convert_load): Disable optimization
    	if we can't estimate relocation overflow with --no-relax.
    	Convert to R_X86_64_32S/R_X86_64_32 for load with locally bound
    	symbols if PIC is false.  Optimize branch to 0 if PIC is false.
    	(elf_x86_64_relocate_section): Don't generate dynamic relocations
    	against undefined weak symbols if PIC is false.
    
    ld/
    
    	PR ld/19609
    	* testsuite/ld-i386/got1.dd: Updated.
    	* testsuite/ld-i386/lea1c.d: Likewise.
    	* testsuite/ld-i386/load1-nacl.d: Likewise.
    	* testsuite/ld-i386/load1.d: Likewise.
    	* testsuite/ld-i386/load4b.d: Likewise.
    	* testsuite/ld-i386/load5b.d: Likewise.
    	* testsuite/ld-i386/mov1b.d: Likewise.
    	* testsuite/ld-x86-64/mov1b.d: Likewise.
    	* testsuite/ld-x86-64/mov1d.d: Likewise.
    	* testsuite/ld-ifunc/ifunc-21-i386.d: Likewise.
    	* testsuite/ld-ifunc/ifunc-21-x86-64.d: Likewise.
    	* testsuite/ld-ifunc/ifunc-22-i386.d: Likewise.
    	* testsuite/ld-ifunc/ifunc-22-x86-64.d: Likewise.
    	* testsuite/ld-x86-64/gotpcrel1.dd: Likewise.
    	* testsuite/ld-x86-64/lea1a.d: Likewise.
    	* testsuite/ld-x86-64/lea1b.d: Likewise.
    	* testsuite/ld-x86-64/lea1c.d: Likewise.
    	* testsuite/ld-x86-64/lea1d.d: Likewise.
    	* testsuite/ld-x86-64/lea1e.d: Likewise.
    	* testsuite/ld-x86-64/lea1f.d: Likewise.
    	* testsuite/ld-x86-64/mov1b.d: Likewise.
    	* testsuite/ld-x86-64/mov1d.d: Likewise.
    	* testsuite/ld-x86-64/pr13082-3b.d: Likewise.
    	* testsuite/ld-x86-64/pr13082-4b.d: Likewise.
    	* testsuite/ld-x86-64/lea1.s: Add tests for 32-bit registers.
    	* testsuite/ld-i386/pr19609-1.s: New file.
    	* testsuite/ld-i386/pr19609-1a.d: Likewise.
    	* testsuite/ld-i386/pr19609-1b.d: Likewise.
    	* testsuite/ld-i386/pr19609-1c.d: Likewise.
    	* testsuite/ld-i386/pr19609-1d.d: Likewise.
    	* testsuite/ld-i386/pr19609-1e.d: Likewise.
    	* testsuite/ld-i386/pr19609-1f.d: Likewise.
    	* testsuite/ld-i386/pr19609-1g.d: Likewise.
    	* testsuite/ld-i386/pr19609-1h.d: Likewise.
    	* testsuite/ld-i386/pr19609-1i.d: Likewise.
    	* testsuite/ld-i386/pr19609-2.s: Likewise.
    	* testsuite/ld-i386/pr19609-2a.d: Likewise.
    	* testsuite/ld-i386/pr19609-2b.d: Likewise.
    	* testsuite/ld-i386/pr19609-2c.d: Likewise.
    	* testsuite/ld-i386/undefweak.s: Likewise.
    	* testsuite/ld-i386/undefweaka.d: Likewise.
    	* testsuite/ld-i386/undefweakb.d: Likewise.
    	* testsuite/ld-x86-64/pr13082-3c.d: Likewise.
    	* testsuite/ld-x86-64/pr13082-3d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-1a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1e.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1f.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1g.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1h.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1i.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1j.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1k.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1l.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-1m.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-2.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-2a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-2b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-2c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-2d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-3.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-3a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-3b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-4.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-4a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-4b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-4c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-4d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-4e.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-5.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-5a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-5b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-5c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-5d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-5e.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-6.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-6a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-6b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-6c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-6d.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-7.s: Likewise.
    	* testsuite/ld-x86-64/pr19609-7a.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-7b.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-7c.d: Likewise.
    	* testsuite/ld-x86-64/pr19609-7d.d: Likewise.
    	* testsuite/ld-i386/i386.exp: Run undefweak tests and tests for
    	PR ld/19609.
    	* testsuite/ld-x86-64/x86-64.exp: Run pr13082-3c, pr13082-3d
    	and tests for PR ld/19609.
Comment 4 H.J. Lu 2016-02-26 18:00:19 UTC
Fixed for 2.27.  No plan to backport to 2.26.
Comment 5 Sourceware Commits 2021-02-04 14:08:57 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1a2f1b54a520b28891910846c8671e1c4bcaf348

commit 1a2f1b54a520b28891910846c8671e1c4bcaf348
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Feb 4 06:02:13 2021 -0800

    x86-64: Provide more info when failed to convert GOTPCREL
    
    Provide
    
    [hjl@gnu-cfl-2 ld]$ ./ld-new -z norelro  -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-x86-64  -melf32_x86_64 -Ttext=0x80000000 -o tmpdir/dump tmpdir/pr19609-7.o
    tmpdir/pr19609-7.o: in function `_start':
    (.text+0x2): failed to convert GOTPCREL relocation against 'foobar'; relink with --no-relax
    [hjl@gnu-cfl-2 ld]$
    
    instead of
    
    [hjl@gnu-cfl-2 ld]$ ld -z norelro  -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-x86-64  -melf32_x86_64 -Ttext=0x80000000 -o tmpdir/dump tmpdir/pr19609-7.o
    ld: failed to convert GOTPCREL relocation; relink with --no-relax
    [hjl@gnu-cfl-2 ld]$
    
    bfd/
    
            PR ld/19609
            * elf64-x86-64.c (elf_x86_64_relocate_section): Provide more
            info when failed to convert GOTPCREL relocation.
    
    ld/
    
            PR ld/19609
            * testsuite/ld-x86-64/pr19609-2a.d: Updated.
            * testsuite/ld-x86-64/pr19609-2b.d: Likewise.
            * testsuite/ld-x86-64/pr19609-4a.d: Likewise.
            * testsuite/ld-x86-64/pr19609-4c.d: Likewise.
            * testsuite/ld-x86-64/pr19609-5d.d: Likewise.
            * testsuite/ld-x86-64/pr19609-7a.d: Likewise.
            * testsuite/ld-x86-64/pr19609-7c.d: Likewise.