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:
parent
e0e51b2391
commit
28f2a4ac6f
8 changed files with 265 additions and 7 deletions
|
@ -1,3 +1,19 @@
|
|||
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.
|
||||
|
||||
2012-12-17 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* Makefile.am: Add copyright notice.
|
||||
|
|
|
@ -2409,6 +2409,20 @@ 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,6 +553,11 @@ 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);
|
||||
|
||||
bool
|
||||
is_section_ordering_specified()
|
||||
{ return this->section_ordering_specified_; }
|
||||
|
|
|
@ -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;
|
||||
|
||||
// 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())
|
||||
|
|
|
@ -250,6 +250,16 @@ final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
|
|||
final_layout.stdout: final_layout
|
||||
$(TEST_NM) -n --synthetic final_layout > final_layout.stdout
|
||||
|
||||
check_SCRIPTS += text_section_grouping.sh
|
||||
check_DATA += text_section_grouping.stdout
|
||||
MOSTLYCLEANFILES += text_section_grouping
|
||||
text_section_grouping.o: text_section_grouping.cc
|
||||
$(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
|
||||
text_section_grouping: text_section_grouping.o gcctestdir/ld
|
||||
$(CXXLINK) -Bgcctestdir/ text_section_grouping.o
|
||||
text_section_grouping.stdout: text_section_grouping
|
||||
$(TEST_NM) -n --synthetic text_section_grouping > text_section_grouping.stdout
|
||||
|
||||
check_PROGRAMS += icf_virtual_function_folding_test
|
||||
MOSTLYCLEANFILES += icf_virtual_function_folding_test
|
||||
icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
|
||||
|
|
|
@ -81,6 +81,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
|
|||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.sh \
|
||||
|
@ -111,6 +112,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
|
|||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.stdout \
|
||||
|
@ -122,6 +124,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
|
|||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test icf_keep_unique_test \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout_sequence.txt \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \
|
||||
|
@ -3701,6 +3704,8 @@ icf_safe_so_test.sh.log: icf_safe_so_test.sh
|
|||
@p='icf_safe_so_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
final_layout.sh.log: final_layout.sh
|
||||
@p='final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
text_section_grouping.sh.log: text_section_grouping.sh
|
||||
@p='text_section_grouping.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
icf_preemptible_functions_test.sh.log: icf_preemptible_functions_test.sh
|
||||
@p='icf_preemptible_functions_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
icf_string_merge_test.sh.log: icf_string_merge_test.sh
|
||||
|
@ -4348,6 +4353,12 @@ uninstall-am:
|
|||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.stdout: final_layout
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -n --synthetic final_layout > final_layout.stdout
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping.o: text_section_grouping.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping: text_section_grouping.o gcctestdir/ld
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ text_section_grouping.o
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping.stdout: text_section_grouping
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -n --synthetic text_section_grouping > text_section_grouping.stdout
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld
|
||||
|
|
72
gold/testsuite/text_section_grouping.cc
Normal file
72
gold/testsuite/text_section_grouping.cc
Normal file
|
@ -0,0 +1,72 @@
|
|||
// text_section_grouping.cc -- a test case for gold
|
||||
|
||||
// Copyright 2012 Free Software Foundation, Inc.
|
||||
// Written by Sriraman Tallam <tmsriram@google.com>.
|
||||
|
||||
// This file is part of gold.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
|
||||
// The goal of this program is to verify if .text sections are grouped
|
||||
// according to prefix. .text.unlikely, .text.startup and .text.hot should
|
||||
// be grouped and placed together.
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.hot.foo")))
|
||||
int hot_foo()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.startup.foo")))
|
||||
int startup_foo()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.unlikely.foo")))
|
||||
int unlikely_foo()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.hot.bar")))
|
||||
int hot_bar()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.startup.bar")))
|
||||
int startup_bar()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__ ((section(".text.unlikely.bar")))
|
||||
int unlikely_bar()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return 1;
|
||||
}
|
65
gold/testsuite/text_section_grouping.sh
Executable file
65
gold/testsuite/text_section_grouping.sh
Executable file
|
@ -0,0 +1,65 @@
|
|||
#!/bin/sh
|
||||
|
||||
# text_section_grouping.sh -- test
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
# Written by Sriraman Tallam <tmsriram@google.com>.
|
||||
|
||||
# This file is part of gold.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
# The goal of this program is to verify if .text sections are grouped
|
||||
# according to prefix. .text.unlikely, .text.startup and .text.hot should
|
||||
# be grouped and placed together.
|
||||
|
||||
set -e
|
||||
|
||||
check()
|
||||
{
|
||||
awk "
|
||||
BEGIN { saw1 = 0; saw2 = 0; err = 0; }
|
||||
/.*$2\$/ { saw1 = 1; }
|
||||
/.*$3\$/ {
|
||||
saw2 = 1;
|
||||
if (!saw1)
|
||||
{
|
||||
printf \"layout of $2 and $3 is not right\\n\";
|
||||
err = 1;
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (!saw1 && !err)
|
||||
{
|
||||
printf \"did not see $2\\n\";
|
||||
exit 1;
|
||||
}
|
||||
if (!saw2 && !err)
|
||||
{
|
||||
printf \"did not see $3\\n\";
|
||||
exit 1;
|
||||
}
|
||||
}" $1
|
||||
}
|
||||
|
||||
# addr (unlikely_*) < addr (startup_*) < addr (hot_*)
|
||||
check text_section_grouping.stdout "unlikely_foo" "startup_foo"
|
||||
check text_section_grouping.stdout "startup_foo" "hot_foo"
|
||||
check text_section_grouping.stdout "unlikely_bar" "startup_bar"
|
||||
check text_section_grouping.stdout "startup_bar" "hot_bar"
|
||||
check text_section_grouping.stdout "unlikely_foo" "startup_bar"
|
||||
check text_section_grouping.stdout "startup_foo" "hot_bar"
|
Loading…
Reference in a new issue