Group text sections with prefixes .text.unlikely,.text.hot and .text.startup

by default.


2012-12-18  Sriraman Tallam  <tmsriram@google.com>

	* 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.
	* testsuite/Makefile.am (text_section_grouping): New test.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/text_section_grouping.cc: New file.
	* testsuite/text_section_grouping.sh: New file.
This commit is contained in:
Sriraman Tallam
2012-12-19 02:55:15 +00:00
parent e0e51b2391
commit 28f2a4ac6f
8 changed files with 265 additions and 7 deletions

View File

@ -2478,6 +2478,19 @@ 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
@ -2491,7 +2504,8 @@ 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())
|| layout->is_section_ordering_specified()
|| this->input_section_order_specified())
{
Input_section isecn(object, shndx, input_section_size, addralign);
/* If section ordering is requested by specifying a ordering file,
@ -3484,7 +3498,9 @@ 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.
// 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".
bool
Output_section::Input_section_sort_section_order_index_compare::operator()(
@ -3494,11 +3510,59 @@ 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();
// Keep input order if section ordering cannot determine order.
if (s1_secn_index == s2_secn_index)
return s1.index() < s2.index();
// If section ordering is specified, it takes precedence.
if (s1_secn_index != s2_secn_index)
return 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)
return s1.index() < s2.index();
else
return s1_group_index < s2_group_index;
}
// This updates the section order index of input sections according to the
@ -3559,7 +3623,8 @@ 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->must_sort_attached_input_sections()
|| this->input_section_order_specified())));
// Sort the input sections.
if (this->must_sort_attached_input_sections())