summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2014-07-02 09:39:41 -0700
committerCary Coutant <ccoutant@google.com>2014-09-02 14:49:18 -0700
commit9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08 (patch)
treeda0a996a6e7e26eec815fc647283fe878fe23e7a
parentdf7e526582809b829ee8651a1315a17627cfea4d (diff)
downloadbinutils-gdb-9860cbcfb60bdae2f9800e6a6ea5f21ef1507d08.tar.gz
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.
-rw-r--r--gold/ChangeLog22
-rw-r--r--gold/ehframe.cc55
-rw-r--r--gold/ehframe.h7
-rw-r--r--gold/output.cc73
4 files changed, 72 insertions, 85 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 4fce2cb21d5..0fa15612b9a 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,25 @@
+2014-09-02 Cary Coutant <ccoutant@google.com>
+
+ 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.
+
2014-08-29 Han Shen <shenhan@google.com>
Jing Yu <jingyu@google.com>
diff --git a/gold/ehframe.cc b/gold/ehframe.cc
index 699073d3a0c..c711bac5f05 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_);
}
diff --git a/gold/ehframe.h b/gold/ehframe.h
index 42ed7f6eb98..2ae12e0e092 100644
--- a/gold/ehframe.h
+++ b/gold/ehframe.h
@@ -211,8 +211,8 @@ class Fde
// FDE in EH_FRAME_HDR. Return the new offset.
template<int size, bool big_endian>
section_offset_type
- write(unsigned char* oview, section_offset_type offset,
- uint64_t address, unsigned int addralign,
+ write(unsigned char* oview, section_offset_type output_section_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);
@@ -317,7 +317,8 @@ class Cie
// writing. Return the new offset.
template<int size, bool big_endian>
section_offset_type
- write(unsigned char* oview, section_offset_type offset, uint64_t address,
+ write(unsigned char* oview, section_offset_type output_section_offset,
+ section_offset_type offset, uint64_t address,
unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
Post_fdes* post_fdes);
diff --git a/gold/output.cc b/gold/output.cc
index c078fbb64d1..3361991a6f7 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -3206,18 +3206,17 @@ class Output_section::Input_section_sort_entry
{
public:
Input_section_sort_entry()
- : input_section_(), index_(-1U), section_has_name_(false),
- section_name_()
+ : input_section_(), index_(-1U), section_name_()
{ }
Input_section_sort_entry(const Input_section& input_section,
unsigned int index,
- bool must_sort_attached_input_sections)
- : input_section_(input_section), index_(index),
- section_has_name_(input_section.is_input_section()
- || input_section.is_relaxed_input_section())
+ bool must_sort_attached_input_sections,
+ const char* output_section_name)
+ : input_section_(input_section), index_(index), section_name_()
{
- if (this->section_has_name_
+ if ((input_section.is_input_section()
+ || input_section.is_relaxed_input_section())
&& must_sort_attached_input_sections)
{
// This is only called single-threaded from Layout::finalize,
@@ -3233,6 +3232,12 @@ class Output_section::Input_section_sort_entry
// Layout::layout if this becomes a speed problem.
this->section_name_ = obj->section_name(input_section.shndx());
}
+ else if (input_section.is_output_section_data()
+ && must_sort_attached_input_sections)
+ {
+ // For linker-generated sections, use the output section name.
+ this->section_name_.assign(output_section_name);
+ }
}
// Return the Input_section.
@@ -3252,16 +3257,10 @@ class Output_section::Input_section_sort_entry
return this->index_;
}
- // Whether there is a section name.
- bool
- section_has_name() const
- { return this->section_has_name_; }
-
// The section name.
const std::string&
section_name() const
{
- gold_assert(this->section_has_name_);
return this->section_name_;
}
@@ -3270,7 +3269,6 @@ class Output_section::Input_section_sort_entry
bool
has_priority() const
{
- gold_assert(this->section_has_name_);
return this->section_name_.find('.', 1) != std::string::npos;
}
@@ -3280,7 +3278,6 @@ class Output_section::Input_section_sort_entry
unsigned int
get_priority() const
{
- gold_assert(this->section_has_name_);
bool is_ctors;
if (is_prefix_of(".ctors.", this->section_name_.c_str())
|| is_prefix_of(".dtors.", this->section_name_.c_str()))
@@ -3339,9 +3336,6 @@ class Output_section::Input_section_sort_entry
Input_section input_section_;
// The index of this Input_section in the original list.
unsigned int index_;
- // Whether this Input_section has a section name--it won't if this
- // is some random Output_section_data.
- bool section_has_name_;
// The section name if there is one.
std::string section_name_;
};
@@ -3377,16 +3371,6 @@ Output_section::Input_section_sort_compare::operator()(
return s1.index() < s2.index();
}
- // We sort all the sections with no names to the end.
- if (!s1.section_has_name() || !s2.section_has_name())
- {
- if (s1.section_has_name())
- return true;
- if (s2.section_has_name())
- return false;
- return s1.index() < s2.index();
- }
-
// A section with a priority follows a section without a priority.
bool s1_has_priority = s1.has_priority();
bool s2_has_priority = s2.has_priority();
@@ -3418,16 +3402,6 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
const Output_section::Input_section_sort_entry& s1,
const Output_section::Input_section_sort_entry& s2) const
{
- // We sort all the sections with no names to the end.
- if (!s1.section_has_name() || !s2.section_has_name())
- {
- if (s1.section_has_name())
- return true;
- if (s2.section_has_name())
- return false;
- return s1.index() < s2.index();
- }
-
// A section without a priority follows a section with a priority.
// This is the reverse of .ctors and .dtors sections.
bool s1_has_priority = s1.has_priority();
@@ -3503,16 +3477,6 @@ Output_section::Input_section_sort_section_prefix_special_ordering_compare
const Output_section::Input_section_sort_entry& s1,
const Output_section::Input_section_sort_entry& s2) const
{
- // We sort all the sections with no names to the end.
- if (!s1.section_has_name() || !s2.section_has_name())
- {
- if (s1.section_has_name())
- return true;
- if (s2.section_has_name())
- return false;
- return s1.index() < s2.index();
- }
-
// Some input section names have special ordering requirements.
int o1 = Layout::special_ordering_of_input_section(s1.section_name().c_str());
int o2 = Layout::special_ordering_of_input_section(s2.section_name().c_str());
@@ -3539,16 +3503,6 @@ Output_section::Input_section_sort_section_name_compare
const Output_section::Input_section_sort_entry& s1,
const Output_section::Input_section_sort_entry& s2) const
{
- // We sort all the sections with no names to the end.
- if (!s1.section_has_name() || !s2.section_has_name())
- {
- if (s1.section_has_name())
- return true;
- if (s2.section_has_name())
- return false;
- return s1.index() < s2.index();
- }
-
// We sort by name.
int compare = s1.section_name().compare(s2.section_name());
if (compare != 0)
@@ -3616,7 +3570,8 @@ Output_section::sort_attached_input_sections()
p != this->input_sections_.end();
++p, ++i)
sort_list.push_back(Input_section_sort_entry(*p, i,
- this->must_sort_attached_input_sections()));
+ this->must_sort_attached_input_sections(),
+ this->name()));
// Sort the input sections.
if (this->must_sort_attached_input_sections())