* 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.
This commit is contained in:
Ian Lance Taylor 2012-12-21 06:24:31 +00:00
parent 600e715a7b
commit edcac0c105
4 changed files with 100 additions and 95 deletions

View 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.

View 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

View 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_; }

View 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())