diff options
author | Cary Coutant <ccoutant@gmail.com> | 2016-12-27 20:50:47 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-12-27 20:50:56 -0800 |
commit | b733bcb7f58c42e0e0d94a3f266a4193030e5f3a (patch) | |
tree | 3ad325d2805aecf4a3e943d47c33f88ca6a24bf6 /gold/copy-relocs.cc | |
parent | 7ff34266fd831f828286e556f9cd681c42c0412c (diff) | |
download | binutils-gdb-b733bcb7f58c42e0e0d94a3f266a4193030e5f3a.tar.gz |
Place copy relocations in .dynbss when target is read-only.
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.
Diffstat (limited to 'gold/copy-relocs.cc')
-rw-r--r-- | gold/copy-relocs.cc | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index ce019c4265e..4fe17e9dfd7 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -141,6 +141,7 @@ Copy_relocs<sh_type, size, big_endian>::make_copy_reloc( unsigned int shndx = sym->shndx(&is_ordinary); gold_assert(is_ordinary); typename elfcpp::Elf_types<size>::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<sh_type, size, big_endian>::make_copy_reloc( Object* obj = sym->object(); Task_lock_obj<Object> 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<size>::Value_type value = sym->value(); @@ -159,16 +171,32 @@ Copy_relocs<sh_type, size, big_endian>::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); |