diff options
author | Ian Lance Taylor <ian@airs.com> | 2011-07-01 22:05:01 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2011-07-01 22:05:01 +0000 |
commit | 07a60597350488f098508ee67717d549a8a0b579 (patch) | |
tree | 2476e48897011f57f41615892bdffda825fde6b2 /gold/layout.cc | |
parent | a931db6a07ac9ae2fec6c31c6d037716050292c5 (diff) | |
download | gdb-07a60597350488f098508ee67717d549a8a0b579.zip gdb-07a60597350488f098508ee67717d549a8a0b579.tar.gz gdb-07a60597350488f098508ee67717d549a8a0b579.tar.bz2 |
PR gold/12571
* options.h (class General_options): Add
--ld-generated-unwind-info.
* ehframe.cc (Fde::write): Add address parameter. Change all
callers. If associated with PLT, fill in address and size.
(Cie::set_output_offset): Only add merge mapping if there is an
object.
(Cie::write): Add address parameter. Change all callers.
(Eh_frame::add_ehframe_for_plt): New function.
* ehframe.h (class Fde): Update declarations. Move shndx_ and
input_offset_ fields into union u_, with new plt field.
(Fde::Fde): Adjust for new union field.
(Fde::Fde) [Output_data version]: New constructor.
(Fde::add_mapping): Only add merge mapping if there is an object.
(class Cie): Update declarations.
(class Eh_frame): Declare add_ehframe_for_plt.
* layout.cc (Layout::layout_eh_frame): Break out code into
make_eh_frame_section, and call it.
(Layout::make_eh_frame_section): New function.
(Layout::add_eh_frame_for_plt): New function.
* layout.h (class Layout): Update declarations.
* merge.cc (Merge_map::add_mapping): Add assertion.
* i386.cc: Include "dwarf.h".
(class Output_data_plt_i386): Make first_plt_entry,
dyn_first_plt_entry, exec_plt_entry, and dyn_plt_entry const. Add
plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie,
and plt_eh_frame_fde.
(Output_data_plt_i386::Output_data_plt_i386): Align to 16-byte
boundary. Call add_eh_frame_for_plt if appropriate.
* x86_64.cc: Include "dwarf.h".
(class Output_data_plt_x86_64): Align to 16-byte boundary. Make
first_plt_entry, plt_entry and tlsdesc_plt_entry const. Add
plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie,
and plt_eh_frame_fde.
(Output_data_plt_x86_64::init): Call add_eh_frame_for_plt if
appropriate.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 127 |
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. |