Convert mov foo@GOT(%reg), %reg to lea foo@GOTOFF(%reg), %reg
2015-04-01 Ilya Tocar <ilya.tocar@intel.com> PR gold/17640 * i386.cc (Target_i386::can_convert_mov_to_lea): New. (Target_i386::Scan::local): Don't create GOT entry, when we can convert GOT to GOTOFF. (Target_i386::Scan::global): Ditto. (Target_i386::Relocate::relocate): Convert mov foo@GOT(%reg), %reg to lea foo@GOTOFF(%reg), %reg if possible. * testsuite/Makefile.am (i386_mov_to_lea): New test. * testsuite/i386_mov_to_lea1.s: New. * testsuite/i386_mov_to_lea2.s: Ditto. * testsuite/i386_mov_to_lea3.s: Ditto. * testsuite/i386_mov_to_lea4.s: Ditto. * testsuite/i386_mov_to_lea5.s: Ditto. * testsuite/i386_mov_to_lea.sh: Ditto.
This commit is contained in:
parent
918357b955
commit
c4fc4724a6
@ -1,3 +1,20 @@
|
||||
2015-04-01 Ilya Tocar <ilya.tocar@intel.com>
|
||||
|
||||
PR gold/17640
|
||||
* i386.cc (Target_i386::can_convert_mov_to_lea): New.
|
||||
(Target_i386::Scan::local): Don't create GOT entry, when we
|
||||
can convert GOT to GOTOFF.
|
||||
(Target_i386::Scan::global): Ditto.
|
||||
(Target_i386::Relocate::relocate): Convert mov foo@GOT(%reg), %reg to
|
||||
lea foo@GOTOFF(%reg), %reg if possible.
|
||||
* testsuite/Makefile.am (i386_mov_to_lea): New test.
|
||||
* testsuite/i386_mov_to_lea1.s: New.
|
||||
* testsuite/i386_mov_to_lea2.s: Ditto.
|
||||
* testsuite/i386_mov_to_lea3.s: Ditto.
|
||||
* testsuite/i386_mov_to_lea4.s: Ditto.
|
||||
* testsuite/i386_mov_to_lea5.s: Ditto.
|
||||
* testsuite/i386_mov_to_lea.sh: Ditto.
|
||||
|
||||
2015-04-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* Makefile.am (ZLIB): New.
|
||||
|
127
gold/i386.cc
127
gold/i386.cc
@ -738,6 +738,26 @@ class Target_i386 : public Sized_target<32, false>
|
||||
static tls::Tls_optimization
|
||||
optimize_tls_reloc(bool is_final, int r_type);
|
||||
|
||||
// Check if relocation against this symbol is a candidate for
|
||||
// conversion from
|
||||
// mov foo@GOT(%reg), %reg
|
||||
// to
|
||||
// lea foo@GOTOFF(%reg), %reg.
|
||||
static bool
|
||||
can_convert_mov_to_lea(const Symbol* gsym)
|
||||
{
|
||||
gold_assert(gsym != NULL);
|
||||
return (gsym->type() != elfcpp::STT_GNU_IFUNC
|
||||
&& !gsym->is_undefined ()
|
||||
&& !gsym->is_from_dynobj()
|
||||
&& !gsym->is_preemptible()
|
||||
&& (!parameters->options().shared()
|
||||
|| (gsym->visibility() != elfcpp::STV_DEFAULT
|
||||
&& gsym->visibility() != elfcpp::STV_PROTECTED)
|
||||
|| parameters->options().Bsymbolic())
|
||||
&& strcmp(gsym->name(), "_DYNAMIC") != 0);
|
||||
}
|
||||
|
||||
// Get the GOT section, creating it if necessary.
|
||||
Output_data_got<32, false>*
|
||||
got_section(Symbol_table*, Layout*);
|
||||
@ -1835,8 +1855,26 @@ Target_i386::Scan::local(Symbol_table* symtab,
|
||||
|
||||
case elfcpp::R_386_GOT32:
|
||||
{
|
||||
// The symbol requires a GOT entry.
|
||||
// We need GOT section.
|
||||
Output_data_got<32, false>* got = target->got_section(symtab, layout);
|
||||
|
||||
// If the relocation symbol isn't IFUNC,
|
||||
// and is local, then we will convert
|
||||
// mov foo@GOT(%reg), %reg
|
||||
// to
|
||||
// lea foo@GOTOFF(%reg), %reg
|
||||
// in Relocate::relocate.
|
||||
if (reloc.get_r_offset() >= 2
|
||||
&& lsym.get_st_type() != elfcpp::STT_GNU_IFUNC)
|
||||
{
|
||||
section_size_type stype;
|
||||
const unsigned char* view = object->section_contents(data_shndx,
|
||||
&stype, true);
|
||||
if (view[reloc.get_r_offset() - 2] == 0x8b)
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, the symbol requires a GOT entry.
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
|
||||
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
|
||||
@ -2229,8 +2267,24 @@ Target_i386::Scan::global(Symbol_table* symtab,
|
||||
|
||||
case elfcpp::R_386_GOT32:
|
||||
{
|
||||
// The symbol requires a GOT entry.
|
||||
// The symbol requires a GOT section.
|
||||
Output_data_got<32, false>* got = target->got_section(symtab, layout);
|
||||
|
||||
// If we convert this from
|
||||
// mov foo@GOT(%reg), %reg
|
||||
// to
|
||||
// lea foo@GOTOFF(%reg), %reg
|
||||
// in Relocate::relocate, then there is nothing to do here.
|
||||
if (reloc.get_r_offset() >= 2
|
||||
&& Target_i386::can_convert_mov_to_lea(gsym))
|
||||
{
|
||||
section_size_type stype;
|
||||
const unsigned char* view = object->section_contents(data_shndx,
|
||||
&stype, true);
|
||||
if (view[reloc.get_r_offset() - 2] == 0x8b)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gsym->final_value_is_known())
|
||||
{
|
||||
// For a STT_GNU_IFUNC symbol we want the PLT address.
|
||||
@ -2732,35 +2786,6 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
|
||||
}
|
||||
}
|
||||
|
||||
// Get the GOT offset if needed.
|
||||
// The GOT pointer points to the end of the GOT section.
|
||||
// We need to subtract the size of the GOT section to get
|
||||
// the actual offset to use in the relocation.
|
||||
bool have_got_offset = false;
|
||||
unsigned int got_offset = 0;
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_386_GOT32:
|
||||
if (gsym != NULL)
|
||||
{
|
||||
gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
|
||||
got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
|
||||
- target->got_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
|
||||
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
|
||||
got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
|
||||
- target->got_size());
|
||||
}
|
||||
have_got_offset = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_386_NONE:
|
||||
@ -2809,8 +2834,44 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_GOT32:
|
||||
gold_assert(have_got_offset);
|
||||
Relocate_functions<32, false>::rel32(view, got_offset);
|
||||
// Convert
|
||||
// mov foo@GOT(%reg), %reg
|
||||
// to
|
||||
// lea foo@GOTOFF(%reg), %reg
|
||||
// if possible.
|
||||
if (rel.get_r_offset() >= 2
|
||||
&& view[-2] == 0x8b
|
||||
&& ((gsym == NULL && !psymval->is_ifunc_symbol())
|
||||
|| (gsym != NULL
|
||||
&& Target_i386::can_convert_mov_to_lea(gsym))))
|
||||
{
|
||||
view[-2] = 0x8d;
|
||||
elfcpp::Elf_types<32>::Elf_Addr value;
|
||||
value = (psymval->value(object, 0)
|
||||
- target->got_plt_section()->address());
|
||||
Relocate_functions<32, false>::rel32(view, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The GOT pointer points to the end of the GOT section.
|
||||
// We need to subtract the size of the GOT section to get
|
||||
// the actual offset to use in the relocation.
|
||||
unsigned int got_offset = 0;
|
||||
if (gsym != NULL)
|
||||
{
|
||||
gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
|
||||
got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
|
||||
- target->got_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
|
||||
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
|
||||
got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
|
||||
- target->got_size());
|
||||
}
|
||||
Relocate_functions<32, false>::rel32(view, got_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_386_GOTOFF:
|
||||
|
@ -962,6 +962,62 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC
|
||||
|
||||
endif TLS
|
||||
|
||||
if DEFAULT_TARGET_I386
|
||||
|
||||
check_SCRIPTS += i386_mov_to_lea.sh
|
||||
check_DATA += i386_mov_to_lea1.stdout i386_mov_to_lea2.stdout \
|
||||
i386_mov_to_lea3.stdout i386_mov_to_lea4.stdout \
|
||||
i386_mov_to_lea5.stdout i386_mov_to_lea6.stdout \
|
||||
i386_mov_to_lea7.stdout i386_mov_to_lea8.stdout
|
||||
MOSTLYCLEANFILES += i386_mov_to_lea1 i386_mov_to_lea2 i386_mov_to_lea3 \
|
||||
i386_mov_to_lea4 i386_mov_to_lea5 i386_mov_to_lea6 \
|
||||
i386_mov_to_lea7 i386_mov_to_lea8
|
||||
|
||||
i386_mov_to_lea1.o: i386_mov_to_lea1.s
|
||||
$(TEST_AS) --32 -o $@ $<
|
||||
i386_mov_to_lea2.o: i386_mov_to_lea2.s
|
||||
$(TEST_AS) --32 -o $@ $<
|
||||
i386_mov_to_lea3.o: i386_mov_to_lea3.s
|
||||
$(TEST_AS) --32 -o $@ $<
|
||||
i386_mov_to_lea4.o: i386_mov_to_lea4.s
|
||||
$(TEST_AS) --32 -o $@ $<
|
||||
i386_mov_to_lea5.o: i386_mov_to_lea5.s
|
||||
$(TEST_AS) --32 -o $@ $<
|
||||
i386_mov_to_lea1: i386_mov_to_lea1.o
|
||||
../ld-new -Bsymbolic -shared -melf_i386 -o $@ $<
|
||||
i386_mov_to_lea2: i386_mov_to_lea1.o
|
||||
../ld-new -pie -melf_i386 -o $@ $<
|
||||
i386_mov_to_lea3: i386_mov_to_lea1.o
|
||||
../ld-new -melf_i386 -o $@ $<
|
||||
i386_mov_to_lea4: i386_mov_to_lea1.o
|
||||
../ld-new -melf_i386 -shared -o $@ $<
|
||||
i386_mov_to_lea5: i386_mov_to_lea2.o
|
||||
../ld-new -melf_i386 -shared -o $@ $<
|
||||
i386_mov_to_lea6: i386_mov_to_lea3.o
|
||||
../ld-new -melf_i386 -shared -o $@ $<
|
||||
i386_mov_to_lea7: i386_mov_to_lea4.o
|
||||
../ld-new -melf_i386 -shared -o $@ $<
|
||||
i386_mov_to_lea8: i386_mov_to_lea5.o
|
||||
../ld-new -melf_i386 -shared -o $@ $<
|
||||
i386_mov_to_lea1.stdout: i386_mov_to_lea1
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea2.stdout: i386_mov_to_lea2
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea3.stdout: i386_mov_to_lea3
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea4.stdout: i386_mov_to_lea4
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea5.stdout: i386_mov_to_lea5
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea6.stdout: i386_mov_to_lea6
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea7.stdout: i386_mov_to_lea7
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
i386_mov_to_lea8.stdout: i386_mov_to_lea8
|
||||
$(TEST_OBJDUMP) -dw $< > $@
|
||||
|
||||
endif DEFAULT_TARGET_I386
|
||||
|
||||
check_PROGRAMS += many_sections_test
|
||||
many_sections_test_SOURCES = many_sections_test.cc
|
||||
many_sections_test_DEPENDENCIES = gcctestdir/ld
|
||||
|
36
gold/testsuite/i386_mov_to_lea.sh
Executable file
36
gold/testsuite/i386_mov_to_lea.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
# i386_mov_to_lea.sh -- a test for mov2lea conversion.
|
||||
|
||||
# Copyright (C) 2010-2015 Free Software Foundation, Inc.
|
||||
# Written by Tocar Ilya <ilya.tocar@intel.com>
|
||||
|
||||
# This file is part of gold.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
set -e
|
||||
|
||||
grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea1.stdout
|
||||
grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea2.stdout
|
||||
grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea3.stdout
|
||||
grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea4.stdout
|
||||
grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea5.stdout
|
||||
grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea6.stdout
|
||||
grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea7.stdout
|
||||
grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea8.stdout
|
||||
|
||||
exit 0
|
11
gold/testsuite/i386_mov_to_lea1.s
Normal file
11
gold/testsuite/i386_mov_to_lea1.s
Normal file
@ -0,0 +1,11 @@
|
||||
.text
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
.size foo, .-foo
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
movl foo@GOT(%ecx), %eax
|
||||
.size bar, .-bar
|
10
gold/testsuite/i386_mov_to_lea2.s
Normal file
10
gold/testsuite/i386_mov_to_lea2.s
Normal file
@ -0,0 +1,10 @@
|
||||
.text
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
.size foo, .-foo
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
movl foo@GOT(%ecx), %eax
|
||||
.size bar, .-bar
|
4
gold/testsuite/i386_mov_to_lea3.s
Normal file
4
gold/testsuite/i386_mov_to_lea3.s
Normal file
@ -0,0 +1,4 @@
|
||||
.type bar, @function
|
||||
bar:
|
||||
movl _DYNAMIC@GOT(%ecx), %eax
|
||||
.size bar, .-bar
|
12
gold/testsuite/i386_mov_to_lea4.s
Normal file
12
gold/testsuite/i386_mov_to_lea4.s
Normal file
@ -0,0 +1,12 @@
|
||||
.text
|
||||
.globl foo
|
||||
.hidden foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
.size foo, .-foo
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
movl foo@GOT(%ecx), %eax
|
||||
.size bar, .-bar
|
12
gold/testsuite/i386_mov_to_lea5.s
Normal file
12
gold/testsuite/i386_mov_to_lea5.s
Normal file
@ -0,0 +1,12 @@
|
||||
.text
|
||||
.globl foo
|
||||
.protected foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
.size foo, .-foo
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
movl foo@GOT(%ecx), %eax
|
||||
.size bar, .-bar
|
Loading…
Reference in New Issue
Block a user