Patch to do reorder text and data sections according to a user specified sequence.

Sriraman Tallam tmsriram@google.com
Wed Mar 3 02:43:00 GMT 2010


Hi Ian,

    I finally got around to making the changes you specified. Please
take a look when you get a chance.

	* layout.cc (Layout::read_layout_from_file): New method.
	(Layout::layout): Pass this pointer to add_input_section.
	(Layout::layout_eh_frame): Ditto.
	* layout.h (Layout::read_layout_from_file): New method.
	(Layout::input_section_order): New method.
	(Layout::input_section_order_): 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::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::section_order_index_): New
	member.
	(Output_section::Input_section_sort_entry::section_order_index): 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.h (Output_section::input_section_order_specified): New
	method.
	(Output_section::set_input_section_order_specified): New method.
	(Input_section::glob_pattern_number): New method.
	(Input_section::set_glob_pattern_number): New method.
	(Input_section::glob_pattern_number_): New member.
	(Input_section::Input_section_sort_section_order_index_compare): New
	struct.
	(Output_section::input_section_order_specified_): New member.
	* testsuite/Makefile.am (final_layout): New test case.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/final_layout.cc: New file.
	* testsuite/final_layout.sh: New file


Thanks,
-Sriraman.


On Thu, Feb 11, 2010 at 9:29 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>>    I have attached a patch to reorder text and data sections in the
>> linker according to a user specified sequence. I have added a new
>> option --final-layout to do this. Currently, this could be done using
>> linker scripts but this patch makes it really easy to do this. Let me
>> explain using a simple example.
>>
>> test.cc
>>
>> void foo()
>> { }
>>
>> void bar()
>> { }
>>
>> int main()
>> {
>>   return 0;
>> }
>>
>> $ g++ -ffunction-sections test.cc
>> $ nm -n a.out
>> ...
>> 000000000040038c T _Z3foov
>> 0000000000400392 T _Z3barv
>> ....
>>
>> foo is laid to be before bar. Now, I can change this order as follows.
>>
>> $ (echo "_Z3barv" && echo "_Z3foov") > sequence.txt
>> $ g++ -ffunction-sections test.cc -Wl,--final-layout,sequence.txt
>> $ nm -n a.out
>> ...
>> 0000000000400658 T _Z3barv
>> 000000000040065e T _Z3foov
>> ...
>>
>> The order is changed.
>>
>> This can be done for text or data sections.
>
>
> As I understand it, in linker terms, you are sorting the sections by
> suffixes.  When two input sections are in the same output section, and
> both input sections have suffixes which appear in the file, then the
> input sections are sorted in the order in which the suffixes appear in
> the file.
>
> I think it would be more natural to sort the input sections by name
> rather than by suffix.  Since you don't want to fuss with writing
> ".text." all the time, suppose we say that we sort the input sections
> by name, and we match the input section names using glob patterns.  We
> already use glob patterns in linker scripts, so that is not a big
> stretch.
>
> Just a few comments on the rest of the patch.
>
>
>
>> +// Read the sequence of input sections from the file specified with
>> +// --final-layout.
>> +
>> +bool
>> +Layout::read_layout_from_file()
>> +{
>> +  const char* filename = parameters->options().final_layout();
>> +  char *buf = NULL;
>> +  size_t len = 0;
>> +  FILE* fp = fopen(filename, "r");
>> +
>> +  if (fp == NULL)
>> +    {
>> +      gold_error(_("Error opening layout file : %s\n"), filename);
>> +      gold_exit(false);
>> +    }
>> +
>> +  while (getline(&buf, &len, fp) != -1)
>> +    {
>> +      buf[strlen(buf) - 1] = 0;
>> +      this->input_section_order_.push_back(std::string(buf));
>> +    }
>> +
>> +  if (buf != NULL)
>> +    free(buf);
>> +
>> +  fclose(fp);
>> +  return true;
>> +}
>
> The getline function is insufficient portable for use in gold.  Search
> for std::getline in options.cc for an alternate approach you can use.
> Emulate the error message style you see there too--no capital letter,
> name the file, no space before colon, no \n.  And if you really want
> to exit on failure, call gold_fatal.
>
>
>> +// If --final-layout option is used, reorder the input sections in
>> +// .text, .data, .bss and .rodata according to the specified sequence.
>> +
>> +void
>> +Layout::section_reorder()
>> +{
>> +  this->read_layout_from_file();
>> +
>> +  for (Section_list::iterator p = this->section_list_.begin();
>> +       p != this->section_list_.end();
>> +       ++p)
>> +    {
>> +      if (strcmp(".text", (*p)->name()) == 0
>> +          || strcmp(".data", (*p)->name()) == 0
>> +          || strcmp(".bss", (*p)->name()) == 0
>> +          || strcmp(".rodata", (*p)->name()) == 0)
>> +        (*p)->reorder_layout(this);
>> +    }
>> +}
>
> Why restrict this to those output sections?  Why not sort input
> sections in any output section?
>
>
>> +  DEFINE_string(final_layout, options::TWO_DASHES, '\0', NULL,
>> +             N_("Layout functions and data in the order specified."),
>> +             N_("FILENAME"));
>
> I'm not sure I care for --final-layout as the option name.  Perhaps
> --section-ordering-file?  Perhaps somebody else has a better idea.
>
>
>> +  // the future, we keep track of the sections.  If the --final-layout
>> +  // 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().final_layout())
>> +    {
>> +      Input_section isecn(object, shndx, shdr.get_sh_size(), addralign);
>> +      isecn.set_section_name(secname);
>> +      this->input_sections_.push_back(isecn);
>> +    }
>
> Don't save the string here, that's just going to bloat memory usage.
> Instead, when you read the file, give each line a number.  Then match
> the section name which you have here against the list of patterns.  If
> you find a match, store the number in the Input_section structure.
> Also, if you find a match, set a flag in the output section.  Then
> sort the sections, by number, in a function called from
> set_final_data_size.
>
> You will see that there is already some section ordering in that
> function, which is used to implement constructor/destructor priority
> ordering.  I guess the priority ordering should take precedence.
> Maybe.
>
> Ian
>
-------------- next part --------------
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.167
diff -u -u -p -r1.167 layout.cc
--- layout.cc	1 Mar 2010 21:43:49 -0000	1.167
+++ layout.cc	3 Mar 2010 02:03:36 -0000
@@ -26,6 +26,7 @@
 #include <cstring>
 #include <algorithm>
 #include <iostream>
+#include <fstream>
 #include <utility>
 #include <fcntl.h>
 #include <unistd.h>
@@ -636,7 +637,8 @@ Layout::layout(Sized_relobj<size, big_en
   // FIXME: Handle SHF_LINK_ORDER somewhere.
 
   *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
-			       this->script_options_->saw_sections_clause());
+			       this->script_options_->saw_sections_clause(),
+                               this);
   this->have_added_input_section_ = true;
 
   return os;
@@ -845,7 +847,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
       // 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,
-				   saw_sections_clause);
+				   saw_sections_clause, this);
       this->have_added_input_section_ = true;
     }
 
@@ -1593,6 +1595,31 @@ Layout::relaxation_loop_body(
   return off;
 }
 
+// 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);
+  std::getline(in, line);   // this chops off the trailing \n, if any
+  if (!in)
+    gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
+               filename, strerror(errno));
+
+  while (in)
+    {
+      if (!line.empty() && line[line.length() - 1] == '\r')   // Windows
+        line.resize(line.length() - 1);
+      this->input_section_order_.push_back(line);
+      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: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.79
diff -u -u -p -r1.79 layout.h
--- layout.h	9 Feb 2010 20:29:44 -0000	1.79
+++ layout.h	3 Mar 2010 02:03:36 -0000
@@ -308,6 +308,13 @@ class Layout
 	 const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
 	 unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
 
+  void
+  read_layout_from_file();
+
+  std::vector<std::string>&
+  input_section_order()
+  { return this->input_section_order_; }
+
   // 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
@@ -1036,6 +1043,8 @@ class Layout
   Segment_states* segment_states_;
   // A relaxation debug checker.  We only create one when in debugging mode.
   Relaxation_debug_check* relaxation_debug_check_;
+  // Vector to store the desired sequence of input_sections.
+  std::vector<std::string> input_section_order_;
 };
 
 // This task handles writing out data in output sections which is not
Index: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.37
diff -u -u -p -r1.37 main.cc
--- main.cc	5 Jan 2010 21:52:51 -0000	1.37
+++ main.cc	3 Mar 2010 02:03:36 -0000
@@ -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: options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.140
diff -u -u -p -r1.140 options.h
--- options.h	13 Feb 2010 02:04:20 -0000	1.140
+++ options.h	3 Mar 2010 02:03:36 -0000
@@ -868,6 +868,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 functions and data in the order specified."),
+		N_("FILENAME"));
+
   DEFINE_special(section_start, options::TWO_DASHES, '\0',
 		 N_("Set address of section"), N_("SECTION=ADDRESS"));
 
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.121
diff -u -u -p -r1.121 output.cc
--- output.cc	1 Mar 2010 21:43:49 -0000	1.121
+++ output.cc	3 Mar 2010 02:03:36 -0000
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <fnmatch.h>
 #include <algorithm>
 #include "libiberty.h"
 
@@ -1893,6 +1894,7 @@ Output_section::Output_section(const cha
     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),
@@ -1961,7 +1963,8 @@ Output_section::add_input_section(Sized_
 				  const char* secname,
 				  const elfcpp::Shdr<size, big_endian>& shdr,
 				  unsigned int reloc_shndx,
-				  bool have_sections_script)
+				  bool have_sections_script,
+				  Layout* layout)
 {
   elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
   if ((addralign & (addralign - 1)) != 0)
@@ -2048,16 +2051,38 @@ Output_section::add_input_section(Sized_
   // 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())
+        {
+          // Check if this section name matches any of the input glob
+          // patterns.
+          unsigned int glob_pattern_number = 1;
+          for (std::vector<std::string>::iterator it_v
+               = layout->input_section_order().begin();
+               it_v != layout->input_section_order().end();
+               ++it_v, ++glob_pattern_number) 
+            {
+              if (fnmatch((*it_v).c_str(),secname, FNM_NOESCAPE) == 0)
+	        {
+                  isecn.set_glob_pattern_number(glob_pattern_number);
+		  this->set_input_section_order_specified();
+                  break;
+                }
+            }
+        }
+      this->input_sections_.push_back(isecn);
+    }
 
   return aligned_offset_in_section;
 }
@@ -2561,7 +2586,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();
@@ -2633,16 +2659,20 @@ class Output_section::Input_section_sort
  public:
   Input_section_sort_entry()
     : input_section_(), index_(-1U), section_has_name_(false),
-      section_name_()
+      section_name_(), section_order_index_(0)
   { }
 
   Input_section_sort_entry(const Input_section& input_section,
-			   unsigned int index)
+			   unsigned int index,
+			   unsigned int section_order_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())
+			|| input_section.is_relaxed_input_section()),
+      section_order_index_(section_order_index)
   {
-    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
@@ -2719,6 +2749,10 @@ class Output_section::Input_section_sort
     return memcmp(base_name + base_len - 2, ".o", 2) == 0;
   }
 
+  unsigned int
+  section_order_index() const
+  { return section_order_index_; }
+
  private:
   // The Input_section we are sorting.
   Input_section input_section_;
@@ -2729,6 +2763,7 @@ class Output_section::Input_section_sort
   bool section_has_name_;
   // The section name if there is one.
   std::string section_name_;
+  unsigned int section_order_index_;
 };
 
 // Return true if S1 should come before S2 in the output section.
@@ -2780,6 +2815,11 @@ Output_section::Input_section_sort_compa
   if (!s1_has_priority && s2_has_priority)
     return true;
 
+  // Check if a input sequence has been specified.
+  if (s1.section_order_index() > 0
+      || s2.section_order_index() > 0)
+    return (s1.section_order_index() < s2.section_order_index());
+
   // Otherwise we sort by name.
   int compare = s1.section_name().compare(s2.section_name());
   if (compare != 0)
@@ -2816,6 +2856,11 @@ Output_section::Input_section_sort_init_
   if (!s1_has_priority && s2_has_priority)
     return false;
 
+  // Check if a input sequence has been specified.
+  if (s1.section_order_index() > 0
+      || s2.section_order_index() > 0)
+    return (s1.section_order_index() < s2.section_order_index());
+
   // Otherwise we sort by name.
   int compare = s1.section_name().compare(s2.section_name());
   if (compare != 0)
@@ -2825,6 +2870,19 @@ Output_section::Input_section_sort_init_
   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
+{
+  if (s1.section_order_index() > 0
+      || s2.section_order_index() > 0)
+    return (s1.section_order_index() < s2.section_order_index());
+  // Otherwise we keep the input order.
+  return s1.index() < s2.index();
+}
+
 // Sort the input sections attached to an output section.
 
 void
@@ -2850,17 +2908,28 @@ Output_section::sort_attached_input_sect
   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,
+                          (*p).glob_pattern_number(),
+			  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();
@@ -4387,7 +4456,8 @@ Output_section::add_input_section<32, fa
     const char* secname,
     const elfcpp::Shdr<32, false>& shdr,
     unsigned int reloc_shndx,
-    bool have_sections_script);
+    bool have_sections_script,
+    Layout* layout);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
@@ -4399,7 +4469,8 @@ Output_section::add_input_section<32, tr
     const char* secname,
     const elfcpp::Shdr<32, true>& shdr,
     unsigned int reloc_shndx,
-    bool have_sections_script);
+    bool have_sections_script,
+    Layout* layout);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
@@ -4411,7 +4482,8 @@ Output_section::add_input_section<64, fa
     const char* secname,
     const elfcpp::Shdr<64, false>& shdr,
     unsigned int reloc_shndx,
-    bool have_sections_script);
+    bool have_sections_script,
+    Layout* layout);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
@@ -4423,7 +4495,8 @@ Output_section::add_input_section<64, tr
     const char* secname,
     const elfcpp::Shdr<64, true>& shdr,
     unsigned int reloc_shndx,
-    bool have_sections_script);
+    bool have_sections_script,
+    Layout* layout);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.102
diff -u -u -p -r1.102 output.h
--- output.h	1 Mar 2010 21:43:50 -0000	1.102
+++ output.h	3 Mar 2010 02:03:36 -0000
@@ -2336,7 +2336,8 @@ class Output_section : public Output_dat
   add_input_section(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);
+		    unsigned int reloc_shndx, bool have_sections_script,
+		    Layout* layout);
 
   // Add generated data POSD to this output section.
   void
@@ -2554,6 +2555,18 @@ class Output_section : public Output_dat
   set_may_sort_attached_input_sections()
   { this->may_sort_attached_input_sections_ = true; }
 
+  // Returns true if one or more input section names match the given
+  // glob patterns through --section-order.
+  bool
+  input_section_order_specified()
+  { return this->input_section_order_specified_; }
+
+  // Record that input sections must be sorted according to the order
+  // specified.
+  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.
@@ -3037,7 +3050,8 @@ class Output_section : public Output_dat
     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))),
+        glob_pattern_number_(0)
     {
       gold_assert(shndx != OUTPUT_SECTION_CODE
 		  && shndx != MERGE_DATA_SECTION_CODE
@@ -3049,7 +3063,8 @@ class Output_section : public Output_dat
 
     // For a non-merge output section.
     Input_section(Output_section_data* posd)
-      : shndx_(OUTPUT_SECTION_CODE), p2align_(0)
+      : shndx_(OUTPUT_SECTION_CODE), p2align_(0),
+        glob_pattern_number_(0)
     {
       this->u1_.data_size = 0;
       this->u2_.posd = posd;
@@ -3060,7 +3075,8 @@ class Output_section : public Output_dat
       : shndx_(is_string
 	       ? MERGE_STRING_SECTION_CODE
 	       : MERGE_DATA_SECTION_CODE),
-	p2align_(0)
+	p2align_(0),
+        glob_pattern_number_(0)
     {
       this->u1_.entsize = entsize;
       this->u2_.posd = posd;
@@ -3068,12 +3084,25 @@ class Output_section : public Output_dat
 
     // 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),
+        glob_pattern_number_(0)
     {
       this->u1_.data_size = 0;
       this->u2_.poris = psection;
     }
 
+    unsigned int
+    glob_pattern_number()
+    {
+      return this->glob_pattern_number_;
+    }
+
+    void
+    set_glob_pattern_number(unsigned int number)
+    {
+      this->glob_pattern_number_ = number;  
+    }
+
     // The required alignment.
     uint64_t
     addralign() const
@@ -3282,6 +3311,9 @@ class Output_section : public Output_dat
       // For RELAXED_INPUT_SECTION_CODE, the data.
       Output_relaxed_input_section* poris;
     } u2_;
+    // The line number of the glob pattern it matches in the --section-order
+    // file.  It is 0 if does not match any pattern.
+    unsigned int glob_pattern_number_;
   };
 
   typedef std::vector<Input_section> Input_section_list;
@@ -3394,6 +3426,15 @@ class Output_section : public Output_dat
 	       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
@@ -3627,6 +3668,9 @@ class Output_section : public Output_dat
   // 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;
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.124
diff -u -u -p -r1.124 Makefile.am
--- testsuite/Makefile.am	27 Feb 2010 00:36:49 -0000	1.124
+++ testsuite/Makefile.am	3 Mar 2010 02:03:36 -0000
@@ -193,6 +193,18 @@ icf_safe_so_test_1.stdout: icf_safe_so_t
 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 "*_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 += basic_test
 check_PROGRAMS += basic_static_test
 check_PROGRAMS += basic_pic_test
Index: testsuite/final_layout.cc
===================================================================
RCS file: testsuite/final_layout.cc
diff -N testsuite/final_layout.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/final_layout.cc	3 Mar 2010 02:03:36 -0000
@@ -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;
+}
Index: testsuite/final_layout.sh
===================================================================
RCS file: testsuite/final_layout.sh
diff -N testsuite/final_layout.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/final_layout.sh	3 Mar 2010 02:03:36 -0000
@@ -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"


More information about the Binutils mailing list