[PATCH] gold: Support SHF_GNU_RETAIN

H.J. Lu hjl.tools@gmail.com
Wed Dec 9 16:07:42 GMT 2020


Keep input SHF_GNU_RETAIN sections and strip output SHF_GNU_RETAIN for
GNU/FreBSD ELFOSABIs.

elfcpp/

	PR gold/27039
	* elfcpp.h (SHF): Add SHF_GNU_RETAIN.

gold/

	PR gold/27039
	* layout.cc (Layout::layout): Strip SHF_GNU_RETAIN.
	* object.cc (Sized_relobj_file::Sized_relobj_file): Initialize
	osabi_.
	(Sized_relobj_file::do_layout): Keep SHF_GNU_RETAIN sections for
	GNU/FreBSD ELFOSABIs.
	* object.h (Sized_relobj_file): Add osabi() and osabi_.
	* testsuite/Makefile.am (check_SCRIPTS): Add retain.sh.
	(check_DATA): Add retain_1.out retain_2.out.
	(MOSTLYCLEANFILES): Add retain_1 retain_2.
	(retain_1.out): New target.
	(retain_1): Likewise.
	(retain_1.o): Likewise.
	(retain_2.out): Likewise.
	(retain_2): Likewise.
	(retain_2.o): Likewise.
	* testsuite/Makefile.in: Regenerated.
	* testsuite/retain.sh: New file.
	* testsuite/retain_1.s: Likewise.
	* testsuite/retain_2.s: Likewise.
---
 elfcpp/elfcpp.h            |   1 +
 gold/layout.cc             |  20 +++++--
 gold/object.cc             |   7 ++-
 gold/object.h              |   7 +++
 gold/testsuite/Makefile.am |  16 ++++++
 gold/testsuite/Makefile.in |  26 ++++++++--
 gold/testsuite/retain.sh   |  60 +++++++++++++++++++++
 gold/testsuite/retain_1.s  | 104 +++++++++++++++++++++++++++++++++++++
 gold/testsuite/retain_2.s  |  22 ++++++++
 9 files changed, 254 insertions(+), 9 deletions(-)
 create mode 100755 gold/testsuite/retain.sh
 create mode 100644 gold/testsuite/retain_1.s
 create mode 100644 gold/testsuite/retain_2.s

diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index 4b6ff94a65..2d333e992f 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -438,6 +438,7 @@ enum SHF
   SHF_TLS = 0x400,
   SHF_COMPRESSED = 0x800,
   SHF_MASKOS = 0x0ff00000,
+  SHF_GNU_RETAIN = 0x200000,
   SHF_MASKPROC = 0xf0000000,
 
   // Indicates this section requires ordering in relation to
diff --git a/gold/layout.cc b/gold/layout.cc
index 8563f11099..9c245a8e76 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1186,10 +1186,18 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
 	  = (parameters->options().text_unlikely_segment()
 	     && is_prefix_of(".text.unlikely",
 			     object->section_name(shndx).c_str()));
+      elfcpp::Elf_Xword ignored_flags;
+      elfcpp::ELFOSABI osabi = object->osabi();
+      if (osabi == elfcpp::ELFOSABI_GNU
+	  || osabi == elfcpp::ELFOSABI_FREEBSD)
+	ignored_flags = elfcpp::SHF_GNU_RETAIN;
+      else
+	ignored_flags = 0;
       if (text_unlikely_segment)
 	{
 	  elfcpp::Elf_Xword flags
-	    = this->get_output_section_flags(shdr.get_sh_flags());
+	    = this->get_output_section_flags(shdr.get_sh_flags()
+					     & ~ignored_flags);
 
 	  Stringpool::Key name_key;
 	  const char* os_name = this->namepool_.add(".text.unlikely", true,
@@ -1212,16 +1220,18 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int 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);
+					       (shdr.get_sh_flags()
+						& ~ignored_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());
+		= this->get_output_section_flags(shdr.get_sh_flags()
+						 & ~ignored_flags);
 
 	      const char* os_name = it->second->name;
 	      Stringpool::Key name_key;
diff --git a/gold/object.cc b/gold/object.cc
index 61aed805c2..0e2bcc131a 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -498,6 +498,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     deferred_layout_relocs_(),
     output_views_(NULL)
 {
+  this->osabi_ = static_cast<elfcpp::ELFOSABI>(ehdr.get_e_ident()[elfcpp::EI_OSABI]);
   this->e_type_ = ehdr.get_e_type();
 }
 
@@ -1716,10 +1717,14 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 
       if (is_pass_one && parameters->options().gc_sections())
 	{
+	  elfcpp::ELFOSABI osabi = this->osabi();
 	  if (this->is_section_name_included(name)
 	      || layout->keep_input_section (this, name)
 	      || sh_type == elfcpp::SHT_INIT_ARRAY
-	      || sh_type == elfcpp::SHT_FINI_ARRAY)
+	      || sh_type == elfcpp::SHT_FINI_ARRAY
+	      || ((osabi == elfcpp::ELFOSABI_GNU
+		   || osabi == elfcpp::ELFOSABI_FREEBSD)
+		  && shdr.get_sh_flags() & elfcpp::SHF_GNU_RETAIN) != 0)
 	    {
 	      symtab->gc()->worklist().push_back(Section_id(this, i));
 	    }
diff --git a/gold/object.h b/gold/object.h
index 656443f062..e73328663d 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -2209,6 +2209,11 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   e_type() const
   { return this->e_type_; }
 
+  // Return the EI_OSABI.
+  elfcpp::ELFOSABI
+  osabi() const
+  { return this->osabi_; }
+
   // Return the number of symbols.  This is only valid after
   // Object::add_symbols has been called.
   unsigned int
@@ -2849,6 +2854,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
 
   // General access to the ELF file.
   elfcpp::Elf_file<size, big_endian, Object> elf_file_;
+  // The EI_OSABI.
+  elfcpp::ELFOSABI osabi_;
   // Type of ELF file (ET_REL or ET_EXEC).  ET_EXEC files are allowed
   // as input files only for the --just-symbols option.
   int e_type_;
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 739ea98dbe..abaaba6661 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -4466,4 +4466,20 @@ pr26936c.o: pr26936c.s
 pr26936d.o: pr26936d.s
 	$(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
 
+check_SCRIPTS += retain.sh
+check_DATA += retain_1.out retain_2.out
+MOSTLYCLEANFILES += retain_1 retain_2
+retain_1.out: retain_1
+	$(TEST_NM) $< >$@
+retain_1: retain_1.o ../ld-new
+	../ld-new  -e _start --gc-sections -o $@  retain_1.o
+retain_1.o: retain_1.s
+	$(TEST_AS) -o $@ $<
+retain_2.out: retain_2
+	$(TEST_READELF) -d $< >$@
+retain_2: retain_2.o ../ld-new
+	../ld-new -pie -e _start --gc-sections -o $@  retain_2.o
+retain_2.o: retain_2.s
+	$(TEST_AS) -o $@ $<
+
 endif DEFAULT_TARGET_X86_64
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index 2c03a992cf..79aed4a763 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -1143,12 +1143,13 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@	split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r
 
 @DEFAULT_TARGET_X86_64_TRUE@am__append_116 = *.dwo *.dwp pr26936a \
-@DEFAULT_TARGET_X86_64_TRUE@	pr26936b
+@DEFAULT_TARGET_X86_64_TRUE@	pr26936b retain_1 retain_2
 @DEFAULT_TARGET_X86_64_TRUE@am__append_117 = dwp_test_1.sh \
-@DEFAULT_TARGET_X86_64_TRUE@	dwp_test_2.sh pr26936.sh
+@DEFAULT_TARGET_X86_64_TRUE@	dwp_test_2.sh pr26936.sh retain.sh
 @DEFAULT_TARGET_X86_64_TRUE@am__append_118 = dwp_test_1.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@	dwp_test_2.stdout pr26936a.stdout \
-@DEFAULT_TARGET_X86_64_TRUE@	pr26936b.stdout
+@DEFAULT_TARGET_X86_64_TRUE@	pr26936b.stdout retain_1.out \
+@DEFAULT_TARGET_X86_64_TRUE@	retain_2.out
 subdir = testsuite
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/ax_pthread.m4 \
@@ -6492,6 +6493,13 @@ pr26936.sh.log: pr26936.sh
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+retain.sh.log: retain.sh
+	@p='retain.sh'; \
+	b='retain.sh'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 object_unittest.log: object_unittest$(EXEEXT)
 	@p='object_unittest$(EXEEXT)'; \
 	b='object_unittest'; \
@@ -10463,6 +10471,18 @@ uninstall-am:
 @DEFAULT_TARGET_X86_64_TRUE@	$(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
 @DEFAULT_TARGET_X86_64_TRUE@pr26936d.o: pr26936d.s
 @DEFAULT_TARGET_X86_64_TRUE@	$(TEST_AS) --gen-debug -mx86-used-note=yes -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@retain_1.out: retain_1
+@DEFAULT_TARGET_X86_64_TRUE@	$(TEST_NM) $< >$@
+@DEFAULT_TARGET_X86_64_TRUE@retain_1: retain_1.o ../ld-new
+@DEFAULT_TARGET_X86_64_TRUE@	../ld-new  -e _start --gc-sections -o $@  retain_1.o
+@DEFAULT_TARGET_X86_64_TRUE@retain_1.o: retain_1.s
+@DEFAULT_TARGET_X86_64_TRUE@	$(TEST_AS) -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@retain_2.out: retain_2
+@DEFAULT_TARGET_X86_64_TRUE@	$(TEST_READELF) -d $< >$@
+@DEFAULT_TARGET_X86_64_TRUE@retain_2: retain_2.o ../ld-new
+@DEFAULT_TARGET_X86_64_TRUE@	../ld-new -pie -e _start --gc-sections -o $@  retain_2.o
+@DEFAULT_TARGET_X86_64_TRUE@retain_2.o: retain_2.s
+@DEFAULT_TARGET_X86_64_TRUE@	$(TEST_AS) -o $@ $<
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/gold/testsuite/retain.sh b/gold/testsuite/retain.sh
new file mode 100755
index 0000000000..0f5c6951c5
--- /dev/null
+++ b/gold/testsuite/retain.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# retain.sh -- Tests for SHF_GNU_RETAIN.
+
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# 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.
+
+set -e
+
+check()
+{
+    number_of_occurrence=`egrep "$2" ./$1 -o | wc -l`
+    if [ $number_of_occurrence != $3 ]
+    then
+	echo "$1: \"$2\" $3: Failed"
+	status=1
+    fi
+}
+
+status=0
+check retain_1.out " T fnretain1" 1
+check retain_1.out " b lsretain0.2" 1
+check retain_1.out " b lsretain1.1" 1
+check retain_1.out " d lsretain2.0" 1
+check retain_1.out " B retain0" 1
+check retain_1.out " B retain1" 1
+check retain_1.out " D retain2" 1
+check retain_1.out " b sretain0" 1
+check retain_1.out " b sretain1" 1
+check retain_1.out " d sretain2" 1
+if grep discard retain_1.out
+then
+  echo "retain_1.out: Garbage collection failed"
+  status=1
+fi
+
+check retain_2.out " \(PREINIT_ARRAY\)" 1
+check retain_2.out " \(PREINIT_ARRAYSZ\)" 1
+check retain_2.out " \(INIT_ARRAY\)" 1
+check retain_2.out " \(INIT_ARRAYSZ\)" 1
+check retain_2.out " \(FINI_ARRAY\)" 1
+check retain_2.out " \(FINI_ARRAYSZ\)" 1
+
+exit $status
diff --git a/gold/testsuite/retain_1.s b/gold/testsuite/retain_1.s
new file mode 100644
index 0000000000..f7716faabe
--- /dev/null
+++ b/gold/testsuite/retain_1.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, %object
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, %object
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, %object
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, %object
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, %object
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, %object
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, %function
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, %object
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, %object
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, %object
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, %object
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, %object
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, %object
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, %function
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, %function
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, %object
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, %object
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, %object
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/gold/testsuite/retain_2.s b/gold/testsuite/retain_2.s
new file mode 100644
index 0000000000..67d86d10cb
--- /dev/null
+++ b/gold/testsuite/retain_2.s
@@ -0,0 +1,22 @@
+	.section .preinit_array.01000,"aw",%preinit_array
+	.dc.a 0
+
+	.section .init_array.01000,"aw",%init_array
+	.dc.a 0
+
+	.section .fini_array.01000,"aw",%fini_array
+	.dc.a 0
+
+	.section .preinit_array.01000,"awR",%preinit_array
+	.dc.a 0
+
+	.section .init_array.01000,"awR",%init_array
+	.dc.a 0
+
+	.section .fini_array.01000,"awR",%fini_array
+	.dc.a 0
+
+	.text
+	.globl _start
+_start:
+	.dc.a 0
-- 
2.29.2



More information about the Binutils mailing list