New gold linker option -z,text-unlikely-segment.
authorSriraman Tallam <tmsriram@google.com>
Fri, 20 Oct 2017 18:00:28 +0000 (11:00 -0700)
committerSriraman Tallam <tmsriram@google.com>
Fri, 20 Oct 2017 18:00:28 +0000 (11:00 -0700)
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.

gold/ChangeLog
gold/layout.cc
gold/options.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/text_unlikely_segment.cc [new file with mode: 0644]
gold/testsuite/text_unlikely_segment.sh [new file with mode: 0755]

index c12214b..ce989f5 100644 (file)
@@ -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
index 5f25fae..15c5434 100644 (file)
@@ -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;
 }
 
index 678ca82..2a43e8d 100644 (file)
@@ -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;
index 8eca3d8..d9a0669 100644 (file)
@@ -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
index 10f9493..b8db70d 100644 (file)
@@ -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 (file)
index 0000000..f8e6dd7
--- /dev/null
@@ -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 (executable)
index 0000000..b01fe6c
--- /dev/null
@@ -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"