Map ".text.hot" and ".text.unlikely" input section prefixes to separate output sections.
Sriraman Tallam
tmsriram@google.com
Thu Nov 15 01:06:00 GMT 2012
Hi Ian,
I finally got around to doing this in a way you suggested a while
back, that is sorting text sections within the output section rather
than creating separate output sections. Patch attached.
Thanks,
-Sri.
On Tue, Sep 13, 2011 at 3:32 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> Sections prefixed with ".text.hot", ".text.unlikely" and
>> ".text.startup" should map to separate output sections so that they
>> can be grouped together. The following simple patch does this. Alright
>> to submit?
>
> The GNU linker puts all .text.hot input sections into the .text output
> section. It just groups them together. I would prefer to do that in
> gold, too. Your patch would create a .text.hot output section, which is
> not what I would like to see.
>
> Ideally gold should group all input sections with the same name
> together, regardless of what output section they are going to. I
> believe this can be done in Output_section::add_input_section if we
> preserve the name in Input_section_list. The main drawback is that this
> may mean giving up on the current optimization of not building an
> Input_section_list.
>
> Ian
-------------- next part --------------
* layout.cc (Layout::layout): sort input sections for .text.
* output.cc (Output_section::Input_section_sort_text_sections_compare
::operator()): New function.
* (Output_section::sort_attached_input_sections): Sort input sections
of ".text" named output section.
* output.h (Output_section::Input_section_sort_text_sections_compare):
New struct.
* 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.
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.239
diff -u -u -p -r1.239 layout.cc
--- layout.cc 16 Oct 2012 16:50:32 -0000 1.239
+++ layout.cc 15 Nov 2012 00:53:42 -0000
@@ -1136,6 +1136,16 @@ Layout::layout(Sized_relobj_file<size, b
&& strcmp(os->name(), ".fini_array") == 0)))
ctors_sections_in_init_array.insert(Section_id(object, shndx));
+ // 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.
+ if (!this->script_options_->saw_sections_clause()
+ && !parameters->options().relocatable()
+ && !os->input_section_order_specified()
+ && strcmp(name, ".text") == 0)
+ os->set_must_sort_attached_input_sections();
+
// FIXME: Handle SHF_LINK_ORDER somewhere.
elfcpp::Elf_Xword orig_flags = os->flags();
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.176
diff -u -u -p -r1.176 output.cc
--- output.cc 1 Nov 2012 22:35:06 -0000 1.176
+++ output.cc 15 Nov 2012 00:53:43 -0000
@@ -3499,6 +3499,81 @@ Output_section::Input_section_sort_secti
return s1_secn_index < s2_secn_index;
}
+// Return true if S1 should come before S2. This function is used to sort
+// text sections. Text sections are grouped according to their prefix. The
+// following prefixes are recognized: ".text.startup", ".text.hot",
+// and ".text.unlikely".
+
+bool
+Output_section::Input_section_sort_text_sections_compare::operator()(
+ const Output_section::Input_section_sort_entry& s1,
+ const Output_section::Input_section_sort_entry& s2) const
+{
+ 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();
+ }
+
+ unsigned int s1_group_index = 0;
+ unsigned int s2_group_index = 0;
+
+ // If it is a text section use the following order:
+ // .text.unlikely, .text.startup, .text.hot, and .text
+ // In some cases one prefix is itself a prefix of another prefix; in
+ // such a case the longer prefix must come first below.
+ struct section_order
+ {
+ const char *name;
+ unsigned int position;
+ } section_prefix [] =
+ {
+ {".text.unlikely", 0},
+ {".text.startup", 1},
+ {".text.hot", 2},
+ {".text", 3}
+ };
+
+ const unsigned int num_prefixes
+ = sizeof(section_prefix) / sizeof(struct section_order);
+
+ s1_group_index = 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].name, s1.section_name().c_str()))
+ {
+ s1_group_index = section_prefix[i].position;
+ flag_done++;
+ }
+
+ if (s2_group_index == num_prefixes
+ && is_prefix_of(section_prefix[i].name, s2.section_name().c_str()))
+ {
+ s2_group_index = section_prefix[i].position;
+ 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
// the order specified in the mapping from Section id to order index.
@@ -3567,6 +3642,9 @@ Output_section::sort_attached_input_sect
|| this->type() == elfcpp::SHT_FINI_ARRAY)
std::sort(sort_list.begin(), sort_list.end(),
Input_section_sort_init_fini_compare());
+ else if (strcmp(this->name(), ".text") == 0)
+ std::sort(sort_list.begin(), sort_list.end(),
+ Input_section_sort_text_sections_compare());
else
std::sort(sort_list.begin(), sort_list.end(),
Input_section_sort_compare());
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.141
diff -u -u -p -r1.141 output.h
--- output.h 5 Oct 2012 00:45:54 -0000 1.141
+++ output.h 15 Nov 2012 00:53:43 -0000
@@ -4102,6 +4102,13 @@ class Output_section : public Output_dat
const Input_section_sort_entry&) const;
};
+ struct Input_section_sort_text_sections_compare
+ {
+ bool
+ operator()(const Input_section_sort_entry&,
+ const Input_section_sort_entry&) const;
+ };
+
// Fill data. This is used to fill in data between input sections.
// It is also used for data statements (BYTE, WORD, etc.) in linker
// scripts. When we have to keep track of the input sections, we
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.200
diff -u -u -p -r1.200 Makefile.am
--- testsuite/Makefile.am 26 Oct 2012 00:50:05 -0000 1.200
+++ testsuite/Makefile.am 15 Nov 2012 00:53:43 -0000
@@ -250,6 +250,16 @@ final_layout: final_layout.o final_layou
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
Index: testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.210
diff -u -u -p -r1.210 Makefile.in
--- testsuite/Makefile.in 26 Oct 2012 00:50:05 -0000 1.210
+++ testsuite/Makefile.in 15 Nov 2012 00:53:43 -0000
@@ -81,6 +81,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__E
@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__E
@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__E
@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 \
@@ -3696,6 +3699,8 @@ icf_safe_so_test.sh.log: icf_safe_so_tes
@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
@@ -4343,6 +4348,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
Index: testsuite/text_section_grouping.cc
===================================================================
RCS file: testsuite/text_section_grouping.cc
diff -N testsuite/text_section_grouping.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/text_section_grouping.cc 15 Nov 2012 00:53:43 -0000
@@ -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;
+}
Index: testsuite/text_section_grouping.sh
===================================================================
RCS file: testsuite/text_section_grouping.sh
diff -N testsuite/text_section_grouping.sh
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/text_section_grouping.sh 15 Nov 2012 00:53:43 -0000
@@ -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"
More information about the Binutils
mailing list