This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] PR gold/17640
- From: Ilya Tocar <tocarip dot intel at gmail dot com>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: Cary Coutant <ccoutant at google dot com>, Binutils <binutils at sourceware dot org>
- Date: Thu, 12 Mar 2015 17:57:32 +0300
- Subject: Re: [PATCH] PR gold/17640
- Authentication-results: sourceware.org; auth=none
- References: <CAHACq4ojyujhxYSsMaF_jSVWUg0=YgNawR6=6XYdZie1PMhXYQ at mail dot gmail dot com> <20150227142003 dot GA122934 at msticlxl7 dot ims dot intel dot com> <CAMe9rOrzXOu+CkT_A7XZLJ1MK_nqnMk69LjgXUSQ-FnS1fKsEQ at mail dot gmail dot com> <CAMe9rOq-uSd64h6eeogR3SywtQipMupN9Ng9-EvPLF+3bp7Exw at mail dot gmail dot com> <20150305104052 dot GA16361 at msticlxl7 dot ims dot intel dot com> <CAMe9rOqRQ+HMS12+hn9Nz0pnb95tUDmbAU2QjK9G1Rc-q=woCA at mail dot gmail dot com> <20150310112745 dot GA104717 at msticlxl7 dot ims dot intel dot com> <CAMe9rOoG6NOVLYxZBJ5KRuS9_47=ptsd=Ft9iA9HfN2Asw0UeQ at mail dot gmail dot com> <20150312143236 dot GA95320 at msticlxl7 dot ims dot intel dot com> <CAMe9rOpn0uGDm1qbwgL-7CiYKjQeSHMHX6WzsnZ6eyfcp2MBAw at mail dot gmail dot com>
On 12 Mar 07:44, H.J. Lu wrote:
> On Thu, Mar 12, 2015 at 7:33 AM, Ilya Tocar <tocarip.intel@gmail.com> wrote:
>
> > I've rebased patch against current trunk, and removed blank lines.
> > Ok for trunk?
> >
> > ---
> > gold/ChangeLog | 16 +++++
> > gold/i386.cc | 122 ++++++++++++++++++++++++++++----------
> > gold/testsuite/Makefile.am | 59 ++++++++++++++++++
> > gold/testsuite/i386_mov_to_lea.sh | 37 ++++++++++++
> > gold/testsuite/i386_mov_to_lea1.s | 11 ++++
> > gold/testsuite/i386_mov_to_lea2.s | 10 ++++
> > gold/testsuite/i386_mov_to_lea3.s | 4 ++
> > gold/testsuite/i386_mov_to_lea4.s | 12 ++++
> > gold/testsuite/i386_mov_to_lea5.s | 12 ++++
> > 9 files changed, 251 insertions(+), 32 deletions(-)
> > create mode 100755 gold/testsuite/i386_mov_to_lea.sh
> > create mode 100644 gold/testsuite/i386_mov_to_lea1.s
> > create mode 100644 gold/testsuite/i386_mov_to_lea2.s
> > create mode 100644 gold/testsuite/i386_mov_to_lea3.s
> > create mode 100644 gold/testsuite/i386_mov_to_lea4.s
> > create mode 100644 gold/testsuite/i386_mov_to_lea5.s
> >
> > diff --git a/gold/ChangeLog b/gold/ChangeLog
> > index f94e170..8b96819 100644
> > --- a/gold/ChangeLog
> > +++ b/gold/ChangeLog
> > @@ -1,3 +1,19 @@
> > +2015-03-12 Ilya Tocar <ilya.tocar@intel.com>
> > +
> > + PR gold/17640
> > + * i386.cc (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-03-11 Cary Coutant <ccoutant@google.com>
> >
> > * options.cc (General_options::finalize): Don't allow -z relro
> > diff --git a/gold/i386.cc b/gold/i386.cc
> > index 24f4103..108f1fb 100644
> > --- a/gold/i386.cc
> > +++ b/gold/i386.cc
> > @@ -1835,8 +1835,27 @@ 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;
> > +
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Please remove the blank line.
>
>
Removed, sorry.
---
gold/ChangeLog | 16 +++++
gold/i386.cc | 121 ++++++++++++++++++++++++++++----------
gold/testsuite/Makefile.am | 59 +++++++++++++++++++
gold/testsuite/i386_mov_to_lea.sh | 37 ++++++++++++
gold/testsuite/i386_mov_to_lea1.s | 11 ++++
gold/testsuite/i386_mov_to_lea2.s | 10 ++++
gold/testsuite/i386_mov_to_lea3.s | 4 ++
gold/testsuite/i386_mov_to_lea4.s | 12 ++++
gold/testsuite/i386_mov_to_lea5.s | 12 ++++
9 files changed, 250 insertions(+), 32 deletions(-)
create mode 100755 gold/testsuite/i386_mov_to_lea.sh
create mode 100644 gold/testsuite/i386_mov_to_lea1.s
create mode 100644 gold/testsuite/i386_mov_to_lea2.s
create mode 100644 gold/testsuite/i386_mov_to_lea3.s
create mode 100644 gold/testsuite/i386_mov_to_lea4.s
create mode 100644 gold/testsuite/i386_mov_to_lea5.s
diff --git a/gold/ChangeLog b/gold/ChangeLog
index f94e170..8b96819 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,19 @@
+2015-03-12 Ilya Tocar <ilya.tocar@intel.com>
+
+ PR gold/17640
+ * i386.cc (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-03-11 Cary Coutant <ccoutant@google.com>
* options.cc (General_options::finalize): Don't allow -z relro
diff --git a/gold/i386.cc b/gold/i386.cc
index 24f4103..dee3abc 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -1835,8 +1835,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
@@ -2231,6 +2249,31 @@ Target_i386::Scan::global(Symbol_table* symtab,
{
// The symbol requires a GOT entry.
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.
+ // Avoid converting _DYNAMIC, because its address may be used.
+ if (reloc.get_r_offset() >= 2
+ && 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"))
+ {
+ 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 +2775,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 +2823,51 @@ 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);
+ // If the relocation symbol isn't IFUNC,
+ // and is local, then we convert
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ if (rel.get_r_offset() >= 2
+ && view[-2] == 0x8b
+ && ((gsym == NULL && !psymval->is_ifunc_symbol())
+ || (gsym != NULL
+ && gsym->type() != elfcpp::STT_GNU_IFUNC
+ && !gsym->is_from_dynobj()
+ && !gsym->is_undefined ()
+ && (!parameters->options().shared()
+ || (gsym->visibility() != elfcpp::STV_DEFAULT
+ && gsym->visibility() != elfcpp::STV_PROTECTED)
+ || parameters->options().Bsymbolic())
+ && !gsym->is_preemptible())))
+ {
+ 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:
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 43da146..5643029 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -957,6 +957,65 @@ 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 \
+ i386_mov_to_lea9.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_lea6
+ $(TEST_READELF) -s $< > $@
+i386_mov_to_lea8.stdout: i386_mov_to_lea7
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea9.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
diff --git a/gold/testsuite/i386_mov_to_lea.sh b/gold/testsuite/i386_mov_to_lea.sh
new file mode 100755
index 0000000..940f6c8
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea.sh
@@ -0,0 +1,37 @@
+#!/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 "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea6.stdout
+grep -q "_DYNAMIC" i386_mov_to_lea7.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea8.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea9.stdout
+
+exit 0
diff --git a/gold/testsuite/i386_mov_to_lea1.s b/gold/testsuite/i386_mov_to_lea1.s
new file mode 100644
index 0000000..6d0f436
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea1.s
@@ -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
diff --git a/gold/testsuite/i386_mov_to_lea2.s b/gold/testsuite/i386_mov_to_lea2.s
new file mode 100644
index 0000000..65f1bfd
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea2.s
@@ -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
diff --git a/gold/testsuite/i386_mov_to_lea3.s b/gold/testsuite/i386_mov_to_lea3.s
new file mode 100644
index 0000000..6785e71
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea3.s
@@ -0,0 +1,4 @@
+ .type bar, @function
+bar:
+ movl _DYNAMIC@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/gold/testsuite/i386_mov_to_lea4.s b/gold/testsuite/i386_mov_to_lea4.s
new file mode 100644
index 0000000..7e4c4db
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea4.s
@@ -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
diff --git a/gold/testsuite/i386_mov_to_lea5.s b/gold/testsuite/i386_mov_to_lea5.s
new file mode 100644
index 0000000..6999aae
--- /dev/null
+++ b/gold/testsuite/i386_mov_to_lea5.s
@@ -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
--
1.8.3.1