From 28f2a4ac6f40b5bf1fccc1fa320b41f82f3c5cc9 Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Wed, 19 Dec 2012 02:55:15 +0000 Subject: [PATCH] Group text sections with prefixes .text.unlikely,.text.hot and .text.startup by default. 2012-12-18 Sriraman Tallam * 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. --- gold/ChangeLog | 16 +++++++ gold/layout.cc | 14 ++++++ gold/layout.h | 5 +++ gold/output.cc | 79 ++++++++++++++++++++++++++++++--- gold/testsuite/Makefile.am | 10 +++++ gold/testsuite/Makefile.in | 11 +++++ gold/testsuite/text_section_grouping.cc | 72 ++++++++++++++++++++++++++++++ gold/testsuite/text_section_grouping.sh | 65 +++++++++++++++++++++++++++ 8 files changed, 265 insertions(+), 7 deletions(-) create mode 100644 gold/testsuite/text_section_grouping.cc create mode 100755 gold/testsuite/text_section_grouping.sh diff --git a/gold/ChangeLog b/gold/ChangeLog index b97d8a2..62ddbc6 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2012-12-18 Sriraman Tallam + + * 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 * Makefile.am: Add copyright notice. diff --git a/gold/layout.cc b/gold/layout.cc index 60fabb8..62b4cad 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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 diff --git a/gold/layout.h b/gold/layout.h index cf41f32..71f1aa7 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -552,6 +552,11 @@ class Layout // Maps section SECN to SEGMENT s. 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() diff --git a/gold/output.cc b/gold/output.cc index 9e3b0b4..39eb1b7 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -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++; + } - return s1_secn_index < s2_secn_index; + 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()) diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index c5c8a99..745e13d 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 6d9c630..b1058b4 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -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 diff --git a/gold/testsuite/text_section_grouping.cc b/gold/testsuite/text_section_grouping.cc new file mode 100644 index 0000000..5a3a809 --- /dev/null +++ b/gold/testsuite/text_section_grouping.cc @@ -0,0 +1,72 @@ +// text_section_grouping.cc -- a test case for gold + +// Copyright 2012 Free Software Foundation, Inc. +// Written by Sriraman Tallam . + +// 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; +} diff --git a/gold/testsuite/text_section_grouping.sh b/gold/testsuite/text_section_grouping.sh new file mode 100755 index 0000000..a79836c --- /dev/null +++ b/gold/testsuite/text_section_grouping.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# text_section_grouping.sh -- test + +# Copyright 2012 Free Software Foundation, Inc. +# Written by Sriraman Tallam . + +# 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" -- 2.7.4