* layout.cc (Layout::special_ordering_of_input_section): New
authorIan Lance Taylor <ian@airs.com>
Fri, 21 Dec 2012 06:24:31 +0000 (06:24 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 21 Dec 2012 06:24:31 +0000 (06:24 +0000)
function.
(Layout::layout): If input section requires special ordering, must
sort input sections.
(Layout::make_output_section): May sort .text input sections.
(Layout::is_section_name_prefix_grouped): Remove.
* layout.h (class Layout): Declare
special_ordering_of_input_section.  Don't declare
is_section_name_prefix_grouped.
* output.cc (Output_section::add_input_section): Revert last
change.
(Output_section::Input_section_sort::match_file_name): Don't crash
if called on output section data.
(Output_section::Input_section_sort_compare): Sort based on
special ordering.
(Output_section::Input_section_sort_section_order_index_compare):
Revert last patch.
(Output_section::sort_attached_input_sections): Likewise.

gold/ChangeLog
gold/layout.cc
gold/layout.h
gold/output.cc

index 62ddbc688a25df601fc7e4824a6f7c5eb5e64555..ae4f83059dbfcaa233eda7e22ef8577f212fbdac 100644 (file)
@@ -1,14 +1,35 @@
+2012-12-20  Ian Lance Taylor  <iant@google.com>
+
+       * layout.cc (Layout::special_ordering_of_input_section): New
+       function.
+       (Layout::layout): If input section requires special ordering, must
+       sort input sections.
+       (Layout::make_output_section): May sort .text input sections.
+       (Layout::is_section_name_prefix_grouped): Remove.
+       * layout.h (class Layout): Declare
+       special_ordering_of_input_section.  Don't declare
+       is_section_name_prefix_grouped.
+       * output.cc (Output_section::add_input_section): Revert last
+       change.
+       (Output_section::Input_section_sort::match_file_name): Don't crash
+       if called on output section data.
+       (Output_section::Input_section_sort_compare): Sort based on
+       special ordering.
+       (Output_section::Input_section_sort_section_order_index_compare):
+       Revert last patch.
+       (Output_section::sort_attached_input_sections): Likewise.
+
 2012-12-18  Sriraman Tallam  <tmsriram@google.com>
 
-       * layout.cc (Layout::is_section_name_prefix_grouped): New function.     
+       * layout.cc (Layout::is_section_name_prefix_grouped): New function.
        * layout.h (Layout::is_section_name_prefix_grouped): New function.
        * output.cc (Output_section::add_input_section): Check if section
        name contains special prefix.  Keep input sections to sort such
        sections.
        (Output_section::Input_section_sort_section_order_index_compare
         ::operator()): Group sections according to prefixes.
-       * (Output_section::sort_attached_input_sections): Add condition
-       to Input_section_entry constructor call.
+       (Output_section::sort_attached_input_sections): Add condition to
+       Input_section_entry constructor call.
        * testsuite/Makefile.am (text_section_grouping): New test.
        * testsuite/Makefile.in: Regenerate.
        * testsuite/text_section_grouping.cc: New file.
index 62b4cadf9d386e92c25e522e86961b7533bb978e..f7f0e7e33a11bbac6bc5aedb25f960ebce4e39f9 100644 (file)
@@ -1033,6 +1033,33 @@ Layout::init_fixed_output_section(const char* name,
   return os;
 }
 
+// Return the index by which an input section should be ordered.  This
+// is used to sort some .text sections, for compatibility with GNU ld.
+
+int
+Layout::special_ordering_of_input_section(const char* name)
+{
+  // The GNU linker has some special handling for some sections that
+  // wind up in the .text section.  Sections that start with these
+  // prefixes must appear first, and must appear in the order listed
+  // here.
+  static const char* const text_section_sort[] = 
+  {
+    ".text.unlikely",
+    ".text.exit",
+    ".text.startup",
+    ".text.hot"
+  };
+
+  for (size_t i = 0;
+       i < sizeof(text_section_sort) / sizeof(text_section_sort[0]);
+       i++)
+    if (is_prefix_of(text_section_sort[i], name))
+      return i;
+
+  return -1;
+}
+
 // Return the output section to use for input section SHNDX, with name
 // NAME, with header HEADER, from object OBJECT.  RELOC_SHNDX is the
 // index of a relocation section which applies to this section, or 0
@@ -1120,6 +1147,13 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
                  || strcmp(name, ".dtors") == 0))))
     os->set_must_sort_attached_input_sections();
 
+  // By default the GNU linker sorts some special text sections ahead
+  // of others.  We are compatible.
+  if (!this->script_options_->saw_sections_clause()
+      && !parameters->options().relocatable()
+      && Layout::special_ordering_of_input_section(name) >= 0)
+    os->set_must_sort_attached_input_sections();
+
   // If this is a .ctors or .ctors.* section being mapped to a
   // .init_array section, or a .dtors or .dtors.* section being mapped
   // to a .fini_array section, we will need to reverse the words if
@@ -1607,6 +1641,15 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
                  || strcmp(name, ".dtors") == 0))))
     os->set_may_sort_attached_input_sections();
 
+  // The GNU linker by default sorts .text.{unlikely,exit,startup,hot}
+  // sections before other .text sections.  We are compatible.  We
+  // need to know that this might happen before we attach any input
+  // sections.
+  if (!this->script_options_->saw_sections_clause()
+      && !parameters->options().relocatable()
+      && strcmp(name, ".text") == 0)
+    os->set_may_sort_attached_input_sections();
+
   // Check for .stab*str sections, as .stab* sections need to link to
   // them.
   if (type == elfcpp::SHT_STRTAB
@@ -2409,20 +2452,6 @@ Layout::relaxation_loop_body(
   return off;
 }
 
-// By default, gold groups input sections with certain prefixes.  This 
-// function returns true if this section name NAME contains such a prefix.
-
-bool
-Layout::is_section_name_prefix_grouped(const char *name)
-{
-  if (is_prefix_of(".text.unlikely", name)
-      || is_prefix_of(".text.startup", name)
-      || is_prefix_of(".text.hot", name))
-    return true;
-
-  return false;
-}
-
 // Search the list of patterns and find the postion of the given section
 // name in the output section.  If the section name matches a glob
 // pattern and a non-glob name, then the non-glob position takes
index 71f1aa7a495854ffb5518ad69d7c06eac2885baf..6da960750473ee5121f05bdcb1165565bc626343 100644 (file)
@@ -553,11 +553,14 @@ class Layout
   void
   insert_section_segment_map(Const_section_id secn, Unique_segment_info *s);
 
-  // By default, gold groups input sections with certain prefixes.  This 
-  // function returns true if this section name NAME contains such a prefix.
-  bool
-  is_section_name_prefix_grouped(const char *name);
-  
+  // Some input sections require special ordering, for compatibility
+  // with GNU ld.  Given the name of an input section, return -1 if it
+  // does not require special ordering.  Otherwise, return the index
+  // by which it should be ordered compared to other input sections
+  // that require special ordering.
+  static int
+  special_ordering_of_input_section(const char* name);
+
   bool
   is_section_ordering_specified()
   { return this->section_ordering_specified_; }
index 39eb1b7dc795012d6b7526ebd63af938a74bd26d..f2321b77fc54188a0b41afb9affb560aced4dfdc 100644 (file)
@@ -2478,19 +2478,6 @@ Output_section::add_input_section(Layout* layout,
         }
     }
 
-  // The GNU linker groups input sections whose names match .text.unlikely.*.
-  // This is used to get better code layout.  We are compatible.
-  // Additionally, it could also be beneficial to group .text.hot.*,
-  // .text.startup.* prefixed input sections.  Function
-  // "is_section_name_prefix_grouped" in layout.cc determines the input
-  // section prefixes that must be grouped.
-  if (!have_sections_script
-      && !parameters->options().relocatable()
-      && !this->input_section_order_specified()
-      && !this->must_sort_attached_input_sections()
-      && layout->is_section_name_prefix_grouped(secname))
-    this->set_input_section_order_specified();
-
   // We need to keep track of this section if we are already keeping
   // track of sections, or if we are relaxing.  Also, if this is a
   // section which requires sorting, or which may require sorting in
@@ -2504,8 +2491,7 @@ Output_section::add_input_section(Layout* layout,
       || this->must_sort_attached_input_sections()
       || parameters->options().user_set_Map()
       || parameters->target().may_relax()
-      || layout->is_section_ordering_specified()
-      || this->input_section_order_specified())
+      || layout->is_section_ordering_specified())
     {
       Input_section isecn(object, shndx, input_section_size, addralign);
       /* If section ordering is requested by specifying a ordering file,
@@ -3337,7 +3323,11 @@ class Output_section::Input_section_sort_entry
   // in order to better support gcc, and we need to be compatible.
   bool
   match_file_name(const char* file_name) const
-  { return Layout::match_file_name(this->input_section_.relobj(), file_name); }
+  {
+    if (this->input_section_.is_output_section_data())
+      return false;
+    return Layout::match_file_name(this->input_section_.relobj(), file_name);
+  }
 
   // Returns 1 if THIS should appear before S in section order, -1 if S
   // appears before THIS and 0 if they are not comparable.
@@ -3409,6 +3399,19 @@ Output_section::Input_section_sort_compare::operator()(
       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());
+  if (o1 != o2)
+    {
+      if (o1 < 0)
+       return false;
+      else if (o2 < 0)
+       return true;
+      else
+       return o1 < o2;
+    }
+
   // 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();
@@ -3498,9 +3501,7 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
 
 // Return true if S1 should come before S2.  Sections that do not match
 // any pattern in the section ordering file are placed ahead of the sections
-// that match some pattern.  This function is also used to group text according
-// to their prefix.  The following prefixes are recognized: ".text.startup",
-// ".text.hot", and ".text.unlikely".
+// that match some pattern.
 
 bool
 Output_section::Input_section_sort_section_order_index_compare::operator()(
@@ -3510,59 +3511,11 @@ Output_section::Input_section_sort_section_order_index_compare::operator()(
   unsigned int s1_secn_index = s1.input_section().section_order_index();
   unsigned int s2_secn_index = s2.input_section().section_order_index();
 
-  // If section ordering is specified, it takes precedence.
-  if (s1_secn_index != s2_secn_index)
-    return s1_secn_index < s2_secn_index;
-
-  // 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();
-    }
-
-  // If it is a text section use the following order:
-  // .text.unlikely, .text.startup, .text.hot. The prefixes
-  // must match those in function is_section_name_prefix_grouped
-  // in layout.cc
-  const char* section_prefix [] = 
-  {
-    ".text.unlikely",
-    ".text.startup",
-    ".text.hot"
-  };
-
-  const unsigned int num_prefixes
-    = sizeof(section_prefix) / sizeof(const char*);
-
-  unsigned int s1_group_index = num_prefixes;
-  unsigned int s2_group_index = num_prefixes;
-
-  unsigned int flag_done = 0;
-  for (unsigned int i = 0; i < num_prefixes && flag_done < 2; i++)
-    {
-      if (s1_group_index == num_prefixes
-         && is_prefix_of(section_prefix[i], s1.section_name().c_str()))
-       {
-          s1_group_index = i;
-         flag_done++;
-       }
-
-      if (s2_group_index == num_prefixes
-         && is_prefix_of(section_prefix[i], s2.section_name().c_str()))
-       {
-          s2_group_index = i;
-         flag_done++;
-       }
-    }
-
-  if (s1_group_index == s2_group_index)
+  // Keep input order if section ordering cannot determine order.
+  if (s1_secn_index == s2_secn_index)
     return s1.index() < s2.index();
-  else
-    return s1_group_index < s2_group_index;
+
+  return s1_secn_index < s2_secn_index;
 }
 
 // This updates the section order index of input sections according to the
@@ -3623,8 +3576,7 @@ 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->input_section_order_specified())));
+                            this->must_sort_attached_input_sections()));
 
   // Sort the input sections.
   if (this->must_sort_attached_input_sections())