aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc127
1 files changed, 83 insertions, 44 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 3152622..11dbbef 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1136,51 +1136,10 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
|| shdr.get_sh_type() == elfcpp::SHT_X86_64_UNWIND);
gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
- const char* const name = ".eh_frame";
- Output_section* os = this->choose_output_section(object, name,
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC, false,
- ORDER_EHFRAME, false);
+ Output_section* os = this->make_eh_frame_section(object);
if (os == NULL)
return NULL;
- if (this->eh_frame_section_ == NULL)
- {
- this->eh_frame_section_ = os;
- this->eh_frame_data_ = new Eh_frame();
-
- // For incremental linking, we do not optimize .eh_frame sections
- // or create a .eh_frame_hdr section.
- if (parameters->options().eh_frame_hdr() && !parameters->incremental())
- {
- Output_section* hdr_os =
- this->choose_output_section(NULL, ".eh_frame_hdr",
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC, false,
- ORDER_EHFRAME, false);
-
- if (hdr_os != NULL)
- {
- Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os,
- this->eh_frame_data_);
- hdr_os->add_output_section_data(hdr_posd);
-
- hdr_os->set_after_input_sections();
-
- if (!this->script_options_->saw_phdrs_clause())
- {
- Output_segment* hdr_oseg;
- hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
- elfcpp::PF_R);
- hdr_oseg->add_output_section_to_nonload(hdr_os,
- elfcpp::PF_R);
- }
-
- this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
- }
- }
- }
-
gold_assert(this->eh_frame_section_ == os);
elfcpp::Elf_Xword orig_flags = os->flags();
@@ -1222,8 +1181,8 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
// We couldn't handle this .eh_frame section for some reason.
// Add it as a normal section.
bool saw_sections_clause = this->script_options_->saw_sections_clause();
- *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
- saw_sections_clause);
+ *off = os->add_input_section(this, object, shndx, ".eh_frame", shdr,
+ reloc_shndx, saw_sections_clause);
this->have_added_input_section_ = true;
if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
@@ -1234,6 +1193,86 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
return os;
}
+// Create and return the magic .eh_frame section. Create
+// .eh_frame_hdr also if appropriate. OBJECT is the object with the
+// input .eh_frame section; it may be NULL.
+
+Output_section*
+Layout::make_eh_frame_section(const Relobj* object)
+{
+ // FIXME: On x86_64, this could use SHT_X86_64_UNWIND rather than
+ // SHT_PROGBITS.
+ Output_section* os = this->choose_output_section(object, ".eh_frame",
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC, false,
+ ORDER_EHFRAME, false);
+ if (os == NULL)
+ return NULL;
+
+ if (this->eh_frame_section_ == NULL)
+ {
+ this->eh_frame_section_ = os;
+ this->eh_frame_data_ = new Eh_frame();
+
+ // For incremental linking, we do not optimize .eh_frame sections
+ // or create a .eh_frame_hdr section.
+ if (parameters->options().eh_frame_hdr() && !parameters->incremental())
+ {
+ Output_section* hdr_os =
+ this->choose_output_section(NULL, ".eh_frame_hdr",
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC, false,
+ ORDER_EHFRAME, false);
+
+ if (hdr_os != NULL)
+ {
+ Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os,
+ this->eh_frame_data_);
+ hdr_os->add_output_section_data(hdr_posd);
+
+ hdr_os->set_after_input_sections();
+
+ if (!this->script_options_->saw_phdrs_clause())
+ {
+ Output_segment* hdr_oseg;
+ hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
+ elfcpp::PF_R);
+ hdr_oseg->add_output_section_to_nonload(hdr_os,
+ elfcpp::PF_R);
+ }
+
+ this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
+ }
+ }
+ }
+
+ return os;
+}
+
+// Add an exception frame for a PLT. This is called from target code.
+
+void
+Layout::add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
+ size_t cie_length, const unsigned char* fde_data,
+ size_t fde_length)
+{
+ if (parameters->incremental())
+ {
+ // FIXME: Maybe this could work some day....
+ return;
+ }
+ Output_section* os = this->make_eh_frame_section(NULL);
+ if (os == NULL)
+ return;
+ this->eh_frame_data_->add_ehframe_for_plt(plt, cie_data, cie_length,
+ fde_data, fde_length);
+ if (!this->added_eh_frame_data_)
+ {
+ os->add_output_section_data(this->eh_frame_data_);
+ this->added_eh_frame_data_ = true;
+ }
+}
+
// Add POSD to an output section using NAME, TYPE, and FLAGS. Return
// the output section.