Implement SORT_BY_INIT_PRIORITY.

2016-06-28  Igor Kudrin  <ikudrin@accesssoftek.com>

gold/
	PR gold/18098
	* script-c.h (Sort_wildcard): Add SORT_WILDCARD_BY_INIT_PRIORITY.
	* script-sections.cc (Input_section_sorter::get_init_priority): New method.
	(Input_section_sorter::operator()): Handle SORT_WILDCARD_BY_INIT_PRIORITY.
	(Output_section_element_input::print): Likewise.
	* script.cc (script_keyword_parsecodes): Add entry SORT_BY_INIT_PRIORITY.
	* yyscript.y (SORT_BY_INIT_PRIORITY): New token.
	(wildcard_section): Handle SORT_BY_INIT_PRIORITY.

	* testsuite/Makefile.am (script_test_14): New test.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/script_test_14.s: New test source file.
	* testsuite/script_test_14.sh: New test script.
	* testsuite/script_test_14.t: New test linker script.
This commit is contained in:
Igor Kudrin
2016-06-28 13:56:05 -07:00
committed by Cary Coutant
parent 9abdce70ac
commit f224a3c590
10 changed files with 283 additions and 6 deletions

View File

@@ -1524,18 +1524,69 @@ class Input_section_sorter
operator()(const Input_section_info&, const Input_section_info&) const;
private:
static unsigned long
get_init_priority(const char*);
Sort_wildcard filename_sort_;
Sort_wildcard section_sort_;
};
// Return a relative priority of the section with the specified NAME
// (a lower value meand a higher priority), or 0 if it should be compared
// with others as strings.
// The implementation of this function is copied from ld/ldlang.c.
unsigned long
Input_section_sorter::get_init_priority(const char* name)
{
char* end;
unsigned long init_priority;
// GCC uses the following section names for the init_priority
// attribute with numerical values 101 and 65535 inclusive. A
// lower value means a higher priority.
//
// 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the
// decimal numerical value of the init_priority attribute.
// The order of execution in .init_array is forward and
// .fini_array is backward.
// 2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the
// decimal numerical value of the init_priority attribute.
// The order of execution in .ctors is backward and .dtors
// is forward.
if (strncmp(name, ".init_array.", 12) == 0
|| strncmp(name, ".fini_array.", 12) == 0)
{
init_priority = strtoul(name + 12, &end, 10);
return *end ? 0 : init_priority;
}
else if (strncmp(name, ".ctors.", 7) == 0
|| strncmp(name, ".dtors.", 7) == 0)
{
init_priority = strtoul(name + 7, &end, 10);
return *end ? 0 : 65535 - init_priority;
}
return 0;
}
bool
Input_section_sorter::operator()(const Input_section_info& isi1,
const Input_section_info& isi2) const
{
if (this->section_sort_ == SORT_WILDCARD_BY_INIT_PRIORITY)
{
unsigned long ip1 = get_init_priority(isi1.section_name().c_str());
unsigned long ip2 = get_init_priority(isi2.section_name().c_str());
if (ip1 != 0 && ip2 != 0 && ip1 != ip2)
return ip1 < ip2;
}
if (this->section_sort_ == SORT_WILDCARD_BY_NAME
|| this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT
|| (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME
&& isi1.addralign() == isi2.addralign()))
&& isi1.addralign() == isi2.addralign())
|| this->section_sort_ == SORT_WILDCARD_BY_INIT_PRIORITY)
{
if (isi1.section_name() != isi2.section_name())
return isi1.section_name() < isi2.section_name();
@@ -1827,6 +1878,10 @@ Output_section_element_input::print(FILE* f) const
fprintf(f, "SORT_BY_ALIGNMENT(SORT_BY_NAME(");
close_parens = 2;
break;
case SORT_WILDCARD_BY_INIT_PRIORITY:
fprintf(f, "SORT_BY_INIT_PRIORITY(");
close_parens = 1;
break;
default:
gold_unreachable();
}