aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc47
1 files changed, 46 insertions, 1 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 6a47064..978828f 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -520,7 +520,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
off_t* off)
{
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
- gold_assert(shdr.get_sh_flags() == elfcpp::SHF_ALLOC);
+ gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
const char* const name = ".eh_frame";
Output_section* os = this->choose_output_section(object,
@@ -531,6 +531,16 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
if (os == NULL)
return NULL;
+ // On some targets gcc assumes that a read-only .eh_frame section
+ // will be merged with a read-write .eh_frame section.
+ if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0
+ && (os->flags() & elfcpp::SHF_WRITE) == 0)
+ {
+ elfcpp::Elf_Xword new_flags = os->flags() | elfcpp::SHF_WRITE;
+ this->write_enable_output_section(os, new_flags);
+ os->set_flags(new_flags);
+ }
+
if (this->eh_frame_section_ == NULL)
{
this->eh_frame_section_ = os;
@@ -778,6 +788,41 @@ Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags)
this->attach_to_segment(os, flags);
}
+// We have to move an existing output section from the read-only
+// segment to the writable segment.
+
+void
+Layout::write_enable_output_section(Output_section* os,
+ elfcpp::Elf_Xword flags)
+{
+ gold_assert((os->flags() & elfcpp::SHF_WRITE) == 0);
+ gold_assert(os->type() == elfcpp::SHT_PROGBITS);
+ gold_assert((flags & elfcpp::SHF_WRITE) != 0);
+ gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
+
+ if (parameters->options().relocatable())
+ return;
+
+ if (this->script_options_->saw_sections_clause())
+ return;
+
+ Segment_list::iterator p;
+ for (p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD
+ && ((*p)->flags() & elfcpp::PF_W) == 0)
+ {
+ (*p)->remove_output_section(os);
+ break;
+ }
+ }
+ gold_assert(p != this->segment_list_.end());
+
+ this->attach_to_segment(os, flags);
+}
+
// Return the number of segments we expect to see.
size_t