aboutsummaryrefslogtreecommitdiff
path: root/gold/copy-relocs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/copy-relocs.cc')
-rw-r--r--gold/copy-relocs.cc44
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);