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): Remove check for position independent code. * x86_64.cc (Target_x86_64::Scan::global): Add check for no position independence before pc absolute may_need_copy_reloc call. Add check for executable output befor pc relative may_need_copy_reloc call. * i386.cc: Ditto. * arm.cc: Ditto. * sparc.cc: Ditto. * tilegx.cc: Ditto. * powerpc.cc: Add check for no position independence before may_need_copy_reloc calls. * 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/arm.cc b/gold/arm.cc index 70e2789..607f9d6 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -8301,7 +8301,8 @@ Target_arm::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 (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -8382,7 +8383,8 @@ Target_arm::Scan::global(Symbol_table* symtab, // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))) { - if (target->may_need_copy_reloc(gsym)) + if (parameters->options().output_is_executable() + && target->may_need_copy_reloc(gsym)) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); diff --git a/gold/i386.cc b/gold/i386.cc index a2f7522..78fe780 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -2113,7 +2113,8 @@ Target_i386::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 (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -2174,7 +2175,8 @@ Target_i386::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 (parameters->options().output_is_executable() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 0589d0c..b9ee86e 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -5819,7 +5819,8 @@ Target_powerpc::Scan::global( if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type, target)) || (size == 64 && is_ifunc && target->abiversion() < 2)) { - if (gsym->may_need_copy_reloc()) + if (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -5882,7 +5883,8 @@ Target_powerpc::Scan::global( // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type, target))) { - if (gsym->may_need_copy_reloc()) + if (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, diff --git a/gold/sparc.cc b/gold/sparc.cc index 2056f50..5a5f76a 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -2634,7 +2634,8 @@ Target_sparc::Scan::global( // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))) { - if (gsym->may_need_copy_reloc()) + if (parameters->options().output_is_executable() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, @@ -2723,7 +2724,8 @@ Target_sparc::Scan::global( break; } - if (gsym->may_need_copy_reloc()) + if (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); diff --git a/gold/symtab.h b/gold/symtab.h index b06c7b4..d304f26 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -821,8 +821,7 @@ class Symbol bool may_need_copy_reloc() const { - return (!parameters->options().output_is_position_independent() - && parameters->options().copyreloc() + return (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 . + +// 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 . + +// 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/tilegx.cc b/gold/tilegx.cc index c194587..1a14dea 100644 --- a/gold/tilegx.cc +++ b/gold/tilegx.cc @@ -3758,7 +3758,8 @@ Target_tilegx::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 (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -3832,7 +3833,8 @@ Target_tilegx::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 (parameters->options().output_is_executable() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); diff --git a/gold/x86_64.cc b/gold/x86_64.cc index bda6227..7f6a7fd 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -2734,7 +2734,8 @@ Target_x86_64::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 (!parameters->options().output_is_position_independent() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -2795,7 +2796,8 @@ Target_x86_64::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 (parameters->options().output_is_executable() + && gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc);