Optimize R_386_GOT32/R_386_GOT32X only if addend is 0

Linker can't optimize R_386_GOT32 and R_386_GOT32X relocations if addend
isn't 0.  It isn't valid to convert

movl	foo@GOT+1(%ecx), %eax

to

leal	foo@GOTOFF+1(%ecx), %eax

nor to convert

movq	foo@GOTPCREL+1(%rip), %rax

to

leaq	foo(%rip), %rax

for x86-64.  We should check if addend is 0 before optimizing R_386_GOT32
and R_386_GOT32X relocations.  Testcases are added for i386 and x86-64.

bfd/

	* elf32-i386.c (elf_i386_convert_load): Skip if addend isn't 0.
	(elf_i386_relocate_section): Skip R_386_GOT32X optimization if
	addend isn't 0.

ld/testsuite/

	* ld-i386/i386.exp: Run mov2a, mov2b and mov3.
	* ld-i386/mov2.s: New file.
	* ld-i386/mov2a.d: Likewise.
	* ld-i386/mov2b.d: Likewise.
	* ld-i386/mov3.d: Likewise.
	* ld-i386/mov3.s: Likewise.
	* ld-x86-64/mov2.s: Likewise.
	* ld-x86-64/mov2a.d: Likewise.
	* ld-x86-64/mov2b.d: Likewise.
	* ld-x86-64/mov2c.d: Likewise.
	* ld-x86-64/mov2d.d: Likewise.
	* ld-x86-64/x86-64.exp: Run mov2a, mov2b, mov2c and mov2d.
This commit is contained in:
H.J. Lu
2015-12-04 08:43:45 -08:00
parent f27c5390b2
commit 02e2aef89b
15 changed files with 186 additions and 13 deletions

View File

@ -1,3 +1,9 @@
2015-12-04 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_convert_load): Skip if addend isn't 0.
(elf_i386_relocate_section): Skip R_386_GOT32X optimization if
addend isn't 0.
2015-12-04 Tristan Gingold <gingold@adacore.com> 2015-12-04 Tristan Gingold <gingold@adacore.com>
* elf.c (rewrite_elf_program_header): Remove useless loop. * elf.c (rewrite_elf_program_header): Remove useless loop.

View File

@ -2820,6 +2820,11 @@ elf_i386_convert_load (bfd *abfd, asection *sec,
if (roff < 2) if (roff < 2)
continue; continue;
/* Addend for R_386_GOT32 and R_386_GOT32X relocations must be 0. */
addend = bfd_get_32 (abfd, contents + roff);
if (addend != 0)
continue;
modrm = bfd_get_8 (abfd, contents + roff - 1); modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5; baseless = (modrm & 0xc7) == 0x5;
@ -2913,11 +2918,6 @@ elf_i386_convert_load (bfd *abfd, asection *sec,
{ {
/* The function is locally defined. */ /* The function is locally defined. */
convert_branch: convert_branch:
addend = bfd_get_32 (abfd, contents + roff);
/* Addend for R_386_GOT32X relocation must be 0. */
if (addend != 0)
continue;
/* Convert R_386_GOT32X to R_386_PC32. */ /* Convert R_386_GOT32X to R_386_PC32. */
if (modrm == 0x15 || (modrm & 0xf8) == 0x90) if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
{ {
@ -3007,11 +3007,6 @@ convert_load:
} }
else else
{ {
/* Addend for R_386_GOT32X relocation must be 0. */
addend = bfd_get_32 (abfd, contents + roff);
if (addend != 0)
continue;
if (opcode == 0x85) if (opcode == 0x85)
{ {
/* Convert "test %reg1, foo@GOT(%reg2)" to /* Convert "test %reg1, foo@GOT(%reg2)" to
@ -3998,8 +3993,11 @@ elf_i386_relocate_section (bfd *output_bfd,
branch to direct branch. It is OK to convert adc, branch to direct branch. It is OK to convert adc,
add, and, cmp, or, sbb, sub, test, xor only when PIC add, and, cmp, or, sbb, sub, test, xor only when PIC
is false. */ is false. */
unsigned int opcode; unsigned int opcode, addend;
opcode = bfd_get_8 (abfd, contents + rel->r_offset - 2); addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
if (addend != 0)
goto r_386_got32;
opcode = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
if (opcode != 0x8b && opcode != 0xff) if (opcode != 0x8b && opcode != 0xff)
goto r_386_got32; goto r_386_got32;
} }
@ -4031,7 +4029,7 @@ elf_i386_relocate_section (bfd *output_bfd,
/* If not PIC, add the .got.plt section address for /* If not PIC, add the .got.plt section address for
baseless addressing. */ baseless addressing. */
unsigned int modrm; unsigned int modrm;
modrm = bfd_get_8 (abfd, contents + rel->r_offset - 1); modrm = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
if ((modrm & 0xc7) == 0x5) if ((modrm & 0xc7) == 0x5)
relocation += offplt; relocation += offplt;
} }

View File

@ -1,3 +1,16 @@
2015-12-04 H.J. Lu <hongjiu.lu@intel.com>
* ld-i386/i386.exp: Run mov2a and mov2b.
* ld-i386/mov2.s: New file.
* ld-i386/mov2a.d: Likewise.
* ld-i386/mov2b.d: Likewise.
* ld-x86-64/mov2.s: Likewise.
* ld-x86-64/mov2a.d: Likewise.
* ld-x86-64/mov2b.d: Likewise.
* ld-x86-64/mov2c.d: Likewise.
* ld-x86-64/mov2d.d: Likewise.
* ld-x86-64/x86-64.exp: Run mov2a, mov2b, mov2c and mov2d.
2015-12-01 H.J. Lu <hongjiu.lu@intel.com> 2015-12-01 H.J. Lu <hongjiu.lu@intel.com>
PR ld/19319 PR ld/19319

View File

@ -293,6 +293,9 @@ run_dump_test "lea1e"
run_dump_test "lea1f" run_dump_test "lea1f"
run_dump_test "mov1a" run_dump_test "mov1a"
run_dump_test "mov1b" run_dump_test "mov1b"
run_dump_test "mov2a"
run_dump_test "mov2b"
run_dump_test "mov3"
run_dump_test "branch1" run_dump_test "branch1"
run_dump_test "call1" run_dump_test "call1"
run_dump_test "call2" run_dump_test "call2"

View File

@ -0,0 +1,15 @@
.section my_section,"aw",@progbits
.long 0x12345678
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl _start
.type _start, @function
_start:
movl foo@GOT+1(%ecx), %eax
movl __start_my_section@GOT+1(%ecx), %eax
movl __stop_my_section@GOT+1(%ecx), %eax
.size _start, .-_start

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --32
#ld: -shared -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
#pass

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --32
#ld: -pie -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
[ ]*[a-f0-9]+: 8b 81 ([0-9a-f]{2} ){4} * mov -0x[a-f0-9]+\(%ecx\),%eax
#pass

View File

@ -0,0 +1,14 @@
#as: --32
#ld: -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\,%eax
[ ]*[a-f0-9]+: 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\,%eax
[ ]*[a-f0-9]+: 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\,%eax
#pass

View File

@ -0,0 +1,15 @@
.section my_section,"aw",@progbits
.long 0x12345678
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl _start
.type _start, @function
_start:
movl foo@GOT+1, %eax
movl __start_my_section@GOT+1, %eax
movl __stop_my_section@GOT+1, %eax
.size _start, .-_start

View File

@ -0,0 +1,15 @@
.section my_section,"aw",@progbits
.long 0x12345678
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl _start
.type _start, @function
_start:
movq foo@GOTPCREL+1(%rip), %rax
movq __start_my_section@GOTPCREL+1(%rip), %rax
movq __stop_my_section@GOTPCREL+1(%rip), %rax
.size _start, .-_start

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --64
#ld: -shared -melf_x86_64
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
#pass

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --64
#ld: -pie -melf_x86_64
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
#pass

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --x32
#ld: -shared -melf32_x86_64
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
#pass

View File

@ -0,0 +1,15 @@
#source: mov2.s
#as: --x32
#ld: -pie -melf32_x86_64
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: 48 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
#pass

View File

@ -321,6 +321,10 @@ run_dump_test "mov1a"
run_dump_test "mov1b" run_dump_test "mov1b"
run_dump_test "mov1c" run_dump_test "mov1c"
run_dump_test "mov1d" run_dump_test "mov1d"
run_dump_test "mov2a"
run_dump_test "mov2b"
run_dump_test "mov2c"
run_dump_test "mov2d"
run_dump_test "load1a" run_dump_test "load1a"
run_dump_test "load1b" run_dump_test "load1b"
run_dump_test "load1c" run_dump_test "load1c"