2010-03-01 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Mon, 1 Mar 2010 21:43:50 +0000 (21:43 +0000)
committerDoug Kwan <dougkwan@google.com>
Mon, 1 Mar 2010 21:43:50 +0000 (21:43 +0000)
* layout.cc (Layout::Layout): Force section types of .init_array*,
.preinit_array* and .fini_array* sections.
* output.cc (Output_section::Input_section_sort_entry::has_priority):
Fix check of return value of std::string::find.().
(Output_section::Input_section_sort_compare::operator()): Remove
comment about .init_array.
(Output_section::Input_section_sort_init_fini_compare::operator()):
New method.
(Output_section::sort_attached_input_sections): Handle .init_array
and .fini_array specially.
* output.h (Output_section::Inut_section_sort_compare): Update
comment.
(Output_section::Input_section_sort_init_fini_compare): New struct.

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

index d6e806d13aad19b123f35e038448a413b386c75a..514310d24de11d0909d63cc5837ca5dd3a0048ea 100644 (file)
@@ -1,3 +1,19 @@
+2010-03-01  Doug Kwan  <dougkwan@google.com>
+
+       * layout.cc (Layout::Layout): Force section types of .init_array*,
+       .preinit_array* and .fini_array* sections.
+       * output.cc (Output_section::Input_section_sort_entry::has_priority):
+       Fix check of return value of std::string::find.().
+       (Output_section::Input_section_sort_compare::operator()): Remove
+       comment about .init_array.
+       (Output_section::Input_section_sort_init_fini_compare::operator()):
+       New method.
+       (Output_section::sort_attached_input_sections): Handle .init_array
+       and .fini_array specially.
+       * output.h (Output_section::Inut_section_sort_compare): Update
+       comment.
+       (Output_section::Input_section_sort_init_fini_compare): New struct.
+
 2010-02-26  Doug Kwan  <dougkwan@google.com>
 
        * arm.cc (Target_arm::Relocate::reloc_is_non_pic): Treat
index c721ba6e5d2bf6e7ffd490a26714268355ebd60c..f95813bd34d91d440f25b607d7ce29df5c4249bc 100644 (file)
@@ -582,19 +582,40 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
 
   Output_section* os;
 
+  // Sometimes .init_array*, .preinit_array* and .fini_array* do not have
+  // correct section types.  Force them here.
+  elfcpp::Elf_Word sh_type = shdr.get_sh_type();
+  if (sh_type == elfcpp::SHT_PROGBITS)
+    {
+      static const char init_array_prefix[] = ".init_array";
+      static const char preinit_array_prefix[] = ".preinit_array";
+      static const char fini_array_prefix[] = ".fini_array";
+      static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1;
+      static size_t preinit_array_prefix_size =
+       sizeof(preinit_array_prefix) - 1;
+      static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1;
+
+      if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0)
+       sh_type = elfcpp::SHT_INIT_ARRAY;
+      else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size)
+              == 0)
+       sh_type = elfcpp::SHT_PREINIT_ARRAY;
+      else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0)
+       sh_type = elfcpp::SHT_FINI_ARRAY;
+    }
+
   // In a relocatable link a grouped section must not be combined with
   // any other sections.
   if (parameters->options().relocatable()
       && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
     {
       name = this->namepool_.add(name, true, NULL);
-      os = this->make_output_section(name, shdr.get_sh_type(),
-                                    shdr.get_sh_flags(), false, false,
-                                    false, false, false);
+      os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false,
+                                    false, false, false, false);
     }
   else
     {
-      os = this->choose_output_section(object, name, shdr.get_sh_type(),
+      os = this->choose_output_section(object, name, sh_type,
                                       shdr.get_sh_flags(), true, false,
                                       false, false, false, false);
       if (os == NULL)
index 1c2533c0c7e4e158b591a9d704892898067eb1e2..d49f08b605c715a10dde25d9703aee206f869c5b 100644 (file)
@@ -2695,7 +2695,7 @@ class Output_section::Input_section_sort_entry
   has_priority() const
   {
     gold_assert(this->section_has_name_);
-    return this->section_name_.find('.', 1);
+    return this->section_name_.find('.', 1) != std::string::npos;
   }
 
   // Return true if this an input file whose base name matches
@@ -2773,8 +2773,6 @@ Output_section::Input_section_sort_compare::operator()(
     }
 
   // A section with a priority follows a section without a priority.
-  // The GNU linker does this for all but .init_array sections; until
-  // further notice we'll assume that that is an mistake.
   bool s1_has_priority = s1.has_priority();
   bool s2_has_priority = s2.has_priority();
   if (s1_has_priority && !s2_has_priority)
@@ -2791,6 +2789,42 @@ Output_section::Input_section_sort_compare::operator()(
   return s1.index() < s2.index();
 }
 
+// Return true if S1 should come before S2 in an .init_array or .fini_array
+// output section.
+
+bool
+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();
+  bool s2_has_priority = s2.has_priority();
+  if (s1_has_priority && !s2_has_priority)
+    return true;
+  if (!s1_has_priority && s2_has_priority)
+    return false;
+
+  // Otherwise we sort by name.
+  int compare = s1.section_name().compare(s2.section_name());
+  if (compare != 0)
+    return compare < 0;
+
+  // Otherwise we keep the input order.
+  return s1.index() < s2.index();
+}
+
 // Sort the input sections attached to an output section.
 
 void
@@ -2819,7 +2853,14 @@ Output_section::sort_attached_input_sections()
     sort_list.push_back(Input_section_sort_entry(*p, i));
 
   // Sort the input sections.
-  std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_compare());
+  if (this->type() == elfcpp::SHT_PREINIT_ARRAY
+      || this->type() == elfcpp::SHT_INIT_ARRAY
+      || this->type() == elfcpp::SHT_FINI_ARRAY)
+    std::sort(sort_list.begin(), sort_list.end(),
+             Input_section_sort_init_fini_compare());
+  else
+    std::sort(sort_list.begin(), sort_list.end(),
+             Input_section_sort_compare());
 
   // Copy the sorted input sections back to our list.
   this->input_sections_.clear();
index 9008bdd66109036c880836c989b0348397f51f65..a63f07c1a0c13241e6985268d63f5ae4c6db8e91 100644 (file)
@@ -3378,7 +3378,7 @@ class Output_section : public Output_data
   // This class is used to sort the input sections.
   class Input_section_sort_entry;
 
-  // This is the sort comparison function.
+  // This is the sort comparison function for ctors and dtors.
   struct Input_section_sort_compare
   {
     bool
@@ -3386,6 +3386,14 @@ class Output_section : public Output_data
               const Input_section_sort_entry&) const;
   };
 
+  // This is the sort comparison function for .init_array and .fini_array.
+  struct Input_section_sort_init_fini_compare
+  {
+    bool
+    operator()(const Input_section_sort_entry&,
+              const Input_section_sort_entry&) const;
+  };
+
   // Fill data.  This is used to fill in data between input sections.
   // It is also used for data statements (BYTE, WORD, etc.) in linker
   // scripts.  When we have to keep track of the input sections, we