mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
* 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:
parent
600e715a7b
commit
edcac0c105
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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_; }
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user