Place copy relocations in .dynbss when target is read-only. 2016-12-27 Cary Coutant gold/ PR ld/20995 * copy-relocs.cc (Copy_relocs::make_copy_reloc): Use .dynbss for read-only data when linking with -z relro. * copy-relocs.h (Copy_relocs::dynrelro_): New data member. * testsuite/Makefile.am (copy_test_relro): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/copy_test_relro.cc: New source file. * testsuite/copy_test_relro_1.cc: New source file. diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index ce019c4..4fe17e9 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -141,6 +141,7 @@ Copy_relocs::make_copy_reloc( unsigned int shndx = sym->shndx(&is_ordinary); gold_assert(is_ordinary); typename elfcpp::Elf_types::Elf_WXword addralign; + bool is_readonly = false; { // Lock the object so we can read from it. This is only called @@ -150,6 +151,17 @@ Copy_relocs::make_copy_reloc( Object* obj = sym->object(); Task_lock_obj tl(dummy_task, obj); addralign = obj->section_addralign(shndx); + if (parameters->options().relro()) + { + if ((obj->section_flags(shndx) & elfcpp::SHF_WRITE) == 0) + is_readonly = true; + else + { + // Symbols in .data.rel.ro should also be treated as read-only. + if (obj->section_name(shndx) == ".data.rel.ro") + is_readonly = true; + } + } } typename Sized_symbol::Value_type value = sym->value(); @@ -159,16 +171,32 @@ Copy_relocs::make_copy_reloc( // Mark the dynamic object as needed for the --as-needed option. sym->object()->set_is_needed(); - if (this->dynbss_ == NULL) + Output_data_space* dynbss; + + if (is_readonly) { - this->dynbss_ = new Output_data_space(addralign, "** dynbss"); - layout->add_output_section_data(".bss", - elfcpp::SHT_NOBITS, - elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->dynbss_, ORDER_BSS, false); + if (this->dynrelro_ == NULL) + { + this->dynrelro_ = new Output_data_space(addralign, "** dynrelro"); + layout->add_output_section_data(".data.rel.ro", + elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->dynrelro_, ORDER_RELRO, false); + } + dynbss = this->dynrelro_; + } + else + { + if (this->dynbss_ == NULL) + { + this->dynbss_ = new Output_data_space(addralign, "** dynbss"); + layout->add_output_section_data(".bss", + elfcpp::SHT_NOBITS, + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->dynbss_, ORDER_BSS, false); + } + dynbss = this->dynbss_; } - - Output_data_space* dynbss = this->dynbss_; if (addralign > dynbss->addralign()) dynbss->set_space_alignment(addralign); diff --git a/gold/copy-relocs.h b/gold/copy-relocs.h index aa42c7c..92b2ceb 100644 --- a/gold/copy-relocs.h +++ b/gold/copy-relocs.h @@ -54,7 +54,8 @@ class Copy_relocs public: Copy_relocs(unsigned int copy_reloc_type) - : entries_(), copy_reloc_type_(copy_reloc_type), dynbss_(NULL) + : entries_(), copy_reloc_type_(copy_reloc_type), dynbss_(NULL), + dynrelro_(NULL) { } // This is called while scanning relocs if we see a relocation @@ -152,8 +153,11 @@ class Copy_relocs // The target specific relocation type of the COPY relocation. const unsigned int copy_reloc_type_; // The dynamic BSS data which goes into the .bss section. This is - // where variables which require COPY relocations are placed. + // where writable variables which require COPY relocations are placed. Output_data_space* dynbss_; + // The dynamic read-only data, which goes into the .dynbss section. This + // is where read-only variables which require COPY relocations are placed. + Output_data_space* dynrelro_; }; } // End namespace gold. diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 6a882ea..d9480ab 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -858,6 +858,16 @@ copy_test_2_pic.o: copy_test_2.cc copy_test_2.so: gcctestdir/ld copy_test_2_pic.o $(CXXLINK) -Bgcctestdir/ -shared copy_test_2_pic.o +check_PROGRAMS += copy_test_relro +copy_test_relro_SOURCES = copy_test_relro.cc +copy_test_relro_DEPENDENCIES = gcctestdir/ld copy_test_relro_1.so +copy_test_relro_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -Wl,-z,relro +copy_test_relro_LDADD = copy_test_relro_1.so +copy_test_relro_1_pic.o: copy_test_relro_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +copy_test_relro_1.so: gcctestdir/ld copy_test_relro_1_pic.o + $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro copy_test_relro_1_pic.o + if !DEFAULT_TARGET_POWERPC check_SCRIPTS += copy_test_protected.sh check_DATA += copy_test_protected.err diff --git a/gold/testsuite/copy_test_relro.cc b/gold/testsuite/copy_test_relro.cc new file mode 100644 index 0000000..297b578 --- /dev/null +++ b/gold/testsuite/copy_test_relro.cc @@ -0,0 +1,45 @@ +// copy_test_relro.cc -- test copy relocs against read-only and relro symbols. + +// Copyright (C) 2016 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// 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. + +#include +#include + +extern char* _etext; +extern char* __data_start; +extern char* _edata; +extern char* _end; + +extern int* const p; +extern const int b[]; +int a = 123; + +int main() +{ + assert(*p == 123); + assert(b[0] == 100); + assert(b[1] == 200); + assert(b[2] == 300); + assert(b[3] == 400); + assert(reinterpret_cast(&p) < reinterpret_cast(&__data_start)); + assert(reinterpret_cast(b) < reinterpret_cast(&__data_start)); + return 0; +} diff --git a/gold/testsuite/copy_test_relro_1.cc b/gold/testsuite/copy_test_relro_1.cc new file mode 100644 index 0000000..d154534 --- /dev/null +++ b/gold/testsuite/copy_test_relro_1.cc @@ -0,0 +1,26 @@ +// copy_test_relro_1.cc -- test copy relocs variables for gold + +// Copyright (C) 2016 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// 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. + +extern int a; +extern int* const p = &a; + +extern const int b[] = { 100, 200, 300, 400 };