* gold.h (is_wildcard_string): New function.
authorSriraman Tallam <tmsriram@google.com>
Tue, 1 Jun 2010 23:37:58 +0000 (23:37 +0000)
committerSriraman Tallam <tmsriram@google.com>
Tue, 1 Jun 2010 23:37:58 +0000 (23:37 +0000)
* layout.cc (Layout::layout): Pass this pointer to add_input_section.
(Layout::layout_eh_frame): Ditto.
(Layout::find_section_order_index): New method.
(Layout::read_layout_from_file): New method.
* layout.h (Layout::find_section_order_index): New method.
(Layout::read_layout_from_file): New method.
(Layout::input_section_position_): New private member.
(Layout::input_section_glob_): New private member.
* main.cc (main): Call read_layout_from_file here.
* options.h (--section-ordering-file): New option.
* output.cc (Output_section::input_section_order_specified_): New
member.
(Output_section::Output_section): Initialize new member.
(Output_section::add_input_section): Add new parameter.
Keep input sections when --section-ordering-file is used.
(Output_section::set_final_data_size): Sort input sections when
section ordering file is specified.
(Output_section::Input_section_sort_entry): Add new parameter.
Check sorting type.
(Output_section::Input_section_sort_entry::compare_section_ordering):
New method.
(Output_section::Input_section_sort_compare::operator()): Change to
consider section_order_index.
(Output_section::Input_section_sort_init_fini_compare::operator()):
Change to consider section_order_index.
(Output_section::Input_section_sort_section_order_index_compare
::operator()): New method.
(Output_section::sort_attached_input_sections): Change to sort
according to section order when specified.
(Output_section::add_input_section<32, true>): Add new parameter.
(Output_section::add_input_section<64, true>): Add new parameter.
(Output_section::add_input_section<32, false>): Add new parameter.
(Output_section::add_input_section<64, false>): Add new parameter.
* output.h (Output_section::add_input_section): Add new parameter.
(Output_section::input_section_order_specified): New
method.
(Output_section::set_input_section_order_specified): New method.
(Input_section::Input_section): Initialize section_order_index_.
(Input_section::section_order_index): New method.
(Input_section::set_section_order_index): New method.
(Input_section::section_order_index_): New member.
(Input_section::Input_section_sort_section_order_index_compare): New
struct.
(Output_section::input_section_order_specified_): New member.
* script-sections.cc (is_wildcard_string): Delete and move modified
method to gold.h.
(Output_section_element_input::Output_section_element_input): Modify
call to is_wildcard_string.
(Output_section_element_input::Input_section_pattern
::Input_section_pattern): Ditto.
(Output_section_element_input::Output_section_element_input): Ditto.
* testsuite/Makefile.am (final_layout): New test case.
* testsuite/Makefile.in: Regenerate.
* testsuite/final_layout.cc: New file.
* testsuite/final_layout.sh: New file.

13 files changed:
gold/ChangeLog
gold/gold.h
gold/layout.cc
gold/layout.h
gold/main.cc
gold/options.h
gold/output.cc
gold/output.h
gold/script-sections.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/final_layout.cc [new file with mode: 0644]
gold/testsuite/final_layout.sh [new file with mode: 0755]

index 2b4e94b9168a5457b9a553ee072b3aa162619039..95e683f4152c27a92ccc34447fdc690e16a2be9f 100644 (file)
@@ -1,3 +1,62 @@
+2010-06-01  Sriraman Tallam  <tmsriram@google.com>
+
+       * gold.h (is_wildcard_string): New function.
+       * layout.cc (Layout::layout): Pass this pointer to add_input_section.
+       (Layout::layout_eh_frame): Ditto.
+       (Layout::find_section_order_index): New method.
+       (Layout::read_layout_from_file): New method.
+       * layout.h (Layout::find_section_order_index): New method.
+       (Layout::read_layout_from_file): New method.
+       (Layout::input_section_position_): New private member.
+       (Layout::input_section_glob_): New private member.
+       * main.cc (main): Call read_layout_from_file here.
+       * options.h (--section-ordering-file): New option.
+       * output.cc (Output_section::input_section_order_specified_): New
+       member.
+       (Output_section::Output_section): Initialize new member.
+       (Output_section::add_input_section): Add new parameter.
+       Keep input sections when --section-ordering-file is used.
+       (Output_section::set_final_data_size): Sort input sections when
+       section ordering file is specified.
+       (Output_section::Input_section_sort_entry): Add new parameter.
+       Check sorting type.
+       (Output_section::Input_section_sort_entry::compare_section_ordering):
+       New method.
+       (Output_section::Input_section_sort_compare::operator()): Change to
+       consider section_order_index.
+       (Output_section::Input_section_sort_init_fini_compare::operator()):
+       Change to consider section_order_index.
+       (Output_section::Input_section_sort_section_order_index_compare
+       ::operator()): New method.
+       (Output_section::sort_attached_input_sections): Change to sort
+       according to section order when specified.
+       (Output_section::add_input_section<32, true>): Add new parameter. 
+       (Output_section::add_input_section<64, true>): Add new parameter. 
+       (Output_section::add_input_section<32, false>): Add new parameter. 
+       (Output_section::add_input_section<64, false>): Add new parameter. 
+       * output.h (Output_section::add_input_section): Add new parameter.
+       (Output_section::input_section_order_specified): New
+       method.
+       (Output_section::set_input_section_order_specified): New method.
+       (Input_section::Input_section): Initialize section_order_index_.
+       (Input_section::section_order_index): New method.
+       (Input_section::set_section_order_index): New method.
+       (Input_section::section_order_index_): New member.
+       (Input_section::Input_section_sort_section_order_index_compare): New
+       struct.
+       (Output_section::input_section_order_specified_): New member.
+       * script-sections.cc (is_wildcard_string): Delete and move modified
+       method to gold.h.
+       (Output_section_element_input::Output_section_element_input): Modify
+       call to is_wildcard_string.
+       (Output_section_element_input::Input_section_pattern
+       ::Input_section_pattern): Ditto.
+       (Output_section_element_input::Output_section_element_input): Ditto.
+       * testsuite/Makefile.am (final_layout): New test case.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/final_layout.cc: New file.
+       * testsuite/final_layout.sh: New file.
+
 2010-06-01  Rafael Espindola  <espindola@google.com>
 
        * plugin.cc (Plugin::load): Pass the output name to the plugin.
index 04b691150990d73fb352c7f5a2d18be3d8e8505f..90f1f7d1f4ecfbf6ae53c5ef387b0d6e55223963 100644 (file)
@@ -401,6 +401,15 @@ string_hash(const Char_type* s)
   return h;
 }
 
+// Return whether STRING contains a wildcard character.  This is used
+// to speed up matching.
+
+inline bool
+is_wildcard_string(const char* s)
+{
+  return strpbrk(s, "?*[") != NULL;
+}
+
 } // End namespace gold.
 
 #endif // !defined(GOLD_GOLD_H)
index 36cfa8bd744063286d5d41fd283ae08de8ed0b30..a39b1157b08b4d6f6ad38a36e745ae55e0d6c45d 100644 (file)
 #include <cstring>
 #include <algorithm>
 #include <iostream>
+#include <fstream>
 #include <utility>
 #include <fcntl.h>
+#include <fnmatch.h>
 #include <unistd.h>
 #include "libiberty.h"
 #include "md5.h"
@@ -668,7 +670,7 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
 
   // FIXME: Handle SHF_LINK_ORDER somewhere.
 
-  *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
+  *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
                               this->script_options_->saw_sections_clause());
   this->have_added_input_section_ = true;
 
@@ -886,7 +888,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
       // We couldn't handle this .eh_frame section for some reason.
       // Add it as a normal section.
       bool saw_sections_clause = this->script_options_->saw_sections_clause();
-      *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
+      *off = os->add_input_section(this, object, shndx, name, shdr, reloc_shndx,
                                   saw_sections_clause);
       this->have_added_input_section_ = true;
     }
@@ -1642,6 +1644,72 @@ Layout::relaxation_loop_body(
   return off;
 }
 
+// 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
+// precedence.  Return 0 if no match is found.
+
+unsigned int
+Layout::find_section_order_index(const std::string& section_name)
+{
+  Unordered_map<std::string, unsigned int>::iterator map_it;
+  map_it = this->input_section_position_.find(section_name);
+  if (map_it != this->input_section_position_.end())
+    return map_it->second;
+
+  // Absolute match failed.  Linear search the glob patterns.
+  std::vector<std::string>::iterator it;
+  for (it = this->input_section_glob_.begin();
+       it != this->input_section_glob_.end();
+       ++it)
+    {
+       if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0)
+         {
+           map_it = this->input_section_position_.find(*it);
+           gold_assert(map_it != this->input_section_position_.end());
+           return map_it->second;
+         }
+    }
+  return 0;
+}
+
+// Read the sequence of input sections from the file specified with
+// --section-ordering-file.
+
+void
+Layout::read_layout_from_file()
+{
+  const char* filename = parameters->options().section_ordering_file();
+  std::ifstream in;
+  std::string line;
+
+  in.open(filename);
+  if (!in)
+    gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
+               filename, strerror(errno));
+
+  std::getline(in, line);   // this chops off the trailing \n, if any
+  unsigned int position = 1;
+
+  while (in)
+    {
+      if (!line.empty() && line[line.length() - 1] == '\r')   // Windows
+        line.resize(line.length() - 1);
+      // Ignore comments, beginning with '#'
+      if (line[0] == '#')
+        {
+          std::getline(in, line);
+          continue;
+        }
+      this->input_section_position_[line] = position;
+      // Store all glob patterns in a vector.
+      if (is_wildcard_string(line.c_str()))
+        this->input_section_glob_.push_back(line);
+      position++;
+      std::getline(in, line);
+    }
+}
+
 // Finalize the layout.  When this is called, we have created all the
 // output sections and all the output segments which are based on
 // input sections.  We have several things to do, and we have to do
index 912be31e15490d604c343b232d8678ce42241ecf..55ad7a6a3a57e11f8019bd051d4d3754b17e5c87 100644 (file)
@@ -308,6 +308,12 @@ class Layout
         const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
         unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
 
+  unsigned int
+  find_section_order_index(const std::string&);
+
+  void
+  read_layout_from_file();
+
   // Layout an input reloc section when doing a relocatable link.  The
   // section is RELOC_SHNDX in OBJECT, with data in SHDR.
   // DATA_SECTION is the reloc section to which it refers.  RR is the
@@ -1037,6 +1043,10 @@ class Layout
   Segment_states* segment_states_;
   // A relaxation debug checker.  We only create one when in debugging mode.
   Relaxation_debug_check* relaxation_debug_check_;
+  // Hash a pattern to its position in the section ordering file.
+  Unordered_map<std::string, unsigned int> input_section_position_;
+  // Vector of glob only patterns in the section_ordering file.
+  std::vector<std::string> input_section_glob_;
 };
 
 // This task handles writing out data in output sections which is not
index e3df9c084841926370a798c2929b8f7f1b0cddbc..631f1ac2d2c263cb7e34ebc9c07ac300b232c14c 100644 (file)
@@ -234,6 +234,9 @@ main(int argc, char** argv)
       layout.incremental_inputs()->report_inputs(command_line.inputs());
     }
 
+  if (parameters->options().section_ordering_file())
+    layout.read_layout_from_file();
+
   // Get the search path from the -L options.
   Dirsearch search_path;
   search_path.initialize(&workqueue, &command_line.options().library_path());
index 1e328a8dbecf94041c858073c0414d4d7699af18..cf1c15375fb7e1e25733d1115ac3112d3f5e255f 100644 (file)
@@ -892,6 +892,10 @@ class General_options
                  N_("Add DIR to link time shared library search path"),
                  N_("DIR"));
 
+  DEFINE_string(section_ordering_file, options::TWO_DASHES, '\0', NULL,
+               N_("Layout sections in the order specified."),
+               N_("FILENAME"));
+
   DEFINE_special(section_start, options::TWO_DASHES, '\0',
                 N_("Set address of section"), N_("SECTION=ADDRESS"));
 
index 752a1d37a044b09b386b47e8ee36e7e0ba6bf442..3cfcf1ebeb49f4fab02a844ac6873ac9fba4cd62 100644 (file)
@@ -1933,6 +1933,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     found_in_sections_clause_(false),
     has_load_address_(false),
     info_uses_section_index_(false),
+    input_section_order_specified_(false),
     may_sort_attached_input_sections_(false),
     must_sort_attached_input_sections_(false),
     attached_input_sections_are_sorted_(false),
@@ -1994,7 +1995,8 @@ Output_section::set_entsize(uint64_t v)
 
 template<int size, bool big_endian>
 off_t
-Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
+Output_section::add_input_section(Layout* layout,
+                                 Sized_relobj<size, big_endian>* object,
                                  unsigned int shndx,
                                  const char* secname,
                                  const elfcpp::Shdr<size, big_endian>& shdr,
@@ -2090,16 +2092,30 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
   // 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
-  // the future, we keep track of the sections.
+  // the future, we keep track of the sections.  If the
+  // --section-ordering-file option is used to specify the order of
+  // sections, we need to keep track of sections.
   if (have_sections_script
       || !this->input_sections_.empty()
       || this->may_sort_attached_input_sections()
       || this->must_sort_attached_input_sections()
       || parameters->options().user_set_Map()
-      || parameters->target().may_relax())
-    this->input_sections_.push_back(Input_section(object, shndx,
-                                                 shdr.get_sh_size(),
-                                                 addralign));
+      || parameters->target().may_relax()
+      || parameters->options().section_ordering_file())
+    {
+      Input_section isecn(object, shndx, shdr.get_sh_size(), addralign);
+      if (parameters->options().section_ordering_file())
+        {
+          unsigned int section_order_index =
+            layout->find_section_order_index(std::string(secname));
+         if (section_order_index != 0)
+            {
+              isecn.set_section_order_index(section_order_index);
+              this->set_input_section_order_specified();
+            }
+        }
+      this->input_sections_.push_back(isecn);
+    }
 
   return aligned_offset_in_section;
 }
@@ -2623,7 +2639,8 @@ Output_section::set_final_data_size()
       return;
     }
 
-  if (this->must_sort_attached_input_sections())
+  if (this->must_sort_attached_input_sections()
+      || this->input_section_order_specified())
     this->sort_attached_input_sections();
 
   uint64_t address = this->address();
@@ -2700,12 +2717,14 @@ class Output_section::Input_section_sort_entry
   { }
 
   Input_section_sort_entry(const Input_section& input_section,
-                          unsigned int index)
+                          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())
   {
-    if (this->section_has_name_)
+    if (this->section_has_name_
+        && must_sort_attached_input_sections)
       {
        // This is only called single-threaded from Layout::finalize,
        // so it is OK to lock.  Unfortunately we have no way to pass
@@ -2782,6 +2801,22 @@ class Output_section::Input_section_sort_entry
     return memcmp(base_name + base_len - 2, ".o", 2) == 0;
   }
 
+  // Returns 0 if sections are not comparable. Returns 1 if THIS is the
+  // first section in order, returns -1 for S.
+  int
+  compare_section_ordering(const Input_section_sort_entry& s) const
+  {
+    gold_assert(this->index_ != -1U);
+    if (this->input_section_.section_order_index() == 0
+        || s.input_section().section_order_index() == 0)
+      return 0;
+    if (this->input_section_.section_order_index()
+        < s.input_section().section_order_index())
+      return 1;
+    else
+      return -1;
+  }
+
  private:
   // The Input_section we are sorting.
   Input_section input_section_;
@@ -2843,6 +2878,12 @@ Output_section::Input_section_sort_compare::operator()(
   if (!s1_has_priority && s2_has_priority)
     return true;
 
+  // Check if a section order exists for these sections through a section
+  // ordering file.  If sequence_num is 0, an order does not exist.
+  int sequence_num = s1.compare_section_ordering(s2);
+  if (sequence_num != 0)
+    return sequence_num == 1;
+
   // Otherwise we sort by name.
   int compare = s1.section_name().compare(s2.section_name());
   if (compare != 0)
@@ -2879,6 +2920,12 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
   if (!s1_has_priority && s2_has_priority)
     return false;
 
+  // Check if a section order exists for these sections through a section
+  // ordering file.  If sequence_num is 0, an order does not exist.
+  int sequence_num = s1.compare_section_ordering(s2);
+  if (sequence_num != 0)
+    return sequence_num == 1;
+
   // Otherwise we sort by name.
   int compare = s1.section_name().compare(s2.section_name());
   if (compare != 0)
@@ -2888,6 +2935,22 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
   return s1.index() < s2.index();
 }
 
+// Return true if S1 should come before S2.
+bool
+Output_section::Input_section_sort_section_order_index_compare::operator()(
+    const Output_section::Input_section_sort_entry& s1,
+    const Output_section::Input_section_sort_entry& s2) const
+{
+  // Check if a section order exists for these sections through a section
+  // ordering file.  If sequence_num is 0, an order does not exist.
+  int sequence_num = s1.compare_section_ordering(s2);
+  if (sequence_num != 0)
+    return sequence_num == 1;
+
+  // Otherwise we keep the input order.
+  return s1.index() < s2.index();
+}
+
 // Sort the input sections attached to an output section.
 
 void
@@ -2913,17 +2976,27 @@ Output_section::sort_attached_input_sections()
   for (Input_section_list::iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p, ++i)
-    sort_list.push_back(Input_section_sort_entry(*p, i));
+      sort_list.push_back(Input_section_sort_entry(*p, i,
+                            this->must_sort_attached_input_sections()));
 
   // Sort the input sections.
-  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());
+  if (this->must_sort_attached_input_sections())
+    {
+      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());
+    }
   else
-    std::sort(sort_list.begin(), sort_list.end(),
-             Input_section_sort_compare());
+    {
+      gold_assert(parameters->options().section_ordering_file());
+      std::sort(sort_list.begin(), sort_list.end(),
+               Input_section_sort_section_order_index_compare());
+    }
 
   // Copy the sorted input sections back to our list.
   this->input_sections_.clear();
@@ -2931,6 +3004,7 @@ Output_section::sort_attached_input_sections()
        p != sort_list.end();
        ++p)
     this->input_sections_.push_back(p->input_section());
+  sort_list.clear();
 
   // Remember that we sorted the input sections, since we might get
   // called again.
@@ -4466,6 +4540,7 @@ Output_file::close()
 template
 off_t
 Output_section::add_input_section<32, false>(
+    Layout* layout,
     Sized_relobj<32, false>* object,
     unsigned int shndx,
     const char* secname,
@@ -4478,6 +4553,7 @@ Output_section::add_input_section<32, false>(
 template
 off_t
 Output_section::add_input_section<32, true>(
+    Layout* layout,
     Sized_relobj<32, true>* object,
     unsigned int shndx,
     const char* secname,
@@ -4490,6 +4566,7 @@ Output_section::add_input_section<32, true>(
 template
 off_t
 Output_section::add_input_section<64, false>(
+    Layout* layout,
     Sized_relobj<64, false>* object,
     unsigned int shndx,
     const char* secname,
@@ -4502,6 +4579,7 @@ Output_section::add_input_section<64, false>(
 template
 off_t
 Output_section::add_input_section<64, true>(
+    Layout* layout,
     Sized_relobj<64, true>* object,
     unsigned int shndx,
     const char* secname,
index eb5d83671cc0be78afe11f871d9eade8a44f8d8f..1a0a8da42c4cdbd0f0478169a77ddc0b30dbe849 100644 (file)
@@ -2515,8 +2515,8 @@ class Output_section : public Output_data
   // within the output section.
   template<int size, bool big_endian>
   off_t
-  add_input_section(Sized_relobj<size, big_endian>* object, unsigned int shndx,
-                   const char *name,
+  add_input_section(Layout* layout, Sized_relobj<size, big_endian>* object,
+                    unsigned int shndx, const char *name,
                    const elfcpp::Shdr<size, big_endian>& shdr,
                    unsigned int reloc_shndx, bool have_sections_script);
 
@@ -2736,6 +2736,18 @@ class Output_section : public Output_data
   set_may_sort_attached_input_sections()
   { this->may_sort_attached_input_sections_ = true; }
 
+   // Returns true if input sections must be sorted according to the
+  // order in which their name appear in the --section-ordering-file.
+  bool
+  input_section_order_specified()
+  { return this->input_section_order_specified_; }
+
+  // Record that input sections must be sorted as some of their names
+  // match the patterns specified through --section-ordering-file.
+  void
+  set_input_section_order_specified()
+  { this->input_section_order_specified_ = true; }
+
   // Return whether the input sections attached to this output section
   // require sorting.  This is used to handle constructor priorities
   // compatibly with GNU ld.
@@ -2972,7 +2984,8 @@ class Output_section : public Output_data
     Input_section(Relobj* object, unsigned int shndx, off_t data_size,
                  uint64_t addralign)
       : shndx_(shndx),
-       p2align_(ffsll(static_cast<long long>(addralign)))
+       p2align_(ffsll(static_cast<long long>(addralign))),
+       section_order_index_(0)
     {
       gold_assert(shndx != OUTPUT_SECTION_CODE
                  && shndx != MERGE_DATA_SECTION_CODE
@@ -2984,7 +2997,8 @@ class Output_section : public Output_data
 
     // For a non-merge output section.
     Input_section(Output_section_data* posd)
-      : shndx_(OUTPUT_SECTION_CODE), p2align_(0)
+      : shndx_(OUTPUT_SECTION_CODE), p2align_(0),
+       section_order_index_(0)
     {
       this->u1_.data_size = 0;
       this->u2_.posd = posd;
@@ -2995,7 +3009,8 @@ class Output_section : public Output_data
       : shndx_(is_string
               ? MERGE_STRING_SECTION_CODE
               : MERGE_DATA_SECTION_CODE),
-       p2align_(0)
+       p2align_(0),
+       section_order_index_(0)
     {
       this->u1_.entsize = entsize;
       this->u2_.posd = posd;
@@ -3003,12 +3018,25 @@ class Output_section : public Output_data
 
     // For a relaxed input section.
     Input_section(Output_relaxed_input_section *psection)
-      : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0)
+      : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0),
+       section_order_index_(0)
     {
       this->u1_.data_size = 0;
       this->u2_.poris = psection;
     }
 
+    unsigned int
+    section_order_index() const
+    {
+      return this->section_order_index_;
+    }
+
+    void
+    set_section_order_index(unsigned int number)
+    {
+      this->section_order_index_ = number;
+    }
+
     // The required alignment.
     uint64_t
     addralign() const
@@ -3234,6 +3262,9 @@ class Output_section : public Output_data
       // For RELAXED_INPUT_SECTION_CODE, the data.
       Output_relaxed_input_section* poris;
     } u2_;
+    // The line number of the pattern it matches in the --section-ordering-file
+    // file.  It is 0 if does not match any pattern.
+    unsigned int section_order_index_;
   };
 
   // Store the list of input sections for this Output_section into the
@@ -3540,6 +3571,15 @@ class Output_section : public Output_data
               const Input_section_sort_entry&) const;
   };
 
+  // This is the sort comparison function when a section order is specified
+  // from an input file.
+  struct Input_section_sort_section_order_index_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
@@ -3707,6 +3747,9 @@ class Output_section : public Output_data
   // section, false if it means the symbol index of the corresponding
   // section symbol.
   bool info_uses_section_index_ : 1;
+  // True if input sections attached to this output section have to be
+  // sorted according to a specified order.
+  bool input_section_order_specified_ : 1;
   // True if the input sections attached to this output section may
   // need sorting.
   bool may_sort_attached_input_sections_ : 1;
index 3266115a9e76b2de94f5c51e9369c55da9334054..2988d106f21747e57ed123d1fcb4e6b915ee1f9e 100644 (file)
@@ -983,15 +983,6 @@ class Output_section_element_fill : public Output_section_element
   Expression* val_;
 };
 
-// Return whether STRING contains a wildcard character.  This is used
-// to speed up matching.
-
-static inline bool
-is_wildcard_string(const std::string& s)
-{
-  return strpbrk(s.c_str(), "?*[") != NULL;
-}
-
 // An input section specification in an output section
 
 class Output_section_element_input : public Output_section_element
@@ -1035,7 +1026,7 @@ class Output_section_element_input : public Output_section_element
     Input_section_pattern(const char* patterna, size_t patternlena,
                          Sort_wildcard sorta)
       : pattern(patterna, patternlena),
-       pattern_is_wildcard(is_wildcard_string(this->pattern)),
+       pattern_is_wildcard(is_wildcard_string(this->pattern.c_str())),
        sort(sorta)
     { }
   };
@@ -1102,7 +1093,7 @@ Output_section_element_input::Output_section_element_input(
   if (spec->file.name.length != 1 || spec->file.name.value[0] != '*')
     this->filename_pattern_.assign(spec->file.name.value,
                                   spec->file.name.length);
-  this->filename_is_wildcard_ = is_wildcard_string(this->filename_pattern_);
+  this->filename_is_wildcard_ = is_wildcard_string(this->filename_pattern_.c_str());
 
   if (spec->input_sections.exclude != NULL)
     {
@@ -1111,7 +1102,7 @@ Output_section_element_input::Output_section_element_input(
           p != spec->input_sections.exclude->end();
           ++p)
        {
-         bool is_wildcard = is_wildcard_string(*p);
+         bool is_wildcard = is_wildcard_string((*p).c_str());
          this->filename_exclusions_.push_back(std::make_pair(*p,
                                                              is_wildcard));
        }
index afb704d15544120364dacf78ff6212847cdfeb89..67d03335f13307c5b07ef94726566ee7d00b18d1 100644 (file)
@@ -193,6 +193,18 @@ icf_safe_so_test_1.stdout: icf_safe_so_test
 icf_safe_so_test_2.stdout: icf_safe_so_test
        $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout
 
+check_SCRIPTS += final_layout.sh
+check_DATA += final_layout.stdout
+MOSTLYCLEANFILES += final_layout
+final_layout.o: final_layout.cc
+       $(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
+final_layout_sequence.txt:
+       (echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt
+final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
+       $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
+final_layout.stdout: final_layout
+       $(TEST_NM) final_layout > final_layout.stdout
+
 check_PROGRAMS += icf_virtual_function_folding_test
 MOSTLYCLEANFILES += icf_virtual_function_folding_test
 icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
index 4470580f1162e237ec5d74ada23fe0280ee40a47..efc3bcd7ff8d368f682513171ad69de80423a2f0 100644 (file)
@@ -62,6 +62,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \
@@ -94,6 +95,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_2.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
@@ -118,6 +120,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test icf_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test \
@@ -2609,6 +2612,14 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_so_test > icf_safe_so_test_1.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test_2.stdout: icf_safe_so_test
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.o: final_layout.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections  -fdata-sections -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout_sequence.txt:
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ (echo "*_Z3barv*" && echo ".text._Z3bazv" && echo "*_Z3foov*" && echo "*global_varb*" && echo "*global_vara*" && echo "*global_varc*") > final_layout_sequence.txt
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.stdout: final_layout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) final_layout > final_layout.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld
diff --git a/gold/testsuite/final_layout.cc b/gold/testsuite/final_layout.cc
new file mode 100644 (file)
index 0000000..f533885
--- /dev/null
@@ -0,0 +1,48 @@
+// final_layout.cc -- a test case for gold
+
+// Copyright 2010 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+// The goal of this program is to verify if --section-ordering-file orders
+// the .text and .data sections correctly as specified.
+
+int global_vara;
+int global_varb;
+int global_varc;
+
+int foo()
+{
+  return 1;
+}
+
+int bar()
+{
+  return 1;
+}
+
+int baz()
+{
+  return 1;
+}
+
+int main()
+{
+  return 1;
+}
diff --git a/gold/testsuite/final_layout.sh b/gold/testsuite/final_layout.sh
new file mode 100755 (executable)
index 0000000..ed7ad78
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# final_layout.sh -- test --final-layout
+
+# Copyright 2010 Free Software Foundation, Inc.
+# Written by Sriraman Tallam <tmsriram@google.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# The goal of this program is to verify if --section-ordering-file works as
+# intended.  File final_layout.cc is in this test.
+
+check()
+{
+    func_addr_1=$((16#`grep $2 $1 | awk '{print $1}'`))
+    func_addr_2=$((16#`grep $3 $1 | awk '{print $1}'`))
+    if [ $func_addr_1 -gt $func_addr_2 ]
+    then
+        echo "final layout of" $2 "and" $3 "is not right."
+       exit 1
+    fi
+}
+
+check final_layout.stdout "_Z3barv" "_Z3bazv"
+check final_layout.stdout "_Z3bazv" "_Z3foov"
+check final_layout.stdout "global_varb" "global_vara"
+check final_layout.stdout "global_vara" "global_varc"