diff --git a/gold/ChangeLog b/gold/ChangeLog index 697a40ade1..6757961e92 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,14 @@ +2017-10-04 Sriraman Tallam + + * 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. + 2017-09-26 Cary Coutant PR gold/22213 diff --git a/gold/Makefile.in b/gold/Makefile.in index a3c8b03bec..f5dbd2e025 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -87,8 +87,8 @@ subdir = . DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/config.in \ - $(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in ffsll.c \ - ftruncate.c mremap.c pread.c yyscript.h yyscript.c \ + $(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in mremap.c \ + ftruncate.c ffsll.c pread.c yyscript.h yyscript.c \ $(srcdir)/../depcomp $(srcdir)/../ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ diff --git a/gold/layout.cc b/gold/layout.cc index 5f25faea55..5d0a885c52 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1180,11 +1180,17 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, { // 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. + // to unique output sections. All ".text.unlikely.*" sections can be + // moved to a unique segment with --text-unlikely-segment option. + // 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()) + bool text_unlikely_segment + = (parameters->options().text_unlikely_segment() + && is_prefix_of(".text.unlikely", + object->section_name(shndx).c_str())); + if (it == this->section_segment_map_.end() + && !text_unlikely_segment) { os = this->choose_output_section(object, name, sh_type, shdr.get_sh_flags(), true, @@ -1198,7 +1204,8 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, elfcpp::Elf_Xword flags = this->get_output_section_flags(shdr.get_sh_flags()); - const char* os_name = it->second->name; + const char* os_name = text_unlikely_segment ? + ".text.unlikely" : 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, @@ -1206,8 +1213,11 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, 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 (!text_unlikely_segment) + { + os->set_extra_segment_flags(it->second->flags); + os->set_segment_alignment(it->second->align); + } } } if (os == NULL) @@ -3449,7 +3459,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 93f81b29af..8828c81016 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 ELF segment."), + N_("Do not move .text.unlikely sections to a separate " + "ELF segment.")); + public: typedef options::Dir_list Dir_list; diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index cae47f1e09..946f88b0db 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/text_unlikely_segment.cc b/gold/testsuite/text_unlikely_segment.cc index e69de29bb2..f8e6dd7e66 100644 --- a/gold/testsuite/text_unlikely_segment.cc +++ 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 + + 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 index e69de29bb2..b01fe6c715 100755 --- a/gold/testsuite/text_unlikely_segment.sh +++ 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 . + +# 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"