From aecf301fb9a06b3d05280260758bcd3e85d7413e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 29 Jun 2011 00:39:54 +0000 Subject: [PATCH] PR gold/12898 * layout.cc (Layout::segment_precedes): Don't crash if a linker script create indistinguishable segments. (Layout::set_segment_offsets): Use stable_sort when sorting segments. Pass this to Compare_segments constructor. * layout.h (class Layout): Make segment_precedes non-static. (class Compare_segments): Change from struct to class. Add layout_ field. Add constructor. * script-sections.cc (Script_sections::attach_sections_using_phdrs_clause): Rename local orphan to is_orphan. Don't report failure to put empty section in segment. On attachment failure, report name of section, and attach to first PT_LOAD segment. --- gold/ChangeLog | 16 ++++++++++++++++ gold/layout.cc | 16 ++++++++++------ gold/layout.h | 14 +++++++++++--- gold/script-sections.cc | 33 ++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index f27f58e77cb..b765cd49462 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2011-06-28 Ian Lance Taylor + + PR gold/12898 + * layout.cc (Layout::segment_precedes): Don't crash if a linker + script create indistinguishable segments. + (Layout::set_segment_offsets): Use stable_sort when sorting + segments. Pass this to Compare_segments constructor. + * layout.h (class Layout): Make segment_precedes non-static. + (class Compare_segments): Change from struct to class. Add + layout_ field. Add constructor. + * script-sections.cc + (Script_sections::attach_sections_using_phdrs_clause): Rename + local orphan to is_orphan. Don't report failure to put empty + section in segment. On attachment failure, report name of + section, and attach to first PT_LOAD segment. + 2011-06-28 Ian Lance Taylor PR gold/12934 diff --git a/gold/layout.cc b/gold/layout.cc index bfb1a7eac72..0ef13aff239 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -2751,7 +2751,7 @@ Layout::create_incremental_info_sections(Symbol_table* symtab) // Return whether SEG1 should be before SEG2 in the output file. This // is based entirely on the segment type and flags. When this is -// called the segment addresses has normally not yet been set. +// called the segment addresses have normally not yet been set. bool Layout::segment_precedes(const Output_segment* seg1, @@ -2877,8 +2877,10 @@ Layout::segment_precedes(const Output_segment* seg1, return (flags1 & elfcpp::PF_R) == 0; // We shouldn't get here--we shouldn't create segments which we - // can't distinguish. - gold_unreachable(); + // can't distinguish. Unless of course we are using a weird linker + // script. + gold_assert(this->script_options_->saw_phdrs_clause()); + return false; } // Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE. @@ -2902,9 +2904,11 @@ off_t Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, unsigned int* pshndx) { - // Sort them into the final order. - std::sort(this->segment_list_.begin(), this->segment_list_.end(), - Layout::Compare_segments()); + // Sort them into the final order. We use a stable sort so that we + // don't randomize the order of indistinguishable segments created + // by linker scripts. + std::stable_sort(this->segment_list_.begin(), this->segment_list_.end(), + Layout::Compare_segments(this)); // Find the PT_LOAD segments, and set their addresses and offsets // and their section's addresses and offsets. diff --git a/gold/layout.h b/gold/layout.h index 0f6840e64d3..4a437b5e140 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -1052,7 +1052,7 @@ class Layout place_orphan_sections_in_script(); // Return whether SEG1 comes before SEG2 in the output file. - static bool + bool segment_precedes(const Output_segment* seg1, const Output_segment* seg2); // Use to save and restore segments during relaxation. @@ -1102,11 +1102,19 @@ class Layout // A comparison class for segments. - struct Compare_segments + class Compare_segments { + public: + Compare_segments(Layout* layout) + : layout_(layout) + { } + bool operator()(const Output_segment* seg1, const Output_segment* seg2) - { return Layout::segment_precedes(seg1, seg2); } + { return this->layout_->segment_precedes(seg1, seg2); } + + private: + Layout* layout_; }; typedef std::vector Output_section_data_list; diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 005f6673e72..1fad88dd81d 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -4050,15 +4050,37 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) p != this->sections_elements_->end(); ++p) { - bool orphan; + bool is_orphan; String_list* old_phdr_names = phdr_names; - Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan); + Output_section* os = (*p)->allocate_to_segment(&phdr_names, &is_orphan); if (os == NULL) continue; + elfcpp::Elf_Word seg_flags = + Layout::section_flags_to_segment(os->flags()); + if (phdr_names == NULL) { - gold_error(_("allocated section not in any segment")); + // Don't worry about empty orphan sections. + if (is_orphan && os->current_data_size() > 0) + gold_error(_("allocated section %s not in any segment"), + os->name()); + + // To avoid later crashes drop this section into the first + // PT_LOAD segment. + for (Phdrs_elements::const_iterator ppe = + this->phdrs_elements_->begin(); + ppe != this->phdrs_elements_->end(); + ++ppe) + { + Output_segment* oseg = (*ppe)->segment(); + if (oseg->type() == elfcpp::PT_LOAD) + { + oseg->add_output_section_to_load(layout, os, seg_flags); + break; + } + } + continue; } @@ -4073,7 +4095,7 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // PT_INTERP segment will pick up following orphan sections, // which does not make sense. If this is not an orphan section, // we trust the linker script. - if (orphan) + if (is_orphan) { // Enable PT_LOAD segments only filtering until we see another // list of segment names. @@ -4094,9 +4116,6 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) && r->second->type() != elfcpp::PT_LOAD) continue; - elfcpp::Elf_Word seg_flags = - Layout::section_flags_to_segment(os->flags()); - if (r->second->type() != elfcpp::PT_LOAD) r->second->add_output_section_to_nonload(os, seg_flags); else -- 2.30.2