diff options
author | Cary Coutant <ccoutant@google.com> | 2014-07-02 09:39:41 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2014-09-02 14:49:18 -0700 |
commit | 9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08 (patch) | |
tree | da0a996a6e7e26eec815fc647283fe878fe23e7a /gold/ehframe.cc | |
parent | df7e526582809b829ee8651a1315a17627cfea4d (diff) | |
download | gdb-9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08.zip gdb-9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08.tar.gz gdb-9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08.tar.bz2 |
Fix problem with optimization of .eh_frame section and --sort-section option.
When --sort-section=name is used, gold will sort the linker-generated contents
of .eh_frame (after optimization) after the endcap provided by crtendS.o.
This causes two problems: the .eh_frame_hdr section is generated assuming that
the optimized .eh_frame contents will be placed at the very beginning of the
section, and the endcap no longer appears at the end of the section.
This patch fixes the first problem by adjusting FDE offsets to take into account
the actual starting offset within the output section, and fixes the second
problem by sorting linker-generated (Output_section_data) sections based on the
name of the output section.
gold/
PR gold/17005
* ehframe.cc (Fde::write): Add output_offset parameter.
(Cie::write): Likewise.
(Eh_frame::set_final_data_size): Account for offset within output
section.
(Eh_frame::do_sized_write): Likewise.
* ehframe.h (Fde::write): Add output_offset parameter.
(Cie::write): Likewise.
* output.cc (Output_section::Input_section_sort_entry): Remove
section_has_name_; add output_section_name parameter. Use
output section name for non-input sections.
(Output_section::Input_section_sort_entry::section_has_name): Remove.
(Output_section::Input_section_sort_entry::section_has_name_): Remove.
(Output_section::Input_section_sort_compare): Remove logic for
sections without names.
(Output_section::Input_section_sort_init_fini_compare): Likewise.
(Output_section::Input_section_sort_section_prefix_special_ordering_compare):
Likewise.
(Output_section::Input_section_sort_section_name_compare): Likewise.
Diffstat (limited to 'gold/ehframe.cc')
-rw-r--r-- | gold/ehframe.cc | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/gold/ehframe.cc b/gold/ehframe.cc index 699073d..c711bac 100644 --- a/gold/ehframe.cc +++ b/gold/ehframe.cc @@ -326,15 +326,16 @@ Eh_frame_hdr::get_fde_addresses(Output_file* of, // Class Fde. // Write the FDE to OVIEW starting at OFFSET. CIE_OFFSET is the -// offset of the CIE in OVIEW. FDE_ENCODING is the encoding, from the -// CIE. ADDRALIGN is the required alignment. ADDRESS is the virtual -// address of OVIEW. Record the FDE pc for EH_FRAME_HDR. Return the -// new offset. +// offset of the CIE in OVIEW. OUTPUT_OFFSET is the offset of the +// Eh_frame section within the output section. FDE_ENCODING is the +// encoding, from the CIE. ADDRALIGN is the required alignment. +// ADDRESS is the virtual address of OVIEW. Record the FDE pc for +// EH_FRAME_HDR. Return the new offset. template<int size, bool big_endian> section_offset_type -Fde::write(unsigned char* oview, section_offset_type offset, - uint64_t address, unsigned int addralign, +Fde::write(unsigned char* oview, section_offset_type output_offset, + section_offset_type offset, uint64_t address, unsigned int addralign, section_offset_type cie_offset, unsigned char fde_encoding, Eh_frame_hdr* eh_frame_hdr) { @@ -389,7 +390,7 @@ Fde::write(unsigned char* oview, section_offset_type offset, // Tell the exception frame header about this FDE. if (eh_frame_hdr != NULL) - eh_frame_hdr->record_fde(offset, fde_encoding); + eh_frame_hdr->record_fde(output_offset + offset, fde_encoding); return offset + aligned_full_length; } @@ -441,17 +442,19 @@ Cie::set_output_offset(section_offset_type output_offset, return output_offset + length; } -// Write the CIE to OVIEW starting at OFFSET. Round up the bytes to -// ADDRALIGN. ADDRESS is the virtual address of OVIEW. +// Write the CIE to OVIEW starting at OFFSET. OUTPUT_OFFSET is the +// offset of the Eh_frame section within the output section. Round up +// the bytes to ADDRALIGN. ADDRESS is the virtual address of OVIEW. // EH_FRAME_HDR is the exception frame header for FDE recording. // POST_FDES stashes FDEs created after mappings were done, for later // writing. Return the new offset. template<int size, bool big_endian> section_offset_type -Cie::write(unsigned char* oview, section_offset_type offset, - uint64_t address, unsigned int addralign, - Eh_frame_hdr* eh_frame_hdr, Post_fdes* post_fdes) +Cie::write(unsigned char* oview, section_offset_type output_offset, + section_offset_type offset, uint64_t address, + unsigned int addralign, Eh_frame_hdr* eh_frame_hdr, + Post_fdes* post_fdes) { gold_assert((offset & (addralign - 1)) == 0); @@ -488,8 +491,8 @@ Cie::write(unsigned char* oview, section_offset_type offset, if ((*p)->post_map()) post_fdes->push_back(Post_fde(*p, cie_offset, fde_encoding)); else - offset = (*p)->write<size, big_endian>(oview, offset, address, - addralign, cie_offset, + offset = (*p)->write<size, big_endian>(oview, output_offset, offset, + address, addralign, cie_offset, fde_encoding, eh_frame_hdr); } @@ -1093,7 +1096,10 @@ Eh_frame::set_final_data_size() return; } - section_offset_type output_offset = 0; + section_offset_type output_start = 0; + if (this->is_offset_valid()) + output_start = this->offset() - this->output_section()->offset(); + section_offset_type output_offset = output_start; for (Unmergeable_cie_offsets::iterator p = this->unmergeable_cie_offsets_.begin(); @@ -1111,10 +1117,10 @@ Eh_frame::set_final_data_size() &this->merge_map_); this->mappings_are_done_ = true; - this->final_data_size_ = output_offset; + this->final_data_size_ = output_offset - output_start; gold_assert((output_offset & (this->addralign() - 1)) == 0); - this->set_data_size(output_offset); + this->set_data_size(this->final_data_size_); } // Return an output offset for an input offset. @@ -1183,23 +1189,26 @@ Eh_frame::do_sized_write(unsigned char* oview) uint64_t address = this->address(); unsigned int addralign = this->addralign(); section_offset_type o = 0; + const off_t output_offset = this->offset() - this->output_section()->offset(); Post_fdes post_fdes; for (Unmergeable_cie_offsets::iterator p = this->unmergeable_cie_offsets_.begin(); p != this->unmergeable_cie_offsets_.end(); ++p) - o = (*p)->write<size, big_endian>(oview, o, address, addralign, - this->eh_frame_hdr_, &post_fdes); + o = (*p)->write<size, big_endian>(oview, output_offset, o, address, + addralign, this->eh_frame_hdr_, + &post_fdes); for (Cie_offsets::iterator p = this->cie_offsets_.begin(); p != this->cie_offsets_.end(); ++p) - o = (*p)->write<size, big_endian>(oview, o, address, addralign, - this->eh_frame_hdr_, &post_fdes); + o = (*p)->write<size, big_endian>(oview, output_offset, o, address, + addralign, this->eh_frame_hdr_, + &post_fdes); for (Post_fdes::iterator p = post_fdes.begin(); p != post_fdes.end(); ++p) - o = (*p).fde->write<size, big_endian>(oview, o, address, addralign, - (*p).cie_offset, + o = (*p).fde->write<size, big_endian>(oview, output_offset, o, address, + addralign, (*p).cie_offset, (*p).fde_encoding, this->eh_frame_hdr_); } |