public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Support SHF_GNU_RETAIN ELF section flag
@ 2020-09-22 20:29 Jozef Lawrynowicz
  2020-09-22 23:24 ` Hans-Peter Nilsson
                   ` (4 more replies)
  0 siblings, 5 replies; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-22 20:29 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 2653 bytes --]

The attached patch adds support for the new SHF_GNU_RETAIN ELF section
flag, which was discussed on the GNU gABI mailing list here:
https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html

The flag is GNU-specific so uses a bit in the SHF_MASKOS mask.
Its precise definition is as follows:

=======================================================================
Section Attribute Flags
+-------------------------------------+
| Name           | Value              |
+-------------------------------------+
| SHF_GNU_RETAIN | 0x200000 (1 << 21) |
+-------------------------------------+

SHF_GNU_RETAIN
  The link editor should not garbage collect the section if it is
  unused.

=======================================================================

The overall intention for this new flag is to enable a new "retain"
attribute to be applied to declarations of functions and data in the
source code. This attribute can be used to ensure the definition
associated with the declaration is present in the linked output file,
even if linker garbage collection would normally remove the containing
section because it is unused.

The new ".retain" assembler directive can be used to apply
SHF_GNU_RETAIN to a section. GCC will emit this directive when
assembling definitions of functions and data that have had the "retain"
attribute applied.

Note that there is *not* a direct mapping of SHF_GNU_RETAIN to the BFD
section flag SEC_KEEP. SEC_KEEP would prevent the user being able to
explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/,
which could be necessary in some situations.

I successfully regtested the patch for the Binutils, GAS and LD
testsuites for the following CPUs, applying the "-elf" suffix when
configuring:
  aarch64 alpha arc arm avr bfin bpf cr16 cris crx csky d10v d30v dlx
  epiphany fr30 frv ft32 h8300 hppa i386 ia64 ia64-vms ip2k iq2000 lm32
  m32c m32r m68hc11 m68hc12 m68k mcore mep metag microblaze mips mmix
  moxie msp430 mt nds32 nfp nios2 or1k pj ppc pru riscv rl78 rx s12z
  s390 score sh sparc spu tic6x tilegx tilepro v850 vax visium wasm32
  x86-64 x86 xc16x xgate xstormy16 xtensa z80

The new tests are passing for all targets except mmix-elf. This target
has a lot of LD failures, particularly --gc-sections doesn't appear to
have any effect. I don't know anything about the target, but I wonder if
it should be added to the hard-coded list of targets that doesn't
support --gc-sections.  I have therefore XFAIL'd the new LD tests for
this target.

I also regtested for i386-pe, to ensure there was no spill-over of the
new functionality into any non-ELF areas.

Ok to apply?

Thanks,
Jozef

[-- Attachment #2: 0001-Support-SHF_GNU_RETAIN-ELF-section-flag.patch --]
[-- Type: text/plain, Size: 41226 bytes --]

From d7f92cd05883567cf07cb8878aa60b666894197d Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Tue, 22 Sep 2020 21:00:35 +0100
Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag

The GNU-specific SHF_GNU_RETAIN ELF section flag is defined as follows:

=======================================================================
Section Attribute Flags
+-------------------------------------+
| Name           | Value              |
+-------------------------------------+
| SHF_GNU_RETAIN | 0x200000 (1 << 21) |
+-------------------------------------+

SHF_GNU_RETAIN
  The link editor should not garbage collect the section if it is
  unused.

=======================================================================

The new ".retain" assembler directive can be used to apply
SHF_GNU_RETAIN to a section.

Note that there is not a direct mapping of SHF_GNU_RETAIN to the BFD
section flag SEC_KEEP. This would prevent the user being able to
explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/.

bfd/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* elflink.c (bfd_elf_gc_sections): gc_mark the section if
	SHF_GNU_RETAIN is set.

binutils/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce SHF_GNU_RETAIN.
	* readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN.
	* testsuite/binutils-all/readelf.exp: Run new test.
	Don't run run_dump_test when there isn't an assembler available.
	* testsuite/binutils-all/retain1.d: New test.
	* testsuite/binutils-all/retain1.s: New test.

gas/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce .retain directive and SHF_GNU_RETAIN.
	* config/obj-elf.c (elf_pseudo_table): Add "retain".
	(obj_elf_retain): New.
	(obj_elf_parse_section_letters): Handle 'R' flag.
	* doc/as.texi: Document .retain directive.
	(Section): Document 'R' flag.
	* testsuite/gas/elf/elf.exp: Run new tests.
	* testsuite/gas/elf/retain1.d: New test.
	* testsuite/gas/elf/retain1.s: New test.
	* testsuite/gas/elf/retain2.d: New test.
	* testsuite/gas/elf/retain2.l: New test.
	* testsuite/gas/elf/retain2.s: New test.
	* testsuite/gas/elf/retain3.d: New test.
	* testsuite/gas/elf/retain3.s: New test.
	* testsuite/gas/elf/section10.d: Adjust test.

include/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* elf/common.h (SHF_GNU_RETAIN): Define.

ld/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce SHF_GNU_RETAIN.
	* ld.texi (garbage collection): Document SHF_GNU_RETAIN.
	(Output Section Discarding): Likewise.
	* testsuite/ld-elf/elf.exp: Run new tests.
	* testsuite/ld-elf/retain1.msg: New test.
	* testsuite/ld-elf/retain1.s: New test.
	* testsuite/ld-elf/retain2.d: New test.
	* testsuite/ld-elf/retain2.ld: New test.
	* testsuite/ld-elf/retain2.map: New test.
	* testsuite/ld-elf/retain3.msg: New test.
	* testsuite/ld-elf/retain3.s: New test.
	* testsuite/ld-elf/retain4.s: New test.
	* testsuite/ld-elf/retain5.s: New test.
	* testsuite/ld-elf/retain6lib.s: New test.
	* testsuite/ld-elf/retain6main.s: New test.
	* testsuite/ld-elf/retain7.msg: New test.
	* testsuite/ld-elf/retain7lib.s: New test.
	* testsuite/ld-elf/retain7main.s: New test.
---
 bfd/elflink.c                               |   3 +-
 binutils/NEWS                               |   4 +
 binutils/readelf.c                          |   4 +
 binutils/testsuite/binutils-all/readelf.exp |   6 +-
 binutils/testsuite/binutils-all/retain1.d   |  17 +++
 binutils/testsuite/binutils-all/retain1.s   | 114 ++++++++++++++++++++
 gas/NEWS                                    |   4 +
 gas/config/obj-elf.c                        |  59 ++++++++++
 gas/doc/as.texi                             |  20 ++++
 gas/testsuite/gas/elf/elf.exp               |   5 +
 gas/testsuite/gas/elf/retain1.d             |  24 +++++
 gas/testsuite/gas/elf/retain1.s             | 114 ++++++++++++++++++++
 gas/testsuite/gas/elf/retain2.d             |   3 +
 gas/testsuite/gas/elf/retain2.l             |   3 +
 gas/testsuite/gas/elf/retain2.s             |   7 ++
 gas/testsuite/gas/elf/retain3.d             |  24 +++++
 gas/testsuite/gas/elf/retain3.s             | 104 ++++++++++++++++++
 gas/testsuite/gas/elf/section10.d           |   4 +-
 include/elf/common.h                        |   1 +
 ld/NEWS                                     |   4 +
 ld/ld.texi                                  |   8 ++
 ld/testsuite/ld-elf/elf.exp                 |  38 ++++++-
 ld/testsuite/ld-elf/retain1.msg             |   9 ++
 ld/testsuite/ld-elf/retain1.s               | 114 ++++++++++++++++++++
 ld/testsuite/ld-elf/retain2.d               |   7 ++
 ld/testsuite/ld-elf/retain2.ld              |   7 ++
 ld/testsuite/ld-elf/retain2.map             |  32 ++++++
 ld/testsuite/ld-elf/retain3.msg             |   9 ++
 ld/testsuite/ld-elf/retain3.s               | 104 ++++++++++++++++++
 ld/testsuite/ld-elf/retain4.s               |  19 ++++
 ld/testsuite/ld-elf/retain5.s               |  13 +++
 ld/testsuite/ld-elf/retain6lib.s            |   6 ++
 ld/testsuite/ld-elf/retain6main.s           |   5 +
 ld/testsuite/ld-elf/retain7.msg             |   1 +
 ld/testsuite/ld-elf/retain7lib.s            |  17 +++
 ld/testsuite/ld-elf/retain7main.s           |  13 +++
 36 files changed, 921 insertions(+), 5 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/retain1.d
 create mode 100644 binutils/testsuite/binutils-all/retain1.s
 create mode 100644 gas/testsuite/gas/elf/retain1.d
 create mode 100644 gas/testsuite/gas/elf/retain1.s
 create mode 100644 gas/testsuite/gas/elf/retain2.d
 create mode 100644 gas/testsuite/gas/elf/retain2.l
 create mode 100644 gas/testsuite/gas/elf/retain2.s
 create mode 100644 gas/testsuite/gas/elf/retain3.d
 create mode 100644 gas/testsuite/gas/elf/retain3.s
 create mode 100644 ld/testsuite/ld-elf/retain1.msg
 create mode 100644 ld/testsuite/ld-elf/retain1.s
 create mode 100644 ld/testsuite/ld-elf/retain2.d
 create mode 100644 ld/testsuite/ld-elf/retain2.ld
 create mode 100644 ld/testsuite/ld-elf/retain2.map
 create mode 100644 ld/testsuite/ld-elf/retain3.msg
 create mode 100644 ld/testsuite/ld-elf/retain3.s
 create mode 100644 ld/testsuite/ld-elf/retain4.s
 create mode 100644 ld/testsuite/ld-elf/retain5.s
 create mode 100644 ld/testsuite/ld-elf/retain6lib.s
 create mode 100644 ld/testsuite/ld-elf/retain6main.s
 create mode 100644 ld/testsuite/ld-elf/retain7.msg
 create mode 100644 ld/testsuite/ld-elf/retain7lib.s
 create mode 100644 ld/testsuite/ld-elf/retain7main.s

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 0e339f3c1e..6d1a1c5105 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -13977,7 +13977,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 			|| (elf_section_data (o)->this_hdr.sh_type
 			    == SHT_FINI_ARRAY)))
 		|| (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
-		    && elf_next_in_group (o) == NULL )))
+		    && elf_next_in_group (o) == NULL)
+		|| (elf_section_flags (o) & SHF_GNU_RETAIN)))
 	  {
 	    if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
 	      return FALSE;
diff --git a/binutils/NEWS b/binutils/NEWS
index c0dc73d7d8..6c7d3f3953 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -4,6 +4,10 @@
   symbol names.  In addition the --demangle=<style>, --no-demangle,
   --recurse-limit and --no-recurse-limit options are also now availale.
 
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+  This flag specifies that the section should not be garbage collected by the
+  linker if it is unused.
+
 Changes in 2.35:
 
 * Changed readelf's display of symbol names when wide mode is not enabled.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index cb4208f7b9..00502f7058 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5977,6 +5977,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
       /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
       /* VLE specific.  */
       /* 25 */ { STRING_COMMA_LEN ("VLE") },
+      /* GNU specific.  */
+      /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") },
     };
 
   if (do_section_details)
@@ -6010,6 +6012,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_EXCLUDE:		sindex = 18; break;
 	    case SHF_COMPRESSED:	sindex = 20; break;
 	    case SHF_GNU_MBIND:		sindex = 24; break;
+	    case SHF_GNU_RETAIN:	sindex = 26; break;
 
 	    default:
 	      sindex = -1;
@@ -6108,6 +6111,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_EXCLUDE:		*p = 'E'; break;
 	    case SHF_COMPRESSED:	*p = 'C'; break;
 	    case SHF_GNU_MBIND:		*p = 'D'; break;
+	    case SHF_GNU_RETAIN:	*p = 'R'; break;
 
 	    default:
 	      if ((filedata->file_header.e_machine == EM_X86_64
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 1fb36ae5c4..6dea09e305 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -364,8 +364,12 @@ readelf_wi_test
 readelf_compressed_wa_test
 
 readelf_dump_test
-run_dump_test "pr25543"
 
+# These dump tests require an assembler.
+if {[which $AS] != 0} then {
+    run_dump_test "pr25543"
+    run_dump_test "retain1"
+}
 
 # PR 13482 - Check for off-by-one errors when dumping .note sections.
 if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
diff --git a/binutils/testsuite/binutils-all/retain1.d b/binutils/testsuite/binutils-all/retain1.d
new file mode 100644
index 0000000000..35d7373cc1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.d
@@ -0,0 +1,17 @@
+#source: retain1.s
+#readelf: -S --wide
+#name: readelf SHF_GNU_RETAIN
+
+#...
+  \[[ 0-9]+\] .bss.retain0.*WAR.*
+  \[[ 0-9]+\] .bss.retain1.*WAR.*
+  \[[ 0-9]+\] .data.retain2.*WAR.*
+  \[[ 0-9]+\] .bss.sretain0.*WAR.*
+  \[[ 0-9]+\] .bss.sretain1.*WAR.*
+  \[[ 0-9]+\] .data.sretain2.*WAR.*
+  \[[ 0-9]+\] .text.fnretain1.*AXR.*
+#...
+  \[[ 0-9]+\] .bss.lsretain0.*WAR.*
+  \[[ 0-9]+\] .bss.lsretain1.*WAR.*
+  \[[ 0-9]+\] .data.lsretain2.*WAR.*
+#pass
diff --git a/binutils/testsuite/binutils-all/retain1.s b/binutils/testsuite/binutils-all/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/NEWS b/gas/NEWS
index 66afd0357b..0d63fad7b3 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -9,6 +9,10 @@
 
 * Configure with --enable-x86-used-note by default for Linux/x86.
 
+* Add support for the .retain directive, which applies the ELF SHF_GNU_RETAIN
+  flag to the specified section.  This flag specifies the section should not be
+  garbage collected by the linker if it is unused.
+
 Changes in 2.35:
 
 * X86 NaCl target support is removed.
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 9e39707801..1469a46039 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -78,6 +78,7 @@ static void obj_elf_gnu_attribute (int);
 static void obj_elf_tls_common (int);
 static void obj_elf_lcomm (int);
 static void obj_elf_struct (int);
+static void obj_elf_retain (int);
 
 static const pseudo_typeS elf_pseudo_table[] =
 {
@@ -119,6 +120,9 @@ static const pseudo_typeS elf_pseudo_table[] =
   /* A GNU extension for object attributes.  */
   {"gnu_attribute", obj_elf_gnu_attribute, 0},
 
+  /* A GNU extension for preventing linker garbage collection of sections.  */
+  {"retain", obj_elf_retain, 0},
+
   /* These are used for dwarf.  */
   {"2byte", cons, 2},
   {"4byte", cons, 4},
@@ -857,6 +861,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
 	case 'd':
 	  *gnu_attr |= SHF_GNU_MBIND;
 	  break;
+	case 'R':
+	  *gnu_attr |= SHF_GNU_RETAIN;
+	  break;
 	case '?':
 	  *is_clone = TRUE;
 	  break;
@@ -1986,6 +1993,58 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
   obj_elf_vendor_attribute (OBJ_ATTR_GNU);
 }
 
+/* Parse a ".retain [name]" directive.
+   The SHF_GNU_RETAIN flag should be applied to the section named "name".
+   If "name" is omitted, apply the flag to the current section being
+   assembled.  */
+static void
+obj_elf_retain (int ignored ATTRIBUTE_UNUSED)
+{
+  const char *name;
+  symbolS *secsym;
+  asection *bfdsec;
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer == '\n')
+    {
+      /* Handle the case when "name" isn't specified.  */
+      name = now_seg->name;
+      if (name == NULL)
+	{
+	  as_bad (_("\".retain\" directive not within a section"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+    }
+  else
+    {
+      /* The "name" argument has been given, validate it.  */
+      name = obj_elf_section_name ();
+      secsym = symbol_find (name);
+      if (secsym == NULL)
+	{
+	  as_bad (_("section '%s' has not been declared"), name);
+	  ignore_rest_of_line ();
+	  return;
+	}
+      else if (secsym != NULL
+	       && !symbol_section_p (secsym))
+	{
+	  as_bad (_("'%s' is not a section name, expected "
+		    "\".retain [name]\""), name);
+	  ignore_rest_of_line ();
+	  return;
+	}
+    }
+  demand_empty_rest_of_line ();
+
+  bfdsec = bfd_get_section_by_name (stdoutput, name);
+  if (bfdsec != NULL)
+    elf_section_flags (bfdsec) |= SHF_GNU_RETAIN;
+  else
+    as_bad (_("Couldn't find BFD section for %s\n"), name);
+}
+
 void
 elf_obj_read_begin_hook (void)
 {
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 112eaf810c..68afaa6aae 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -4468,6 +4468,7 @@ Some machine configurations provide additional directives.
 * Quad::                        @code{.quad @var{bignums}}
 * Reloc::			@code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]}
 * Rept::			@code{.rept @var{count}}
+* Retain::			@code{.retain [@var{name}]}
 * Sbttl::                       @code{.sbttl "@var{subheading}"}
 @ifset COFF
 * Scl::                         @code{.scl @var{class}}
@@ -6468,6 +6469,22 @@ is equivalent to assembling
 A count of zero is allowed, but nothing is generated.  Negative counts are not
 allowed and if encountered will be treated as if they were zero.
 
+@ifset ELF
+@node Retain
+@section @code{.retain [@var{name}]}
+
+@cindex @code{retain} directive
+@cindex SHF_GNU_RETAIN
+
+Apply the @code{SHF_GNU_RETAIN} flag to the section named @var{name}.
+If @var{name} is omitted, apply the flag to the current section being
+assembled.
+
+The @code{SHF_GNU_RETAIN} flag specifies that the section should not be
+garbage collected by the linker if it is unused.
+
+@end ifset
+
 @node Sbttl
 @section @code{.sbttl "@var{subheading}"}
 
@@ -6546,6 +6563,9 @@ ignored.  (For compatibility with the ELF version)
 section is not readable (meaningful for PE targets)
 @item 0-9
 single-digit power-of-two section alignment (GNU extension)
+@item R
+retained section (apply SHF_GNU_RETAIN to prevent linker garbage
+collection, GNU ELF extension)
 @end table
 
 If no flags are specified, the default flags depend upon the section name.  If
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 8520421ba3..3a4879e348 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -307,6 +307,11 @@ if { [is_elf_format] } then {
 
     run_dump_test "strtab"
 
+    # Tests for the .retain directive/SHF_GNU_RETAIN.
+    run_dump_test "retain1"
+    run_dump_test "retain2"
+    run_dump_test "retain3"
+
     run_dump_test "bignums"
     run_dump_test "section-symbol-redef"
     
diff --git a/gas/testsuite/gas/elf/retain1.d b/gas/testsuite/gas/elf/retain1.d
new file mode 100644
index 0000000000..439a60ca21
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain1.d
@@ -0,0 +1,24 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 1
+
+#...
+  \[..\] .bss.discard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.discard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.discard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.sdiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .text.fndiscard0[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+  \[..\] .bss.retain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.retain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.retain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.sretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .text.fnretain1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+  \[..\] .text.fndiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+#...
+  \[..\] .bss.lsretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.lsretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.lsretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain1.s b/gas/testsuite/gas/elf/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/testsuite/gas/elf/retain2.d b/gas/testsuite/gas/elf/retain2.d
new file mode 100644
index 0000000000..ca58b250b6
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.d
@@ -0,0 +1,3 @@
+#name: SHF_GNU_RETAIN 2
+#error_output: retain2.l
+#skip: hppa-*-*
diff --git a/gas/testsuite/gas/elf/retain2.l b/gas/testsuite/gas/elf/retain2.l
new file mode 100644
index 0000000000..5a44012567
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.l
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: section '.data.foo' has not been declared
+[^:]*:7: Error: 'myvar' is not a section name, expected ".retain \[name\]"
diff --git a/gas/testsuite/gas/elf/retain2.s b/gas/testsuite/gas/elf/retain2.s
new file mode 100644
index 0000000000..75eb26d7f7
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.s
@@ -0,0 +1,7 @@
+.retain ".data.foo"
+.section .data,"aw"
+.global myvar
+.type myvar, STT_OBJECT
+myvar:
+	.byte 2
+.retain "myvar"
diff --git a/gas/testsuite/gas/elf/retain3.d b/gas/testsuite/gas/elf/retain3.d
new file mode 100644
index 0000000000..2d5ca68086
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain3.d
@@ -0,0 +1,24 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 3 (use flags set on .section directive)
+
+#...
+  \[..\] .bss.discard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.discard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.discard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.sdiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .text.fndiscard0[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+  \[..\] .bss.retain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.retain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.retain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.sretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .text.fnretain1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+  \[..\] .text.fndiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+#...
+  \[..\] .bss.lsretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.lsretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.lsretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain3.s b/gas/testsuite/gas/elf/retain3.s
new file mode 100644
index 0000000000..065399ec6f
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain3.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, STT_OBJECT
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, STT_OBJECT
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, STT_OBJECT
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, STT_OBJECT
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, STT_OBJECT
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, STT_OBJECT
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, STT_OBJECT
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, STT_OBJECT
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, STT_OBJECT
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d
index 554a791f1d..ef91d7d086 100644
--- a/gas/testsuite/gas/elf/section10.d
+++ b/gas/testsuite/gas/elf/section10.d
@@ -18,7 +18,7 @@
 #...
 [ 	]*\[.*\][ 	]+sec3
 [ 	]*PROGBITS.*
-[ 	]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
+[ 	]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
 #...
 [ 	]*\[.*\][ 	]+sec4
 [ 	]*LOOS\+0x11[ 	].*
@@ -26,7 +26,7 @@
 #...
 [ 	]*\[.*\][ 	]+sec5
 [ 	]*LOUSER\+0x9[ 	].*
-[ 	]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
+[ 	]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
 [ 	]*\[.*\][ 	]+.data.foo
 [ 	]*LOUSER\+0x7f000000[ 	].*
 [ 	]*\[0+003\]: WRITE, ALLOC
diff --git a/include/elf/common.h b/include/elf/common.h
index 805058146a..364c58a7de 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -554,6 +554,7 @@
 /* #define SHF_MASKOS	0x0F000000    *//* OS-specific semantics */
 #define SHF_MASKOS	0x0FF00000	/* New value, Oct 4, 1999 Draft */
 #define SHF_GNU_BUILD_NOTE    (1 << 20)	/* Section contains GNU BUILD ATTRIBUTE notes.  */
+#define SHF_GNU_RETAIN	      (1 << 21)	/* Section should not be garbage collected by the linker.  */
 #define SHF_MASKPROC	0xF0000000	/* Processor-specific semantics */
 
 /* This used to be implemented as a processor specific section flag.
diff --git a/ld/NEWS b/ld/NEWS
index 695348141b..1c3cc9d20a 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -13,6 +13,10 @@
   unless you are working on a project that has its own analogue
   of symbol tables that are not reflected in the ELF symtabs.
 
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+  This flag specifies that the section should not be garbage collected by the
+  linker if it is unused.
+
 Changes in 2.35:
 
 * X86 NaCl target support is removed.
diff --git a/ld/ld.texi b/ld/ld.texi
index 7d961c3bb8..5daffbeb5f 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1781,6 +1781,10 @@ specified either by one of the options @samp{--entry},
 @samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY}
 command in the linker script.
 
+As a GNU extension, ELF input sections marked with the
+@code{SHF_GNU_RETAIN} flag will not be garbage collected if they are
+unused.
+
 @kindex --print-gc-sections
 @kindex --no-print-gc-sections
 @cindex garbage collection
@@ -5226,6 +5230,10 @@ The special output section name @samp{/DISCARD/} may be used to discard
 input sections.  Any input sections which are assigned to an output
 section named @samp{/DISCARD/} are not included in the output file.
 
+This can be used to discard input sections marked with the ELF flag
+@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker
+garbage collection when they are unused.
+
 Note, sections that match the @samp{/DISCARD/} output section will be
 discarded even if they are in an ELF section group which has other
 members which are not being discarded.  This is deliberate.
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index c0d67d80d2..bf39e0a586 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -188,6 +188,8 @@ if { [istarget *-*-*linux*]
 	]
 }
 
+# mmix is supposed to support --gc-sections, but the option has no effect,
+# so these tests are XFAIL'd for the target.
 if [check_gc_sections_available] {
     run_ld_link_tests [list \
 	[list "__patchable_function_entries section 2" \
@@ -225,7 +227,41 @@ if [check_gc_sections_available] {
 	    {pr25490-6.s} \
 	    [list [list "readelf" {-SW} $pr25490_6_exp]] \
 	    "pr25490-6.exe"] \
-	]
+	[list "SHF_GNU_RETAIN 1" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain1.s} \
+	    {{ ld retain1.msg }} \
+	    "retain1.exe"] \
+	[list "SHF_GNU_RETAIN 3 (use flags set on .section directive)" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain3.s} \
+	    {{ ld retain3.msg }} \
+	    "retain3.exe"] \
+	[list "SHF_GNU_RETAIN 4 (keep sections referenced by retained sections)" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain4.s} {} \
+	    "retain4.exe"] \
+	[list "SHF_GNU_RETAIN 5 (keep orphaned sections when not discarding)" \
+	    "--gc-sections -e _start --print-gc-sections --orphan-handling=place" "" "" \
+	    {retain5.s} {} \
+	    "retain5.exe"] \
+	[list "Build libretain6.a" \
+	    "" "" "" \
+	    {retain6lib.s} {} "libretain6.a"] \
+	[list "SHF_GNU_RETAIN 6 (don't pull SHF_GNU_RETAIN section out of lib)" \
+	    "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain6" "" \
+	    {retain6main.s} {} \
+	    "retain6.exe"] \
+	[list "Build libretain7.a" \
+	    "" "" "" \
+	    {retain7lib.s} {} "libretain7.a"] \
+	[list "SHF_GNU_RETAIN 7 (pull section out of lib required by SHF_GNU_RETAIN section)" \
+	    "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain7" "" \
+	    {retain7main.s} \
+	    {{ ld retain7.msg }} \
+	    "retain7.exe"] \
+	] \
+    "mmix-*-*"
 }
 
 set LDFLAGS $old_ldflags
diff --git a/ld/testsuite/ld-elf/retain1.msg b/ld/testsuite/ld-elf/retain1.msg
new file mode 100644
index 0000000000..9a265c980f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1.msg
@@ -0,0 +1,9 @@
+.*: removing unused section '.bss.discard0' in file.*
+.*: removing unused section '.bss.discard1' in file.*
+.*: removing unused section '.data.discard2' in file.*
+.*: removing unused section '.bss.sdiscard0' in file.*
+.*: removing unused section '.bss.sdiscard1' in file.*
+.*: removing unused section '.data.sdiscard2' in file.*
+.*: removing unused section '.text.fndiscard0' in file.*
+.*: removing unused section '.text.fndiscard2' in file.*
+#pass
diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d
new file mode 100644
index 0000000000..941b002948
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.d
@@ -0,0 +1,7 @@
+# Test that sections marked with SHF_GNU_RETAIN can be removed by placing them
+# in /DISCARD/.
+# source: retain1.s
+# ld: -e _start -Map=retain2.map --gc-sections --script=retain2.ld
+# map: retain2.map
+# skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+# xfail: mmix-*-*
diff --git a/ld/testsuite/ld-elf/retain2.ld b/ld/testsuite/ld-elf/retain2.ld
new file mode 100644
index 0000000000..8ef982753c
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.ld
@@ -0,0 +1,7 @@
+SECTIONS
+{
+  /DISCARD/ :
+  {
+    *(.text.fnretain1)
+  }
+}
diff --git a/ld/testsuite/ld-elf/retain2.map b/ld/testsuite/ld-elf/retain2.map
new file mode 100644
index 0000000000..4028aa1f58
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.map
@@ -0,0 +1,32 @@
+# Test that .text.fnretain1, which has the SHF_GNU_RETAIN flag, can still be
+# explicitly discarded from the output file.
+
+#...
+Discarded input sections
+
+ .text.*
+#...
+ .data.*
+#...
+ .bss.*
+#...
+ .bss.discard0.*
+#...
+ .bss.discard1.*
+#...
+ .data.discard2.*
+#...
+ .bss.sdiscard0.*
+#...
+ .bss.sdiscard1.*
+#...
+ .data.sdiscard2.*
+#...
+ .text.fndiscard0.*
+#...
+ .text.fnretain1.*
+#...
+ .text.fndiscard2.*
+#...
+Memory Configuration
+#pass
diff --git a/ld/testsuite/ld-elf/retain3.msg b/ld/testsuite/ld-elf/retain3.msg
new file mode 100644
index 0000000000..9a265c980f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.msg
@@ -0,0 +1,9 @@
+.*: removing unused section '.bss.discard0' in file.*
+.*: removing unused section '.bss.discard1' in file.*
+.*: removing unused section '.data.discard2' in file.*
+.*: removing unused section '.bss.sdiscard0' in file.*
+.*: removing unused section '.bss.sdiscard1' in file.*
+.*: removing unused section '.data.sdiscard2' in file.*
+.*: removing unused section '.text.fndiscard0' in file.*
+.*: removing unused section '.text.fndiscard2' in file.*
+#pass
diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s
new file mode 100644
index 0000000000..065399ec6f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, STT_OBJECT
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, STT_OBJECT
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, STT_OBJECT
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, STT_OBJECT
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, STT_OBJECT
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, STT_OBJECT
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, STT_OBJECT
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, STT_OBJECT
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, STT_OBJECT
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain4.s b/ld/testsuite/ld-elf/retain4.s
new file mode 100644
index 0000000000..080a5dfc2e
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain4.s
@@ -0,0 +1,19 @@
+/* The retention of bar should also prevent foo from being gc'ed, since bar
+   references foo.  */
+	.section	.text.foo,"ax"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text.bar,"axR"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.long foo
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain5.s b/ld/testsuite/ld-elf/retain5.s
new file mode 100644
index 0000000000..5ffadad694
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5.s
@@ -0,0 +1,13 @@
+/* A section which doesn't match any linker script input section rules but
+   has SHF_GNU_RETAIN applied should not be garbage collected.  */
+	.section	.orphaned_section,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain6lib.s b/ld/testsuite/ld-elf/retain6lib.s
new file mode 100644
index 0000000000..4de7adea3d
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6lib.s
@@ -0,0 +1,6 @@
+/* The link will fail if foo is included because undefined_sym is not defined.  */
+	.section	.text.foo,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.long undefined_sym
diff --git a/ld/testsuite/ld-elf/retain6main.s b/ld/testsuite/ld-elf/retain6main.s
new file mode 100644
index 0000000000..7c722481e8
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6main.s
@@ -0,0 +1,5 @@
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain7.msg b/ld/testsuite/ld-elf/retain7.msg
new file mode 100644
index 0000000000..c21e3b9d75
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7.msg
@@ -0,0 +1 @@
+.*: removing unused section '.text.discard_from_lib' in file.*
diff --git a/ld/testsuite/ld-elf/retain7lib.s b/ld/testsuite/ld-elf/retain7lib.s
new file mode 100644
index 0000000000..2aebf32bd0
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7lib.s
@@ -0,0 +1,17 @@
+	.section	.text.bar,"ax"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.word 0
+
+	.section	.text.retain_from_lib,"axR"
+	.global	retain_from_lib
+	.type	retain_from_lib, STT_FUNC
+retain_from_lib:
+	.word 0
+
+	.section	.text.discard_from_lib,"ax"
+	.global	discard_from_lib
+	.type	discard_from_lib, STT_FUNC
+discard_from_lib:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain7main.s b/ld/testsuite/ld-elf/retain7main.s
new file mode 100644
index 0000000000..d8ce70e718
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7main.s
@@ -0,0 +1,13 @@
+/* Undefined symbol reference in retained section .text.foo requires symbol
+   definition to be pulled out of library.  */
+	.section	.text.foo,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.long bar
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
-- 
2.28.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
@ 2020-09-22 23:24 ` Hans-Peter Nilsson
  2020-09-22 23:58 ` H.J. Lu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: Hans-Peter Nilsson @ 2020-09-22 23:24 UTC (permalink / raw)
  To: Jozef Lawrynowicz; +Cc: binutils

On Tue, 22 Sep 2020, Jozef Lawrynowicz wrote:
> The new tests are passing for all targets except mmix-elf.

There is no mmix-elf target: if it's buildable, that's a
mistake.  I'm not sure what kind of abomination results, if it's
a goldblum-fly or karloff-frankensteins. :)

The target mmix a.k.a. mmix-knuth-mmixware assembles to ELF, but
links to MMO by use of the generic linker machinery.  You *can*
link to ELF by means of the linker option "-m elf64mmix".

brgds, H-P


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
  2020-09-22 23:24 ` Hans-Peter Nilsson
@ 2020-09-22 23:58 ` H.J. Lu
  2020-09-23  1:09 ` Fangrui Song
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 37+ messages in thread
From: H.J. Lu @ 2020-09-22 23:58 UTC (permalink / raw)
  To: Binutils

On Tue, Sep 22, 2020 at 1:30 PM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> The attached patch adds support for the new SHF_GNU_RETAIN ELF section
> flag, which was discussed on the GNU gABI mailing list here:
> https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
>
> The flag is GNU-specific so uses a bit in the SHF_MASKOS mask.
> Its precise definition is as follows:
>
> =======================================================================
> Section Attribute Flags
> +-------------------------------------+
> | Name           | Value              |
> +-------------------------------------+
> | SHF_GNU_RETAIN | 0x200000 (1 << 21) |
> +-------------------------------------+
>
> SHF_GNU_RETAIN
>   The link editor should not garbage collect the section if it is
>   unused.
>
> =======================================================================
>
> The overall intention for this new flag is to enable a new "retain"
> attribute to be applied to declarations of functions and data in the
> source code. This attribute can be used to ensure the definition
> associated with the declaration is present in the linked output file,
> even if linker garbage collection would normally remove the containing
> section because it is unused.
>
> The new ".retain" assembler directive can be used to apply
> SHF_GNU_RETAIN to a section. GCC will emit this directive when
> assembling definitions of functions and data that have had the "retain"
> attribute applied.
>
> Note that there is *not* a direct mapping of SHF_GNU_RETAIN to the BFD
> section flag SEC_KEEP. SEC_KEEP would prevent the user being able to
> explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/,
> which could be necessary in some situations.
>
> I successfully regtested the patch for the Binutils, GAS and LD
> testsuites for the following CPUs, applying the "-elf" suffix when
> configuring:
>   aarch64 alpha arc arm avr bfin bpf cr16 cris crx csky d10v d30v dlx
>   epiphany fr30 frv ft32 h8300 hppa i386 ia64 ia64-vms ip2k iq2000 lm32
>   m32c m32r m68hc11 m68hc12 m68k mcore mep metag microblaze mips mmix
>   moxie msp430 mt nds32 nfp nios2 or1k pj ppc pru riscv rl78 rx s12z
>   s390 score sh sparc spu tic6x tilegx tilepro v850 vax visium wasm32
>   x86-64 x86 xc16x xgate xstormy16 xtensa z80
>
> The new tests are passing for all targets except mmix-elf. This target
> has a lot of LD failures, particularly --gc-sections doesn't appear to
> have any effect. I don't know anything about the target, but I wonder if
> it should be added to the hard-coded list of targets that doesn't
> support --gc-sections.  I have therefore XFAIL'd the new LD tests for
> this target.
>
> I also regtested for i386-pe, to ensure there was no spill-over of the
> new functionality into any non-ELF areas.
>
> Ok to apply?
>
> Thanks,
> Jozef

+  /* A GNU extension for preventing linker garbage collection of sections.  */
+  {"retain", obj_elf_retain, 0},
+

Why is this needed?  Isn't

@@ -857,6 +861,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
  case 'd':
   *gnu_attr |= SHF_GNU_MBIND;
   break;
+ case 'R':
+  *gnu_attr |= SHF_GNU_RETAIN;
+  break;
  case '?':
   *is_clone = TRUE;
   break;

enough?  The .section directive is used for all other SHF_XXX bits.   I don't
think we need a separate directive for SHF_GNU_RETAIN?


-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
  2020-09-22 23:24 ` Hans-Peter Nilsson
  2020-09-22 23:58 ` H.J. Lu
@ 2020-09-23  1:09 ` Fangrui Song
  2020-09-23  9:58   ` Jozef Lawrynowicz
  2020-09-23 12:13 ` Jozef Lawrynowicz
  2020-09-28 11:35 ` Pedro Alves
  4 siblings, 1 reply; 37+ messages in thread
From: Fangrui Song @ 2020-09-23  1:09 UTC (permalink / raw)
  To: binutils

On 2020-09-22, Jozef Lawrynowicz wrote:
>The attached patch adds support for the new SHF_GNU_RETAIN ELF section
>flag, which was discussed on the GNU gABI mailing list here:
>https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
>
>The flag is GNU-specific so uses a bit in the SHF_MASKOS mask.
>Its precise definition is as follows:

We already have a way to create an artificial reference:

   .reloc ., R_X86_64_NONE, target_symbol

If we allow a relocation number for the second operand

   .reloc ., 0, target_symbol

this will be generic. You can insert the directives in a GC root (e.g.
_start or a symbol referenced by -u or maybe an .init_array)

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23  1:09 ` Fangrui Song
@ 2020-09-23  9:58   ` Jozef Lawrynowicz
  2020-09-23 13:39     ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23  9:58 UTC (permalink / raw)
  To: Hans-Peter Nilsson, H.J. Lu, Fangrui Song; +Cc: binutils

On Tue, Sep 22, 2020 at 07:24:01PM -0400, Hans-Peter Nilsson wrote:
> On Tue, 22 Sep 2020, Jozef Lawrynowicz wrote:
> > The new tests are passing for all targets except mmix-elf.
> 
> There is no mmix-elf target: if it's buildable, that's a
> mistake.  I'm not sure what kind of abomination results, if it's
> a goldblum-fly or karloff-frankensteins. :)
> 
> The target mmix a.k.a. mmix-knuth-mmixware assembles to ELF, but
> links to MMO by use of the generic linker machinery.  You *can*
> link to ELF by means of the linker option "-m elf64mmix".
> 
> brgds, H-P
> 

Ah, thanks for the info. I formed that list of targets by just
extracting the CPU name from all the files in bfd/ with "elf" in the
name.

mmix-elf is buildable, and most tests pass, but it definitely appears
that a lot is broken!

  ==> mmix-elf/binutils.sum <==
  # of expected passes            122
  # of unexpected failures        38
  ==> mmix-elf/gas.sum <==
  # of expected passes            446
  # of unexpected failures        68
  ==> mmix-elf/ld.sum <==
  # of expected passes            430
  # of unexpected failures        158

I'll remove any mmix-elf-specific XFAIL-ing from the patch.

On Tue, Sep 22, 2020 at 04:58:23PM -0700, H.J. Lu via Binutils wrote:
> On Tue, Sep 22, 2020 at 1:30 PM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> +  /* A GNU extension for preventing linker garbage collection of sections.  */
> +  {"retain", obj_elf_retain, 0},
> +
> 
> Why is this needed?  Isn't
> 
> @@ -857,6 +861,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
>   case 'd':
>    *gnu_attr |= SHF_GNU_MBIND;
>    break;
> + case 'R':
> +  *gnu_attr |= SHF_GNU_RETAIN;
> +  break;
>   case '?':
>    *is_clone = TRUE;
>    break;
> 
> enough?  The .section directive is used for all other SHF_XXX bits.   I don't
> think we need a separate directive for SHF_GNU_RETAIN?

GCC doesn't know if SHF_GNU_RETAIN is required when creating a section,
since the "retain" attribute is applied to function and data
declarations.

So rather than emitting the section directive again, which could be
confusing if there are two almost identical section declarations, the
".retain" directive describes the precise augmentation to make to the
already-declared section.

I think that:

>  .section .text,"ax"
>    ...
>  foo:
>    ...
>  .retain
>  retained_fn:
>    ...

is some nice syntactic sugar compared to:

>  .section .text,"ax"
>    ...
>  foo:
>    ...
>  .section .text,"axR"
>  retained_fn:
>    ...

It's also partly for convenience; we have other directives which are
synonyms or short-hand for each other.

There's a bug in my patch where a .section directive without the
"R" flag overrides an earlier .section directive for the same section
with the "R" flag and clobbers SHF_GNU_RETAIN, I need to fix that.

On Tue, Sep 22, 2020 at 06:09:30PM -0700, Fangrui Song wrote:
> On 2020-09-22, Jozef Lawrynowicz wrote:
> > The attached patch adds support for the new SHF_GNU_RETAIN ELF section
> > flag, which was discussed on the GNU gABI mailing list here:
> > https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
> > 
> > The flag is GNU-specific so uses a bit in the SHF_MASKOS mask.
> > Its precise definition is as follows:
> 
> We already have a way to create an artificial reference:
> 
>   .reloc ., R_X86_64_NONE, target_symbol
> 
> If we allow a relocation number for the second operand
> 
>   .reloc ., 0, target_symbol
> 
> this will be generic. You can insert the directives in a GC root (e.g.
> _start or a symbol referenced by -u or maybe an .init_array)

I don't really understand how this would work in most cases when the
compiler or assembler aren't building the file which will contain the
eventual GC root. How are they to know what the GC root is anyway? What
if the assumed GC root changes after the files are built?

I also don't see any advantage of re-purposing .reloc for this use case,
over having a precisely defined new section flag. You would also have to
look at relocations defined in the GC root function (mixed with
relocations used for other purposes) to work out which sections are
being retained, instead of having retention being a property of the
section itself.

Thanks,
Jozef

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
                   ` (2 preceding siblings ...)
  2020-09-23  1:09 ` Fangrui Song
@ 2020-09-23 12:13 ` Jozef Lawrynowicz
  2020-09-23 13:59   ` Alan Modra
  2020-09-28 11:35 ` Pedro Alves
  4 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23 12:13 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 3108 bytes --]

Attached a revised patch:
- Removed mmix-*-* XFAILs
- Fixed SHF_GNU_RETAIN being clobbered when using the .section directive
  without the "R" flag, after the section has previously been marked
  with SHF_GNU_RETAIN. Added tests for this behavior.

Thanks,
Jozef

On Tue, Sep 22, 2020 at 09:29:33PM +0100, Jozef Lawrynowicz wrote:
> The attached patch adds support for the new SHF_GNU_RETAIN ELF section
> flag, which was discussed on the GNU gABI mailing list here:
> https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
> 
> The flag is GNU-specific so uses a bit in the SHF_MASKOS mask.
> Its precise definition is as follows:
> 
> =======================================================================
> Section Attribute Flags
> +-------------------------------------+
> | Name           | Value              |
> +-------------------------------------+
> | SHF_GNU_RETAIN | 0x200000 (1 << 21) |
> +-------------------------------------+
> 
> SHF_GNU_RETAIN
>   The link editor should not garbage collect the section if it is
>   unused.
> 
> =======================================================================
> 
> The overall intention for this new flag is to enable a new "retain"
> attribute to be applied to declarations of functions and data in the
> source code. This attribute can be used to ensure the definition
> associated with the declaration is present in the linked output file,
> even if linker garbage collection would normally remove the containing
> section because it is unused.
> 
> The new ".retain" assembler directive can be used to apply
> SHF_GNU_RETAIN to a section. GCC will emit this directive when
> assembling definitions of functions and data that have had the "retain"
> attribute applied.
> 
> Note that there is *not* a direct mapping of SHF_GNU_RETAIN to the BFD
> section flag SEC_KEEP. SEC_KEEP would prevent the user being able to
> explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/,
> which could be necessary in some situations.
> 
> I successfully regtested the patch for the Binutils, GAS and LD
> testsuites for the following CPUs, applying the "-elf" suffix when
> configuring:
>   aarch64 alpha arc arm avr bfin bpf cr16 cris crx csky d10v d30v dlx
>   epiphany fr30 frv ft32 h8300 hppa i386 ia64 ia64-vms ip2k iq2000 lm32
>   m32c m32r m68hc11 m68hc12 m68k mcore mep metag microblaze mips mmix
>   moxie msp430 mt nds32 nfp nios2 or1k pj ppc pru riscv rl78 rx s12z
>   s390 score sh sparc spu tic6x tilegx tilepro v850 vax visium wasm32
>   x86-64 x86 xc16x xgate xstormy16 xtensa z80
> 
> The new tests are passing for all targets except mmix-elf. This target
> has a lot of LD failures, particularly --gc-sections doesn't appear to
> have any effect. I don't know anything about the target, but I wonder if
> it should be added to the hard-coded list of targets that doesn't
> support --gc-sections.  I have therefore XFAIL'd the new LD tests for
> this target.
> 
> I also regtested for i386-pe, to ensure there was no spill-over of the
> new functionality into any non-ELF areas.
> 
> Ok to apply?
> 
> Thanks,
> Jozef

[-- Attachment #2: 0001-Support-SHF_GNU_RETAIN-ELF-section-flag.patch --]
[-- Type: text/plain, Size: 43996 bytes --]

From 862a04415e1b490b4561fe5a44c9fa4120c50825 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Tue, 22 Sep 2020 21:00:35 +0100
Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag

The GNU-specific SHF_GNU_RETAIN ELF section flag is defined as follows:

=======================================================================
Section Attribute Flags
+-------------------------------------+
| Name           | Value              |
+-------------------------------------+
| SHF_GNU_RETAIN | 0x200000 (1 << 21) |
+-------------------------------------+

SHF_GNU_RETAIN
  The link editor should not garbage collect the section if it is
  unused.

=======================================================================

The new ".retain" assembler directive can be used to apply
SHF_GNU_RETAIN to a section.

Note that there is not a direct mapping of SHF_GNU_RETAIN to the BFD
section flag SEC_KEEP. SEC_KEEP would prevent the user being able to
explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/.

bfd/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* elflink.c (bfd_elf_gc_sections): gc_mark the section if
	SHF_GNU_RETAIN is set.

binutils/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce SHF_GNU_RETAIN.
	* readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN.
	* testsuite/binutils-all/readelf.exp: Run new test.
	Don't run run_dump_test when there isn't an assembler available.
	* testsuite/binutils-all/retain1.d: New test.
	* testsuite/binutils-all/retain1.s: New test.

gas/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce .retain directive and SHF_GNU_RETAIN.
	* config/obj-elf.c (elf_pseudo_table): Add "retain".
	(obj_elf_retain): New.
	(obj_elf_parse_section_letters): Handle 'R' flag.
	* doc/as.texi: Document .retain directive.
	(Section): Document 'R' flag.
	* testsuite/gas/elf/elf.exp: Run new tests.
	* testsuite/gas/elf/retain1.d: New test.
	* testsuite/gas/elf/retain1.s: New test.
	* testsuite/gas/elf/retain2.d: New test.
	* testsuite/gas/elf/retain2.l: New test.
	* testsuite/gas/elf/retain2.s: New test.
	* testsuite/gas/elf/retain3.d: New test.
	* testsuite/gas/elf/retain3.s: New test.
	* testsuite/gas/elf/section10.d: Adjust test.

include/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* elf/common.h (SHF_GNU_RETAIN): Define.

ld/ChangeLog:

2020-09-22  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* NEWS: Announce SHF_GNU_RETAIN.
	* ld.texi (garbage collection): Document SHF_GNU_RETAIN.
	(Output Section Discarding): Likewise.
	* testsuite/ld-elf/elf.exp: Run new tests.
	* testsuite/ld-elf/retain1.msg: New test.
	* testsuite/ld-elf/retain1.s: New test.
	* testsuite/ld-elf/retain2.d: New test.
	* testsuite/ld-elf/retain2.ld: New test.
	* testsuite/ld-elf/retain2.map: New test.
	* testsuite/ld-elf/retain3.msg: New test.
	* testsuite/ld-elf/retain3.s: New test.
	* testsuite/ld-elf/retain4.s: New test.
	* testsuite/ld-elf/retain5.s: New test.
	* testsuite/ld-elf/retain6lib.s: New test.
	* testsuite/ld-elf/retain6main.s: New test.
	* testsuite/ld-elf/retain7.msg: New test.
	* testsuite/ld-elf/retain7lib.s: New test.
	* testsuite/ld-elf/retain7main.s: New test.
---
 bfd/elflink.c                               |   3 +-
 binutils/NEWS                               |   4 +
 binutils/readelf.c                          |   4 +
 binutils/testsuite/binutils-all/readelf.exp |   6 +-
 binutils/testsuite/binutils-all/retain1.d   |  17 +++
 binutils/testsuite/binutils-all/retain1.s   | 114 ++++++++++++++++++++
 gas/NEWS                                    |   4 +
 gas/config/obj-elf.c                        |  71 +++++++++++-
 gas/doc/as.texi                             |  20 ++++
 gas/testsuite/gas/elf/elf.exp               |   7 ++
 gas/testsuite/gas/elf/retain1.d             |  24 +++++
 gas/testsuite/gas/elf/retain1.s             | 114 ++++++++++++++++++++
 gas/testsuite/gas/elf/retain2.d             |   3 +
 gas/testsuite/gas/elf/retain2.l             |   3 +
 gas/testsuite/gas/elf/retain2.s             |   7 ++
 gas/testsuite/gas/elf/retain3.d             |  24 +++++
 gas/testsuite/gas/elf/retain3.s             | 104 ++++++++++++++++++
 gas/testsuite/gas/elf/retain4.d             |   6 ++
 gas/testsuite/gas/elf/retain4.s             |  20 ++++
 gas/testsuite/gas/elf/retain5.d             |   6 ++
 gas/testsuite/gas/elf/retain5.s             |  18 ++++
 gas/testsuite/gas/elf/section10.d           |   4 +-
 include/elf/common.h                        |   1 +
 ld/NEWS                                     |   4 +
 ld/ld.texi                                  |   8 ++
 ld/testsuite/ld-elf/elf.exp                 |  33 ++++++
 ld/testsuite/ld-elf/retain1.msg             |   9 ++
 ld/testsuite/ld-elf/retain1.s               | 114 ++++++++++++++++++++
 ld/testsuite/ld-elf/retain2.d               |   6 ++
 ld/testsuite/ld-elf/retain2.ld              |   7 ++
 ld/testsuite/ld-elf/retain2.map             |  32 ++++++
 ld/testsuite/ld-elf/retain3.msg             |   9 ++
 ld/testsuite/ld-elf/retain3.s               | 104 ++++++++++++++++++
 ld/testsuite/ld-elf/retain4.s               |  19 ++++
 ld/testsuite/ld-elf/retain5.s               |  13 +++
 ld/testsuite/ld-elf/retain6lib.s            |   6 ++
 ld/testsuite/ld-elf/retain6main.s           |   5 +
 ld/testsuite/ld-elf/retain7.msg             |   1 +
 ld/testsuite/ld-elf/retain7lib.s            |  17 +++
 ld/testsuite/ld-elf/retain7main.s           |  13 +++
 40 files changed, 977 insertions(+), 7 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/retain1.d
 create mode 100644 binutils/testsuite/binutils-all/retain1.s
 create mode 100644 gas/testsuite/gas/elf/retain1.d
 create mode 100644 gas/testsuite/gas/elf/retain1.s
 create mode 100644 gas/testsuite/gas/elf/retain2.d
 create mode 100644 gas/testsuite/gas/elf/retain2.l
 create mode 100644 gas/testsuite/gas/elf/retain2.s
 create mode 100644 gas/testsuite/gas/elf/retain3.d
 create mode 100644 gas/testsuite/gas/elf/retain3.s
 create mode 100644 gas/testsuite/gas/elf/retain4.d
 create mode 100644 gas/testsuite/gas/elf/retain4.s
 create mode 100644 gas/testsuite/gas/elf/retain5.d
 create mode 100644 gas/testsuite/gas/elf/retain5.s
 create mode 100644 ld/testsuite/ld-elf/retain1.msg
 create mode 100644 ld/testsuite/ld-elf/retain1.s
 create mode 100644 ld/testsuite/ld-elf/retain2.d
 create mode 100644 ld/testsuite/ld-elf/retain2.ld
 create mode 100644 ld/testsuite/ld-elf/retain2.map
 create mode 100644 ld/testsuite/ld-elf/retain3.msg
 create mode 100644 ld/testsuite/ld-elf/retain3.s
 create mode 100644 ld/testsuite/ld-elf/retain4.s
 create mode 100644 ld/testsuite/ld-elf/retain5.s
 create mode 100644 ld/testsuite/ld-elf/retain6lib.s
 create mode 100644 ld/testsuite/ld-elf/retain6main.s
 create mode 100644 ld/testsuite/ld-elf/retain7.msg
 create mode 100644 ld/testsuite/ld-elf/retain7lib.s
 create mode 100644 ld/testsuite/ld-elf/retain7main.s

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 0e339f3c1e..6d1a1c5105 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -13977,7 +13977,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 			|| (elf_section_data (o)->this_hdr.sh_type
 			    == SHT_FINI_ARRAY)))
 		|| (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
-		    && elf_next_in_group (o) == NULL )))
+		    && elf_next_in_group (o) == NULL)
+		|| (elf_section_flags (o) & SHF_GNU_RETAIN)))
 	  {
 	    if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
 	      return FALSE;
diff --git a/binutils/NEWS b/binutils/NEWS
index c0dc73d7d8..6c7d3f3953 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -4,6 +4,10 @@
   symbol names.  In addition the --demangle=<style>, --no-demangle,
   --recurse-limit and --no-recurse-limit options are also now availale.
 
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+  This flag specifies that the section should not be garbage collected by the
+  linker if it is unused.
+
 Changes in 2.35:
 
 * Changed readelf's display of symbol names when wide mode is not enabled.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index cb4208f7b9..00502f7058 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5977,6 +5977,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
       /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
       /* VLE specific.  */
       /* 25 */ { STRING_COMMA_LEN ("VLE") },
+      /* GNU specific.  */
+      /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") },
     };
 
   if (do_section_details)
@@ -6010,6 +6012,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_EXCLUDE:		sindex = 18; break;
 	    case SHF_COMPRESSED:	sindex = 20; break;
 	    case SHF_GNU_MBIND:		sindex = 24; break;
+	    case SHF_GNU_RETAIN:	sindex = 26; break;
 
 	    default:
 	      sindex = -1;
@@ -6108,6 +6111,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_EXCLUDE:		*p = 'E'; break;
 	    case SHF_COMPRESSED:	*p = 'C'; break;
 	    case SHF_GNU_MBIND:		*p = 'D'; break;
+	    case SHF_GNU_RETAIN:	*p = 'R'; break;
 
 	    default:
 	      if ((filedata->file_header.e_machine == EM_X86_64
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 1fb36ae5c4..6dea09e305 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -364,8 +364,12 @@ readelf_wi_test
 readelf_compressed_wa_test
 
 readelf_dump_test
-run_dump_test "pr25543"
 
+# These dump tests require an assembler.
+if {[which $AS] != 0} then {
+    run_dump_test "pr25543"
+    run_dump_test "retain1"
+}
 
 # PR 13482 - Check for off-by-one errors when dumping .note sections.
 if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
diff --git a/binutils/testsuite/binutils-all/retain1.d b/binutils/testsuite/binutils-all/retain1.d
new file mode 100644
index 0000000000..35d7373cc1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.d
@@ -0,0 +1,17 @@
+#source: retain1.s
+#readelf: -S --wide
+#name: readelf SHF_GNU_RETAIN
+
+#...
+  \[[ 0-9]+\] .bss.retain0.*WAR.*
+  \[[ 0-9]+\] .bss.retain1.*WAR.*
+  \[[ 0-9]+\] .data.retain2.*WAR.*
+  \[[ 0-9]+\] .bss.sretain0.*WAR.*
+  \[[ 0-9]+\] .bss.sretain1.*WAR.*
+  \[[ 0-9]+\] .data.sretain2.*WAR.*
+  \[[ 0-9]+\] .text.fnretain1.*AXR.*
+#...
+  \[[ 0-9]+\] .bss.lsretain0.*WAR.*
+  \[[ 0-9]+\] .bss.lsretain1.*WAR.*
+  \[[ 0-9]+\] .data.lsretain2.*WAR.*
+#pass
diff --git a/binutils/testsuite/binutils-all/retain1.s b/binutils/testsuite/binutils-all/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/NEWS b/gas/NEWS
index 66afd0357b..0d63fad7b3 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -9,6 +9,10 @@
 
 * Configure with --enable-x86-used-note by default for Linux/x86.
 
+* Add support for the .retain directive, which applies the ELF SHF_GNU_RETAIN
+  flag to the specified section.  This flag specifies the section should not be
+  garbage collected by the linker if it is unused.
+
 Changes in 2.35:
 
 * X86 NaCl target support is removed.
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 9e39707801..5e384f2c58 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -78,6 +78,7 @@ static void obj_elf_gnu_attribute (int);
 static void obj_elf_tls_common (int);
 static void obj_elf_lcomm (int);
 static void obj_elf_struct (int);
+static void obj_elf_retain (int);
 
 static const pseudo_typeS elf_pseudo_table[] =
 {
@@ -119,6 +120,9 @@ static const pseudo_typeS elf_pseudo_table[] =
   /* A GNU extension for object attributes.  */
   {"gnu_attribute", obj_elf_gnu_attribute, 0},
 
+  /* A GNU extension for preventing linker garbage collection of sections.  */
+  {"retain", obj_elf_retain, 0},
+
   /* These are used for dwarf.  */
   {"2byte", cons, 2},
   {"4byte", cons, 4},
@@ -802,9 +806,15 @@ obj_elf_change_section (const char *name,
 		as_bad (_("changed section attributes for %s"), name);
 	    }
 	  else
-	    /* FIXME: Maybe we should consider removing a previously set
-	       processor or application specific attribute as suspicious ?  */
-	    elf_section_flags (sec) = attr;
+	    {
+	      /* Don't clobber SHF_GNU_RETAIN if it has been previously set on
+		 the section.  */
+	      attr |= (elf_section_flags (sec) & SHF_GNU_RETAIN);
+
+	      /* FIXME: Maybe we should consider removing a previously set
+		 processor or application specific attribute as suspicious ?  */
+	      elf_section_flags (sec) = attr;
+	    }
 
 	  if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
 	    as_bad (_("changed section entity size for %s"), name);
@@ -857,6 +867,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
 	case 'd':
 	  *gnu_attr |= SHF_GNU_MBIND;
 	  break;
+	case 'R':
+	  *gnu_attr |= SHF_GNU_RETAIN;
+	  break;
 	case '?':
 	  *is_clone = TRUE;
 	  break;
@@ -1986,6 +1999,58 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
   obj_elf_vendor_attribute (OBJ_ATTR_GNU);
 }
 
+/* Parse a ".retain [name]" directive.
+   The SHF_GNU_RETAIN flag should be applied to the section named "name".
+   If "name" is omitted, apply the flag to the current section being
+   assembled.  */
+static void
+obj_elf_retain (int ignored ATTRIBUTE_UNUSED)
+{
+  const char *name;
+  symbolS *secsym;
+  asection *bfdsec;
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer == '\n')
+    {
+      /* Handle the case when "name" isn't specified.  */
+      name = now_seg->name;
+      if (name == NULL)
+	{
+	  as_bad (_("\".retain\" directive not within a section"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+    }
+  else
+    {
+      /* The "name" argument has been given, validate it.  */
+      name = obj_elf_section_name ();
+      secsym = symbol_find (name);
+      if (secsym == NULL)
+	{
+	  as_bad (_("section '%s' has not been declared"), name);
+	  ignore_rest_of_line ();
+	  return;
+	}
+      else if (secsym != NULL
+	       && !symbol_section_p (secsym))
+	{
+	  as_bad (_("'%s' is not a section name, expected "
+		    "\".retain [name]\""), name);
+	  ignore_rest_of_line ();
+	  return;
+	}
+    }
+  demand_empty_rest_of_line ();
+
+  bfdsec = bfd_get_section_by_name (stdoutput, name);
+  if (bfdsec != NULL)
+    elf_section_flags (bfdsec) |= SHF_GNU_RETAIN;
+  else
+    as_bad (_("Couldn't find BFD section for %s\n"), name);
+}
+
 void
 elf_obj_read_begin_hook (void)
 {
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 112eaf810c..68afaa6aae 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -4468,6 +4468,7 @@ Some machine configurations provide additional directives.
 * Quad::                        @code{.quad @var{bignums}}
 * Reloc::			@code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]}
 * Rept::			@code{.rept @var{count}}
+* Retain::			@code{.retain [@var{name}]}
 * Sbttl::                       @code{.sbttl "@var{subheading}"}
 @ifset COFF
 * Scl::                         @code{.scl @var{class}}
@@ -6468,6 +6469,22 @@ is equivalent to assembling
 A count of zero is allowed, but nothing is generated.  Negative counts are not
 allowed and if encountered will be treated as if they were zero.
 
+@ifset ELF
+@node Retain
+@section @code{.retain [@var{name}]}
+
+@cindex @code{retain} directive
+@cindex SHF_GNU_RETAIN
+
+Apply the @code{SHF_GNU_RETAIN} flag to the section named @var{name}.
+If @var{name} is omitted, apply the flag to the current section being
+assembled.
+
+The @code{SHF_GNU_RETAIN} flag specifies that the section should not be
+garbage collected by the linker if it is unused.
+
+@end ifset
+
 @node Sbttl
 @section @code{.sbttl "@var{subheading}"}
 
@@ -6546,6 +6563,9 @@ ignored.  (For compatibility with the ELF version)
 section is not readable (meaningful for PE targets)
 @item 0-9
 single-digit power-of-two section alignment (GNU extension)
+@item R
+retained section (apply SHF_GNU_RETAIN to prevent linker garbage
+collection, GNU ELF extension)
 @end table
 
 If no flags are specified, the default flags depend upon the section name.  If
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 8520421ba3..c0dfdf504f 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -307,6 +307,13 @@ if { [is_elf_format] } then {
 
     run_dump_test "strtab"
 
+    # Tests for the .retain directive/SHF_GNU_RETAIN.
+    run_dump_test "retain1"
+    run_dump_test "retain2"
+    run_dump_test "retain3"
+    run_dump_test "retain4"
+    run_dump_test "retain5"
+
     run_dump_test "bignums"
     run_dump_test "section-symbol-redef"
     
diff --git a/gas/testsuite/gas/elf/retain1.d b/gas/testsuite/gas/elf/retain1.d
new file mode 100644
index 0000000000..439a60ca21
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain1.d
@@ -0,0 +1,24 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 1
+
+#...
+  \[..\] .bss.discard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.discard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.discard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.sdiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .text.fndiscard0[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+  \[..\] .bss.retain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.retain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.retain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.sretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .text.fnretain1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+  \[..\] .text.fndiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+#...
+  \[..\] .bss.lsretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.lsretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.lsretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain1.s b/gas/testsuite/gas/elf/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/testsuite/gas/elf/retain2.d b/gas/testsuite/gas/elf/retain2.d
new file mode 100644
index 0000000000..ca58b250b6
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.d
@@ -0,0 +1,3 @@
+#name: SHF_GNU_RETAIN 2
+#error_output: retain2.l
+#skip: hppa-*-*
diff --git a/gas/testsuite/gas/elf/retain2.l b/gas/testsuite/gas/elf/retain2.l
new file mode 100644
index 0000000000..5a44012567
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.l
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: section '.data.foo' has not been declared
+[^:]*:7: Error: 'myvar' is not a section name, expected ".retain \[name\]"
diff --git a/gas/testsuite/gas/elf/retain2.s b/gas/testsuite/gas/elf/retain2.s
new file mode 100644
index 0000000000..75eb26d7f7
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain2.s
@@ -0,0 +1,7 @@
+.retain ".data.foo"
+.section .data,"aw"
+.global myvar
+.type myvar, STT_OBJECT
+myvar:
+	.byte 2
+.retain "myvar"
diff --git a/gas/testsuite/gas/elf/retain3.d b/gas/testsuite/gas/elf/retain3.d
new file mode 100644
index 0000000000..2d5ca68086
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain3.d
@@ -0,0 +1,24 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 3 (use flags set on .section directive)
+
+#...
+  \[..\] .bss.discard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.discard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.discard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .bss.sdiscard1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .data.sdiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+  \[..\] .text.fndiscard0[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+  \[..\] .bss.retain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.retain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.retain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.sretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.sretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .text.fnretain1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+  \[..\] .text.fndiscard2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+#...
+  \[..\] .bss.lsretain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .bss.lsretain1[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+  \[..\] .data.lsretain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain3.s b/gas/testsuite/gas/elf/retain3.s
new file mode 100644
index 0000000000..065399ec6f
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain3.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, STT_OBJECT
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, STT_OBJECT
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, STT_OBJECT
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, STT_OBJECT
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, STT_OBJECT
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, STT_OBJECT
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, STT_OBJECT
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, STT_OBJECT
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, STT_OBJECT
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/gas/testsuite/gas/elf/retain4.d b/gas/testsuite/gas/elf/retain4.d
new file mode 100644
index 0000000000..eacad20635
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain4.d
@@ -0,0 +1,6 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 4 (switch to SHF_GNU_RETAIN section without "R" flag)
+
+#...
+  \[..\] .text.foo[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain4.s b/gas/testsuite/gas/elf/retain4.s
new file mode 100644
index 0000000000..48aeae2a11
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain4.s
@@ -0,0 +1,20 @@
+/* SHF_GNU_RETAIN should not be clobbered when switching to a section without
+   explicitly specifying the flag.  */
+	.section	.text.foo,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text.foo,"ax"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.word 0
+
+	.section	.text.main,"ax"
+	.global	main
+	.type	main, STT_FUNC
+main:
+	.word 0
+
diff --git a/gas/testsuite/gas/elf/retain5.d b/gas/testsuite/gas/elf/retain5.d
new file mode 100644
index 0000000000..9edbfad710
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain5.d
@@ -0,0 +1,6 @@
+#readelf: -S --wide
+#name: SHF_GNU_RETAIN 5 (apply "R" flag to existing section)
+
+#...
+  \[..\] .text.foo[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+#pass
diff --git a/gas/testsuite/gas/elf/retain5.s b/gas/testsuite/gas/elf/retain5.s
new file mode 100644
index 0000000000..c2957a7db4
--- /dev/null
+++ b/gas/testsuite/gas/elf/retain5.s
@@ -0,0 +1,18 @@
+/* Applying the "R" flag to an existing section should apply SHF_GNU_RETAIN.  */
+	.section	.text.foo,"ax"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text.foo,"axR"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.word 0
+
+	.section	.text.main,"ax"
+	.global	main
+	.type	main, STT_FUNC
+main:
+	.word 0
diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d
index 554a791f1d..ef91d7d086 100644
--- a/gas/testsuite/gas/elf/section10.d
+++ b/gas/testsuite/gas/elf/section10.d
@@ -18,7 +18,7 @@
 #...
 [ 	]*\[.*\][ 	]+sec3
 [ 	]*PROGBITS.*
-[ 	]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
+[ 	]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
 #...
 [ 	]*\[.*\][ 	]+sec4
 [ 	]*LOOS\+0x11[ 	].*
@@ -26,7 +26,7 @@
 #...
 [ 	]*\[.*\][ 	]+sec5
 [ 	]*LOUSER\+0x9[ 	].*
-[ 	]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
+[ 	]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
 [ 	]*\[.*\][ 	]+.data.foo
 [ 	]*LOUSER\+0x7f000000[ 	].*
 [ 	]*\[0+003\]: WRITE, ALLOC
diff --git a/include/elf/common.h b/include/elf/common.h
index 805058146a..364c58a7de 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -554,6 +554,7 @@
 /* #define SHF_MASKOS	0x0F000000    *//* OS-specific semantics */
 #define SHF_MASKOS	0x0FF00000	/* New value, Oct 4, 1999 Draft */
 #define SHF_GNU_BUILD_NOTE    (1 << 20)	/* Section contains GNU BUILD ATTRIBUTE notes.  */
+#define SHF_GNU_RETAIN	      (1 << 21)	/* Section should not be garbage collected by the linker.  */
 #define SHF_MASKPROC	0xF0000000	/* Processor-specific semantics */
 
 /* This used to be implemented as a processor specific section flag.
diff --git a/ld/NEWS b/ld/NEWS
index 695348141b..1c3cc9d20a 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -13,6 +13,10 @@
   unless you are working on a project that has its own analogue
   of symbol tables that are not reflected in the ELF symtabs.
 
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+  This flag specifies that the section should not be garbage collected by the
+  linker if it is unused.
+
 Changes in 2.35:
 
 * X86 NaCl target support is removed.
diff --git a/ld/ld.texi b/ld/ld.texi
index 7d961c3bb8..5daffbeb5f 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1781,6 +1781,10 @@ specified either by one of the options @samp{--entry},
 @samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY}
 command in the linker script.
 
+As a GNU extension, ELF input sections marked with the
+@code{SHF_GNU_RETAIN} flag will not be garbage collected if they are
+unused.
+
 @kindex --print-gc-sections
 @kindex --no-print-gc-sections
 @cindex garbage collection
@@ -5226,6 +5230,10 @@ The special output section name @samp{/DISCARD/} may be used to discard
 input sections.  Any input sections which are assigned to an output
 section named @samp{/DISCARD/} are not included in the output file.
 
+This can be used to discard input sections marked with the ELF flag
+@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker
+garbage collection when they are unused.
+
 Note, sections that match the @samp{/DISCARD/} output section will be
 discarded even if they are in an ELF section group which has other
 members which are not being discarded.  This is deliberate.
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index c0d67d80d2..9046bc870a 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -225,6 +225,39 @@ if [check_gc_sections_available] {
 	    {pr25490-6.s} \
 	    [list [list "readelf" {-SW} $pr25490_6_exp]] \
 	    "pr25490-6.exe"] \
+	[list "SHF_GNU_RETAIN 1" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain1.s} \
+	    {{ ld retain1.msg }} \
+	    "retain1.exe"] \
+	[list "SHF_GNU_RETAIN 3 (use flags set on .section directive)" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain3.s} \
+	    {{ ld retain3.msg }} \
+	    "retain3.exe"] \
+	[list "SHF_GNU_RETAIN 4 (keep sections referenced by retained sections)" \
+	    "--gc-sections -e _start --print-gc-sections" "" "" \
+	    {retain4.s} {} \
+	    "retain4.exe"] \
+	[list "SHF_GNU_RETAIN 5 (keep orphaned sections when not discarding)" \
+	    "--gc-sections -e _start --print-gc-sections --orphan-handling=place" "" "" \
+	    {retain5.s} {} \
+	    "retain5.exe"] \
+	[list "Build libretain6.a" \
+	    "" "" "" \
+	    {retain6lib.s} {} "libretain6.a"] \
+	[list "SHF_GNU_RETAIN 6 (don't pull SHF_GNU_RETAIN section out of lib)" \
+	    "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain6" "" \
+	    {retain6main.s} {} \
+	    "retain6.exe"] \
+	[list "Build libretain7.a" \
+	    "" "" "" \
+	    {retain7lib.s} {} "libretain7.a"] \
+	[list "SHF_GNU_RETAIN 7 (pull section out of lib required by SHF_GNU_RETAIN section)" \
+	    "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain7" "" \
+	    {retain7main.s} \
+	    {{ ld retain7.msg }} \
+	    "retain7.exe"] \
 	]
 }
 
diff --git a/ld/testsuite/ld-elf/retain1.msg b/ld/testsuite/ld-elf/retain1.msg
new file mode 100644
index 0000000000..9a265c980f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1.msg
@@ -0,0 +1,9 @@
+.*: removing unused section '.bss.discard0' in file.*
+.*: removing unused section '.bss.discard1' in file.*
+.*: removing unused section '.data.discard2' in file.*
+.*: removing unused section '.bss.sdiscard0' in file.*
+.*: removing unused section '.bss.sdiscard1' in file.*
+.*: removing unused section '.data.sdiscard2' in file.*
+.*: removing unused section '.text.fndiscard0' in file.*
+.*: removing unused section '.text.fndiscard2' in file.*
+#pass
diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s
new file mode 100644
index 0000000000..e799ff72ec
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1.s
@@ -0,0 +1,114 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"aw"
+	.type	retain0, STT_OBJECT
+	.retain	.bss.retain0
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"aw"
+	.type	retain1, STT_OBJECT
+	.retain	.bss.retain1
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"aw"
+	.type	retain2, STT_OBJECT
+	.retain	.data.retain2
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"aw"
+	.type	sretain0, STT_OBJECT
+	.retain	.bss.sretain0
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"aw"
+	.type	sretain1, STT_OBJECT
+	.retain	.bss.sretain1
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aw"
+	.type	sretain2, STT_OBJECT
+	.retain	.data.sretain2
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"ax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+	.retain	.text.fnretain1
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"aw"
+	.type	lsretain0.2, STT_OBJECT
+	.retain	.bss.lsretain0
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aw"
+	.type	lsretain1.1, STT_OBJECT
+	.retain	.bss.lsretain1
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aw"
+	.type	lsretain2.0, STT_OBJECT
+	.retain	.data.lsretain2
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d
new file mode 100644
index 0000000000..9834d58297
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.d
@@ -0,0 +1,6 @@
+# Test that sections marked with SHF_GNU_RETAIN can be removed by placing them
+# in /DISCARD/.
+# source: retain1.s
+# ld: -e _start -Map=retain2.map --gc-sections --script=retain2.ld
+# map: retain2.map
+# skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
diff --git a/ld/testsuite/ld-elf/retain2.ld b/ld/testsuite/ld-elf/retain2.ld
new file mode 100644
index 0000000000..8ef982753c
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.ld
@@ -0,0 +1,7 @@
+SECTIONS
+{
+  /DISCARD/ :
+  {
+    *(.text.fnretain1)
+  }
+}
diff --git a/ld/testsuite/ld-elf/retain2.map b/ld/testsuite/ld-elf/retain2.map
new file mode 100644
index 0000000000..4028aa1f58
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.map
@@ -0,0 +1,32 @@
+# Test that .text.fnretain1, which has the SHF_GNU_RETAIN flag, can still be
+# explicitly discarded from the output file.
+
+#...
+Discarded input sections
+
+ .text.*
+#...
+ .data.*
+#...
+ .bss.*
+#...
+ .bss.discard0.*
+#...
+ .bss.discard1.*
+#...
+ .data.discard2.*
+#...
+ .bss.sdiscard0.*
+#...
+ .bss.sdiscard1.*
+#...
+ .data.sdiscard2.*
+#...
+ .text.fndiscard0.*
+#...
+ .text.fnretain1.*
+#...
+ .text.fndiscard2.*
+#...
+Memory Configuration
+#pass
diff --git a/ld/testsuite/ld-elf/retain3.msg b/ld/testsuite/ld-elf/retain3.msg
new file mode 100644
index 0000000000..9a265c980f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.msg
@@ -0,0 +1,9 @@
+.*: removing unused section '.bss.discard0' in file.*
+.*: removing unused section '.bss.discard1' in file.*
+.*: removing unused section '.data.discard2' in file.*
+.*: removing unused section '.bss.sdiscard0' in file.*
+.*: removing unused section '.bss.sdiscard1' in file.*
+.*: removing unused section '.data.sdiscard2' in file.*
+.*: removing unused section '.text.fndiscard0' in file.*
+.*: removing unused section '.text.fndiscard2' in file.*
+#pass
diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s
new file mode 100644
index 0000000000..065399ec6f
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, STT_OBJECT
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, STT_OBJECT
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, STT_OBJECT
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, STT_OBJECT
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, STT_OBJECT
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, STT_OBJECT
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, STT_FUNC
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, STT_OBJECT
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, STT_OBJECT
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, STT_OBJECT
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, STT_OBJECT
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, STT_OBJECT
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, STT_OBJECT
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, STT_FUNC
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, STT_FUNC
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, STT_OBJECT
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, STT_OBJECT
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, STT_OBJECT
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain4.s b/ld/testsuite/ld-elf/retain4.s
new file mode 100644
index 0000000000..080a5dfc2e
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain4.s
@@ -0,0 +1,19 @@
+/* The retention of bar should also prevent foo from being gc'ed, since bar
+   references foo.  */
+	.section	.text.foo,"ax"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text.bar,"axR"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.long foo
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain5.s b/ld/testsuite/ld-elf/retain5.s
new file mode 100644
index 0000000000..5ffadad694
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5.s
@@ -0,0 +1,13 @@
+/* A section which doesn't match any linker script input section rules but
+   has SHF_GNU_RETAIN applied should not be garbage collected.  */
+	.section	.orphaned_section,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.word 0
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain6lib.s b/ld/testsuite/ld-elf/retain6lib.s
new file mode 100644
index 0000000000..4de7adea3d
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6lib.s
@@ -0,0 +1,6 @@
+/* The link will fail if foo is included because undefined_sym is not defined.  */
+	.section	.text.foo,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.long undefined_sym
diff --git a/ld/testsuite/ld-elf/retain6main.s b/ld/testsuite/ld-elf/retain6main.s
new file mode 100644
index 0000000000..7c722481e8
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6main.s
@@ -0,0 +1,5 @@
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain7.msg b/ld/testsuite/ld-elf/retain7.msg
new file mode 100644
index 0000000000..c21e3b9d75
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7.msg
@@ -0,0 +1 @@
+.*: removing unused section '.text.discard_from_lib' in file.*
diff --git a/ld/testsuite/ld-elf/retain7lib.s b/ld/testsuite/ld-elf/retain7lib.s
new file mode 100644
index 0000000000..2aebf32bd0
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7lib.s
@@ -0,0 +1,17 @@
+	.section	.text.bar,"ax"
+	.global	bar
+	.type	bar, STT_FUNC
+bar:
+	.word 0
+
+	.section	.text.retain_from_lib,"axR"
+	.global	retain_from_lib
+	.type	retain_from_lib, STT_FUNC
+retain_from_lib:
+	.word 0
+
+	.section	.text.discard_from_lib,"ax"
+	.global	discard_from_lib
+	.type	discard_from_lib, STT_FUNC
+discard_from_lib:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain7main.s b/ld/testsuite/ld-elf/retain7main.s
new file mode 100644
index 0000000000..d8ce70e718
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7main.s
@@ -0,0 +1,13 @@
+/* Undefined symbol reference in retained section .text.foo requires symbol
+   definition to be pulled out of library.  */
+	.section	.text.foo,"axR"
+	.global	foo
+	.type	foo, STT_FUNC
+foo:
+	.long bar
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, STT_FUNC
+_start:
+	.word 0
-- 
2.28.0


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23  9:58   ` Jozef Lawrynowicz
@ 2020-09-23 13:39     ` H.J. Lu
  2020-09-23 13:51       ` Michael Matz
  0 siblings, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-23 13:39 UTC (permalink / raw)
  To: Hans-Peter Nilsson, H.J. Lu, Fangrui Song, Binutils

On Wed, Sep 23, 2020 at 2:58 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Tue, Sep 22, 2020 at 07:24:01PM -0400, Hans-Peter Nilsson wrote:
> > On Tue, 22 Sep 2020, Jozef Lawrynowicz wrote:
> > > The new tests are passing for all targets except mmix-elf.
> >
> > There is no mmix-elf target: if it's buildable, that's a
> > mistake.  I'm not sure what kind of abomination results, if it's
> > a goldblum-fly or karloff-frankensteins. :)
> >
> > The target mmix a.k.a. mmix-knuth-mmixware assembles to ELF, but
> > links to MMO by use of the generic linker machinery.  You *can*
> > link to ELF by means of the linker option "-m elf64mmix".
> >
> > brgds, H-P
> >
>
> Ah, thanks for the info. I formed that list of targets by just
> extracting the CPU name from all the files in bfd/ with "elf" in the
> name.
>
> mmix-elf is buildable, and most tests pass, but it definitely appears
> that a lot is broken!
>
>   ==> mmix-elf/binutils.sum <==
>   # of expected passes            122
>   # of unexpected failures        38
>   ==> mmix-elf/gas.sum <==
>   # of expected passes            446
>   # of unexpected failures        68
>   ==> mmix-elf/ld.sum <==
>   # of expected passes            430
>   # of unexpected failures        158
>
> I'll remove any mmix-elf-specific XFAIL-ing from the patch.
>
> On Tue, Sep 22, 2020 at 04:58:23PM -0700, H.J. Lu via Binutils wrote:
> > On Tue, Sep 22, 2020 at 1:30 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > +  /* A GNU extension for preventing linker garbage collection of sections.  */
> > +  {"retain", obj_elf_retain, 0},
> > +
> >
> > Why is this needed?  Isn't
> >
> > @@ -857,6 +861,9 @@ obj_elf_parse_section_letters (char *str, size_t len,
> >   case 'd':
> >    *gnu_attr |= SHF_GNU_MBIND;
> >    break;
> > + case 'R':
> > +  *gnu_attr |= SHF_GNU_RETAIN;
> > +  break;
> >   case '?':
> >    *is_clone = TRUE;
> >    break;
> >
> > enough?  The .section directive is used for all other SHF_XXX bits.   I don't
> > think we need a separate directive for SHF_GNU_RETAIN?
>
> GCC doesn't know if SHF_GNU_RETAIN is required when creating a section,
> since the "retain" attribute is applied to function and data
> declarations.
>
> So rather than emitting the section directive again, which could be
> confusing if there are two almost identical section declarations, the
> ".retain" directive describes the precise augmentation to make to the
> already-declared section.
>
> I think that:
>
> >  .section .text,"ax"
> >    ...
> >  foo:
> >    ...
> >  .retain
> >  retained_fn:
> >    ...
>
> is some nice syntactic sugar compared to:
>
> >  .section .text,"ax"
> >    ...
> >  foo:
> >    ...
> >  .section .text,"axR"
> >  retained_fn:
> >    ...
>
> It's also partly for convenience; we have other directives which are
> synonyms or short-hand for each other.
>

You don't need to keep the whole section when only one symbol should
be kept.  Please drop the .retain directive.  GCC, as and ld should do the
right thing with

.section .text,"ax"
   ...
foo:
  ...
 .section .text,"axR"

 retained_fn:

where foo can be dropped and retained_fn will be kept.

H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 13:39     ` H.J. Lu
@ 2020-09-23 13:51       ` Michael Matz
  2020-09-23 16:52         ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Matz @ 2020-09-23 13:51 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Hans-Peter Nilsson, Fangrui Song, Binutils

Hello,

On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:

> > I think that:
> >
> > >  .section .text,"ax"
> > >    ...
> > >  foo:
> > >    ...
> > >  .retain
> > >  retained_fn:
> > >    ...
> >
> > is some nice syntactic sugar compared to:
> >
> > >  .section .text,"ax"
> > >    ...
> > >  foo:
> > >    ...
> > >  .section .text,"axR"
> > >  retained_fn:
> > >    ...
> >
> > It's also partly for convenience; we have other directives which are
> > synonyms or short-hand for each other.
> >
> 
> You don't need to keep the whole section when only one symbol should
> be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> right thing with
> 
> .section .text,"ax"
>    ...
> foo:
>   ...
>  .section .text,"axR"
> 
>  retained_fn:
> 
> where foo can be dropped and retained_fn will be kept.

This is not what we discussed at the ABI list, the flag is per section, so 
either the whole section is retained or not.  What you describe is 
something else that would work on a per symbol basis, which would have to 
be specified in a different way and might or might not be a good idea.  
But let's not conflate these two.

About the .retain syntactic sugar: I also think it's not necessary, the 
.section directive with R flag merging is good enough IMHO.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 12:13 ` Jozef Lawrynowicz
@ 2020-09-23 13:59   ` Alan Modra
  2020-09-23 16:54     ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: Alan Modra @ 2020-09-23 13:59 UTC (permalink / raw)
  To: binutils

On Wed, Sep 23, 2020 at 01:13:48PM +0100, Jozef Lawrynowicz wrote:
> Attached a revised patch:
> - Removed mmix-*-* XFAILs
> - Fixed SHF_GNU_RETAIN being clobbered when using the .section directive
>   without the "R" flag, after the section has previously been marked
>   with SHF_GNU_RETAIN. Added tests for this behavior.

In my quick scan over your patch, I didn't see anything that would set
ELFOSABI_GNU.  Since SHF_GNU_RETAIN is in the SHF_MASKOS range,
generating sections with the flag set should also set OSABI, and
if an object has the wrong OSABI you can't interpret that bit as
SHF_GNU_RETAIN.  See has_gnu_osabi for the way this is handled in
bfd.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 13:51       ` Michael Matz
@ 2020-09-23 16:52         ` Jozef Lawrynowicz
  2020-09-23 17:13           ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23 16:52 UTC (permalink / raw)
  To: Michael Matz; +Cc: H.J. Lu, Binutils

On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> Hello,
> 
> On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> 
> > > I think that:
> > >
> > > >  .section .text,"ax"
> > > >    ...
> > > >  foo:
> > > >    ...
> > > >  .retain
> > > >  retained_fn:
> > > >    ...
> > >
> > > is some nice syntactic sugar compared to:
> > >
> > > >  .section .text,"ax"
> > > >    ...
> > > >  foo:
> > > >    ...
> > > >  .section .text,"axR"
> > > >  retained_fn:
> > > >    ...
> > >
> > > It's also partly for convenience; we have other directives which are
> > > synonyms or short-hand for each other.
> > >
> > 
> > You don't need to keep the whole section when only one symbol should
> > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > right thing with
> > 
> > .section .text,"ax"
> >    ...
> > foo:
> >   ...
> >  .section .text,"axR"
> > 
> >  retained_fn:
> > 
> > where foo can be dropped and retained_fn will be kept.
> 
> This is not what we discussed at the ABI list, the flag is per section, so 
> either the whole section is retained or not.  What you describe is 
> something else that would work on a per symbol basis, which would have to 
> be specified in a different way and might or might not be a good idea.  
> But let's not conflate these two.

Also, the linker cannot currently dissect a section and remove a
particular unused symbol anyway. Since garbage collection only operates
on the section level, marking the section itself as "retained" seems
most appropriate.

As an aside.. we would run into limitations in the ELF format if trying
to mark the symbol itself as "retained". You cannot define "retain" as a
new symbol type or binding, because there is not a one-to-one mapping of
"retain" to the existing symbol types and bindings i.e. a retained
symbol might be STT_OBJECT or STT_FUNC, or STB_LOCAL or STB_GLOBAL.
st_other could be another place to store the requirement to "retain" a
symbol, but all those available bits are used up (albeit some
unofficially).

I'm not saying there's no way it could be done, but these are the
hurdles I discovered when considering that path to implementing the
"retain" behavior.

> About the .retain syntactic sugar: I also think it's not necessary, the 
> .section directive with R flag merging is good enough IMHO.

I'm OK with removing the .retain directive, since there is some
consensus it is not necessary. Also, I thought it made life easier for
GCC to mark sections as retained by omitting the section name from the
directive, but I've discovered a way around that now.

Thanks,
Jozef

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 13:59   ` Alan Modra
@ 2020-09-23 16:54     ` Jozef Lawrynowicz
  0 siblings, 0 replies; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23 16:54 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On Wed, Sep 23, 2020 at 11:29:05PM +0930, Alan Modra via Binutils wrote:
> On Wed, Sep 23, 2020 at 01:13:48PM +0100, Jozef Lawrynowicz wrote:
> > Attached a revised patch:
> > - Removed mmix-*-* XFAILs
> > - Fixed SHF_GNU_RETAIN being clobbered when using the .section directive
> >   without the "R" flag, after the section has previously been marked
> >   with SHF_GNU_RETAIN. Added tests for this behavior.
> 
> In my quick scan over your patch, I didn't see anything that would set
> ELFOSABI_GNU.  Since SHF_GNU_RETAIN is in the SHF_MASKOS range,
> generating sections with the flag set should also set OSABI, and
> if an object has the wrong OSABI you can't interpret that bit as
> SHF_GNU_RETAIN.  See has_gnu_osabi for the way this is handled in
> bfd.

Ah yes, I'll fix that.

Thanks,
Jozef

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 16:52         ` Jozef Lawrynowicz
@ 2020-09-23 17:13           ` H.J. Lu
  2020-09-23 18:47             ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-23 17:13 UTC (permalink / raw)
  To: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > Hello,
> >
> > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> >
> > > > I think that:
> > > >
> > > > >  .section .text,"ax"
> > > > >    ...
> > > > >  foo:
> > > > >    ...
> > > > >  .retain
> > > > >  retained_fn:
> > > > >    ...
> > > >
> > > > is some nice syntactic sugar compared to:
> > > >
> > > > >  .section .text,"ax"
> > > > >    ...
> > > > >  foo:
> > > > >    ...
> > > > >  .section .text,"axR"
> > > > >  retained_fn:
> > > > >    ...
> > > >
> > > > It's also partly for convenience; we have other directives which are
> > > > synonyms or short-hand for each other.
> > > >
> > >
> > > You don't need to keep the whole section when only one symbol should
> > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > right thing with
> > >
> > > .section .text,"ax"
> > >    ...
> > > foo:
> > >   ...
> > >  .section .text,"axR"
> > >
> > >  retained_fn:
> > >
> > > where foo can be dropped and retained_fn will be kept.
> >
> > This is not what we discussed at the ABI list, the flag is per section, so
> > either the whole section is retained or not.  What you describe is
> > something else that would work on a per symbol basis, which would have to
> > be specified in a different way and might or might not be a good idea.
> > But let's not conflate these two.
>
> Also, the linker cannot currently dissect a section and remove a
> particular unused symbol anyway. Since garbage collection only operates
> on the section level, marking the section itself as "retained" seems
> most appropriate.

It can be done.  If you put your branch on

https://gitlab.com/x86-binutils/binutils-gdb

I can help you implement it.

> As an aside.. we would run into limitations in the ELF format if trying
> to mark the symbol itself as "retained". You cannot define "retain" as a
> new symbol type or binding, because there is not a one-to-one mapping of
> "retain" to the existing symbol types and bindings i.e. a retained
> symbol might be STT_OBJECT or STT_FUNC, or STB_LOCAL or STB_GLOBAL.
> st_other could be another place to store the requirement to "retain" a
> symbol, but all those available bits are used up (albeit some
> unofficially).
>
> I'm not saying there's no way it could be done, but these are the
> hurdles I discovered when considering that path to implementing the
> "retain" behavior.
>
> > About the .retain syntactic sugar: I also think it's not necessary, the
> > .section directive with R flag merging is good enough IMHO.
>
> I'm OK with removing the .retain directive, since there is some
> consensus it is not necessary. Also, I thought it made life easier for
> GCC to mark sections as retained by omitting the section name from the
> directive, but I've discovered a way around that now.
>
> Thanks,
> Jozef



-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 17:13           ` H.J. Lu
@ 2020-09-23 18:47             ` Jozef Lawrynowicz
  2020-09-23 19:03               ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23 18:47 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > Hello,
> > >
> > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > >
> > > > > I think that:
> > > > >
> > > > > >  .section .text,"ax"
> > > > > >    ...
> > > > > >  foo:
> > > > > >    ...
> > > > > >  .retain
> > > > > >  retained_fn:
> > > > > >    ...
> > > > >
> > > > > is some nice syntactic sugar compared to:
> > > > >
> > > > > >  .section .text,"ax"
> > > > > >    ...
> > > > > >  foo:
> > > > > >    ...
> > > > > >  .section .text,"axR"
> > > > > >  retained_fn:
> > > > > >    ...
> > > > >
> > > > > It's also partly for convenience; we have other directives which are
> > > > > synonyms or short-hand for each other.
> > > > >
> > > >
> > > > You don't need to keep the whole section when only one symbol should
> > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > right thing with
> > > >
> > > > .section .text,"ax"
> > > >    ...
> > > > foo:
> > > >   ...
> > > >  .section .text,"axR"
> > > >
> > > >  retained_fn:
> > > >
> > > > where foo can be dropped and retained_fn will be kept.
> > >
> > > This is not what we discussed at the ABI list, the flag is per section, so
> > > either the whole section is retained or not.  What you describe is
> > > something else that would work on a per symbol basis, which would have to
> > > be specified in a different way and might or might not be a good idea.
> > > But let's not conflate these two.
> >
> > Also, the linker cannot currently dissect a section and remove a
> > particular unused symbol anyway. Since garbage collection only operates
> > on the section level, marking the section itself as "retained" seems
> > most appropriate.
> 
> It can be done.  If you put your branch on
> 
> https://gitlab.com/x86-binutils/binutils-gdb
> 
> I can help you implement it.

It's not something I have time to look into at the moment, for now the
aim is just to prevent garbage collection of sections.

However, it would certainly be a useful enhancement for the linker, and
is something I would be interested in working on in the future, so I
appreciate the offer.

Thanks,
Jozef

> 
> > As an aside.. we would run into limitations in the ELF format if trying
> > to mark the symbol itself as "retained". You cannot define "retain" as a
> > new symbol type or binding, because there is not a one-to-one mapping of
> > "retain" to the existing symbol types and bindings i.e. a retained
> > symbol might be STT_OBJECT or STT_FUNC, or STB_LOCAL or STB_GLOBAL.
> > st_other could be another place to store the requirement to "retain" a
> > symbol, but all those available bits are used up (albeit some
> > unofficially).
> >
> > I'm not saying there's no way it could be done, but these are the
> > hurdles I discovered when considering that path to implementing the
> > "retain" behavior.
> >
> > > About the .retain syntactic sugar: I also think it's not necessary, the
> > > .section directive with R flag merging is good enough IMHO.
> >
> > I'm OK with removing the .retain directive, since there is some
> > consensus it is not necessary. Also, I thought it made life easier for
> > GCC to mark sections as retained by omitting the section name from the
> > directive, but I've discovered a way around that now.
> >
> > Thanks,
> > Jozef
> 
> 
> 
> -- 
> H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 18:47             ` Jozef Lawrynowicz
@ 2020-09-23 19:03               ` H.J. Lu
  2020-09-23 20:04                 ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-23 19:03 UTC (permalink / raw)
  To: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > Hello,
> > > >
> > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > >
> > > > > > I think that:
> > > > > >
> > > > > > >  .section .text,"ax"
> > > > > > >    ...
> > > > > > >  foo:
> > > > > > >    ...
> > > > > > >  .retain
> > > > > > >  retained_fn:
> > > > > > >    ...
> > > > > >
> > > > > > is some nice syntactic sugar compared to:
> > > > > >
> > > > > > >  .section .text,"ax"
> > > > > > >    ...
> > > > > > >  foo:
> > > > > > >    ...
> > > > > > >  .section .text,"axR"
> > > > > > >  retained_fn:
> > > > > > >    ...
> > > > > >
> > > > > > It's also partly for convenience; we have other directives which are
> > > > > > synonyms or short-hand for each other.
> > > > > >
> > > > >
> > > > > You don't need to keep the whole section when only one symbol should
> > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > right thing with
> > > > >
> > > > > .section .text,"ax"
> > > > >    ...
> > > > > foo:
> > > > >   ...
> > > > >  .section .text,"axR"
> > > > >
> > > > >  retained_fn:
> > > > >
> > > > > where foo can be dropped and retained_fn will be kept.
> > > >
> > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > either the whole section is retained or not.  What you describe is
> > > > something else that would work on a per symbol basis, which would have to
> > > > be specified in a different way and might or might not be a good idea.
> > > > But let's not conflate these two.
> > >
> > > Also, the linker cannot currently dissect a section and remove a
> > > particular unused symbol anyway. Since garbage collection only operates
> > > on the section level, marking the section itself as "retained" seems
> > > most appropriate.
> >
> > It can be done.  If you put your branch on
> >
> > https://gitlab.com/x86-binutils/binutils-gdb
> >
> > I can help you implement it.
>
> It's not something I have time to look into at the moment, for now the
> aim is just to prevent garbage collection of sections.

Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
to the framework.  Check how SHF_GNU_MBIND works.

> However, it would certainly be a useful enhancement for the linker, and
> is something I would be interested in working on in the future, so I
> appreciate the offer.
>

-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 19:03               ` H.J. Lu
@ 2020-09-23 20:04                 ` Jozef Lawrynowicz
  2020-09-23 20:17                   ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-23 20:04 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > Hello,
> > > > >
> > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > >
> > > > > > > I think that:
> > > > > > >
> > > > > > > >  .section .text,"ax"
> > > > > > > >    ...
> > > > > > > >  foo:
> > > > > > > >    ...
> > > > > > > >  .retain
> > > > > > > >  retained_fn:
> > > > > > > >    ...
> > > > > > >
> > > > > > > is some nice syntactic sugar compared to:
> > > > > > >
> > > > > > > >  .section .text,"ax"
> > > > > > > >    ...
> > > > > > > >  foo:
> > > > > > > >    ...
> > > > > > > >  .section .text,"axR"
> > > > > > > >  retained_fn:
> > > > > > > >    ...
> > > > > > >
> > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > synonyms or short-hand for each other.
> > > > > > >
> > > > > >
> > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > right thing with
> > > > > >
> > > > > > .section .text,"ax"
> > > > > >    ...
> > > > > > foo:
> > > > > >   ...
> > > > > >  .section .text,"axR"
> > > > > >
> > > > > >  retained_fn:
> > > > > >
> > > > > > where foo can be dropped and retained_fn will be kept.
> > > > >
> > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > either the whole section is retained or not.  What you describe is
> > > > > something else that would work on a per symbol basis, which would have to
> > > > > be specified in a different way and might or might not be a good idea.
> > > > > But let's not conflate these two.
> > > >
> > > > Also, the linker cannot currently dissect a section and remove a
> > > > particular unused symbol anyway. Since garbage collection only operates
> > > > on the section level, marking the section itself as "retained" seems
> > > > most appropriate.
> > >
> > > It can be done.  If you put your branch on
> > >
> > > https://gitlab.com/x86-binutils/binutils-gdb
> > >
> > > I can help you implement it.
> >
> > It's not something I have time to look into at the moment, for now the
> > aim is just to prevent garbage collection of sections.
> 
> Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> to the framework.  Check how SHF_GNU_MBIND works.

Sorry, I don't understand.

Are you saying that LD already supports the garbage collection of
individual unused symbol definitions from input sections? Whilst
retaining other symbol definitions which are required by the program?
I cannot find any reference to this.

How does that relate to SHF_GNU_MBIND? I looked at all the references
to "mbind" in Binutils and nothing seemed related garbage collection of
sections, since SHF_GNU_MBIND is just used to indicate a particular
section should be placed in a special memory area.

Thanks,
Jozef

> 
> > However, it would certainly be a useful enhancement for the linker, and
> > is something I would be interested in working on in the future, so I
> > appreciate the offer.
> >
> 
> -- 
> H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 20:04                 ` Jozef Lawrynowicz
@ 2020-09-23 20:17                   ` H.J. Lu
  2020-09-23 23:29                     ` Fangrui Song
  2020-09-24 13:18                     ` H.J. Lu
  0 siblings, 2 replies; 37+ messages in thread
From: H.J. Lu @ 2020-09-23 20:17 UTC (permalink / raw)
  To: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > Hello,
> > > > > >
> > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > >
> > > > > > > > I think that:
> > > > > > > >
> > > > > > > > >  .section .text,"ax"
> > > > > > > > >    ...
> > > > > > > > >  foo:
> > > > > > > > >    ...
> > > > > > > > >  .retain
> > > > > > > > >  retained_fn:
> > > > > > > > >    ...
> > > > > > > >
> > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > >
> > > > > > > > >  .section .text,"ax"
> > > > > > > > >    ...
> > > > > > > > >  foo:
> > > > > > > > >    ...
> > > > > > > > >  .section .text,"axR"
> > > > > > > > >  retained_fn:
> > > > > > > > >    ...
> > > > > > > >
> > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > synonyms or short-hand for each other.
> > > > > > > >
> > > > > > >
> > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > right thing with
> > > > > > >
> > > > > > > .section .text,"ax"
> > > > > > >    ...
> > > > > > > foo:
> > > > > > >   ...
> > > > > > >  .section .text,"axR"
> > > > > > >
> > > > > > >  retained_fn:
> > > > > > >
> > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > >
> > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > either the whole section is retained or not.  What you describe is
> > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > But let's not conflate these two.
> > > > >
> > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > on the section level, marking the section itself as "retained" seems
> > > > > most appropriate.
> > > >
> > > > It can be done.  If you put your branch on
> > > >
> > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > >
> > > > I can help you implement it.
> > >
> > > It's not something I have time to look into at the moment, for now the
> > > aim is just to prevent garbage collection of sections.
> >
> > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > to the framework.  Check how SHF_GNU_MBIND works.
>
> Sorry, I don't understand.
>
> Are you saying that LD already supports the garbage collection of
> individual unused symbol definitions from input sections? Whilst
> retaining other symbol definitions which are required by the program?
> I cannot find any reference to this.
>
> How does that relate to SHF_GNU_MBIND? I looked at all the references
> to "mbind" in Binutils and nothing seemed related garbage collection of
> sections, since SHF_GNU_MBIND is just used to indicate a particular
> section should be placed in a special memory area.

For

section .text,"ax"
   ...
foo:
  ...
 .section .text,"axR"
retained_fn:

you need to create a new .text section with SHF_GNU_RETAIN for
retained_fn.   See get_section in obj-elf.c.  If you want to avoid
merging .text section with SHF_GNU_RETAIN with other .text
sections by ld -r, linker needs to distinguish sections of the
same name with and without SHF_GNU_RETAIN.

-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 20:17                   ` H.J. Lu
@ 2020-09-23 23:29                     ` Fangrui Song
  2020-09-24 11:39                       ` Jozef Lawrynowicz
  2020-09-24 13:27                       ` Michael Matz
  2020-09-24 13:18                     ` H.J. Lu
  1 sibling, 2 replies; 37+ messages in thread
From: Fangrui Song @ 2020-09-23 23:29 UTC (permalink / raw)
  To: jozef.l; +Cc: Michael Matz, Binutils, H.J. Lu, ccoutant

Hi Jozef,

I saw your proposal https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
I did not subscribe to gnu-gabi before yesterday so it is inconvenient for me to
reply there. Since SHF_GNU_RETAIN is a new feature, and we already have facility
for making arbitrary sections alive with R_*_NONE, can you highlight the selling
point of a new flag?

Copying me previous reply here
> We already have a way to create an artificial reference:
> 
>   .reloc ., R_X86_64_NONE, target_symbol
> 
> If we allow a relocation number for the second operand
> 
>   .reloc ., 0, target_symbol
> 
> this will be generic. You can insert the directives in a GC root (e.g.
> _start or a symbol referenced by -u or maybe an .init_array)

If you do not want to touch the section containing the -e (--entry) symbol, you
can use:

   .section .init_array.1,"a",@init_array
   .reloc ., R_X86_64_NONE, retained_section

(I find that gold has an internal error with such a relocation.)
But GNU ld should have been supported this for a very long time.

(I added these directives to llvm last year: https://reviews.llvm.org/D62014 )

---

For a new section flag, there are a bunch of things needing thoughts

* assembler

The .retain directive seems to be discouraged... For section flags:

.section .foo,"a"
.section .foo,"aR"        # is this a new section
.pushsection .foo,"aR"    # is this a new section

Does the compiler need to remember that a section has the flag?
(Think how this works with __attribute__((section(...))); many asm streamers are
one-pass)

* linker
- What does -r do on two sections of the same, one with the flag and the other
without? (as HJ mentioned)
- Does the output section have the flag?
- Does the flag retain other sections in the same section group?


On 2020-09-23, H.J. Lu via Binutils wrote:
>On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
><jozef.l@mittosystems.com> wrote:
>>
>> On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
>> > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
>> > <jozef.l@mittosystems.com> wrote:
>> > >
>> > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
>> > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
>> > > > <jozef.l@mittosystems.com> wrote:
>> > > > >
>> > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
>> > > > > > Hello,
>> > > > > >
>> > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
>> > > > > >
>> > > > > > > > I think that:
>> > > > > > > >
>> > > > > > > > >  .section .text,"ax"
>> > > > > > > > >    ...
>> > > > > > > > >  foo:
>> > > > > > > > >    ...
>> > > > > > > > >  .retain
>> > > > > > > > >  retained_fn:
>> > > > > > > > >    ...
>> > > > > > > >
>> > > > > > > > is some nice syntactic sugar compared to:
>> > > > > > > >
>> > > > > > > > >  .section .text,"ax"
>> > > > > > > > >    ...
>> > > > > > > > >  foo:
>> > > > > > > > >    ...
>> > > > > > > > >  .section .text,"axR"
>> > > > > > > > >  retained_fn:
>> > > > > > > > >    ...
>> > > > > > > >
>> > > > > > > > It's also partly for convenience; we have other directives which are
>> > > > > > > > synonyms or short-hand for each other.
>> > > > > > > >
>> > > > > > >
>> > > > > > > You don't need to keep the whole section when only one symbol should
>> > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
>> > > > > > > right thing with
>> > > > > > >
>> > > > > > > .section .text,"ax"
>> > > > > > >    ...
>> > > > > > > foo:
>> > > > > > >   ...
>> > > > > > >  .section .text,"axR"
>> > > > > > >
>> > > > > > >  retained_fn:
>> > > > > > >
>> > > > > > > where foo can be dropped and retained_fn will be kept.
>> > > > > >
>> > > > > > This is not what we discussed at the ABI list, the flag is per section, so
>> > > > > > either the whole section is retained or not.  What you describe is
>> > > > > > something else that would work on a per symbol basis, which would have to
>> > > > > > be specified in a different way and might or might not be a good idea.
>> > > > > > But let's not conflate these two.
>> > > > >
>> > > > > Also, the linker cannot currently dissect a section and remove a
>> > > > > particular unused symbol anyway. Since garbage collection only operates
>> > > > > on the section level, marking the section itself as "retained" seems
>> > > > > most appropriate.
>> > > >
>> > > > It can be done.  If you put your branch on
>> > > >
>> > > > https://gitlab.com/x86-binutils/binutils-gdb
>> > > >
>> > > > I can help you implement it.
>> > >
>> > > It's not something I have time to look into at the moment, for now the
>> > > aim is just to prevent garbage collection of sections.
>> >
>> > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
>> > to the framework.  Check how SHF_GNU_MBIND works.
>>
>> Sorry, I don't understand.
>>
>> Are you saying that LD already supports the garbage collection of
>> individual unused symbol definitions from input sections? Whilst
>> retaining other symbol definitions which are required by the program?
>> I cannot find any reference to this.
>>
>> How does that relate to SHF_GNU_MBIND? I looked at all the references
>> to "mbind" in Binutils and nothing seemed related garbage collection of
>> sections, since SHF_GNU_MBIND is just used to indicate a particular
>> section should be placed in a special memory area.
>
>For
>
>section .text,"ax"
>   ...
>foo:
>  ...
> .section .text,"axR"
>retained_fn:
>
>you need to create a new .text section with SHF_GNU_RETAIN for
>retained_fn.   See get_section in obj-elf.c.  If you want to avoid
>merging .text section with SHF_GNU_RETAIN with other .text
>sections by ld -r, linker needs to distinguish sections of the
>same name with and without SHF_GNU_RETAIN.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 23:29                     ` Fangrui Song
@ 2020-09-24 11:39                       ` Jozef Lawrynowicz
  2020-09-24 19:06                         ` Fangrui Song
  2020-09-24 13:27                       ` Michael Matz
  1 sibling, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-24 11:39 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Michael Matz, Binutils, H.J. Lu, ccoutant

On Wed, Sep 23, 2020 at 04:29:43PM -0700, Fangrui Song wrote:
> Hi Jozef,

Hi Fangrui,

> I saw your proposal https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
> I did not subscribe to gnu-gabi before yesterday so it is inconvenient for me to
> reply there. Since SHF_GNU_RETAIN is a new feature, and we already have facility
> for making arbitrary sections alive with R_*_NONE, can you highlight the selling
> point of a new flag?
> 
> Copying me previous reply here
> > We already have a way to create an artificial reference:
> > 
> >   .reloc ., R_X86_64_NONE, target_symbol
> > 
> > If we allow a relocation number for the second operand
> > 
> >   .reloc ., 0, target_symbol
> > 
> > this will be generic. You can insert the directives in a GC root (e.g.
> > _start or a symbol referenced by -u or maybe an .init_array)
> 
> If you do not want to touch the section containing the -e (--entry) symbol, you
> can use:
> 
>   .section .init_array.1,"a",@init_array
>   .reloc ., R_X86_64_NONE, retained_section
> 
> (I find that gold has an internal error with such a relocation.)
> But GNU ld should have been supported this for a very long time.
> 
> (I added these directives to llvm last year: https://reviews.llvm.org/D62014 )
> 

The fact that this relies on the compiler knowing a specific section
will be present in a linker script, when we are dealing with such a
broad ecosystem of targets and operating systems, makes me uneasy. The
functionality simply breaks if the user has a custom linker script which
does not have .init_array.

Many embedded applications can be written without requiring this
section. If someone has written their linker script from scratch, only
including the section directives for the sections they actually need,
why must we enforce that they have a .init_array input section rule just
so they can make use of the "retain" attribute. It doesn't make sense -
.init_array and "retain" are not related.

Even if this approach would work and pick the right section, I think
it is nicer for the user for the "retain" attribute to have a
dedicated ELF construct which describes the requirement to retain the
section, instead of using an existing construct whose purpose is not
related.

Your average user is going to be very confused why there are relocs in
section X which point to various symbols in their code. If they have
written the entire application, they might be able to infer that it is
the "retain" attribute which generated these relocs, but if someone else
wrote the code or the code is from a library or SDK it will not be
clear.

Ok we could maybe name a reloc like BFD_RELOC_RETAIN, but then what
would the description be?
  This relocation type does not actually perform any relocation action,
  but is used to indicate that the symbol it references should not be
  discarded by linker garbage collection. It must be placed in a section
  which will definitely be present in the linked output file, and not be
  subject to garbage collection, otherwise it will not have any effect.

Can you tell me why it is preferable to use the relocation mechanism to
implement this, instead of a precisely defined new section flag?

Why must we look to workarounds to implement something like this
anyway?  We can work out the details of a new section flag, and ensure
it is precisely specified to ensure robustness, and then developers can
benefit from understanding more about how their program has been put
together.

Do we want to make life easier for ourselves, or easier for our users?

I get that ABI changes can be a bit disruptive, but this new flag in
particular really isn't complicated anyway.

> ---
> 
> For a new section flag, there are a bunch of things needing thoughts
> 
> * assembler
> 
> The .retain directive seems to be discouraged... For section flags:
> 
> .section .foo,"a"
> .section .foo,"aR"        # is this a new section
> .pushsection .foo,"aR"    # is this a new section

No they are not new sections. From my original proposal:

> Alternatively, the "R" flag is recognized by the "flags" argument to the
> .section directive and will apply SHF_GNU_RETAIN to that section.
> It is intended that SHF_GNU_RETAIN does not interfere with any validation when
> switching to a section. It can be used to augment the section flags in a section
> which has already been created.

When you have two .section directives for the same section, GAS
"switches" between them instead of creating new sections, which is what
I referred to above.

This is why the .retain directive more precisely describes what is
happening. The compiler is telling the assembler that the section
containing the declaration of the function or data symbol should have
the SHF_GNU_RETAIN flag applied.

> 
> Does the compiler need to remember that a section has the flag?
> (Think how this works with __attribute__((section(...))); many asm streamers are
> one-pass)

The compiler does not need to worry about sections beyond getting the
name of the section the declaration is in. The "retain" attribute just
means that the section containing the declaration of the function or
data object must be retained, so it emits a directive to describe that.
Once the assembler has set SHF_GNU_RETAIN on a section, it will not be
unset.

I expect the most common use case to actually be when either the
"section" attribute has been used, or the -f{function,data}-sections GCC
options have been passed. If the user is trying to make the most out of
garbage collection, they should be using -f{function,data}-sections.

> 
> * linker
> - What does -r do on two sections of the same, one with the flag and the other
> without? (as HJ mentioned)

To reply to H.J. as well for this point:
I don't think this warrants any special behavior, SHF_GNU_RETAIN doesn't
need to change the behavior of section merging. The user should put the
object to retain in it's own section if they don't want large parts of
their program to possibly be unnecessarily retained. The unique section
name they give their SHF_GNU_RETAIN section will not be merged into a
general output section name until they perform the final non-relocatable
link.

A section with SHF_GNU_RETAIN applied is being retained because it
contains some information that is important to the program. So wherever
the that information ends up needs to be retained.

> - Does the output section have the flag?

SHF_GNU_RETAIN is applied to an input section.
To ensure the input section is retained, SHF_GNU_RETAIN must be applied
to any section that input section is merged with. The flag doesn't get
removed from output sections.

> - Does the flag retain other sections in the same section group?

Yes.
From the description on section groups from the ELF spec:
  ... such groups must be included or omitted from the linked
  object as a unit.

I think potentially the only confusing part of any section flag merging
behavior is the fact that the assembly code might have different
.section directives for the same section, some with "R" and some without
(+1 for a .retain directive ;)).
Once the assembler has emitted its output, the SHF_GNU_RETAIN flag
applied to an input section behaves like any other section flag.
There is only one line of linker code which does anything specific with
SHF_GNU_RETAIN, and that is the code in bfd/elflink.c to "gc_mark" the
section.

Thanks,
Jozef

> 
> 
> On 2020-09-23, H.J. Lu via Binutils wrote:
> > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > > 
> > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > Hello,
> > > > > > > >
> > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > >
> > > > > > > > > > I think that:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .retain
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > right thing with
> > > > > > > > >
> > > > > > > > > .section .text,"ax"
> > > > > > > > >    ...
> > > > > > > > > foo:
> > > > > > > > >   ...
> > > > > > > > >  .section .text,"axR"
> > > > > > > > >
> > > > > > > > >  retained_fn:
> > > > > > > > >
> > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > >
> > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > But let's not conflate these two.
> > > > > > >
> > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > most appropriate.
> > > > > >
> > > > > > It can be done.  If you put your branch on
> > > > > >
> > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > >
> > > > > > I can help you implement it.
> > > > >
> > > > > It's not something I have time to look into at the moment, for now the
> > > > > aim is just to prevent garbage collection of sections.
> > > >
> > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > 
> > > Sorry, I don't understand.
> > > 
> > > Are you saying that LD already supports the garbage collection of
> > > individual unused symbol definitions from input sections? Whilst
> > > retaining other symbol definitions which are required by the program?
> > > I cannot find any reference to this.
> > > 
> > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > section should be placed in a special memory area.
> > 
> > For
> > 
> > section .text,"ax"
> >   ...
> > foo:
> >  ...
> > .section .text,"axR"
> > retained_fn:
> > 
> > you need to create a new .text section with SHF_GNU_RETAIN for
> > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > merging .text section with SHF_GNU_RETAIN with other .text
> > sections by ld -r, linker needs to distinguish sections of the
> > same name with and without SHF_GNU_RETAIN.


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 20:17                   ` H.J. Lu
  2020-09-23 23:29                     ` Fangrui Song
@ 2020-09-24 13:18                     ` H.J. Lu
  2020-09-24 13:49                       ` Jozef Lawrynowicz
  1 sibling, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-24 13:18 UTC (permalink / raw)
  To: Michael Matz, Binutils

On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > Hello,
> > > > > > >
> > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > >
> > > > > > > > > I think that:
> > > > > > > > >
> > > > > > > > > >  .section .text,"ax"
> > > > > > > > > >    ...
> > > > > > > > > >  foo:
> > > > > > > > > >    ...
> > > > > > > > > >  .retain
> > > > > > > > > >  retained_fn:
> > > > > > > > > >    ...
> > > > > > > > >
> > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > >
> > > > > > > > > >  .section .text,"ax"
> > > > > > > > > >    ...
> > > > > > > > > >  foo:
> > > > > > > > > >    ...
> > > > > > > > > >  .section .text,"axR"
> > > > > > > > > >  retained_fn:
> > > > > > > > > >    ...
> > > > > > > > >
> > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > >
> > > > > > > >
> > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > right thing with
> > > > > > > >
> > > > > > > > .section .text,"ax"
> > > > > > > >    ...
> > > > > > > > foo:
> > > > > > > >   ...
> > > > > > > >  .section .text,"axR"
> > > > > > > >
> > > > > > > >  retained_fn:
> > > > > > > >
> > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > >
> > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > But let's not conflate these two.
> > > > > >
> > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > most appropriate.
> > > > >
> > > > > It can be done.  If you put your branch on
> > > > >
> > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > >
> > > > > I can help you implement it.
> > > >
> > > > It's not something I have time to look into at the moment, for now the
> > > > aim is just to prevent garbage collection of sections.
> > >
> > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > to the framework.  Check how SHF_GNU_MBIND works.
> >
> > Sorry, I don't understand.
> >
> > Are you saying that LD already supports the garbage collection of
> > individual unused symbol definitions from input sections? Whilst
> > retaining other symbol definitions which are required by the program?
> > I cannot find any reference to this.
> >
> > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > to "mbind" in Binutils and nothing seemed related garbage collection of
> > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > section should be placed in a special memory area.
>
> For
>
> section .text,"ax"
>    ...
> foo:
>   ...
>  .section .text,"axR"
> retained_fn:
>
> you need to create a new .text section with SHF_GNU_RETAIN for
> retained_fn.   See get_section in obj-elf.c.  If you want to avoid

See users/hjl/elf/master branch at:

https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master

I removed the .retain directive.

> merging .text section with SHF_GNU_RETAIN with other .text
> sections by ld -r, linker needs to distinguish sections of the
> same name with and without SHF_GNU_RETAIN.
>
> --
> H.J.



-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-23 23:29                     ` Fangrui Song
  2020-09-24 11:39                       ` Jozef Lawrynowicz
@ 2020-09-24 13:27                       ` Michael Matz
  1 sibling, 0 replies; 37+ messages in thread
From: Michael Matz @ 2020-09-24 13:27 UTC (permalink / raw)
  To: Fangrui Song; +Cc: jozef.l, Binutils, H.J. Lu, ccoutant

Hello,

On Wed, 23 Sep 2020, Fangrui Song wrote:

> Since SHF_GNU_RETAIN is a new feature, and we already have facility for 
> making arbitrary sections alive with R_*_NONE, can you highlight the 
> selling point of a new flag?

I wouldn't call this a facility.  I call it a hack that accidentally works 
for this purpose.

> Copying me previous reply here
> > We already have a way to create an artificial reference:
> > 
> >   .reloc ., R_X86_64_NONE, target_symbol
> > 
> > If we allow a relocation number for the second operand
> > 
> >   .reloc ., 0, target_symbol
> > 
> > this will be generic. You can insert the directives in a GC root (e.g.
> > _start or a symbol referenced by -u or maybe an .init_array)
> 
> If you do not want to touch the section containing the -e (--entry) symbol,
> you
> can use:
> 
>   .section .init_array.1,"a",@init_array
>   .reloc ., R_X86_64_NONE, retained_section

And what makes .init_array be retained?  To which data item does the 
relocation apply, what if .init_array is empty?  I think using this to 
force sections be retained is a terrible idea (I was split minds about 
calling this idea cute vs. terrible ;-) ).

> For a new section flag, there are a bunch of things needing thoughts

I think the answer to each of these things is obvious:

> * assembler
> 
> The .retain directive seems to be discouraged... For section flags:
> 
> .section .foo,"a"
> .section .foo,"aR"        # is this a new section
> .pushsection .foo,"aR"    # is this a new section
> 
> Does the compiler need to remember that a section has the flag?

Why should it need to remember?  (E.g. GCC does, but why would it matter?)  
The assembler merges the flags, no need to remember things.

> * linker
> - What does -r do on two sections of the same, one with the flag and the other
> without? (as HJ mentioned)

It merges the flag with logical or.

> - Does the output section have the flag?

Yes.

> - Does the flag retain other sections in the same section group?

Yes.


Ciao,
Michael.

> 
> 
> On 2020-09-23, H.J. Lu via Binutils wrote:
> > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > > 
> > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > Hello,
> > > > > > > >
> > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > >
> > > > > > > > > > I think that:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .retain
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > It's also partly for convenience; we have other directives
> > > which are
> > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > You don't need to keep the whole section when only one symbol
> > > should
> > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld
> > > should do the
> > > > > > > > > right thing with
> > > > > > > > >
> > > > > > > > > .section .text,"ax"
> > > > > > > > >    ...
> > > > > > > > > foo:
> > > > > > > > >   ...
> > > > > > > > >  .section .text,"axR"
> > > > > > > > >
> > > > > > > > >  retained_fn:
> > > > > > > > >
> > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > >
> > > > > > > > This is not what we discussed at the ABI list, the flag is per
> > > section, so
> > > > > > > > either the whole section is retained or not.  What you describe
> > > is
> > > > > > > > something else that would work on a per symbol basis, which
> > > would have to
> > > > > > > > be specified in a different way and might or might not be a good
> > > idea.
> > > > > > > > But let's not conflate these two.
> > > > > > >
> > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > particular unused symbol anyway. Since garbage collection only
> > > operates
> > > > > > > on the section level, marking the section itself as "retained"
> > > seems
> > > > > > > most appropriate.
> > > > > >
> > > > > > It can be done.  If you put your branch on
> > > > > >
> > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > >
> > > > > > I can help you implement it.
> > > > >
> > > > > It's not something I have time to look into at the moment, for now the
> > > > > aim is just to prevent garbage collection of sections.
> > > >
> > > > Linker and assembler already support it.   You just need to add
> > > SHF_GNU_RETAIN
> > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > 
> > > Sorry, I don't understand.
> > > 
> > > Are you saying that LD already supports the garbage collection of
> > > individual unused symbol definitions from input sections? Whilst
> > > retaining other symbol definitions which are required by the program?
> > > I cannot find any reference to this.
> > > 
> > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > section should be placed in a special memory area.
> > 
> > For
> > 
> > section .text,"ax"
> >   ...
> > foo:
> >  ...
> > .section .text,"axR"
> > retained_fn:
> > 
> > you need to create a new .text section with SHF_GNU_RETAIN for
> > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > merging .text section with SHF_GNU_RETAIN with other .text
> > sections by ld -r, linker needs to distinguish sections of the
> > same name with and without SHF_GNU_RETAIN.
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 13:18                     ` H.J. Lu
@ 2020-09-24 13:49                       ` Jozef Lawrynowicz
  2020-09-24 13:59                         ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-24 13:49 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Michael Matz, Binutils

On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > Hello,
> > > > > > > >
> > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > >
> > > > > > > > > > I think that:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .retain
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > >
> > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > >  foo:
> > > > > > > > > > >    ...
> > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >    ...
> > > > > > > > > >
> > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > right thing with
> > > > > > > > >
> > > > > > > > > .section .text,"ax"
> > > > > > > > >    ...
> > > > > > > > > foo:
> > > > > > > > >   ...
> > > > > > > > >  .section .text,"axR"
> > > > > > > > >
> > > > > > > > >  retained_fn:
> > > > > > > > >
> > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > >
> > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > But let's not conflate these two.
> > > > > > >
> > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > most appropriate.
> > > > > >
> > > > > > It can be done.  If you put your branch on
> > > > > >
> > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > >
> > > > > > I can help you implement it.
> > > > >
> > > > > It's not something I have time to look into at the moment, for now the
> > > > > aim is just to prevent garbage collection of sections.
> > > >
> > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > to the framework.  Check how SHF_GNU_MBIND works.
> > >
> > > Sorry, I don't understand.
> > >
> > > Are you saying that LD already supports the garbage collection of
> > > individual unused symbol definitions from input sections? Whilst
> > > retaining other symbol definitions which are required by the program?
> > > I cannot find any reference to this.
> > >
> > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > section should be placed in a special memory area.
> >
> > For
> >
> > section .text,"ax"
> >    ...
> > foo:
> >   ...
> >  .section .text,"axR"
> > retained_fn:
> >
> > you need to create a new .text section with SHF_GNU_RETAIN for
> > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> 
> See users/hjl/elf/master branch at:
> 
> https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> 
> I removed the .retain directive.

Thanks, the formalization of section flag merging in the assembler is
nice.

My only comment is that I used the "STT_*" syntax in the .type directive
instead of % because some targets didn't like the % syntax and emmited
an error. I don't remember which, maybe it was mmix-elf, in which case
we don't care :)

When I re-test I'll see if the errors pop up again.

I still need to add the GNU OSABI handling, but with that and your
patches we are probably ready to apply after a final official sign-off.

How would that work logistically, I apply my patch and you apply yours
after? Or do we align off-master and apply as one patch?

Thanks,
Jozef

> 
> > merging .text section with SHF_GNU_RETAIN with other .text
> > sections by ld -r, linker needs to distinguish sections of the
> > same name with and without SHF_GNU_RETAIN.
> >
> > --
> > H.J.
> 
> 
> 
> -- 
> H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 13:49                       ` Jozef Lawrynowicz
@ 2020-09-24 13:59                         ` H.J. Lu
  2020-09-24 16:56                           ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-24 13:59 UTC (permalink / raw)
  To: H.J. Lu, Michael Matz, Binutils

On Thu, Sep 24, 2020 at 6:49 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> > On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > > Hello,
> > > > > > > > >
> > > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > > >
> > > > > > > > > > > I think that:
> > > > > > > > > > >
> > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > >    ...
> > > > > > > > > > > >  foo:
> > > > > > > > > > > >    ...
> > > > > > > > > > > >  .retain
> > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > >    ...
> > > > > > > > > > >
> > > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > > >
> > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > >    ...
> > > > > > > > > > > >  foo:
> > > > > > > > > > > >    ...
> > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > >    ...
> > > > > > > > > > >
> > > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > > right thing with
> > > > > > > > > >
> > > > > > > > > > .section .text,"ax"
> > > > > > > > > >    ...
> > > > > > > > > > foo:
> > > > > > > > > >   ...
> > > > > > > > > >  .section .text,"axR"
> > > > > > > > > >
> > > > > > > > > >  retained_fn:
> > > > > > > > > >
> > > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > > >
> > > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > > But let's not conflate these two.
> > > > > > > >
> > > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > > most appropriate.
> > > > > > >
> > > > > > > It can be done.  If you put your branch on
> > > > > > >
> > > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > > >
> > > > > > > I can help you implement it.
> > > > > >
> > > > > > It's not something I have time to look into at the moment, for now the
> > > > > > aim is just to prevent garbage collection of sections.
> > > > >
> > > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > >
> > > > Sorry, I don't understand.
> > > >
> > > > Are you saying that LD already supports the garbage collection of
> > > > individual unused symbol definitions from input sections? Whilst
> > > > retaining other symbol definitions which are required by the program?
> > > > I cannot find any reference to this.
> > > >
> > > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > > section should be placed in a special memory area.
> > >
> > > For
> > >
> > > section .text,"ax"
> > >    ...
> > > foo:
> > >   ...
> > >  .section .text,"axR"
> > > retained_fn:
> > >
> > > you need to create a new .text section with SHF_GNU_RETAIN for
> > > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> >
> > See users/hjl/elf/master branch at:
> >
> > https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> >
> > I removed the .retain directive.
>
> Thanks, the formalization of section flag merging in the assembler is
> nice.
>
> My only comment is that I used the "STT_*" syntax in the .type directive
> instead of % because some targets didn't like the % syntax and emmited
> an error. I don't remember which, maybe it was mmix-elf, in which case
> we don't care :)

Some targets don't support @object.  %object works for all targets.

> When I re-test I'll see if the errors pop up again.
>
> I still need to add the GNU OSABI handling, but with that and your
> patches we are probably ready to apply after a final official sign-off.
>
> How would that work logistically, I apply my patch and you apply yours
> after? Or do we align off-master and apply as one patch?
>

Please get an account on gitlab.com and send me your account name.
Then you can put your branch in

https://gitlab.com/x86-binutils/binutils-gdb

and we can work together to finish it.


--
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 13:59                         ` H.J. Lu
@ 2020-09-24 16:56                           ` Jozef Lawrynowicz
  2020-09-24 17:04                             ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-24 16:56 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Michael Matz, Binutils

On Thu, Sep 24, 2020 at 06:59:07AM -0700, H.J. Lu via Binutils wrote:
> On Thu, Sep 24, 2020 at 6:49 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> > > On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > >
> > > > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > > > Hello,
> > > > > > > > > >
> > > > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > > > >
> > > > > > > > > > > > I think that:
> > > > > > > > > > > >
> > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > >    ...
> > > > > > > > > > > > >  foo:
> > > > > > > > > > > > >    ...
> > > > > > > > > > > > >  .retain
> > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > >    ...
> > > > > > > > > > > >
> > > > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > > > >
> > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > >    ...
> > > > > > > > > > > > >  foo:
> > > > > > > > > > > > >    ...
> > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > >    ...
> > > > > > > > > > > >
> > > > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > > > right thing with
> > > > > > > > > > >
> > > > > > > > > > > .section .text,"ax"
> > > > > > > > > > >    ...
> > > > > > > > > > > foo:
> > > > > > > > > > >   ...
> > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > >
> > > > > > > > > > >  retained_fn:
> > > > > > > > > > >
> > > > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > > > >
> > > > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > > > But let's not conflate these two.
> > > > > > > > >
> > > > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > > > most appropriate.
> > > > > > > >
> > > > > > > > It can be done.  If you put your branch on
> > > > > > > >
> > > > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > > > >
> > > > > > > > I can help you implement it.
> > > > > > >
> > > > > > > It's not something I have time to look into at the moment, for now the
> > > > > > > aim is just to prevent garbage collection of sections.
> > > > > >
> > > > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > > >
> > > > > Sorry, I don't understand.
> > > > >
> > > > > Are you saying that LD already supports the garbage collection of
> > > > > individual unused symbol definitions from input sections? Whilst
> > > > > retaining other symbol definitions which are required by the program?
> > > > > I cannot find any reference to this.
> > > > >
> > > > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > > > section should be placed in a special memory area.
> > > >
> > > > For
> > > >
> > > > section .text,"ax"
> > > >    ...
> > > > foo:
> > > >   ...
> > > >  .section .text,"axR"
> > > > retained_fn:
> > > >
> > > > you need to create a new .text section with SHF_GNU_RETAIN for
> > > > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > >
> > > See users/hjl/elf/master branch at:
> > >
> > > https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> > >
> > > I removed the .retain directive.
> >
> > Thanks, the formalization of section flag merging in the assembler is
> > nice.
> >
> > My only comment is that I used the "STT_*" syntax in the .type directive
> > instead of % because some targets didn't like the % syntax and emmited
> > an error. I don't remember which, maybe it was mmix-elf, in which case
> > we don't care :)
> 
> Some targets don't support @object.  %object works for all targets.

Ah yes, it is in fact the non-existent mmix-elf that can't assemble
%object but it works for all real targets.

However, some targets don't support the .bss pseudo op which is used in
your new tests, so those are failing in some cases.

Thanks,
Jozef

> 
> > When I re-test I'll see if the errors pop up again.
> >
> > I still need to add the GNU OSABI handling, but with that and your
> > patches we are probably ready to apply after a final official sign-off.
> >
> > How would that work logistically, I apply my patch and you apply yours
> > after? Or do we align off-master and apply as one patch?
> >
> 
> Please get an account on gitlab.com and send me your account name.
> Then you can put your branch in
> 
> https://gitlab.com/x86-binutils/binutils-gdb
> 
> and we can work together to finish it.
> 
> 
> --
> H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 16:56                           ` Jozef Lawrynowicz
@ 2020-09-24 17:04                             ` H.J. Lu
  2020-09-24 17:18                               ` Jozef Lawrynowicz
  0 siblings, 1 reply; 37+ messages in thread
From: H.J. Lu @ 2020-09-24 17:04 UTC (permalink / raw)
  To: H.J. Lu, Michael Matz, Binutils

On Thu, Sep 24, 2020 at 9:56 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Thu, Sep 24, 2020 at 06:59:07AM -0700, H.J. Lu via Binutils wrote:
> > On Thu, Sep 24, 2020 at 6:49 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> > > > On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > > > > Hello,
> > > > > > > > > > >
> > > > > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > > > > >
> > > > > > > > > > > > > I think that:
> > > > > > > > > > > > >
> > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >  .retain
> > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > >
> > > > > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > > > > >
> > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > >
> > > > > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > > > > right thing with
> > > > > > > > > > > >
> > > > > > > > > > > > .section .text,"ax"
> > > > > > > > > > > >    ...
> > > > > > > > > > > > foo:
> > > > > > > > > > > >   ...
> > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > >
> > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > >
> > > > > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > > > > >
> > > > > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > > > > But let's not conflate these two.
> > > > > > > > > >
> > > > > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > > > > most appropriate.
> > > > > > > > >
> > > > > > > > > It can be done.  If you put your branch on
> > > > > > > > >
> > > > > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > > > > >
> > > > > > > > > I can help you implement it.
> > > > > > > >
> > > > > > > > It's not something I have time to look into at the moment, for now the
> > > > > > > > aim is just to prevent garbage collection of sections.
> > > > > > >
> > > > > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > > > >
> > > > > > Sorry, I don't understand.
> > > > > >
> > > > > > Are you saying that LD already supports the garbage collection of
> > > > > > individual unused symbol definitions from input sections? Whilst
> > > > > > retaining other symbol definitions which are required by the program?
> > > > > > I cannot find any reference to this.
> > > > > >
> > > > > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > > > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > > > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > > > > section should be placed in a special memory area.
> > > > >
> > > > > For
> > > > >
> > > > > section .text,"ax"
> > > > >    ...
> > > > > foo:
> > > > >   ...
> > > > >  .section .text,"axR"
> > > > > retained_fn:
> > > > >
> > > > > you need to create a new .text section with SHF_GNU_RETAIN for
> > > > > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > > >
> > > > See users/hjl/elf/master branch at:
> > > >
> > > > https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> > > >
> > > > I removed the .retain directive.
> > >
> > > Thanks, the formalization of section flag merging in the assembler is
> > > nice.
> > >
> > > My only comment is that I used the "STT_*" syntax in the .type directive
> > > instead of % because some targets didn't like the % syntax and emmited
> > > an error. I don't remember which, maybe it was mmix-elf, in which case
> > > we don't care :)
> >
> > Some targets don't support @object.  %object works for all targets.
>
> Ah yes, it is in fact the non-existent mmix-elf that can't assemble
> %object but it works for all real targets.
>
> However, some targets don't support the .bss pseudo op which is used in
> your new tests, so those are failing in some cases.
>

Which ELF targets don't support .bss? gas/testsuite/gas/elf/bss.s has

.bss

Do they fail this test?

-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 17:04                             ` H.J. Lu
@ 2020-09-24 17:18                               ` Jozef Lawrynowicz
  2020-09-24 17:37                                 ` H.J. Lu
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-24 17:18 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Thu, Sep 24, 2020 at 10:04:46AM -0700, H.J. Lu via Binutils wrote:
> On Thu, Sep 24, 2020 at 9:56 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Thu, Sep 24, 2020 at 06:59:07AM -0700, H.J. Lu via Binutils wrote:
> > > On Thu, Sep 24, 2020 at 6:49 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> > > > > On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > >
> > > > > > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > >
> > > > > > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > > > > > Hello,
> > > > > > > > > > > >
> > > > > > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > > I think that:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >  .retain
> > > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > > > > > right thing with
> > > > > > > > > > > > >
> > > > > > > > > > > > > .section .text,"ax"
> > > > > > > > > > > > >    ...
> > > > > > > > > > > > > foo:
> > > > > > > > > > > > >   ...
> > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > >
> > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > >
> > > > > > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > > > > > >
> > > > > > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > > > > > But let's not conflate these two.
> > > > > > > > > > >
> > > > > > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > > > > > most appropriate.
> > > > > > > > > >
> > > > > > > > > > It can be done.  If you put your branch on
> > > > > > > > > >
> > > > > > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > > > > > >
> > > > > > > > > > I can help you implement it.
> > > > > > > > >
> > > > > > > > > It's not something I have time to look into at the moment, for now the
> > > > > > > > > aim is just to prevent garbage collection of sections.
> > > > > > > >
> > > > > > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > > > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > > > > >
> > > > > > > Sorry, I don't understand.
> > > > > > >
> > > > > > > Are you saying that LD already supports the garbage collection of
> > > > > > > individual unused symbol definitions from input sections? Whilst
> > > > > > > retaining other symbol definitions which are required by the program?
> > > > > > > I cannot find any reference to this.
> > > > > > >
> > > > > > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > > > > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > > > > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > > > > > section should be placed in a special memory area.
> > > > > >
> > > > > > For
> > > > > >
> > > > > > section .text,"ax"
> > > > > >    ...
> > > > > > foo:
> > > > > >   ...
> > > > > >  .section .text,"axR"
> > > > > > retained_fn:
> > > > > >
> > > > > > you need to create a new .text section with SHF_GNU_RETAIN for
> > > > > > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > > > >
> > > > > See users/hjl/elf/master branch at:
> > > > >
> > > > > https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> > > > >
> > > > > I removed the .retain directive.
> > > >
> > > > Thanks, the formalization of section flag merging in the assembler is
> > > > nice.
> > > >
> > > > My only comment is that I used the "STT_*" syntax in the .type directive
> > > > instead of % because some targets didn't like the % syntax and emmited
> > > > an error. I don't remember which, maybe it was mmix-elf, in which case
> > > > we don't care :)
> > >
> > > Some targets don't support @object.  %object works for all targets.
> >
> > Ah yes, it is in fact the non-existent mmix-elf that can't assemble
> > %object but it works for all real targets.
> >
> > However, some targets don't support the .bss pseudo op which is used in
> > your new tests, so those are failing in some cases.
> >
> 
> Which ELF targets don't support .bss? gas/testsuite/gas/elf/bss.s has
> 
> .bss
> 
> Do they fail this test?

That test only runs for i?86-*-* x86_64-*-* ia64-*-* arm-*-* aarch64-*-*

The .bss directive causes an error for the following targets:
  arc-elf avr-elf cr16-elf cris-elf crx-elf d10v-elf d30v-elf dlx-elf
  epiphany-elf fr30-elf frv-elf ft32-elf h8300-elf ip2k-elf iq2000-elf
  lm32-elf m32r-elf m68hc11-elf m68hc12-elf mep-elf metag-elf mmix-elf
  mmix-elf moxie-elf msp430-elf mt-elf nios2-elf or1k-elf pj-elf ppc-elf
  pru-elf s12z-elf sh-elf sparc-elf tic6x-elf tilegx-elf tilepro-elf
  wasm32-elf xgate-elf xstormy16-elf xtensa-elf z80-elf

Thanks,
Jozef

> 
> -- 
> H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 17:18                               ` Jozef Lawrynowicz
@ 2020-09-24 17:37                                 ` H.J. Lu
  0 siblings, 0 replies; 37+ messages in thread
From: H.J. Lu @ 2020-09-24 17:37 UTC (permalink / raw)
  To: Binutils

On Thu, Sep 24, 2020 at 10:18 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Thu, Sep 24, 2020 at 10:04:46AM -0700, H.J. Lu via Binutils wrote:
> > On Thu, Sep 24, 2020 at 9:56 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Thu, Sep 24, 2020 at 06:59:07AM -0700, H.J. Lu via Binutils wrote:
> > > > On Thu, Sep 24, 2020 at 6:49 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Thu, Sep 24, 2020 at 06:18:05AM -0700, H.J. Lu via Binutils wrote:
> > > > > > On Wed, Sep 23, 2020 at 1:17 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > >
> > > > > > > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
> > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
> > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
> > > > > > > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
> > > > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
> > > > > > > > > > > > > Hello,
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > > > I think that:
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > > >  .retain
> > > > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > is some nice syntactic sugar compared to:
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >  .section .text,"ax"
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > > >  foo:
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > It's also partly for convenience; we have other directives which are
> > > > > > > > > > > > > > > synonyms or short-hand for each other.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > You don't need to keep the whole section when only one symbol should
> > > > > > > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
> > > > > > > > > > > > > > right thing with
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > .section .text,"ax"
> > > > > > > > > > > > > >    ...
> > > > > > > > > > > > > > foo:
> > > > > > > > > > > > > >   ...
> > > > > > > > > > > > > >  .section .text,"axR"
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >  retained_fn:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > where foo can be dropped and retained_fn will be kept.
> > > > > > > > > > > > >
> > > > > > > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
> > > > > > > > > > > > > either the whole section is retained or not.  What you describe is
> > > > > > > > > > > > > something else that would work on a per symbol basis, which would have to
> > > > > > > > > > > > > be specified in a different way and might or might not be a good idea.
> > > > > > > > > > > > > But let's not conflate these two.
> > > > > > > > > > > >
> > > > > > > > > > > > Also, the linker cannot currently dissect a section and remove a
> > > > > > > > > > > > particular unused symbol anyway. Since garbage collection only operates
> > > > > > > > > > > > on the section level, marking the section itself as "retained" seems
> > > > > > > > > > > > most appropriate.
> > > > > > > > > > >
> > > > > > > > > > > It can be done.  If you put your branch on
> > > > > > > > > > >
> > > > > > > > > > > https://gitlab.com/x86-binutils/binutils-gdb
> > > > > > > > > > >
> > > > > > > > > > > I can help you implement it.
> > > > > > > > > >
> > > > > > > > > > It's not something I have time to look into at the moment, for now the
> > > > > > > > > > aim is just to prevent garbage collection of sections.
> > > > > > > > >
> > > > > > > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
> > > > > > > > > to the framework.  Check how SHF_GNU_MBIND works.
> > > > > > > >
> > > > > > > > Sorry, I don't understand.
> > > > > > > >
> > > > > > > > Are you saying that LD already supports the garbage collection of
> > > > > > > > individual unused symbol definitions from input sections? Whilst
> > > > > > > > retaining other symbol definitions which are required by the program?
> > > > > > > > I cannot find any reference to this.
> > > > > > > >
> > > > > > > > How does that relate to SHF_GNU_MBIND? I looked at all the references
> > > > > > > > to "mbind" in Binutils and nothing seemed related garbage collection of
> > > > > > > > sections, since SHF_GNU_MBIND is just used to indicate a particular
> > > > > > > > section should be placed in a special memory area.
> > > > > > >
> > > > > > > For
> > > > > > >
> > > > > > > section .text,"ax"
> > > > > > >    ...
> > > > > > > foo:
> > > > > > >   ...
> > > > > > >  .section .text,"axR"
> > > > > > > retained_fn:
> > > > > > >
> > > > > > > you need to create a new .text section with SHF_GNU_RETAIN for
> > > > > > > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
> > > > > >
> > > > > > See users/hjl/elf/master branch at:
> > > > > >
> > > > > > https://gitlab.com/x86-binutils/binutils-gdb/-/commits/users/hjl/elf/master
> > > > > >
> > > > > > I removed the .retain directive.
> > > > >
> > > > > Thanks, the formalization of section flag merging in the assembler is
> > > > > nice.
> > > > >
> > > > > My only comment is that I used the "STT_*" syntax in the .type directive
> > > > > instead of % because some targets didn't like the % syntax and emmited
> > > > > an error. I don't remember which, maybe it was mmix-elf, in which case
> > > > > we don't care :)
> > > >
> > > > Some targets don't support @object.  %object works for all targets.
> > >
> > > Ah yes, it is in fact the non-existent mmix-elf that can't assemble
> > > %object but it works for all real targets.
> > >
> > > However, some targets don't support the .bss pseudo op which is used in
> > > your new tests, so those are failing in some cases.
> > >
> >
> > Which ELF targets don't support .bss? gas/testsuite/gas/elf/bss.s has
> >
> > .bss
> >
> > Do they fail this test?
>
> That test only runs for i?86-*-* x86_64-*-* ia64-*-* arm-*-* aarch64-*-*
>
> The .bss directive causes an error for the following targets:
>   arc-elf avr-elf cr16-elf cris-elf crx-elf d10v-elf d30v-elf dlx-elf
>   epiphany-elf fr30-elf frv-elf ft32-elf h8300-elf ip2k-elf iq2000-elf
>   lm32-elf m32r-elf m68hc11-elf m68hc12-elf mep-elf metag-elf mmix-elf
>   mmix-elf moxie-elf msp430-elf mt-elf nios2-elf or1k-elf pj-elf ppc-elf
>   pru-elf s12z-elf sh-elf sparc-elf tic6x-elf tilegx-elf tilepro-elf
>   wasm32-elf xgate-elf xstormy16-elf xtensa-elf z80-elf
>

Fixed on users/hjl/elf/master branch.


-- 
H.J.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-24 11:39                       ` Jozef Lawrynowicz
@ 2020-09-24 19:06                         ` Fangrui Song
  0 siblings, 0 replies; 37+ messages in thread
From: Fangrui Song @ 2020-09-24 19:06 UTC (permalink / raw)
  To: Jozef Lawrynowicz; +Cc: Michael Matz, Binutils, H.J. Lu, ccoutant

On 2020-09-24, Jozef Lawrynowicz wrote:
>On Wed, Sep 23, 2020 at 04:29:43PM -0700, Fangrui Song wrote:
>> Hi Jozef,
>
>Hi Fangrui,
>
>> I saw your proposal https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
>> I did not subscribe to gnu-gabi before yesterday so it is inconvenient for me to
>> reply there. Since SHF_GNU_RETAIN is a new feature, and we already have facility
>> for making arbitrary sections alive with R_*_NONE, can you highlight the selling
>> point of a new flag?
>>
>> Copying me previous reply here
>> > We already have a way to create an artificial reference:
>> >
>> >   .reloc ., R_X86_64_NONE, target_symbol
>> >
>> > If we allow a relocation number for the second operand
>> >
>> >   .reloc ., 0, target_symbol
>> >
>> > this will be generic. You can insert the directives in a GC root (e.g.
>> > _start or a symbol referenced by -u or maybe an .init_array)
>>
>> If you do not want to touch the section containing the -e (--entry) symbol, you
>> can use:
>>
>>   .section .init_array.1,"a",@init_array
>>   .reloc ., R_X86_64_NONE, retained_section
>>
>> (I find that gold has an internal error with such a relocation.)
>> But GNU ld should have been supported this for a very long time.
>>
>> (I added these directives to llvm last year: https://reviews.llvm.org/D62014 )
>>
>
>The fact that this relies on the compiler knowing a specific section
>will be present in a linker script, when we are dealing with such a
>broad ecosystem of targets and operating systems, makes me uneasy. The
>functionality simply breaks if the user has a custom linker script which
>does not have .init_array.
>
>Many embedded applications can be written without requiring this
>section. If someone has written their linker script from scratch, only
>including the section directives for the sections they actually need,
>why must we enforce that they have a .init_array input section rule just
>so they can make use of the "retain" attribute. It doesn't make sense -
>.init_array and "retain" are not related.

I use .init_array (which happens to be a GC root) as an example, not
that I am advertising .init_array . My main point is about .reloc
You can use a .reloc directive in a known GC root. .init_array happens
to be such a GC root so I used it as an example. It is not too bad if
you think about a benign zero-sized section.

>Even if this approach would work and pick the right section, I think
>it is nicer for the user for the "retain" attribute to have a
>dedicated ELF construct which describes the requirement to retain the
>section, instead of using an existing construct whose purpose is not
>related.

Relocations are the keystone of --gc-sections. In some cases we want a
dependency relation but do not want the relocation to alter the content.
We use R_*_NONE in such cases.

A relocation gives more control than a section flag. In cases you need
"if this section is retained, please retain some other sections",
instead of "please always retain these sections".

>Your average user is going to be very confused why there are relocs in
>section X which point to various symbols in their code. If they have
>written the entire application, they might be able to infer that it is
>the "retain" attribute which generated these relocs, but if someone else
>wrote the code or the code is from a library or SDK it will not be
>clear.
>
>Ok we could maybe name a reloc like BFD_RELOC_RETAIN, but then what
>would the description be?
>  This relocation type does not actually perform any relocation action,
>  but is used to indicate that the symbol it references should not be
>  discarded by linker garbage collection. It must be placed in a section
>  which will definitely be present in the linked output file, and not be
>  subject to garbage collection, otherwise it will not have any effect.
>
>Can you tell me why it is preferable to use the relocation mechanism to
>implement this, instead of a precisely defined new section flag?
>
>Why must we look to workarounds to implement something like this
>anyway?  We can work out the details of a new section flag, and ensure
>it is precisely specified to ensure robustness, and then developers can
>benefit from understanding more about how their program has been put
>together.
>
>Do we want to make life easier for ourselves, or easier for our users?
>
>I get that ABI changes can be a bit disruptive, but this new flag in
>particular really isn't complicated anyway.
>
>> ---
>>
>> For a new section flag, there are a bunch of things needing thoughts
>>
>> * assembler
>>
>> The .retain directive seems to be discouraged... For section flags:
>>
>> .section .foo,"a"
>> .section .foo,"aR"        # is this a new section
>> .pushsection .foo,"aR"    # is this a new section
>
>No they are not new sections. From my original proposal:

If we use a section flag, my expected behavior for the second .section
with different flags is an error:
https://sourceware.org/pipermail/binutils/2020-February/109945.html

>> .section .foo,"a"
>> .section .foo,"aR"        # error

In this case, I agree that a separate directive can be more convenient
because the compiler does not need to known the flag when it is about to
emit the first .section directive (for example, due to a faraway __attribute__((section(...))))

But then, it will be an innovation I don't know a precedent exists.

>> Alternatively, the "R" flag is recognized by the "flags" argument to the
>> .section directive and will apply SHF_GNU_RETAIN to that section.
>> It is intended that SHF_GNU_RETAIN does not interfere with any validation when
>> switching to a section. It can be used to augment the section flags in a section
>> which has already been created.
>
>When you have two .section directives for the same section, GAS
>"switches" between them instead of creating new sections, which is what
>I referred to above.
>
>This is why the .retain directive more precisely describes what is
>happening. The compiler is telling the assembler that the section
>containing the declaration of the function or data symbol should have
>the SHF_GNU_RETAIN flag applied.
>
>>
>> Does the compiler need to remember that a section has the flag?
>> (Think how this works with __attribute__((section(...))); many asm streamers are
>> one-pass)
>
>The compiler does not need to worry about sections beyond getting the
>name of the section the declaration is in. The "retain" attribute just
>means that the section containing the declaration of the function or
>data object must be retained, so it emits a directive to describe that.
>Once the assembler has set SHF_GNU_RETAIN on a section, it will not be
>unset.
>
>I expect the most common use case to actually be when either the
>"section" attribute has been used, or the -f{function,data}-sections GCC
>options have been passed. If the user is trying to make the most out of
>garbage collection, they should be using -f{function,data}-sections.
>
>>
>> * linker
>> - What does -r do on two sections of the same, one with the flag and the other
>> without? (as HJ mentioned)
>
>To reply to H.J. as well for this point:
>I don't think this warrants any special behavior, SHF_GNU_RETAIN doesn't
>need to change the behavior of section merging. The user should put the
>object to retain in it's own section if they don't want large parts of
>their program to possibly be unnecessarily retained. The unique section
>name they give their SHF_GNU_RETAIN section will not be merged into a
>general output section name until they perform the final non-relocatable
>link.
>
>A section with SHF_GNU_RETAIN applied is being retained because it
>contains some information that is important to the program. So wherever
>the that information ends up needs to be retained.
>
>> - Does the output section have the flag?
>
>SHF_GNU_RETAIN is applied to an input section.
>To ensure the input section is retained, SHF_GNU_RETAIN must be applied
>to any section that input section is merged with. The flag doesn't get
>removed from output sections.
>
>> - Does the flag retain other sections in the same section group?
>
>Yes.
From the description on section groups from the ELF spec:
>  ... such groups must be included or omitted from the linked
>  object as a unit.
>
>I think potentially the only confusing part of any section flag merging
>behavior is the fact that the assembly code might have different
>.section directives for the same section, some with "R" and some without
>(+1 for a .retain directive ;)).
>Once the assembler has emitted its output, the SHF_GNU_RETAIN flag
>applied to an input section behaves like any other section flag.
>There is only one line of linker code which does anything specific with
>SHF_GNU_RETAIN, and that is the code in bfd/elflink.c to "gc_mark" the
>section.
>
>Thanks,
>Jozef
>
>>
>>
>> On 2020-09-23, H.J. Lu via Binutils wrote:
>> > On Wed, Sep 23, 2020 at 1:04 PM Jozef Lawrynowicz
>> > <jozef.l@mittosystems.com> wrote:
>> > >
>> > > On Wed, Sep 23, 2020 at 12:03:28PM -0700, H.J. Lu via Binutils wrote:
>> > > > On Wed, Sep 23, 2020 at 11:47 AM Jozef Lawrynowicz
>> > > > <jozef.l@mittosystems.com> wrote:
>> > > > >
>> > > > > On Wed, Sep 23, 2020 at 10:13:37AM -0700, H.J. Lu via Binutils wrote:
>> > > > > > On Wed, Sep 23, 2020 at 9:52 AM Jozef Lawrynowicz
>> > > > > > <jozef.l@mittosystems.com> wrote:
>> > > > > > >
>> > > > > > > On Wed, Sep 23, 2020 at 01:51:56PM +0000, Michael Matz wrote:
>> > > > > > > > Hello,
>> > > > > > > >
>> > > > > > > > On Wed, 23 Sep 2020, H.J. Lu via Binutils wrote:
>> > > > > > > >
>> > > > > > > > > > I think that:
>> > > > > > > > > >
>> > > > > > > > > > >  .section .text,"ax"
>> > > > > > > > > > >    ...
>> > > > > > > > > > >  foo:
>> > > > > > > > > > >    ...
>> > > > > > > > > > >  .retain
>> > > > > > > > > > >  retained_fn:
>> > > > > > > > > > >    ...
>> > > > > > > > > >
>> > > > > > > > > > is some nice syntactic sugar compared to:
>> > > > > > > > > >
>> > > > > > > > > > >  .section .text,"ax"
>> > > > > > > > > > >    ...
>> > > > > > > > > > >  foo:
>> > > > > > > > > > >    ...
>> > > > > > > > > > >  .section .text,"axR"
>> > > > > > > > > > >  retained_fn:
>> > > > > > > > > > >    ...
>> > > > > > > > > >
>> > > > > > > > > > It's also partly for convenience; we have other directives which are
>> > > > > > > > > > synonyms or short-hand for each other.
>> > > > > > > > > >
>> > > > > > > > >
>> > > > > > > > > You don't need to keep the whole section when only one symbol should
>> > > > > > > > > be kept.  Please drop the .retain directive.  GCC, as and ld should do the
>> > > > > > > > > right thing with
>> > > > > > > > >
>> > > > > > > > > .section .text,"ax"
>> > > > > > > > >    ...
>> > > > > > > > > foo:
>> > > > > > > > >   ...
>> > > > > > > > >  .section .text,"axR"
>> > > > > > > > >
>> > > > > > > > >  retained_fn:
>> > > > > > > > >
>> > > > > > > > > where foo can be dropped and retained_fn will be kept.
>> > > > > > > >
>> > > > > > > > This is not what we discussed at the ABI list, the flag is per section, so
>> > > > > > > > either the whole section is retained or not.  What you describe is
>> > > > > > > > something else that would work on a per symbol basis, which would have to
>> > > > > > > > be specified in a different way and might or might not be a good idea.
>> > > > > > > > But let's not conflate these two.
>> > > > > > >
>> > > > > > > Also, the linker cannot currently dissect a section and remove a
>> > > > > > > particular unused symbol anyway. Since garbage collection only operates
>> > > > > > > on the section level, marking the section itself as "retained" seems
>> > > > > > > most appropriate.
>> > > > > >
>> > > > > > It can be done.  If you put your branch on
>> > > > > >
>> > > > > > https://gitlab.com/x86-binutils/binutils-gdb
>> > > > > >
>> > > > > > I can help you implement it.
>> > > > >
>> > > > > It's not something I have time to look into at the moment, for now the
>> > > > > aim is just to prevent garbage collection of sections.
>> > > >
>> > > > Linker and assembler already support it.   You just need to add SHF_GNU_RETAIN
>> > > > to the framework.  Check how SHF_GNU_MBIND works.
>> > >
>> > > Sorry, I don't understand.
>> > >
>> > > Are you saying that LD already supports the garbage collection of
>> > > individual unused symbol definitions from input sections? Whilst
>> > > retaining other symbol definitions which are required by the program?
>> > > I cannot find any reference to this.
>> > >
>> > > How does that relate to SHF_GNU_MBIND? I looked at all the references
>> > > to "mbind" in Binutils and nothing seemed related garbage collection of
>> > > sections, since SHF_GNU_MBIND is just used to indicate a particular
>> > > section should be placed in a special memory area.
>> >
>> > For
>> >
>> > section .text,"ax"
>> >   ...
>> > foo:
>> >  ...
>> > .section .text,"axR"
>> > retained_fn:
>> >
>> > you need to create a new .text section with SHF_GNU_RETAIN for
>> > retained_fn.   See get_section in obj-elf.c.  If you want to avoid
>> > merging .text section with SHF_GNU_RETAIN with other .text
>> > sections by ld -r, linker needs to distinguish sections of the
>> > same name with and without SHF_GNU_RETAIN.
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
                   ` (3 preceding siblings ...)
  2020-09-23 12:13 ` Jozef Lawrynowicz
@ 2020-09-28 11:35 ` Pedro Alves
  2020-09-28 12:28   ` Jozef Lawrynowicz
  4 siblings, 1 reply; 37+ messages in thread
From: Pedro Alves @ 2020-09-28 11:35 UTC (permalink / raw)
  To: binutils

On 9/22/20 9:29 PM, Jozef Lawrynowicz wrote:
> 
> The overall intention for this new flag is to enable a new "retain"
> attribute to be applied to declarations of functions and data in the
> source code. This attribute can be used to ensure the definition
> associated with the declaration is present in the linked output file,
> even if linker garbage collection would normally remove the containing
> section because it is unused.

On a high level, this sounds pretty much like __attribute__((used)).
Couldn't the new section flag be wired to that attribute?  

I mean, isn't it a bug if linker garbage collection eliminates a
function marked with __attribute__((used)) ?

 "used

   This attribute, attached to a function, means that code must be emitted 
   for the function even if it appears that the function is not referenced."

I was surprised to not see any mention of the "used" attribute in the
proposal, neither here, nor in gABI mailing list discussion linked.
But maybe I missed it.

Pedro Alves

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-28 11:35 ` Pedro Alves
@ 2020-09-28 12:28   ` Jozef Lawrynowicz
  2020-09-28 14:46     ` Pedro Alves
  0 siblings, 1 reply; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-28 12:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

On Mon, Sep 28, 2020 at 12:35:28PM +0100, Pedro Alves wrote:
> On 9/22/20 9:29 PM, Jozef Lawrynowicz wrote:
> > 
> > The overall intention for this new flag is to enable a new "retain"
> > attribute to be applied to declarations of functions and data in the
> > source code. This attribute can be used to ensure the definition
> > associated with the declaration is present in the linked output file,
> > even if linker garbage collection would normally remove the containing
> > section because it is unused.
> 
> On a high level, this sounds pretty much like __attribute__((used)).
> Couldn't the new section flag be wired to that attribute?  
> 
> I mean, isn't it a bug if linker garbage collection eliminates a
> function marked with __attribute__((used)) ?
> 
>  "used
> 
>    This attribute, attached to a function, means that code must be emitted 
>    for the function even if it appears that the function is not referenced."
> 
> I was surprised to not see any mention of the "used" attribute in the
> proposal, neither here, nor in gABI mailing list discussion linked.
> But maybe I missed it.

In an early version of the implementation, I tried tying the
behavior to the "used" attribute, but it caused some problems.

I believe the issues mainly came from the usage of "used" in
libgcc/crtstuff.c. The functions there are static and unused, so have
"used" applied to prevent removal by the compiler. However, that does
not mean that all of those functions should be included in every program
linking against libgcc.

I don't remember the exact failure mode, I think it may have been that
lots of tests were failing due to "multiple definition of ..." errors,
or perhaps "undefined reference to ...".

The "retain" attribute implies the "used" attribute, so if the user
wants to prevent compiler optimization AND linker optimization, "retain"
can be used. To prevent only compiler optimization, "used" should be
applied.

Jozef
> 
> Pedro Alves

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-28 12:28   ` Jozef Lawrynowicz
@ 2020-09-28 14:46     ` Pedro Alves
  2020-09-29 13:18       ` Michael Matz
  0 siblings, 1 reply; 37+ messages in thread
From: Pedro Alves @ 2020-09-28 14:46 UTC (permalink / raw)
  To: binutils

On 9/28/20 1:28 PM, Jozef Lawrynowicz wrote:
> On Mon, Sep 28, 2020 at 12:35:28PM +0100, Pedro Alves wrote:
>> On 9/22/20 9:29 PM, Jozef Lawrynowicz wrote:
>>>
>>> The overall intention for this new flag is to enable a new "retain"
>>> attribute to be applied to declarations of functions and data in the
>>> source code. This attribute can be used to ensure the definition
>>> associated with the declaration is present in the linked output file,
>>> even if linker garbage collection would normally remove the containing
>>> section because it is unused.
>>
>> On a high level, this sounds pretty much like __attribute__((used)).
>> Couldn't the new section flag be wired to that attribute?  
>>
>> I mean, isn't it a bug if linker garbage collection eliminates a
>> function marked with __attribute__((used)) ?
>>
>>  "used
>>
>>    This attribute, attached to a function, means that code must be emitted 
>>    for the function even if it appears that the function is not referenced."
>>
>> I was surprised to not see any mention of the "used" attribute in the
>> proposal, neither here, nor in gABI mailing list discussion linked.
>> But maybe I missed it.
> 
> In an early version of the implementation, I tried tying the
> behavior to the "used" attribute, but it caused some problems.
> 
> I believe the issues mainly came from the usage of "used" in
> libgcc/crtstuff.c. The functions there are static and unused, so have
> "used" applied to prevent removal by the compiler. However, that does
> not mean that all of those functions should be included in every program
> linking against libgcc.
> 
> I don't remember the exact failure mode, I think it may have been that
> lots of tests were failing due to "multiple definition of ..." errors,
> or perhaps "undefined reference to ...".

That's really strange, and to be honest, not very convincing.

If there are multiple static functions with the same name in the same
translation unit, when you should be getting errors at compile time.

If OTOH, your early implementation resulted in undefined references,
then it just sounds like a bug in your implementation, since as you say,
__attribute__((retain)) is a superset of __attribute__((used)).  As in,
undefined references suggests the function wasn't emitted, contrary to
the point of the attribute.

> 
> The "retain" attribute implies the "used" attribute, so if the user
> wants to prevent compiler optimization AND linker optimization, "retain"
> can be used. To prevent only compiler optimization, "used" should be
> applied.

I'm not convinced such a distinction makes sense.  Maybe a small self
contained use case where the distinction makes a difference and is
desirable would help.

Pedro Alves

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-28 14:46     ` Pedro Alves
@ 2020-09-29 13:18       ` Michael Matz
  2020-09-29 13:22         ` Jozef Lawrynowicz
  2020-09-29 13:48         ` Pedro Alves
  0 siblings, 2 replies; 37+ messages in thread
From: Michael Matz @ 2020-09-29 13:18 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

Hello,

On Mon, 28 Sep 2020, Pedro Alves wrote:

> >>> The overall intention for this new flag is to enable a new "retain"
> >>> attribute to be applied to declarations of functions and data in the
> >>> source code. This attribute can be used to ensure the definition
> >>> associated with the declaration is present in the linked output file,
> >>> even if linker garbage collection would normally remove the containing
> >>> section because it is unused.
> >>
> >> On a high level, this sounds pretty much like __attribute__((used)).
> >> Couldn't the new section flag be wired to that attribute?  
> >>
> >> I mean, isn't it a bug if linker garbage collection eliminates a
> >> function marked with __attribute__((used)) ?
> >>
> >>  "used
> >>
> >>    This attribute, attached to a function, means that code must be emitted 
> >>    for the function even if it appears that the function is not referenced."
> >>
> >> I was surprised to not see any mention of the "used" attribute in the
> >> proposal, neither here, nor in gABI mailing list discussion linked.
> >> But maybe I missed it.
> > 
> > In an early version of the implementation, I tried tying the
> > behavior to the "used" attribute, but it caused some problems.
> > 
> > I believe the issues mainly came from the usage of "used" in
> > libgcc/crtstuff.c. The functions there are static and unused, so have
> > "used" applied to prevent removal by the compiler. However, that does
> > not mean that all of those functions should be included in every program
> > linking against libgcc.
> > 
> > I don't remember the exact failure mode, I think it may have been that
> > lots of tests were failing due to "multiple definition of ..." errors,
> > or perhaps "undefined reference to ...".
> 
> That's really strange, and to be honest, not very convincing.
> 
> If there are multiple static functions with the same name in the same
> translation unit, when you should be getting errors at compile time.
> 
> If OTOH, your early implementation resulted in undefined references,
> then it just sounds like a bug in your implementation, since as you say,
> __attribute__((retain)) is a superset of __attribute__((used)).  As in,
> undefined references suggests the function wasn't emitted, contrary to
> the point of the attribute.
> 
> > 
> > The "retain" attribute implies the "used" attribute, so if the user
> > wants to prevent compiler optimization AND linker optimization, "retain"
> > can be used. To prevent only compiler optimization, "used" should be
> > applied.
> 
> I'm not convinced such a distinction makes sense.  Maybe a small self
> contained use case where the distinction makes a difference and is
> desirable would help.

We should remember that this thread is about the addition of the section 
flag, which affects but isn't directly related to how it's going to be 
used in source code in a high level language.  If it's the pre-existing 
"used" or a new "retain" attribute, or an attribute at all or just left to 
section markers or pragmas: a discussion about that doesn't need to hold 
up the addition of the ELF feature.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 13:18       ` Michael Matz
@ 2020-09-29 13:22         ` Jozef Lawrynowicz
  2020-09-29 13:48         ` Pedro Alves
  1 sibling, 0 replies; 37+ messages in thread
From: Jozef Lawrynowicz @ 2020-09-29 13:22 UTC (permalink / raw)
  To: Michael Matz; +Cc: Pedro Alves, binutils

On Tue, Sep 29, 2020 at 01:18:31PM +0000, Michael Matz wrote:
> Hello,
> 
> On Mon, 28 Sep 2020, Pedro Alves wrote:
> 
> > >>> The overall intention for this new flag is to enable a new "retain"
> > >>> attribute to be applied to declarations of functions and data in the
> > >>> source code. This attribute can be used to ensure the definition
> > >>> associated with the declaration is present in the linked output file,
> > >>> even if linker garbage collection would normally remove the containing
> > >>> section because it is unused.
> > >>
> > >> On a high level, this sounds pretty much like __attribute__((used)).
> > >> Couldn't the new section flag be wired to that attribute?  
> > >>
> > >> I mean, isn't it a bug if linker garbage collection eliminates a
> > >> function marked with __attribute__((used)) ?
> > >>
> > >>  "used
> > >>
> > >>    This attribute, attached to a function, means that code must be emitted 
> > >>    for the function even if it appears that the function is not referenced."
> > >>
> > >> I was surprised to not see any mention of the "used" attribute in the
> > >> proposal, neither here, nor in gABI mailing list discussion linked.
> > >> But maybe I missed it.
> > > 
> > > In an early version of the implementation, I tried tying the
> > > behavior to the "used" attribute, but it caused some problems.
> > > 
> > > I believe the issues mainly came from the usage of "used" in
> > > libgcc/crtstuff.c. The functions there are static and unused, so have
> > > "used" applied to prevent removal by the compiler. However, that does
> > > not mean that all of those functions should be included in every program
> > > linking against libgcc.
> > > 
> > > I don't remember the exact failure mode, I think it may have been that
> > > lots of tests were failing due to "multiple definition of ..." errors,
> > > or perhaps "undefined reference to ...".
> > 
> > That's really strange, and to be honest, not very convincing.
> > 
> > If there are multiple static functions with the same name in the same
> > translation unit, when you should be getting errors at compile time.
> > 
> > If OTOH, your early implementation resulted in undefined references,
> > then it just sounds like a bug in your implementation, since as you say,
> > __attribute__((retain)) is a superset of __attribute__((used)).  As in,
> > undefined references suggests the function wasn't emitted, contrary to
> > the point of the attribute.
> > 
> > > 
> > > The "retain" attribute implies the "used" attribute, so if the user
> > > wants to prevent compiler optimization AND linker optimization, "retain"
> > > can be used. To prevent only compiler optimization, "used" should be
> > > applied.
> > 
> > I'm not convinced such a distinction makes sense.  Maybe a small self
> > contained use case where the distinction makes a difference and is
> > desirable would help.
> 
> We should remember that this thread is about the addition of the section 
> flag, which affects but isn't directly related to how it's going to be 
> used in source code in a high level language.  If it's the pre-existing 
> "used" or a new "retain" attribute, or an attribute at all or just left to 
> section markers or pragmas: a discussion about that doesn't need to hold 
> up the addition of the ELF feature.

Yep, thanks Michael.

I'm working on the GCC implementation at the moment, I'll review what
happens if "used" implies SHF_GNU_RETAIN before I submit to gcc-patches,
and that aspect of the implementation can be discussed there.

Jozef

> 
> 
> Ciao,
> Michael.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 13:18       ` Michael Matz
  2020-09-29 13:22         ` Jozef Lawrynowicz
@ 2020-09-29 13:48         ` Pedro Alves
  2020-09-29 13:55           ` Michael Matz
  1 sibling, 1 reply; 37+ messages in thread
From: Pedro Alves @ 2020-09-29 13:48 UTC (permalink / raw)
  To: Michael Matz; +Cc: binutils

On 9/29/20 2:18 PM, Michael Matz wrote:

> We should remember that this thread is about the addition of the section 
> flag, which affects but isn't directly related to how it's going to be 
> used in source code in a high level language.  If it's the pre-existing 
> "used" or a new "retain" attribute, or an attribute at all or just left to 
> section markers or pragmas: a discussion about that doesn't need to hold 
> up the addition of the ELF feature.

I never suggested that it should (hold up the ELF feature).  I was
replying to this in the original message:

> The overall intention for this new flag is to enable a new "retain"
> attribute to be applied to declarations of functions and data in the
> source code. This attribute can be used to ensure the definition
> associated with the declaration is present in the linked output file,
> even if linker garbage collection would normally remove the containing
> section because it is unused.

Discussing the intention of a new proposed mechanism seems apropos.
Sometimes the high level usage model influences the low level design too.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 13:48         ` Pedro Alves
@ 2020-09-29 13:55           ` Michael Matz
  2020-09-29 14:04             ` Pedro Alves
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Matz @ 2020-09-29 13:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

Hello,

On Tue, 29 Sep 2020, Pedro Alves wrote:

> > We should remember that this thread is about the addition of the section 
> > flag, which affects but isn't directly related to how it's going to be 
> > used in source code in a high level language.  If it's the pre-existing 
> > "used" or a new "retain" attribute, or an attribute at all or just left to 
> > section markers or pragmas: a discussion about that doesn't need to hold 
> > up the addition of the ELF feature.
> 
> I never suggested that it should (hold up the ELF feature).

Okay.

> I was replying to this in the original message:
> 
> > The overall intention for this new flag is to enable a new "retain"
> > attribute to be applied to declarations of functions and data in the
> > source code. This attribute can be used to ensure the definition
> > associated with the declaration is present in the linked output file,
> > even if linker garbage collection would normally remove the containing
> > section because it is unused.
> 
> Discussing the intention of a new proposed mechanism seems apropos.
> Sometimes the high level usage model influences the low level design too.

Definitely.  But used vs retain attribute seemed like a too detailed 
distinction to make at this point.  For the GCC patches it's totally 
appropriate, though, as planned.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 13:55           ` Michael Matz
@ 2020-09-29 14:04             ` Pedro Alves
  2020-09-29 14:10               ` Michael Matz
  0 siblings, 1 reply; 37+ messages in thread
From: Pedro Alves @ 2020-09-29 14:04 UTC (permalink / raw)
  To: Michael Matz; +Cc: binutils

On 9/29/20 2:55 PM, Michael Matz wrote:

> Definitely.  But used vs retain attribute seemed like a too detailed 
> distinction to make at this point.  For the GCC patches it's totally 
> appropriate, though, as planned.

It's only planned now because I brought it up.  I think that shooting
down a subthread like this implying I'm getting in the way is kind of
uncalled for, to be honest.  If anything, it should make people wonder
whether a better name for the flag would be SHF_GNU_USED, so that we
don't end up with more than one term for the same thing in the
toolchain.  Though yes, that's minor.

Anyway, please don't let me hold anything up.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 14:04             ` Pedro Alves
@ 2020-09-29 14:10               ` Michael Matz
  2020-09-29 14:11                 ` Pedro Alves
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Matz @ 2020-09-29 14:10 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

Hello,

On Tue, 29 Sep 2020, Pedro Alves wrote:

> > Definitely.  But used vs retain attribute seemed like a too detailed 
> > distinction to make at this point.  For the GCC patches it's totally 
> > appropriate, though, as planned.
> 
> It's only planned now because I brought it up.  I think that shooting
> down a subthread like this implying I'm getting in the way is kind of
> uncalled for, to be honest.

Apologies, then, sorry.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] Support SHF_GNU_RETAIN ELF section flag
  2020-09-29 14:10               ` Michael Matz
@ 2020-09-29 14:11                 ` Pedro Alves
  0 siblings, 0 replies; 37+ messages in thread
From: Pedro Alves @ 2020-09-29 14:11 UTC (permalink / raw)
  To: Michael Matz; +Cc: binutils

On 9/29/20 3:10 PM, Michael Matz wrote:
> Hello,
> 
> On Tue, 29 Sep 2020, Pedro Alves wrote:
> 
>>> Definitely.  But used vs retain attribute seemed like a too detailed 
>>> distinction to make at this point.  For the GCC patches it's totally 
>>> appropriate, though, as planned.
>>
>> It's only planned now because I brought it up.  I think that shooting
>> down a subthread like this implying I'm getting in the way is kind of
>> uncalled for, to be honest.
> 
> Apologies, then, sorry.

No harm done.

Cheers,
Pedro Alves

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2020-09-29 14:11 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-22 20:29 [PATCH] Support SHF_GNU_RETAIN ELF section flag Jozef Lawrynowicz
2020-09-22 23:24 ` Hans-Peter Nilsson
2020-09-22 23:58 ` H.J. Lu
2020-09-23  1:09 ` Fangrui Song
2020-09-23  9:58   ` Jozef Lawrynowicz
2020-09-23 13:39     ` H.J. Lu
2020-09-23 13:51       ` Michael Matz
2020-09-23 16:52         ` Jozef Lawrynowicz
2020-09-23 17:13           ` H.J. Lu
2020-09-23 18:47             ` Jozef Lawrynowicz
2020-09-23 19:03               ` H.J. Lu
2020-09-23 20:04                 ` Jozef Lawrynowicz
2020-09-23 20:17                   ` H.J. Lu
2020-09-23 23:29                     ` Fangrui Song
2020-09-24 11:39                       ` Jozef Lawrynowicz
2020-09-24 19:06                         ` Fangrui Song
2020-09-24 13:27                       ` Michael Matz
2020-09-24 13:18                     ` H.J. Lu
2020-09-24 13:49                       ` Jozef Lawrynowicz
2020-09-24 13:59                         ` H.J. Lu
2020-09-24 16:56                           ` Jozef Lawrynowicz
2020-09-24 17:04                             ` H.J. Lu
2020-09-24 17:18                               ` Jozef Lawrynowicz
2020-09-24 17:37                                 ` H.J. Lu
2020-09-23 12:13 ` Jozef Lawrynowicz
2020-09-23 13:59   ` Alan Modra
2020-09-23 16:54     ` Jozef Lawrynowicz
2020-09-28 11:35 ` Pedro Alves
2020-09-28 12:28   ` Jozef Lawrynowicz
2020-09-28 14:46     ` Pedro Alves
2020-09-29 13:18       ` Michael Matz
2020-09-29 13:22         ` Jozef Lawrynowicz
2020-09-29 13:48         ` Pedro Alves
2020-09-29 13:55           ` Michael Matz
2020-09-29 14:04             ` Pedro Alves
2020-09-29 14:10               ` Michael Matz
2020-09-29 14:11                 ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).