Allow copy relocations with pie links
Sriraman Tallam
tmsriram@google.com
Wed May 7 23:20:00 GMT 2014
Hi,
With -pie and x86, the linker complains if it sees a PC-relative relocation
to access a global as it expects a GOTPCREL relocation. This is really not
necessary as the linker could use a copy relocation to get around it. This
patch enables copy relocations with pie.
Context:
This is useful because the GCC compiler with option -fpie makes
every extern global access go through the GOT. That is because the compiler
cannot tell if a global will end up being defined in the executable or not
and is conservative. This ends up hurting performance when the binary is linked
as mostly static where most of the globals do end up being defined in the
executable. By allowing copy relocs with fPIE, the compiler need not generate
a GOTPCREL(GOT access) for any global access. It can safely assume that all
globals will be defined in the executable and generate a PC-relative access
instead. Gold can then create a copy reloc for only the undefined globals.
This optimization helps improve a couple of Google benchmarks by 1-4%. The
performance improvement is primarily from removing the additional memory
access to load the address of a variable using the GOT.
ChangeLog:
* symtab.h (may_need_copy_reloc): Extra default parameter to
indicate if this is a PC relative relocation.
* x86_64.cc (Target_x86_64<size>::Scan::global): Call
may_need_copy_reloc with parameter set to true.
* testsuite/pie_copyrelocs_test.cc: New file.
* testsuite/pie_copyrelocs_shared_test.cc: New file.
* Makefile.am (pie_copyrelocs_test): New test.
* Makefile.in: Regenerate.
Patch attached.
Comments?
Thanks
Sri
-------------- next part --------------
Optimizing accesses to Globals with -fpie -pie:
With -pie and x86, the linker complains if it sees a PC-relative relocation
to access a global as it expects a GOTPCREL relocation. This is really not
necessary as the linker could use a copy relocation to get around it. This
patch enables copy relocations with pie.
Context:
This is useful because currently the GCC compiler with option -fpie makes
every extern global access go through the GOT. That is because the compiler
cannot tell if a global will end up being defined in the executable or not
and is conservative. This ends up hurting performance when the binary is linked
as mostly static where most of the globals do end up being defined in the
executable. By allowing copy relocs with fPIE, the compiler need not generate
a GOTPCREL(GOT access) for any global access. It can safely assume that all
globals will be defined in the executable and generate a PC-relative access
instead. Gold can then create a copy reloc for only the undefined globals.
This optimization helps improve a couple of Google benchmarks by 1-4%. The
performance improvement is primarily from removing the additional memory
access to load the address of a variable using the GOT.
ChangeLog:
* symtab.h (may_need_copy_reloc): Extra default parameter to
indicate if this is a PC relative relocation.
* x86_64.cc (Target_x86_64<size>::Scan::global): Call
may_need_copy_reloc with parameter set to true.
* testsuite/pie_copyrelocs_test.cc: New file.
* testsuite/pie_copyrelocs_shared_test.cc: New file.
* Makefile.am (pie_copyrelocs_test): New test.
* Makefile.in: Regenerate.
diff --git a/gold/symtab.h b/gold/symtab.h
index b06c7b4..a2ab11c 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -818,10 +818,14 @@ class Symbol
// Return true if this may need a COPY relocation.
// References from an executable object to non-function symbols
// defined in a dynamic object may need a COPY relocation.
+ // is_access_pcrel is true means the access to this symbol is via
+ // a pc relative relocation, in which case it is fine to use a
+ // copy reloc with position independent code.
bool
- may_need_copy_reloc() const
+ may_need_copy_reloc(bool is_access_pcrel=false) const
{
- return (!parameters->options().output_is_position_independent()
+ return ((!parameters->options().output_is_position_independent()
+ || is_access_pcrel)
&& parameters->options().copyreloc()
&& this->is_from_dynobj()
&& !this->is_func());
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 52cc05e..58c3b40 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -517,6 +517,16 @@ two_file_pie_test: two_file_test_1_pie.o two_file_test_1b_pie.o \
two_file_test_2_pie.o two_file_test_main_pie.o gcctestdir/ld
$(CXXLINK) -Bgcctestdir/ -pie two_file_test_1_pie.o two_file_test_1b_pie.o two_file_test_2_pie.o two_file_test_main_pie.o
+check_PROGRAMS += pie_copyrelocs_test
+pie_copyrelocs_test_SOURCES = pie_copyrelocs_test.cc
+pie_copyrelocs_test_DEPENDENCIES = gcctestdir/ld pie_copyrelocs_shared_test.so
+pie_copyrelocs_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -pie
+pie_copyrelocs_test_LDADD = pie_copyrelocs_shared_test.so
+pie_copyrelocs_shared_test.o: pie_copyrelocs_shared_test.cc
+ $(CXXCOMPILE) -O2 -fpic -c -o $@ $<
+pie_copyrelocs_shared_test.so: pie_copyrelocs_shared_test.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -shared pie_copyrelocs_shared_test.o
+
check_SCRIPTS += two_file_shared.sh
check_DATA += two_file_shared.dbg
MOSTLYCLEANFILES += two_file_shared.dbg
diff --git a/gold/testsuite/pie_copyrelocs_shared_test.cc b/gold/testsuite/pie_copyrelocs_shared_test.cc
index e69de29..8513417 100644
--- a/gold/testsuite/pie_copyrelocs_shared_test.cc
+++ b/gold/testsuite/pie_copyrelocs_shared_test.cc
@@ -0,0 +1,26 @@
+// pie_copyrelocs_shared_test.cc -- a test case for gold, used
+// by pie_copyrelocs_test
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.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.
+
+
+
+int glob_a = 128;
diff --git a/gold/testsuite/pie_copyrelocs_test.cc b/gold/testsuite/pie_copyrelocs_test.cc
index e69de29..bebe89d 100644
--- a/gold/testsuite/pie_copyrelocs_test.cc
+++ b/gold/testsuite/pie_copyrelocs_test.cc
@@ -0,0 +1,31 @@
+// pie_coprelocs_test.cc -- a test case for gold
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.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.
+
+// Check if copy relocs are used to access globals below when -fpie is
+// is not used to compile but -pie is used to link.
+
+extern int glob_a;
+
+int main ()
+{
+ return glob_a - 128;
+}
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index bda6227..9887ea6 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -2795,7 +2795,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
// Make a dynamic relocation if necessary.
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
- if (gsym->may_need_copy_reloc())
+ if (gsym->may_need_copy_reloc(true))
{
target->copy_reloc(symtab, layout, object,
data_shndx, output_section, gsym, reloc);
More information about the Binutils
mailing list