PR gold/12898
authorIan Lance Taylor <ian@airs.com>
Wed, 29 Jun 2011 00:39:54 +0000 (00:39 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 29 Jun 2011 00:39:54 +0000 (00:39 +0000)
* 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
gold/layout.cc
gold/layout.h
gold/script-sections.cc

index f27f58e77cbab1d9709460b206fbf5a3444564d8..b765cd49462a3b55fee36fff18e46661f0346822 100644 (file)
@@ -1,3 +1,19 @@
+2011-06-28  Ian Lance Taylor  <iant@google.com>
+
+       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  <iant@google.com>
 
        PR gold/12934
index bfb1a7eac724751b2f33fcf4de461156b86094fb..0ef13aff2390ee8bb2c443c9c6d553a7aae4d921 100644 (file)
@@ -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.
index 0f6840e64d3b80275a73b48a171bf2ef220f6977..4a437b5e1408022792649562384e0f94262870dd 100644 (file)
@@ -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*> Output_section_data_list;
index 005f6673e72dd9c61931805802f16f5416134481..1fad88dd81d8b4193deeec2b3a72aaac19b6e8c8 100644 (file)
@@ -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