diff options
-rw-r--r-- | gold/ChangeLog | 12 | ||||
-rw-r--r-- | gold/layout.cc | 75 | ||||
-rw-r--r-- | gold/options.h | 5 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 10 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 11 | ||||
-rw-r--r-- | gold/testsuite/text_unlikely_segment.cc | 30 | ||||
-rwxr-xr-x | gold/testsuite/text_unlikely_segment.sh | 60 |
7 files changed, 178 insertions, 25 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index c12214b..ce989f5 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,15 @@ +2017-10-04 Sriraman Tallam <tmsriram@google.com> + + * options.h (-z,text_unlikely_segment): New option. + * layout.cc (Layout::layout): Create new output section + for .text.unlikely sections with the new option. + (Layout::segment_precedes): Check for the new option + when segment flags match. + * testsuite/text_unlikely_segment.cc: New test source. + * testsuite/text_unlikely_segment.sh: New test script. + * testsuite/Makefile.am (text_unlikely_segment): New test. + * testsuite/Makefile.in: Regenerate. + 2017-10-19 Umesh Kalappa <ukalappa@cisco.com> * arm.cc (Stub::do_fixed_endian_write):Far call stubs support for arm diff --git a/gold/layout.cc b/gold/layout.cc index 5f25fae..15c5434 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1178,38 +1178,62 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx, } else { - // Plugins can choose to place one or more subsets of sections in - // unique segments and this is done by mapping these section subsets - // to unique output sections. Check if this section needs to be - // remapped to a unique output section. - Section_segment_map::iterator it - = this->section_segment_map_.find(Const_section_id(object, shndx)); - if (it == this->section_segment_map_.end()) - { - os = this->choose_output_section(object, name, sh_type, - shdr.get_sh_flags(), true, - ORDER_INVALID, false, false, - true); - } - else - { - // We know the name of the output section, directly call - // get_output_section here by-passing choose_output_section. + // All ".text.unlikely.*" sections can be moved to a unique + // segment with --text-unlikely-segment option. + bool text_unlikely_segment + = (parameters->options().text_unlikely_segment() + && is_prefix_of(".text.unlikely", + object->section_name(shndx).c_str())); + if (text_unlikely_segment) + { elfcpp::Elf_Xword flags = this->get_output_section_flags(shdr.get_sh_flags()); - const char* os_name = it->second->name; Stringpool::Key name_key; - os_name = this->namepool_.add(os_name, true, &name_key); + const char* os_name = this->namepool_.add(".text.unlikely", true, + &name_key); os = this->get_output_section(os_name, name_key, sh_type, flags, ORDER_INVALID, false); - if (!os->is_unique_segment()) + // Map this output section to a unique segment. This is done to + // separate "text" that is not likely to be executed from "text" + // that is likely executed. + os->set_is_unique_segment(); + } + else + { + // Plugins can choose to place one or more subsets of sections in + // unique segments and this is done by mapping these section subsets + // to unique output sections. Check if this section needs to be + // remapped to a unique output section. + Section_segment_map::iterator it + = this->section_segment_map_.find(Const_section_id(object, shndx)); + if (it == this->section_segment_map_.end()) { - os->set_is_unique_segment(); - os->set_extra_segment_flags(it->second->flags); - os->set_segment_alignment(it->second->align); + os = this->choose_output_section(object, name, sh_type, + shdr.get_sh_flags(), true, + ORDER_INVALID, false, false, + true); } - } + else + { + // We know the name of the output section, directly call + // get_output_section here by-passing choose_output_section. + elfcpp::Elf_Xword flags + = this->get_output_section_flags(shdr.get_sh_flags()); + + const char* os_name = it->second->name; + Stringpool::Key name_key; + os_name = this->namepool_.add(os_name, true, &name_key); + os = this->get_output_section(os_name, name_key, sh_type, flags, + ORDER_INVALID, false); + if (!os->is_unique_segment()) + { + os->set_is_unique_segment(); + os->set_extra_segment_flags(it->second->flags); + os->set_segment_alignment(it->second->align); + } + } + } if (os == NULL) return NULL; } @@ -3449,7 +3473,8 @@ Layout::segment_precedes(const Output_segment* seg1, // here if plugins want unique segments for subsets of sections. gold_assert(this->script_options_->saw_phdrs_clause() || parameters->options().any_section_start() - || this->is_unique_segment_for_sections_specified()); + || this->is_unique_segment_for_sections_specified() + || parameters->options().text_unlikely_segment()); return false; } diff --git a/gold/options.h b/gold/options.h index 678ca82..2a43e8d 100644 --- a/gold/options.h +++ b/gold/options.h @@ -1492,6 +1492,11 @@ class General_options DEFINE_bool_alias(textoff, text, options::DASH_Z, '\0', N_("Permit relocations in read-only segments"), NULL, true); + DEFINE_bool(text_unlikely_segment, options::DASH_Z, '\0', false, + N_("Move .text.unlikely sections to a separate segment."), + N_("Do not move .text.unlikely sections to a separate " + "segment.")); + public: typedef options::Dir_list Dir_list; diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 8eca3d8..d9a0669 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -340,6 +340,16 @@ section_sorting_name: section_sorting_name.o gcctestdir/ld section_sorting_name.stdout: section_sorting_name $(TEST_NM) -n --synthetic section_sorting_name > section_sorting_name.stdout +check_SCRIPTS += text_unlikely_segment.sh +check_DATA += text_unlikely_segment_readelf.stdout +MOSTLYCLEANFILES += text_unlikely_segment +text_unlikely_segment.o: text_unlikely_segment.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +text_unlikely_segment: text_unlikely_segment.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,-z,text-unlikely-segment text_unlikely_segment.o +text_unlikely_segment_readelf.stdout: text_unlikely_segment + $(TEST_READELF) -Wl $< >$@ + check_PROGRAMS += icf_virtual_function_folding_test MOSTLYCLEANFILES += icf_virtual_function_folding_test icf_virtual_function_folding_test.map 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 10f9493..b8db70d 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -87,6 +87,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ section_sorting_name.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_unlikely_segment.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 \ @@ -114,6 +115,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_no_grouping.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ section_sorting_name.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_unlikely_segment_readelf.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 \ @@ -139,6 +141,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_no_grouping \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ section_sorting_name \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_unlikely_segment \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test.map \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \ @@ -5148,6 +5151,8 @@ text_section_grouping.sh.log: text_section_grouping.sh @p='text_section_grouping.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) section_sorting_name.sh.log: section_sorting_name.sh @p='section_sorting_name.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +text_unlikely_segment.sh.log: text_unlikely_segment.sh + @p='text_unlikely_segment.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 @@ -6015,6 +6020,12 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--sort-section=name section_sorting_name.o @GCC_TRUE@@NATIVE_LINKER_TRUE@section_sorting_name.stdout: section_sorting_name @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -n --synthetic section_sorting_name > section_sorting_name.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@text_unlikely_segment.o: text_unlikely_segment.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@text_unlikely_segment: text_unlikely_segment.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,-z,text-unlikely-segment text_unlikely_segment.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@text_unlikely_segment_readelf.stdout: text_unlikely_segment +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -Wl $< >$@ @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_unlikely_segment.cc b/gold/testsuite/text_unlikely_segment.cc new file mode 100644 index 0000000..f8e6dd7 --- /dev/null +++ b/gold/testsuite/text_unlikely_segment.cc @@ -0,0 +1,30 @@ +/* text_unlikey_segment.cc -- a test case for gold + + Copyright (C) 2017 onwards 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. */ + +__attribute__((section(".text.unlikely"))) +int foo(void) { + return 0; +} + +int main(void) { + return 0; +} diff --git a/gold/testsuite/text_unlikely_segment.sh b/gold/testsuite/text_unlikely_segment.sh new file mode 100755 index 0000000..b01fe6c --- /dev/null +++ b/gold/testsuite/text_unlikely_segment.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# plugin_final_layout.sh -- test + +# Copyright (C) 2011-2017 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 -z,text-unlikely-segment works as +# intended. File text_unlikely_segment.cc is part of this test. + + +set -e + +# With readelf -l, an ELF Section to Segment mapping is printed as : +############################################## +# Section to Segment mapping: +# Segment Sections... +# ... +# 0x .text.unlikely +# ... +############################################## +# Check if .text.unlikely is the only section in the segment. +check_unique_segment() +{ + awk " +BEGIN { saw_section = 0; saw_unique = 0; } +/$2/ { saw_section = 1; } +/[ ]*0[0-9][ ]*$2[ ]*\$/ { saw_unique = 1; } +END { + if (!saw_section) + { + printf \"Section $2 not seen in output\\n\"; + exit 1; + } + else if (!saw_unique) + { + printf \"Unique segment not seen for: $2\\n\"; + exit 1; + } + }" $1 +} + +check_unique_segment text_unlikely_segment_readelf.stdout ".text.unlikely" |