diff options
author | Ian Lance Taylor <iant@google.com> | 2008-03-12 04:38:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2008-03-12 04:38:42 +0000 |
commit | 1650c4ff500bc54eea33d31ae9396434a3e13733 (patch) | |
tree | 36c7a4a10c6005e8ab65e0afb8b9230d49a50c39 /gold/layout.cc | |
parent | e00eeb0a11ba17abc1166adb7f94097ae37c470c (diff) | |
download | gdb-1650c4ff500bc54eea33d31ae9396434a3e13733.zip gdb-1650c4ff500bc54eea33d31ae9396434a3e13733.tar.gz gdb-1650c4ff500bc54eea33d31ae9396434a3e13733.tar.bz2 |
Combine read-only .eh_frame sections with read-write .eh_frame
sections.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 47 |
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 |