diff options
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 ce019c4..4fe17e9 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); |