aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog27
-rw-r--r--gold/layout.cc57
-rw-r--r--gold/layout.h13
-rw-r--r--gold/output.cc98
4 files changed, 100 insertions, 95 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 62ddbc688a2..ae4f83059db 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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.
diff --git a/gold/layout.cc b/gold/layout.cc
index 62b4cadf9d3..f7f0e7e33a1 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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
diff --git a/gold/layout.h b/gold/layout.h
index 71f1aa7a495..6da96075047 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -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_; }
diff --git a/gold/output.cc b/gold/output.cc
index 39eb1b7dc79..f2321b77fc5 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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())