diff mbox series

"used" attribute saves decl from linker garbage collection

Message ID 20201103174007.sjcttm5nbqxl33na@jozef-acer-manjaro
State New
Headers show
Series "used" attribute saves decl from linker garbage collection | expand

Commit Message

Jozef Lawrynowicz Nov. 3, 2020, 5:40 p.m. UTC
The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
OSABI targets, so that declarations that have the "used" attribute
applied will be saved from linker garbage collection.

TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
directive for the decl, and the assembler will apply the SHF_GNU_RETAIN
flag to the section containing the decl.
The linker will not garbage collect sections marked with the
SHF_GNU_RETAIN flag.

SHF_GNU_RETAIN is a GNU OSABI ELF extension, and it was discussed on the
GNU gABI mailing list here:
https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html

The Binutils patch to implement .retain and other SHF_GNU_RETAIN
handling is posted here:
https://sourceware.org/pipermail/binutils/2020-November/113993.html

Successfully bootstrapped and regtested for x86_64-pc-linux-gnu, and
regtested for arm-none-eabi.

Ok for trunk?

Thanks,
Jozef
From 0827e28480b7edd07cda4f938bdd14b1cbdf1fa2 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Thu, 29 Oct 2020 21:00:07 +0000
Subject: [PATCH] Implement TARGET_MARK_DECL_PRESERVED for ELF GNU OSABI
 targets

The GAS .retain directive will apply the SHF_GNU_RETAIN flag to the
section containing the symbol that must be preserved.

gcc/ChangeLog:

	* config.in: Regenerate.
	* config/elfos.h (TARGET_ASM_MARK_DECL_PRESERVED): Define for
	HAVE_GAS_RETAIN.
	* configure: Regenerate.
	* configure.ac: Define HAVE_GAS_RETAIN.
	* doc/extend.texi (used attribute): Document saving from linker garbage
	collection.
	* doc/sourcebuild.texi: Document "retain" effective target keyword.
	* doc/tm.texi: Regenerate.
	* output.h (default_elf_mark_decl_preserved): New.
	* target.def (mark_decl_preserved): Mention GAS .retain directive.
	* varasm.c (default_elf_mark_decl_preserved): New.

gcc/testsuite/ChangeLog:

	* c-c++-common/attr-used-2.c: Test for .retain in assembler output.
	* c-c++-common/attr-used.c: Likewise.
	* lib/target-supports.exp (check_effective_target_retain): New.
---
 gcc/config.in                            |  6 ++++
 gcc/config/elfos.h                       |  7 +++++
 gcc/configure                            | 35 ++++++++++++++++++++++++
 gcc/configure.ac                         |  8 ++++++
 gcc/doc/extend.texi                      |  6 ++++
 gcc/doc/sourcebuild.texi                 |  3 ++
 gcc/doc/tm.texi                          |  2 +-
 gcc/output.h                             |  4 +++
 gcc/target.def                           |  2 +-
 gcc/testsuite/c-c++-common/attr-used-2.c |  1 +
 gcc/testsuite/c-c++-common/attr-used.c   |  2 ++
 gcc/testsuite/lib/target-supports.exp    |  9 ++++++
 gcc/varasm.c                             | 13 +++++++++
 13 files changed, 96 insertions(+), 2 deletions(-)

Comments

H.J. Lu Nov. 3, 2020, 5:57 p.m. UTC | #1
On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> OSABI targets, so that declarations that have the "used" attribute
> applied will be saved from linker garbage collection.
>
> TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"

Can you use the "R" flag instead?

> directive for the decl, and the assembler will apply the SHF_GNU_RETAIN
> flag to the section containing the decl.
> The linker will not garbage collect sections marked with the
> SHF_GNU_RETAIN flag.
>
> SHF_GNU_RETAIN is a GNU OSABI ELF extension, and it was discussed on the
> GNU gABI mailing list here:
> https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
>
> The Binutils patch to implement .retain and other SHF_GNU_RETAIN
> handling is posted here:
> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>
> Successfully bootstrapped and regtested for x86_64-pc-linux-gnu, and
> regtested for arm-none-eabi.
>
> Ok for trunk?
>
> Thanks,
> Jozef
Jozef Lawrynowicz Nov. 3, 2020, 6:22 p.m. UTC | #2
On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > OSABI targets, so that declarations that have the "used" attribute
> > applied will be saved from linker garbage collection.
> >
> > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> 
> Can you use the "R" flag instead?
> 

For the benefit of this mailing list, I have copied my response from the
Binutils mailing list regarding this.
The "comm_section" example I gave is actually innacurate, but you can
see the examples of the variety of sections that would need to be
handled by doing

$ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."

> ... snip ...
> Secondly, for seamless integration with the "used" attribute, we must be
> able to to mark the symbol with the used attribute applied as "retained"
> without changing its section name. For GCC "named" sections, this is
> straightforward, but for "unnamed" sections it is a giant mess.
>
> The section name for a GCC "unnamed" section is not readily available,
> instead a string which contains the full assembly code to switch to one
> of these text/data/bss/rodata/comm etc. sections is encoded in the
> structure.
>
> Backends define the assembly code to switch to these sections (some
> "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> "comm_section", might correspond to a .bss section, or emit a .comm
> directive. I even looked at trying to parse them to extract what the
> name of a section will be, but it would be very messy and not robust.
>
> Meanwhile, having a .retain <symbol_name> directive is a very simmple
> solution, and keeps the GCC implementation really concise (patch
> attached). The assembler will know for sure what the section containing
> the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
>
> Finally, having a .retain directive means that we don't need to support
> multiple sections with the same name, but different states for the "R"
> flag. For example, and Fangrui raised this point in previous discussion,
> the following is undesirable, as it violates the rule we have about
> section flags set in .section directives being the same for sections of
> the same name:
>
>   .section .text,"ax",%progbits
>    ...
>   .section .text,"axR",%progbits
>   ....
>
>
> The above would be required if GCC can only mark decls are retained by
> explicitly placing them in a section with the SHF_GNU_RETAIN flag
> applied. The .retain <symbol_name> directive greatly simplifies the
> process for GCC.

> > directive for the decl, and the assembler will apply the SHF_GNU_RETAIN
> > flag to the section containing the decl.
> > The linker will not garbage collect sections marked with the
> > SHF_GNU_RETAIN flag.
> >
> > SHF_GNU_RETAIN is a GNU OSABI ELF extension, and it was discussed on the
> > GNU gABI mailing list here:
> > https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html
> >
> > The Binutils patch to implement .retain and other SHF_GNU_RETAIN
> > handling is posted here:
> > https://sourceware.org/pipermail/binutils/2020-November/113993.html
> >
> > Successfully bootstrapped and regtested for x86_64-pc-linux-gnu, and
> > regtested for arm-none-eabi.
> >
> > Ok for trunk?
> >
> > Thanks,
> > Jozef
> 
> 
> 
> -- 
> H.J.
H.J. Lu Nov. 3, 2020, 7:58 p.m. UTC | #3
On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > OSABI targets, so that declarations that have the "used" attribute
> > > applied will be saved from linker garbage collection.
> > >
> > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> >
> > Can you use the "R" flag instead?
> >
>
> For the benefit of this mailing list, I have copied my response from the
> Binutils mailing list regarding this.
> The "comm_section" example I gave is actually innacurate, but you can
> see the examples of the variety of sections that would need to be
> handled by doing
>
> $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
>
> > ... snip ...
> > Secondly, for seamless integration with the "used" attribute, we must be
> > able to to mark the symbol with the used attribute applied as "retained"
> > without changing its section name. For GCC "named" sections, this is
> > straightforward, but for "unnamed" sections it is a giant mess.
> >
> > The section name for a GCC "unnamed" section is not readily available,
> > instead a string which contains the full assembly code to switch to one
> > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > structure.
> >
> > Backends define the assembly code to switch to these sections (some
> > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > "comm_section", might correspond to a .bss section, or emit a .comm
> > directive. I even looked at trying to parse them to extract what the
> > name of a section will be, but it would be very messy and not robust.
> >
> > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > solution, and keeps the GCC implementation really concise (patch
> > attached). The assembler will know for sure what the section containing
> > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> >

Please take a look at

https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain

which is built in top of

https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html

I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
Jozef Lawrynowicz Nov. 3, 2020, 8:46 p.m. UTC | #4
On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > OSABI targets, so that declarations that have the "used" attribute
> > > > applied will be saved from linker garbage collection.
> > > >
> > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > >
> > > Can you use the "R" flag instead?
> > >
> >
> > For the benefit of this mailing list, I have copied my response from the
> > Binutils mailing list regarding this.
> > The "comm_section" example I gave is actually innacurate, but you can
> > see the examples of the variety of sections that would need to be
> > handled by doing
> >
> > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> >
> > > ... snip ...
> > > Secondly, for seamless integration with the "used" attribute, we must be
> > > able to to mark the symbol with the used attribute applied as "retained"
> > > without changing its section name. For GCC "named" sections, this is
> > > straightforward, but for "unnamed" sections it is a giant mess.
> > >
> > > The section name for a GCC "unnamed" section is not readily available,
> > > instead a string which contains the full assembly code to switch to one
> > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > structure.
> > >
> > > Backends define the assembly code to switch to these sections (some
> > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > directive. I even looked at trying to parse them to extract what the
> > > name of a section will be, but it would be very messy and not robust.
> > >
> > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > solution, and keeps the GCC implementation really concise (patch
> > > attached). The assembler will know for sure what the section containing
> > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > >
> 
> Please take a look at
> 
> https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> 
> which is built in top of
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> 
> I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> want, you extract my flags2 change and use it for SHF_GNU_RETAIN.

In your patch you have to make the assumption that data_section, always
corresponds to a section named .data. For just this example, c6x (which
supports the GNU ELF OSABI) does not fit the rule:

> c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""

data_section for c6x corresponds to .fardata, not .data. So the use of
"used" on a data declaration would place it in a different section, that
if the "used" attribute was not applied.

For c6x and mips, readonly_data_section does not correspond to .rodata,
so that assumption cannot be made either:
> c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */

The same can be said for bss_section for c6x as well.

Furthermore, this is only considering the examples in
default_elf_select_section - the less standard unnamed section are used
in many backend's implementation of select_section, and we would need to
work out what section name they correspond to to properly support
SHF_GNU_RETAIN.

For every unnamed section, you either have to assume what the
corresponding section name is, or parse the associated assembly output
string for the section.

Given these edge cases which must be handled for GCC to robustly emit
the "R" flag for sections containing "used" symbols, surely it is
preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
emit a .retain <symname> directive, which is extremely simple and
doesn't require any handling of these edge cases and non-standard
backend implementations.

The point about multiple section directives, some with the "R" flag some
without, still applies as a downside to trying to emit the .section
directives for the "used" attribute.

Thanks,
Jozef

> 
> -- 
> H.J.
H.J. Lu Nov. 3, 2020, 9 p.m. UTC | #5
On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > applied will be saved from linker garbage collection.
> > > > >
> > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > >
> > > > Can you use the "R" flag instead?
> > > >
> > >
> > > For the benefit of this mailing list, I have copied my response from the
> > > Binutils mailing list regarding this.
> > > The "comm_section" example I gave is actually innacurate, but you can
> > > see the examples of the variety of sections that would need to be
> > > handled by doing
> > >
> > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > >
> > > > ... snip ...
> > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > without changing its section name. For GCC "named" sections, this is
> > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > >
> > > > The section name for a GCC "unnamed" section is not readily available,
> > > > instead a string which contains the full assembly code to switch to one
> > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > structure.
> > > >
> > > > Backends define the assembly code to switch to these sections (some
> > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > directive. I even looked at trying to parse them to extract what the
> > > > name of a section will be, but it would be very messy and not robust.
> > > >
> > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > solution, and keeps the GCC implementation really concise (patch
> > > > attached). The assembler will know for sure what the section containing
> > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > >
> >
> > Please take a look at
> >
> > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> >
> > which is built in top of
> >
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> >
> > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
>
> In your patch you have to make the assumption that data_section, always
> corresponds to a section named .data. For just this example, c6x (which
> supports the GNU ELF OSABI) does not fit the rule:
>
> > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
>
> data_section for c6x corresponds to .fardata, not .data. So the use of
> "used" on a data declaration would place it in a different section, that
> if the "used" attribute was not applied.
>
> For c6x and mips, readonly_data_section does not correspond to .rodata,
> so that assumption cannot be made either:
> > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
>
> The same can be said for bss_section for c6x as well.

Just add and use named_xxx_section.

> Furthermore, this is only considering the examples in
> default_elf_select_section - the less standard unnamed section are used
> in many backend's implementation of select_section, and we would need to
> work out what section name they correspond to to properly support
> SHF_GNU_RETAIN.
>
> For every unnamed section, you either have to assume what the
> corresponding section name is, or parse the associated assembly output
> string for the section.

My change is just  an example to show how it can be done, not a complete one.

> Given these edge cases which must be handled for GCC to robustly emit
> the "R" flag for sections containing "used" symbols, surely it is
> preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> emit a .retain <symname> directive, which is extremely simple and
> doesn't require any handling of these edge cases and non-standard
> backend implementations.

It is used to update the symbol table.  Other usage is abuse.

> The point about multiple section directives, some with the "R" flag some
> without, still applies as a downside to trying to emit the .section
> directives for the "used" attribute.
>
H.J. Lu Nov. 3, 2020, 9:09 p.m. UTC | #6
On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > applied will be saved from linker garbage collection.
> > > > > >
> > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > >
> > > > > Can you use the "R" flag instead?
> > > > >
> > > >
> > > > For the benefit of this mailing list, I have copied my response from the
> > > > Binutils mailing list regarding this.
> > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > see the examples of the variety of sections that would need to be
> > > > handled by doing
> > > >
> > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > >
> > > > > ... snip ...
> > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > without changing its section name. For GCC "named" sections, this is
> > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > >
> > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > instead a string which contains the full assembly code to switch to one
> > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > structure.
> > > > >
> > > > > Backends define the assembly code to switch to these sections (some
> > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > directive. I even looked at trying to parse them to extract what the
> > > > > name of a section will be, but it would be very messy and not robust.
> > > > >
> > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > attached). The assembler will know for sure what the section containing
> > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > >
> > >
> > > Please take a look at
> > >
> > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > >
> > > which is built in top of
> > >
> > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > >
> > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> >
> > In your patch you have to make the assumption that data_section, always
> > corresponds to a section named .data. For just this example, c6x (which
> > supports the GNU ELF OSABI) does not fit the rule:
> >
> > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> >
> > data_section for c6x corresponds to .fardata, not .data. So the use of
> > "used" on a data declaration would place it in a different section, that
> > if the "used" attribute was not applied.
> >
> > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > so that assumption cannot be made either:
> > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> >
> > The same can be said for bss_section for c6x as well.
>
> Just add and use named_xxx_section.
>
> > Furthermore, this is only considering the examples in
> > default_elf_select_section - the less standard unnamed section are used
> > in many backend's implementation of select_section, and we would need to
> > work out what section name they correspond to to properly support
> > SHF_GNU_RETAIN.
> >
> > For every unnamed section, you either have to assume what the
> > corresponding section name is, or parse the associated assembly output
> > string for the section.
>
> My change is just  an example to show how it can be done, not a complete one.
>
> > Given these edge cases which must be handled for GCC to robustly emit
> > the "R" flag for sections containing "used" symbols, surely it is
> > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > emit a .retain <symname> directive, which is extremely simple and
> > doesn't require any handling of these edge cases and non-standard
> > backend implementations.
>
> It is used to update the symbol table.  Other usage is abuse.
>

For

[hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
static int xyzzy __attribute__((__used__)) = 1;
int foo[0x40000];
[hjl@gnu-cfl-2 gcc]$

foo should be removed by ld --gc-sections if it is unreferenced.  But your
patch makes it impossible.
Jozef Lawrynowicz Nov. 3, 2020, 9:57 p.m. UTC | #7
On Tue, Nov 03, 2020 at 01:09:43PM -0800, H.J. Lu via Gcc-patches wrote:
> On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > > applied will be saved from linker garbage collection.
> > > > > > >
> > > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > > >
> > > > > > Can you use the "R" flag instead?
> > > > > >
> > > > >
> > > > > For the benefit of this mailing list, I have copied my response from the
> > > > > Binutils mailing list regarding this.
> > > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > > see the examples of the variety of sections that would need to be
> > > > > handled by doing
> > > > >
> > > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > > >
> > > > > > ... snip ...
> > > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > > without changing its section name. For GCC "named" sections, this is
> > > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > > >
> > > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > > instead a string which contains the full assembly code to switch to one
> > > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > > structure.
> > > > > >
> > > > > > Backends define the assembly code to switch to these sections (some
> > > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > > directive. I even looked at trying to parse them to extract what the
> > > > > > name of a section will be, but it would be very messy and not robust.
> > > > > >
> > > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > > attached). The assembler will know for sure what the section containing
> > > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > > >
> > > >
> > > > Please take a look at
> > > >
> > > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > > >
> > > > which is built in top of
> > > >
> > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > > >
> > > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> > >
> > > In your patch you have to make the assumption that data_section, always
> > > corresponds to a section named .data. For just this example, c6x (which
> > > supports the GNU ELF OSABI) does not fit the rule:
> > >
> > > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> > >
> > > data_section for c6x corresponds to .fardata, not .data. So the use of
> > > "used" on a data declaration would place it in a different section, that
> > > if the "used" attribute was not applied.
> > >
> > > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > > so that assumption cannot be made either:
> > > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> > >
> > > The same can be said for bss_section for c6x as well.
> >
> > Just add and use named_xxx_section.
> >

I guess new macros for targets that use non-standard names in unnamed
sections could work.

  c6x/elf-common.h:
    #define READONLY_DATA_SECTION_NAME ".const"
    #define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"

> > > Furthermore, this is only considering the examples in
> > > default_elf_select_section - the less standard unnamed section are used
> > > in many backend's implementation of select_section, and we would need to
> > > work out what section name they correspond to to properly support
> > > SHF_GNU_RETAIN.
> > >
> > > For every unnamed section, you either have to assume what the
> > > corresponding section name is, or parse the associated assembly output
> > > string for the section.
> >
> > My change is just  an example to show how it can be done, not a complete one.
> >
> > > Given these edge cases which must be handled for GCC to robustly emit
> > > the "R" flag for sections containing "used" symbols, surely it is
> > > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > > emit a .retain <symname> directive, which is extremely simple and
> > > doesn't require any handling of these edge cases and non-standard
> > > backend implementations.
> >
> > It is used to update the symbol table.  Other usage is abuse.
> >

We can't update the symbol table because there is no room left in ELF
for new symbol flags. But the least we can do is convey the requirement
for a *symbol* to be retained from the compiler to the assembler. How
the assembler communicates to the linker that a symbol or section must
be retained is between those two programs and the object file format.

In this case we must use the section flag SHF_GNU_RETAIN. It is not
ideal, but this appears to be the best vehicle for communicating the
requirement to retain a symbol from the assembler to the linker.

Theoretically if we could set an ELF symbol flag for a symbol being
"retained", then we would use a ".retain" directive. The fact we
can't actually communicate the requirement for a symbol to be retained
from the assembler to the linker, because of limitations of the object
file format, is not related to the output of the compiler (IMO).

The following also seems like abuse to me, we can't change set/unset
other flags between .section directives for the same section, but we can
for SHF_GNU_RETAIN?

    .text
  main:
    ...
    .section .text,"axR"
  retained_fn:
    ...
    .section .text,"ax"
  do_stuff:
    ...

There would be further debate about whether the assembler should create
separate sections for the about .text, or merge them into one with
logical OR of the flags. I never did make my mind up about which is
best. Merging is closest to what would happen if we could communicate
"retain" as a property of the symbol.

> 
> For
> 
> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> static int xyzzy __attribute__((__used__)) = 1;
> int foo[0x40000];
> [hjl@gnu-cfl-2 gcc]$
> 
> foo should be removed by ld --gc-sections if it is unreferenced.  But your
> patch makes it impossible.

The same could be said if:
  static int xyzzy = 1;
  int foo[0x40000];

  int
  main (void)
  {
    while (xxyzzy);
  }

foo would be unnecessarily retained. If the user wants optimal operation
of garbage collection, they should use -ffunction/data-sections, the
"section" attribute on xyyzzy, or place foo in another file.

On a related note, in relocatable output from the linker, unique section
names .text.XXXX appear to normally be unhandled in linker scripts for
ld -r, so they will not get merged into an output section, and can still
be properly garbage collected when linking the final executable file.

Thanks,
Jozef

> 
> -- 
> H.J.
H.J. Lu Nov. 3, 2020, 10:11 p.m. UTC | #8
On Tue, Nov 3, 2020 at 1:57 PM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Tue, Nov 03, 2020 at 01:09:43PM -0800, H.J. Lu via Gcc-patches wrote:
> > On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > >
> > > > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > > > applied will be saved from linker garbage collection.
> > > > > > > >
> > > > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > > > >
> > > > > > > Can you use the "R" flag instead?
> > > > > > >
> > > > > >
> > > > > > For the benefit of this mailing list, I have copied my response from the
> > > > > > Binutils mailing list regarding this.
> > > > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > > > see the examples of the variety of sections that would need to be
> > > > > > handled by doing
> > > > > >
> > > > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > > > >
> > > > > > > ... snip ...
> > > > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > > > without changing its section name. For GCC "named" sections, this is
> > > > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > > > >
> > > > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > > > instead a string which contains the full assembly code to switch to one
> > > > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > > > structure.
> > > > > > >
> > > > > > > Backends define the assembly code to switch to these sections (some
> > > > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > > > directive. I even looked at trying to parse them to extract what the
> > > > > > > name of a section will be, but it would be very messy and not robust.
> > > > > > >
> > > > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > > > attached). The assembler will know for sure what the section containing
> > > > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > > > >
> > > > >
> > > > > Please take a look at
> > > > >
> > > > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > > > >
> > > > > which is built in top of
> > > > >
> > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > > > >
> > > > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> > > >
> > > > In your patch you have to make the assumption that data_section, always
> > > > corresponds to a section named .data. For just this example, c6x (which
> > > > supports the GNU ELF OSABI) does not fit the rule:
> > > >
> > > > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> > > >
> > > > data_section for c6x corresponds to .fardata, not .data. So the use of
> > > > "used" on a data declaration would place it in a different section, that
> > > > if the "used" attribute was not applied.
> > > >
> > > > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > > > so that assumption cannot be made either:
> > > > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> > > >
> > > > The same can be said for bss_section for c6x as well.
> > >
> > > Just add and use named_xxx_section.
> > >
>
> I guess new macros for targets that use non-standard names in unnamed
> sections could work.
>
>   c6x/elf-common.h:
>     #define READONLY_DATA_SECTION_NAME ".const"
>     #define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
>
> > > > Furthermore, this is only considering the examples in
> > > > default_elf_select_section - the less standard unnamed section are used
> > > > in many backend's implementation of select_section, and we would need to
> > > > work out what section name they correspond to to properly support
> > > > SHF_GNU_RETAIN.
> > > >
> > > > For every unnamed section, you either have to assume what the
> > > > corresponding section name is, or parse the associated assembly output
> > > > string for the section.
> > >
> > > My change is just  an example to show how it can be done, not a complete one.
> > >
> > > > Given these edge cases which must be handled for GCC to robustly emit
> > > > the "R" flag for sections containing "used" symbols, surely it is
> > > > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > > > emit a .retain <symname> directive, which is extremely simple and
> > > > doesn't require any handling of these edge cases and non-standard
> > > > backend implementations.
> > >
> > > It is used to update the symbol table.  Other usage is abuse.
> > >
>
> We can't update the symbol table because there is no room left in ELF
> for new symbol flags. But the least we can do is convey the requirement
> for a *symbol* to be retained from the compiler to the assembler. How
> the assembler communicates to the linker that a symbol or section must
> be retained is between those two programs and the object file format.

But you want to only want to keep one symbol, not necessarily the whole
section which contains the symbol.

> In this case we must use the section flag SHF_GNU_RETAIN. It is not
> ideal, but this appears to be the best vehicle for communicating the
> requirement to retain a symbol from the assembler to the linker.
>
> Theoretically if we could set an ELF symbol flag for a symbol being
> "retained", then we would use a ".retain" directive. The fact we
> can't actually communicate the requirement for a symbol to be retained
> from the assembler to the linker, because of limitations of the object
> file format, is not related to the output of the compiler (IMO).
>
> The following also seems like abuse to me, we can't change set/unset
> other flags between .section directives for the same section, but we can
> for SHF_GNU_RETAIN?
>
>     .text
>   main:
>     ...
>     .section .text,"axR"
>   retained_fn:
>     ...
>     .section .text,"ax"
>   do_stuff:
>     ...

SHF_GNU_RETAIN has special handling.

> There would be further debate about whether the assembler should create
> separate sections for the about .text, or merge them into one with
> logical OR of the flags. I never did make my mind up about which is
> best. Merging is closest to what would happen if we could communicate
> "retain" as a property of the symbol.
>
> >
> > For
> >
> > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > static int xyzzy __attribute__((__used__)) = 1;
> > int foo[0x40000];
> > [hjl@gnu-cfl-2 gcc]$
> >
> > foo should be removed by ld --gc-sections if it is unreferenced.  But your
> > patch makes it impossible.
>
> The same could be said if:
>   static int xyzzy = 1;
>   int foo[0x40000];
>
>   int
>   main (void)
>   {
>     while (xxyzzy);
>   }
>
> foo would be unnecessarily retained. If the user wants optimal operation

ld --gc-sections will remove foo.  My point is there should be no .retain
directive.

> of garbage collection, they should use -ffunction/data-sections, the
> "section" attribute on xyyzzy, or place foo in another file.
>
> On a related note, in relocatable output from the linker, unique section
> names .text.XXXX appear to normally be unhandled in linker scripts for
> ld -r, so they will not get merged into an output section, and can still
> be properly garbage collected when linking the final executable file.
>
> Thanks,
> Jozef
>
> >
> > --
> > H.J.
H.J. Lu Nov. 4, 2020, 1:47 p.m. UTC | #9
On Tue, Nov 3, 2020 at 2:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Nov 3, 2020 at 1:57 PM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Tue, Nov 03, 2020 at 01:09:43PM -0800, H.J. Lu via Gcc-patches wrote:
> > > On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> > > > <jozef.l@mittosystems.com> wrote:
> > > > >
> > > > > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > >
> > > > > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > > > > applied will be saved from linker garbage collection.
> > > > > > > > >
> > > > > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > > > > >
> > > > > > > > Can you use the "R" flag instead?
> > > > > > > >
> > > > > > >
> > > > > > > For the benefit of this mailing list, I have copied my response from the
> > > > > > > Binutils mailing list regarding this.
> > > > > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > > > > see the examples of the variety of sections that would need to be
> > > > > > > handled by doing
> > > > > > >
> > > > > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > > > > >
> > > > > > > > ... snip ...
> > > > > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > > > > without changing its section name. For GCC "named" sections, this is
> > > > > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > > > > >
> > > > > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > > > > instead a string which contains the full assembly code to switch to one
> > > > > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > > > > structure.
> > > > > > > >
> > > > > > > > Backends define the assembly code to switch to these sections (some
> > > > > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > > > > directive. I even looked at trying to parse them to extract what the
> > > > > > > > name of a section will be, but it would be very messy and not robust.
> > > > > > > >
> > > > > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > > > > attached). The assembler will know for sure what the section containing
> > > > > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > > > > >
> > > > > >
> > > > > > Please take a look at
> > > > > >
> > > > > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > > > > >
> > > > > > which is built in top of
> > > > > >
> > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > > > > >
> > > > > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > > > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> > > > >
> > > > > In your patch you have to make the assumption that data_section, always
> > > > > corresponds to a section named .data. For just this example, c6x (which
> > > > > supports the GNU ELF OSABI) does not fit the rule:
> > > > >
> > > > > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> > > > >
> > > > > data_section for c6x corresponds to .fardata, not .data. So the use of
> > > > > "used" on a data declaration would place it in a different section, that
> > > > > if the "used" attribute was not applied.
> > > > >
> > > > > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > > > > so that assumption cannot be made either:
> > > > > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > > > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> > > > >
> > > > > The same can be said for bss_section for c6x as well.
> > > >
> > > > Just add and use named_xxx_section.
> > > >
> >
> > I guess new macros for targets that use non-standard names in unnamed
> > sections could work.
> >
> >   c6x/elf-common.h:
> >     #define READONLY_DATA_SECTION_NAME ".const"
> >     #define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> >
> > > > > Furthermore, this is only considering the examples in
> > > > > default_elf_select_section - the less standard unnamed section are used
> > > > > in many backend's implementation of select_section, and we would need to
> > > > > work out what section name they correspond to to properly support
> > > > > SHF_GNU_RETAIN.
> > > > >
> > > > > For every unnamed section, you either have to assume what the
> > > > > corresponding section name is, or parse the associated assembly output
> > > > > string for the section.
> > > >
> > > > My change is just  an example to show how it can be done, not a complete one.
> > > >
> > > > > Given these edge cases which must be handled for GCC to robustly emit
> > > > > the "R" flag for sections containing "used" symbols, surely it is
> > > > > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > > > > emit a .retain <symname> directive, which is extremely simple and
> > > > > doesn't require any handling of these edge cases and non-standard
> > > > > backend implementations.
> > > >
> > > > It is used to update the symbol table.  Other usage is abuse.
> > > >
> >
> > We can't update the symbol table because there is no room left in ELF
> > for new symbol flags. But the least we can do is convey the requirement
> > for a *symbol* to be retained from the compiler to the assembler. How
> > the assembler communicates to the linker that a symbol or section must
> > be retained is between those two programs and the object file format.
>
> But you want to only want to keep one symbol, not necessarily the whole
> section which contains the symbol.
>
> > In this case we must use the section flag SHF_GNU_RETAIN. It is not
> > ideal, but this appears to be the best vehicle for communicating the
> > requirement to retain a symbol from the assembler to the linker.
> >
> > Theoretically if we could set an ELF symbol flag for a symbol being
> > "retained", then we would use a ".retain" directive. The fact we
> > can't actually communicate the requirement for a symbol to be retained
> > from the assembler to the linker, because of limitations of the object
> > file format, is not related to the output of the compiler (IMO).
> >
> > The following also seems like abuse to me, we can't change set/unset
> > other flags between .section directives for the same section, but we can
> > for SHF_GNU_RETAIN?
> >
> >     .text
> >   main:
> >     ...
> >     .section .text,"axR"
> >   retained_fn:
> >     ...
> >     .section .text,"ax"
> >   do_stuff:
> >     ...
>
> SHF_GNU_RETAIN has special handling.
>
> > There would be further debate about whether the assembler should create
> > separate sections for the about .text, or merge them into one with
> > logical OR of the flags. I never did make my mind up about which is
> > best. Merging is closest to what would happen if we could communicate
> > "retain" as a property of the symbol.
> >
> > >
> > > For
> > >
> > > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > static int xyzzy __attribute__((__used__)) = 1;
> > > int foo[0x40000];
> > > [hjl@gnu-cfl-2 gcc]$
> > >
> > > foo should be removed by ld --gc-sections if it is unreferenced.  But your
> > > patch makes it impossible.
> >
> > The same could be said if:
> >   static int xyzzy = 1;
> >   int foo[0x40000];
> >
> >   int
> >   main (void)
> >   {
> >     while (xxyzzy);
> >   }
> >
> > foo would be unnecessarily retained. If the user wants optimal operation
>
> ld --gc-sections will remove foo.  My point is there should be no .retain
> directive.
>
> > of garbage collection, they should use -ffunction/data-sections, the
> > "section" attribute on xyyzzy, or place foo in another file.
> >
> > On a related note, in relocatable output from the linker, unique section
> > names .text.XXXX appear to normally be unhandled in linker scripts for
> > ld -r, so they will not get merged into an output section, and can still
> > be properly garbage collected when linking the final executable file.
> >
> > Thanks,
> > Jozef

Please take a look at users/hjl/elf/shf_retain branch:

https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain

for a complete implementation.
Jozef Lawrynowicz Nov. 4, 2020, 2:41 p.m. UTC | #10
On Wed, Nov 04, 2020 at 05:47:28AM -0800, H.J. Lu wrote:
> On Tue, Nov 3, 2020 at 2:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Nov 3, 2020 at 1:57 PM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Tue, Nov 03, 2020 at 01:09:43PM -0800, H.J. Lu via Gcc-patches wrote:
> > > > On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> > > > > <jozef.l@mittosystems.com> wrote:
> > > > > >
> > > > > > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > >
> > > > > > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > >
> > > > > > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > > > > > applied will be saved from linker garbage collection.
> > > > > > > > > >
> > > > > > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > > > > > >
> > > > > > > > > Can you use the "R" flag instead?
> > > > > > > > >
> > > > > > > >
> > > > > > > > For the benefit of this mailing list, I have copied my response from the
> > > > > > > > Binutils mailing list regarding this.
> > > > > > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > > > > > see the examples of the variety of sections that would need to be
> > > > > > > > handled by doing
> > > > > > > >
> > > > > > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > > > > > >
> > > > > > > > > ... snip ...
> > > > > > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > > > > > without changing its section name. For GCC "named" sections, this is
> > > > > > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > > > > > >
> > > > > > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > > > > > instead a string which contains the full assembly code to switch to one
> > > > > > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > > > > > structure.
> > > > > > > > >
> > > > > > > > > Backends define the assembly code to switch to these sections (some
> > > > > > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > > > > > directive. I even looked at trying to parse them to extract what the
> > > > > > > > > name of a section will be, but it would be very messy and not robust.
> > > > > > > > >
> > > > > > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > > > > > attached). The assembler will know for sure what the section containing
> > > > > > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > > > > > >
> > > > > > >
> > > > > > > Please take a look at
> > > > > > >
> > > > > > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > > > > > >
> > > > > > > which is built in top of
> > > > > > >
> > > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > > > > > >
> > > > > > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > > > > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> > > > > >
> > > > > > In your patch you have to make the assumption that data_section, always
> > > > > > corresponds to a section named .data. For just this example, c6x (which
> > > > > > supports the GNU ELF OSABI) does not fit the rule:
> > > > > >
> > > > > > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> > > > > >
> > > > > > data_section for c6x corresponds to .fardata, not .data. So the use of
> > > > > > "used" on a data declaration would place it in a different section, that
> > > > > > if the "used" attribute was not applied.
> > > > > >
> > > > > > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > > > > > so that assumption cannot be made either:
> > > > > > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > > > > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> > > > > >
> > > > > > The same can be said for bss_section for c6x as well.
> > > > >
> > > > > Just add and use named_xxx_section.
> > > > >
> > >
> > > I guess new macros for targets that use non-standard names in unnamed
> > > sections could work.
> > >
> > >   c6x/elf-common.h:
> > >     #define READONLY_DATA_SECTION_NAME ".const"
> > >     #define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > >
> > > > > > Furthermore, this is only considering the examples in
> > > > > > default_elf_select_section - the less standard unnamed section are used
> > > > > > in many backend's implementation of select_section, and we would need to
> > > > > > work out what section name they correspond to to properly support
> > > > > > SHF_GNU_RETAIN.
> > > > > >
> > > > > > For every unnamed section, you either have to assume what the
> > > > > > corresponding section name is, or parse the associated assembly output
> > > > > > string for the section.
> > > > >
> > > > > My change is just  an example to show how it can be done, not a complete one.
> > > > >
> > > > > > Given these edge cases which must be handled for GCC to robustly emit
> > > > > > the "R" flag for sections containing "used" symbols, surely it is
> > > > > > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > > > > > emit a .retain <symname> directive, which is extremely simple and
> > > > > > doesn't require any handling of these edge cases and non-standard
> > > > > > backend implementations.
> > > > >
> > > > > It is used to update the symbol table.  Other usage is abuse.
> > > > >
> > >
> > > We can't update the symbol table because there is no room left in ELF
> > > for new symbol flags. But the least we can do is convey the requirement
> > > for a *symbol* to be retained from the compiler to the assembler. How
> > > the assembler communicates to the linker that a symbol or section must
> > > be retained is between those two programs and the object file format.
> >
> > But you want to only want to keep one symbol, not necessarily the whole
> > section which contains the symbol.
> >
> > > In this case we must use the section flag SHF_GNU_RETAIN. It is not
> > > ideal, but this appears to be the best vehicle for communicating the
> > > requirement to retain a symbol from the assembler to the linker.
> > >
> > > Theoretically if we could set an ELF symbol flag for a symbol being
> > > "retained", then we would use a ".retain" directive. The fact we
> > > can't actually communicate the requirement for a symbol to be retained
> > > from the assembler to the linker, because of limitations of the object
> > > file format, is not related to the output of the compiler (IMO).
> > >
> > > The following also seems like abuse to me, we can't change set/unset
> > > other flags between .section directives for the same section, but we can
> > > for SHF_GNU_RETAIN?
> > >
> > >     .text
> > >   main:
> > >     ...
> > >     .section .text,"axR"
> > >   retained_fn:
> > >     ...
> > >     .section .text,"ax"
> > >   do_stuff:
> > >     ...
> >
> > SHF_GNU_RETAIN has special handling.
> >
> > > There would be further debate about whether the assembler should create
> > > separate sections for the about .text, or merge them into one with
> > > logical OR of the flags. I never did make my mind up about which is
> > > best. Merging is closest to what would happen if we could communicate
> > > "retain" as a property of the symbol.
> > >
> > > >
> > > > For
> > > >
> > > > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > > static int xyzzy __attribute__((__used__)) = 1;
> > > > int foo[0x40000];
> > > > [hjl@gnu-cfl-2 gcc]$
> > > >
> > > > foo should be removed by ld --gc-sections if it is unreferenced.  But your
> > > > patch makes it impossible.
> > >
> > > The same could be said if:
> > >   static int xyzzy = 1;
> > >   int foo[0x40000];
> > >
> > >   int
> > >   main (void)
> > >   {
> > >     while (xxyzzy);
> > >   }
> > >
> > > foo would be unnecessarily retained. If the user wants optimal operation
> >
> > ld --gc-sections will remove foo.  My point is there should be no .retain
> > directive.
> >
> > > of garbage collection, they should use -ffunction/data-sections, the
> > > "section" attribute on xyyzzy, or place foo in another file.
> > >
> > > On a related note, in relocatable output from the linker, unique section
> > > names .text.XXXX appear to normally be unhandled in linker scripts for
> > > ld -r, so they will not get merged into an output section, and can still
> > > be properly garbage collected when linking the final executable file.
> > >
> > > Thanks,
> > > Jozef
> 
> Please take a look at users/hjl/elf/shf_retain branch:
> 
> https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> 
> for a complete implementation.

Thanks for looking into this, however your patch changes the section
that a declaration that has the "used" attribute applied is placed in.

  $ cat tester.c
  void __attribute__((used)) foo (void)
  {
    while (1);
  }
  $ head tester.s
          .file   "tester.c"
          .text
          .section        .text.foo,"axR",@progbits
          .globl  foo
          .type   foo, @function

The behavior of the "used" attribute changes depending on if
SHF_GNU_RETAIN is supported:
- Without SHF_GNU_RETAIN, "foo" is placed in the ".text" section.
- With SHF_GNU_RETAIN, "foo" is placed in the ".text.foo" section.

I raised this point in my RFC
(https://gcc.gnu.org/pipermail/gcc-patches/2020-October/555594.html)
> If "used" did apply SHF_GNU_RETAIN, we would also have to
> consider the above options for how to apply SHF_GNU_RETAIN to the
> section. Since the "used" attribute has been around for a while 
> it might not be appropriate for its behavior to be changed to place the
> associated declaration in its own, unique section, as in option (2).
>
> ....
>
> So nothing that can't be worked around, but I am more concerned about
> the wider impact of changing the attribute, which is not represented by
> this small subset of testing. The changes would also only affect targets
> that support the GNU ELF OSABI, which would lead to inconsistent
> behavior between non-GNU OS's. Perhaps this isn't an issue since we can
> just document it in the description for the "used" attribute:
>   As a GNU ELF extension, the declaration the "used" attribute is
>   applied to will be placed in a new, uniquely named section with the
>   SHF_GNU_RETAIN flag applied.
>
> I think that unless "used" creates a new, uniquely named SHF_GNU_RETAIN
> section for a declaration, there is merit to having a separate "retain"
> attribute that has this behavior.

I have a stronger opinion on this now than I did then - I don't think
declarations with the "used" attribute applied should be put in a unique
section, unless the user requests it by using -ffunction/data-sections
or the "section" attribute.

I personally do not see the problem with the .retain attribute, however
if it is going to be a barrier to getting the functionality committed, I
am happy to change it, since I really just want the functionality in
upstream sources.

If a global maintainer would comment on whether any of the proposed
approaches are acceptable, then I will try to block out time from other
deadlines so I can work on the fixups and submit a patch in time for the
GCC 11 freeze.

Thanks,
Jozef

> 
> -- 
> H.J.
H.J. Lu Nov. 4, 2020, 2:48 p.m. UTC | #11
On Wed, Nov 4, 2020 at 6:41 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Wed, Nov 04, 2020 at 05:47:28AM -0800, H.J. Lu wrote:
> > On Tue, Nov 3, 2020 at 2:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Tue, Nov 3, 2020 at 1:57 PM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Tue, Nov 03, 2020 at 01:09:43PM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > On Tue, Nov 3, 2020 at 1:00 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > >
> > > > > > On Tue, Nov 3, 2020 at 12:46 PM Jozef Lawrynowicz
> > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > >
> > > > > > > On Tue, Nov 03, 2020 at 11:58:04AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > > On Tue, Nov 3, 2020 at 10:22 AM Jozef Lawrynowicz
> > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, Nov 03, 2020 at 09:57:58AM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > > > > > > On Tue, Nov 3, 2020 at 9:41 AM Jozef Lawrynowicz
> > > > > > > > > > <jozef.l@mittosystems.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > The attached patch implements TARGET_ASM_MARK_DECL_PRESERVED for ELF GNU
> > > > > > > > > > > OSABI targets, so that declarations that have the "used" attribute
> > > > > > > > > > > applied will be saved from linker garbage collection.
> > > > > > > > > > >
> > > > > > > > > > > TARGET_ASM_MARK_DECL_PRESERVED will emit an assembler ".retain"
> > > > > > > > > >
> > > > > > > > > > Can you use the "R" flag instead?
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > For the benefit of this mailing list, I have copied my response from the
> > > > > > > > > Binutils mailing list regarding this.
> > > > > > > > > The "comm_section" example I gave is actually innacurate, but you can
> > > > > > > > > see the examples of the variety of sections that would need to be
> > > > > > > > > handled by doing
> > > > > > > > >
> > > > > > > > > $ git grep -A2 "define.*SECTION_ASM_OP" gcc/ | grep "\".*\."
> > > > > > > > >
> > > > > > > > > > ... snip ...
> > > > > > > > > > Secondly, for seamless integration with the "used" attribute, we must be
> > > > > > > > > > able to to mark the symbol with the used attribute applied as "retained"
> > > > > > > > > > without changing its section name. For GCC "named" sections, this is
> > > > > > > > > > straightforward, but for "unnamed" sections it is a giant mess.
> > > > > > > > > >
> > > > > > > > > > The section name for a GCC "unnamed" section is not readily available,
> > > > > > > > > > instead a string which contains the full assembly code to switch to one
> > > > > > > > > > of these text/data/bss/rodata/comm etc. sections is encoded in the
> > > > > > > > > > structure.
> > > > > > > > > >
> > > > > > > > > > Backends define the assembly code to switch to these sections (some
> > > > > > > > > > "*ASM_OP*" macro) in a variety of ways. For example, the unnamed section
> > > > > > > > > > "comm_section", might correspond to a .bss section, or emit a .comm
> > > > > > > > > > directive. I even looked at trying to parse them to extract what the
> > > > > > > > > > name of a section will be, but it would be very messy and not robust.
> > > > > > > > > >
> > > > > > > > > > Meanwhile, having a .retain <symbol_name> directive is a very simmple
> > > > > > > > > > solution, and keeps the GCC implementation really concise (patch
> > > > > > > > > > attached). The assembler will know for sure what the section containing
> > > > > > > > > > the symbol will be, and can apply the SHF_GNU_RETAIN flag directly.
> > > > > > > > > >
> > > > > > > >
> > > > > > > > Please take a look at
> > > > > > > >
> > > > > > > > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> > > > > > > >
> > > > > > > > which is built in top of
> > > > > > > >
> > > > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/539963.html
> > > > > > > >
> > > > > > > > I think SECTION2_RETAIN matches SHF_GNU_RETAIN well.  If you
> > > > > > > > want, you extract my flags2 change and use it for SHF_GNU_RETAIN.
> > > > > > >
> > > > > > > In your patch you have to make the assumption that data_section, always
> > > > > > > corresponds to a section named .data. For just this example, c6x (which
> > > > > > > supports the GNU ELF OSABI) does not fit the rule:
> > > > > > >
> > > > > > > > c6x/elf-common.h:#define DATA_SECTION_ASM_OP "\t.section\t\".fardata\",\"aw\""
> > > > > > >
> > > > > > > data_section for c6x corresponds to .fardata, not .data. So the use of
> > > > > > > "used" on a data declaration would place it in a different section, that
> > > > > > > if the "used" attribute was not applied.
> > > > > > >
> > > > > > > For c6x and mips, readonly_data_section does not correspond to .rodata,
> > > > > > > so that assumption cannot be made either:
> > > > > > > > c6x/elf-common.h:#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > > > > > > mips/mips.h:#define READONLY_DATA_SECTION_ASM_OP        "\t.rdata"      /* read-only data */
> > > > > > >
> > > > > > > The same can be said for bss_section for c6x as well.
> > > > > >
> > > > > > Just add and use named_xxx_section.
> > > > > >
> > > >
> > > > I guess new macros for targets that use non-standard names in unnamed
> > > > sections could work.
> > > >
> > > >   c6x/elf-common.h:
> > > >     #define READONLY_DATA_SECTION_NAME ".const"
> > > >     #define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".const\",\"a\",@progbits"
> > > >
> > > > > > > Furthermore, this is only considering the examples in
> > > > > > > default_elf_select_section - the less standard unnamed section are used
> > > > > > > in many backend's implementation of select_section, and we would need to
> > > > > > > work out what section name they correspond to to properly support
> > > > > > > SHF_GNU_RETAIN.
> > > > > > >
> > > > > > > For every unnamed section, you either have to assume what the
> > > > > > > corresponding section name is, or parse the associated assembly output
> > > > > > > string for the section.
> > > > > >
> > > > > > My change is just  an example to show how it can be done, not a complete one.
> > > > > >
> > > > > > > Given these edge cases which must be handled for GCC to robustly emit
> > > > > > > the "R" flag for sections containing "used" symbols, surely it is
> > > > > > > preferable to leverage the existing TARGET_ASM_MARK_DECL_PRESERVED and
> > > > > > > emit a .retain <symname> directive, which is extremely simple and
> > > > > > > doesn't require any handling of these edge cases and non-standard
> > > > > > > backend implementations.
> > > > > >
> > > > > > It is used to update the symbol table.  Other usage is abuse.
> > > > > >
> > > >
> > > > We can't update the symbol table because there is no room left in ELF
> > > > for new symbol flags. But the least we can do is convey the requirement
> > > > for a *symbol* to be retained from the compiler to the assembler. How
> > > > the assembler communicates to the linker that a symbol or section must
> > > > be retained is between those two programs and the object file format.
> > >
> > > But you want to only want to keep one symbol, not necessarily the whole
> > > section which contains the symbol.
> > >
> > > > In this case we must use the section flag SHF_GNU_RETAIN. It is not
> > > > ideal, but this appears to be the best vehicle for communicating the
> > > > requirement to retain a symbol from the assembler to the linker.
> > > >
> > > > Theoretically if we could set an ELF symbol flag for a symbol being
> > > > "retained", then we would use a ".retain" directive. The fact we
> > > > can't actually communicate the requirement for a symbol to be retained
> > > > from the assembler to the linker, because of limitations of the object
> > > > file format, is not related to the output of the compiler (IMO).
> > > >
> > > > The following also seems like abuse to me, we can't change set/unset
> > > > other flags between .section directives for the same section, but we can
> > > > for SHF_GNU_RETAIN?
> > > >
> > > >     .text
> > > >   main:
> > > >     ...
> > > >     .section .text,"axR"
> > > >   retained_fn:
> > > >     ...
> > > >     .section .text,"ax"
> > > >   do_stuff:
> > > >     ...
> > >
> > > SHF_GNU_RETAIN has special handling.
> > >
> > > > There would be further debate about whether the assembler should create
> > > > separate sections for the about .text, or merge them into one with
> > > > logical OR of the flags. I never did make my mind up about which is
> > > > best. Merging is closest to what would happen if we could communicate
> > > > "retain" as a property of the symbol.
> > > >
> > > > >
> > > > > For
> > > > >
> > > > > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > > > static int xyzzy __attribute__((__used__)) = 1;
> > > > > int foo[0x40000];
> > > > > [hjl@gnu-cfl-2 gcc]$
> > > > >
> > > > > foo should be removed by ld --gc-sections if it is unreferenced.  But your
> > > > > patch makes it impossible.
> > > >
> > > > The same could be said if:
> > > >   static int xyzzy = 1;
> > > >   int foo[0x40000];
> > > >
> > > >   int
> > > >   main (void)
> > > >   {
> > > >     while (xxyzzy);
> > > >   }
> > > >
> > > > foo would be unnecessarily retained. If the user wants optimal operation
> > >
> > > ld --gc-sections will remove foo.  My point is there should be no .retain
> > > directive.
> > >
> > > > of garbage collection, they should use -ffunction/data-sections, the
> > > > "section" attribute on xyyzzy, or place foo in another file.
> > > >
> > > > On a related note, in relocatable output from the linker, unique section
> > > > names .text.XXXX appear to normally be unhandled in linker scripts for
> > > > ld -r, so they will not get merged into an output section, and can still
> > > > be properly garbage collected when linking the final executable file.
> > > >
> > > > Thanks,
> > > > Jozef
> >
> > Please take a look at users/hjl/elf/shf_retain branch:
> >
> > https://gitlab.com/x86-gcc/gcc/-/commits/users/hjl/elf/shf_retain
> >
> > for a complete implementation.
>
> Thanks for looking into this, however your patch changes the section
> that a declaration that has the "used" attribute applied is placed in.
>
>   $ cat tester.c
>   void __attribute__((used)) foo (void)
>   {
>     while (1);
>   }
>   $ head tester.s
>           .file   "tester.c"
>           .text
>           .section        .text.foo,"axR",@progbits
>           .globl  foo
>           .type   foo, @function
>
> The behavior of the "used" attribute changes depending on if
> SHF_GNU_RETAIN is supported:
> - Without SHF_GNU_RETAIN, "foo" is placed in the ".text" section.
> - With SHF_GNU_RETAIN, "foo" is placed in the ".text.foo" section.
>

1. SHF_GNU_RETAIN always changes the behavior no matter what
we do.
2. The "R" section flag creates a unique section, which means

.section        .text.foo,"axR",@progbits

is equivalent to

 .section        .text,"axR",@progbits

If you don't want to change the behavior, you don't need SHF_GNU_RETAIN.
Hans-Peter Nilsson Nov. 4, 2020, 6:09 p.m. UTC | #12
On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> I personally do not see the problem with the .retain attribute, however
> if it is going to be a barrier to getting the functionality committed, I
> am happy to change it, since I really just want the functionality in
> upstream sources.
>
> If a global maintainer would comment on whether any of the proposed
> approaches are acceptable, then I will try to block out time from other
> deadlines so I can work on the fixups and submit a patch in time for the
> GCC 11 freeze.
>
> Thanks,
> Jozef

I'm not much more than a random voice, but an assembly directive
that specifies the symbol (IIUC your .retain directive) to
adjust a symbol attribute sounds cleaner to me, than requiring
gcc to know that this requires it to adjust what it knows about
section flags (again, IIUC).

brgds, H-P
H.J. Lu Nov. 4, 2020, 6:18 p.m. UTC | #13
On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
> On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> > I personally do not see the problem with the .retain attribute, however
> > if it is going to be a barrier to getting the functionality committed, I
> > am happy to change it, since I really just want the functionality in
> > upstream sources.
> >
> > If a global maintainer would comment on whether any of the proposed
> > approaches are acceptable, then I will try to block out time from other
> > deadlines so I can work on the fixups and submit a patch in time for the
> > GCC 11 freeze.
> >
> > Thanks,
> > Jozef
>
> I'm not much more than a random voice, but an assembly directive
> that specifies the symbol (IIUC your .retain directive) to

But .retain directive DOES NOT adjust symbol attribute.  Instead, it sets
the SHF_GNU_RETAIN bit on the section which contains the symbol
definition.  The same section can have many unrelated symbols.

> adjust a symbol attribute sounds cleaner to me, than requiring
> gcc to know that this requires it to adjust what it knows about
> section flags (again, IIUC).
>
> brgds, H-P
Hans-Peter Nilsson Nov. 4, 2020, 9:03 p.m. UTC | #14
On Wed, 4 Nov 2020, H.J. Lu wrote:
> On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> >
> > On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> > > I personally do not see the problem with the .retain attribute, however
> > > if it is going to be a barrier to getting the functionality committed, I
> > > am happy to change it, since I really just want the functionality in
> > > upstream sources.
> > >
> > > If a global maintainer would comment on whether any of the proposed
> > > approaches are acceptable, then I will try to block out time from other
> > > deadlines so I can work on the fixups and submit a patch in time for the
> > > GCC 11 freeze.
> > >
> > > Thanks,
> > > Jozef
> >
> > I'm not much more than a random voice, but an assembly directive
> > that specifies the symbol (IIUC your .retain directive) to
>
> But .retain directive DOES NOT adjust symbol attribute.  Instead, it sets
> the SHF_GNU_RETAIN bit on the section which contains the symbol
> definition.  The same section can have many unrelated symbols.

That's an implementation detail *left to the assembler and
linker*.  It's not something the compiler needs to know, and
teoretically it could even change.

> > adjust a symbol attribute sounds cleaner to me, than requiring
> > gcc to know that this requires it to adjust what it knows about
> > section flags (again, IIUC).
> >
> > brgds, H-P
>
>
>
> --
> H.J.
>
H.J. Lu Nov. 4, 2020, 9:40 p.m. UTC | #15
On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > >
> > > On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> > > > I personally do not see the problem with the .retain attribute, however
> > > > if it is going to be a barrier to getting the functionality committed, I
> > > > am happy to change it, since I really just want the functionality in
> > > > upstream sources.
> > > >
> > > > If a global maintainer would comment on whether any of the proposed
> > > > approaches are acceptable, then I will try to block out time from other
> > > > deadlines so I can work on the fixups and submit a patch in time for the
> > > > GCC 11 freeze.
> > > >
> > > > Thanks,
> > > > Jozef
> > >
> > > I'm not much more than a random voice, but an assembly directive
> > > that specifies the symbol (IIUC your .retain directive) to
> >
> > But .retain directive DOES NOT adjust symbol attribute.  Instead, it sets
> > the SHF_GNU_RETAIN bit on the section which contains the symbol
> > definition.  The same section can have many unrelated symbols.
>
> That's an implementation detail *left to the assembler and
> linker*.  It's not something the compiler needs to know, and
> teoretically it could even change.
>

The ELF extension is SHF_GNU_RETAIN.  .retain directive is a hack
which I strongly objected and showed that it wasn't needed to implement
SHF_GNU_RETAIN in binutils.
Hans-Peter Nilsson Nov. 4, 2020, 9:56 p.m. UTC | #16
On Wed, 4 Nov 2020, H.J. Lu wrote:

> On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> >
> > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > >
> > > > On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> > > > > I personally do not see the problem with the .retain attribute, however
> > > > > if it is going to be a barrier to getting the functionality committed, I
> > > > > am happy to change it, since I really just want the functionality in
> > > > > upstream sources.
> > > > >
> > > > > If a global maintainer would comment on whether any of the proposed
> > > > > approaches are acceptable, then I will try to block out time from other
> > > > > deadlines so I can work on the fixups and submit a patch in time for the
> > > > > GCC 11 freeze.
> > > > >
> > > > > Thanks,
> > > > > Jozef
> > > >
> > > > I'm not much more than a random voice, but an assembly directive
> > > > that specifies the symbol (IIUC your .retain directive) to
> > >
> > > But .retain directive DOES NOT adjust symbol attribute.

I see I missed to point out that I was speaking about the *gcc
symbol* attribute "used".

> > > Instead, it sets
> > > the SHF_GNU_RETAIN bit on the section which contains the symbol
> > > definition.  The same section can have many unrelated symbols.
> >
> > That's an implementation detail *left to the assembler and
> > linker*.  It's not something the compiler needs to know, and
> > teoretically it could even change.
> >
>
> The ELF extension is SHF_GNU_RETAIN.  .retain directive is a hack
> which I strongly objected and showed that it wasn't needed to implement
> SHF_GNU_RETAIN in binutils.

It's still an implementation detail better kept in the
assembler, that the mechanism used to retain a symbol for the
compiler, happens to map to a section attribute.  Some may call
*that* a hack.

It's cleaner to the compiler if it can pass on to the assembler
the specific symbol that needs to be kept.

brgds, H-P
H.J. Lu Nov. 4, 2020, 10:18 p.m. UTC | #17
On Wed, Nov 4, 2020 at 1:56 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
>
>
> On Wed, 4 Nov 2020, H.J. Lu wrote:
>
> > On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > >
> > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > >
> > > > > On Wed, 4 Nov 2020, Jozef Lawrynowicz wrote:
> > > > > > I personally do not see the problem with the .retain attribute, however
> > > > > > if it is going to be a barrier to getting the functionality committed, I
> > > > > > am happy to change it, since I really just want the functionality in
> > > > > > upstream sources.
> > > > > >
> > > > > > If a global maintainer would comment on whether any of the proposed
> > > > > > approaches are acceptable, then I will try to block out time from other
> > > > > > deadlines so I can work on the fixups and submit a patch in time for the
> > > > > > GCC 11 freeze.
> > > > > >
> > > > > > Thanks,
> > > > > > Jozef
> > > > >
> > > > > I'm not much more than a random voice, but an assembly directive
> > > > > that specifies the symbol (IIUC your .retain directive) to
> > > >
> > > > But .retain directive DOES NOT adjust symbol attribute.
>
> I see I missed to point out that I was speaking about the *gcc
> symbol* attribute "used".

There is no such corresponding symbol attribute in ELF.

> > > > Instead, it sets
> > > > the SHF_GNU_RETAIN bit on the section which contains the symbol
> > > > definition.  The same section can have many unrelated symbols.
> > >
> > > That's an implementation detail *left to the assembler and
> > > linker*.  It's not something the compiler needs to know, and
> > > teoretically it could even change.
> > >
> >
> > The ELF extension is SHF_GNU_RETAIN.  .retain directive is a hack
> > which I strongly objected and showed that it wasn't needed to implement
> > SHF_GNU_RETAIN in binutils.
>
> It's still an implementation detail better kept in the
> assembler, that the mechanism used to retain a symbol for the
> compiler, happens to map to a section attribute.  Some may call
> *that* a hack.
>
> It's cleaner to the compiler if it can pass on to the assembler
> the specific symbol that needs to be kept.
>

SHF_GNU_RETAIN is for section and GCC should place the symbol,
which should be kept, in the SHF_GNU_RETAIN section directly, not
through .retain directive.
Hans-Peter Nilsson Nov. 4, 2020, 11 p.m. UTC | #18
On Wed, 4 Nov 2020, H.J. Lu wrote:
> On Wed, Nov 4, 2020 at 1:56 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > On Wed, 4 Nov 2020, H.J. Lu wrote:
> >
> > > On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > >
> > > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > > > I'm not much more than a random voice, but an assembly directive
> > > > > > that specifies the symbol (IIUC your .retain directive) to
> > > > >
> > > > > But .retain directive DOES NOT adjust symbol attribute.
> >
> > I see I missed to point out that I was speaking about the *gcc
> > symbol* attribute "used".
>
> There is no such corresponding symbol attribute in ELF.

I have not missed that, nor that SHF_GNU_RETAIN is so new that
it's not in binutils master.  I have also not missed that gcc
caters to other object formats too.  A common symbol-specific
directive such as .retain, would be better than messing with
section attributes, for gcc.

> > It's cleaner to the compiler if it can pass on to the assembler
> > the specific symbol that needs to be kept.
> >
>
> SHF_GNU_RETAIN is for section and GCC should place the symbol,
> which should be kept, in the SHF_GNU_RETAIN section directly, not
> through .retain directive.

This is where opinions differ.  Anyway, this is now repetition;
I'm done.

brgds, H-P
H.J. Lu Nov. 4, 2020, 11:58 p.m. UTC | #19
On Wed, Nov 4, 2020 at 3:00 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > On Wed, Nov 4, 2020 at 1:56 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > >
> > > > On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > >
> > > > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > > > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > > > > I'm not much more than a random voice, but an assembly directive
> > > > > > > that specifies the symbol (IIUC your .retain directive) to
> > > > > >
> > > > > > But .retain directive DOES NOT adjust symbol attribute.
> > >
> > > I see I missed to point out that I was speaking about the *gcc
> > > symbol* attribute "used".
> >
> > There is no such corresponding symbol attribute in ELF.
>
> I have not missed that, nor that SHF_GNU_RETAIN is so new that
> it's not in binutils master.  I have also not missed that gcc
> caters to other object formats too.  A common symbol-specific
> directive such as .retain, would be better than messing with
> section attributes, for gcc.

This is totally irrelevant to SHF_GNU_RETAIN.

> > > It's cleaner to the compiler if it can pass on to the assembler
> > > the specific symbol that needs to be kept.
> > >
> >
> > SHF_GNU_RETAIN is for section and GCC should place the symbol,
> > which should be kept, in the SHF_GNU_RETAIN section directly, not
> > through .retain directive.
>
> This is where opinions differ.  Anyway, this is now repetition;
> I'm done.

.retain is ill-defined.   For example,

[hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
static int xyzzy __attribute__((__used__));
[hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
[hjl@gnu-cfl-2 gcc]$ cat x.s
.file "x.c"
.text
.retain xyzzy  <<<<<<<<< What does it do?
.local xyzzy
.comm xyzzy,4,4
.ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
.section .note.GNU-stack,"",@progbits
[hjl@gnu-cfl-2 gcc]$

A symbol directive should operate on the symbol table.
With 'R' flag, we got

.file "x.c"
.text
.section .bss.xyzzy,"awR",@nobits
.align 4
.type xyzzy, @object
.size xyzzy, 4
xyzzy:
.zero 4
.ident "GCC: (GNU) 11.0.0 20201104 (experimental)"
.section .note.GNU-stack,"",@progbits
Jozef Lawrynowicz Nov. 5, 2020, 11 a.m. UTC | #20
On Wed, Nov 04, 2020 at 03:58:56PM -0800, H.J. Lu wrote:
> On Wed, Nov 4, 2020 at 3:00 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> >
> > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > On Wed, Nov 4, 2020 at 1:56 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > >
> > > > > On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > > >
> > > > > > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > > > > On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > > > > > > > I'm not much more than a random voice, but an assembly directive
> > > > > > > > that specifies the symbol (IIUC your .retain directive) to
> > > > > > >
> > > > > > > But .retain directive DOES NOT adjust symbol attribute.
> > > >
> > > > I see I missed to point out that I was speaking about the *gcc
> > > > symbol* attribute "used".
> > >
> > > There is no such corresponding symbol attribute in ELF.
> >
> > I have not missed that, nor that SHF_GNU_RETAIN is so new that
> > it's not in binutils master.  I have also not missed that gcc
> > caters to other object formats too.  A common symbol-specific
> > directive such as .retain, would be better than messing with
> > section attributes, for gcc.
> 
> This is totally irrelevant to SHF_GNU_RETAIN.
> 
> > > > It's cleaner to the compiler if it can pass on to the assembler
> > > > the specific symbol that needs to be kept.
> > > >
> > >
> > > SHF_GNU_RETAIN is for section and GCC should place the symbol,
> > > which should be kept, in the SHF_GNU_RETAIN section directly, not
> > > through .retain directive.
> >
> > This is where opinions differ.  Anyway, this is now repetition;
> > I'm done.
> 
> .retain is ill-defined.   For example,
> 
> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> static int xyzzy __attribute__((__used__));
> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> [hjl@gnu-cfl-2 gcc]$ cat x.s
> .file "x.c"
> .text
> .retain xyzzy  <<<<<<<<< What does it do?
> .local xyzzy
> .comm xyzzy,4,4
> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> .section .note.GNU-stack,"",@progbits
> [hjl@gnu-cfl-2 gcc]$
> 
> A symbol directive should operate on the symbol table.
> With 'R' flag, we got
> 
> .file "x.c"
> .text
> .section .bss.xyzzy,"awR",@nobits
> .align 4
> .type xyzzy, @object
> .size xyzzy, 4
> xyzzy:
> .zero 4
> .ident "GCC: (GNU) 11.0.0 20201104 (experimental)"
> .section .note.GNU-stack,"",@progbits

I still think it is very wrong for the "used" attribute to place the
symbol in a unique section. The structure of the sections in the object
file should be no different whether the "used" attribute was applied to
a symbol or not.

I will therefore have to make changes to GCC so that we can get the name
of "unnamed" sections, and emit a .section directive with the "R" flag
set on that section name, in order to avoid using a .retain directive.

"used" applied to a function
---
  Before:
    TEXT_SECTION_ASM_OP 
    func:

  After:
    .section TEXT_SECTION_NAME,"axR",%progbits
    func:

Where TEXT_SECTION_NAME is a new macro which defines the section name
corresponding to TEXT_SECTION_ASM_OP.
Similar new macros are required for all *SECTION_ASM_OP.

Since we can't use the .retain directive, this is the cludge that will
be required to robustly support all targets.

The alternative is to just infer that the mapping of unnamed sections to
section names is always the following:
  text_section    -> .text,"ax",%progbits
  data_section    -> .data,"aw"
  bss_section     -> .bss,"aw",%nobits
  rodata_section  -> .rodata,"a",
  etc.

This section name assumption does not hold for a couple of ELF targets.

Also, many targets omit the specification of the flags, leaving that
choice to the assembler, instead the compiler will now have to infer
what the assembler will do, all because we can't have the .retain
directive.

.retain <symname> makes life very easy for GCC, but I understand your
objection from a theoretical point of view.

You previously objected to .retain <section_name>, to apply
SHF_GNU_RETAIN to <section_name>. This does not violate your rule about
a directive applying flags to a different type of structure to what is
named in the directive.

If we can have .retain <section_name>, then we don't have to make
assumptions about section flags in GCC, we can just name the section use
in the ASM_OP.

Do you still oppose .retain <section_name>?

Another alternative is to disallow "used" from applying SHF_GNU_RETAIN,
unless the symbol is in a named section. Obviously this is pretty gross,
but would mean we don't need to handle *SECTION_ASM_OP sections.

Thanks,
Jozef
> 
> -- 
> H.J.
Hans-Peter Nilsson Nov. 5, 2020, 11:21 a.m. UTC | #21
On Wed, 4 Nov 2020, H.J. Lu wrote:
> .retain is ill-defined.   For example,
>
> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> static int xyzzy __attribute__((__used__));
> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> [hjl@gnu-cfl-2 gcc]$ cat x.s
> .file "x.c"
> .text
> .retain xyzzy  <<<<<<<<< What does it do?
> .local xyzzy
> .comm xyzzy,4,4
> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> .section .note.GNU-stack,"",@progbits
> [hjl@gnu-cfl-2 gcc]$

To answer that question: it's up to the assembler, but for ELF
and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
set SHF_GNU_RETAIN for the section where the symbol ends up.
We both know this isn't rocket science with binutils.

brgds, H-P
Jozef Lawrynowicz Nov. 5, 2020, 11:37 a.m. UTC | #22
On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > .retain is ill-defined.   For example,
> >
> > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > static int xyzzy __attribute__((__used__));
> > [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > [hjl@gnu-cfl-2 gcc]$ cat x.s
> > .file "x.c"
> > .text
> > .retain xyzzy  <<<<<<<<< What does it do?
> > .local xyzzy
> > .comm xyzzy,4,4
> > .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > .section .note.GNU-stack,"",@progbits
> > [hjl@gnu-cfl-2 gcc]$
> 
> To answer that question: it's up to the assembler, but for ELF
> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> set SHF_GNU_RETAIN for the section where the symbol ends up.
> We both know this isn't rocket science with binutils.

Indeed, and my patch handles it trivially:
https://sourceware.org/pipermail/binutils/2020-November/113993.html

  +void
  +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
  .... snip ....
  +  sym = get_sym_from_input_line_and_check ();
  +  symbol_get_obj (sym)->retain = 1;

  @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
    }
       }
   
  +  if (symbol_get_obj (symp)->retain)
  +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
  +
     /* Double check weak symbols.  */
     if (S_IS_WEAK (symp))
       {

We could check that the symbol named in the .retain directive has
already been defined, however this isn't compatible with GCC
mark_decl_preserved handling, since mark_decl_preserved is called
emitted before the local symbols are defined in the assembly output
file.

GAS should at least validate that the symbol named in the .retain
directive does end up as a symbol though.

Thanks,
Jozef


> 
> brgds, H-P
H.J. Lu Nov. 5, 2020, 2:34 p.m. UTC | #23
On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > .retain is ill-defined.   For example,
> > >
> > > [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > static int xyzzy __attribute__((__used__));
> > > [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > > [hjl@gnu-cfl-2 gcc]$ cat x.s
> > > .file "x.c"
> > > .text
> > > .retain xyzzy  <<<<<<<<< What does it do?
> > > .local xyzzy
> > > .comm xyzzy,4,4
> > > .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > > .section .note.GNU-stack,"",@progbits
> > > [hjl@gnu-cfl-2 gcc]$
> >
> > To answer that question: it's up to the assembler, but for ELF
> > and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > set SHF_GNU_RETAIN for the section where the symbol ends up.
> > We both know this isn't rocket science with binutils.
>
> Indeed, and my patch handles it trivially:
> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>
>   +void
>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
>   .... snip ....
>   +  sym = get_sym_from_input_line_and_check ();
>   +  symbol_get_obj (sym)->retain = 1;
>
>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
>     }
>        }
>
>   +  if (symbol_get_obj (symp)->retain)
>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
>   +
>      /* Double check weak symbols.  */
>      if (S_IS_WEAK (symp))
>        {
>
> We could check that the symbol named in the .retain directive has
> already been defined, however this isn't compatible with GCC
> mark_decl_preserved handling, since mark_decl_preserved is called
> emitted before the local symbols are defined in the assembly output
> file.
>
> GAS should at least validate that the symbol named in the .retain
> directive does end up as a symbol though.
>

Don't add .retain.
Jeff Law Nov. 6, 2020, 11:21 p.m. UTC | #24
On 11/5/20 4:00 AM, Jozef Lawrynowicz wrote:
> On Wed, Nov 04, 2020 at 03:58:56PM -0800, H.J. Lu wrote:
>> On Wed, Nov 4, 2020 at 3:00 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>> On Wed, Nov 4, 2020 at 1:56 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>>>
>>>>>> On Wed, Nov 4, 2020 at 1:03 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>>>>>> On Wed, Nov 4, 2020 at 10:09 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>>>>>>>>> I'm not much more than a random voice, but an assembly directive
>>>>>>>>> that specifies the symbol (IIUC your .retain directive) to
>>>>>>>> But .retain directive DOES NOT adjust symbol attribute.
>>>>> I see I missed to point out that I was speaking about the *gcc
>>>>> symbol* attribute "used".
>>>> There is no such corresponding symbol attribute in ELF.
>>> I have not missed that, nor that SHF_GNU_RETAIN is so new that
>>> it's not in binutils master.  I have also not missed that gcc
>>> caters to other object formats too.  A common symbol-specific
>>> directive such as .retain, would be better than messing with
>>> section attributes, for gcc.
>> This is totally irrelevant to SHF_GNU_RETAIN.
>>
>>>>> It's cleaner to the compiler if it can pass on to the assembler
>>>>> the specific symbol that needs to be kept.
>>>>>
>>>> SHF_GNU_RETAIN is for section and GCC should place the symbol,
>>>> which should be kept, in the SHF_GNU_RETAIN section directly, not
>>>> through .retain directive.
>>> This is where opinions differ.  Anyway, this is now repetition;
>>> I'm done.
>> .retain is ill-defined.   For example,
>>
>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
>> static int xyzzy __attribute__((__used__));
>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
>> [hjl@gnu-cfl-2 gcc]$ cat x.s
>> .file "x.c"
>> .text
>> .retain xyzzy  <<<<<<<<< What does it do?
>> .local xyzzy
>> .comm xyzzy,4,4
>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
>> .section .note.GNU-stack,"",@progbits
>> [hjl@gnu-cfl-2 gcc]$
>>
>> A symbol directive should operate on the symbol table.
>> With 'R' flag, we got
>>
>> .file "x.c"
>> .text
>> .section .bss.xyzzy,"awR",@nobits
>> .align 4
>> .type xyzzy, @object
>> .size xyzzy, 4
>> xyzzy:
>> .zero 4
>> .ident "GCC: (GNU) 11.0.0 20201104 (experimental)"
>> .section .note.GNU-stack,"",@progbits
> I still think it is very wrong for the "used" attribute to place the
> symbol in a unique section. The structure of the sections in the object
> file should be no different whether the "used" attribute was applied to
> a symbol or not.

I tend to agree here.  Also note that someone could have a section
attribute in addition to the used attribute and that section attribute
might reference any arbitrary section.


> I will therefore have to make changes to GCC so that we can get the name
> of "unnamed" sections, and emit a .section directive with the "R" flag
> set on that section name, in order to avoid using a .retain directive.

ISTM that we could have the .retain <sym> set the R flag in the bfd
section associated with <sym>'s definition.  That has other impacts
(namely that anything else in the same section is retained as well).


THe other alternative is to carry the attribute on the symbol into the
linker and teach the linker about the new symbol flag.


I don't have any fundamental objections to .retain.  I'm not sure why HJ
is so dead set against it.


jeff
Jeff Law Nov. 6, 2020, 11:22 p.m. UTC | #25
On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>> .retain is ill-defined.   For example,
>>>>
>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
>>>> static int xyzzy __attribute__((__used__));
>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
>>>> .file "x.c"
>>>> .text
>>>> .retain xyzzy  <<<<<<<<< What does it do?
>>>> .local xyzzy
>>>> .comm xyzzy,4,4
>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
>>>> .section .note.GNU-stack,"",@progbits
>>>> [hjl@gnu-cfl-2 gcc]$
>>> To answer that question: it's up to the assembler, but for ELF
>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
>>> We both know this isn't rocket science with binutils.
>> Indeed, and my patch handles it trivially:
>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>>
>>   +void
>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
>>   .... snip ....
>>   +  sym = get_sym_from_input_line_and_check ();
>>   +  symbol_get_obj (sym)->retain = 1;
>>
>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
>>     }
>>        }
>>
>>   +  if (symbol_get_obj (symp)->retain)
>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
>>   +
>>      /* Double check weak symbols.  */
>>      if (S_IS_WEAK (symp))
>>        {
>>
>> We could check that the symbol named in the .retain directive has
>> already been defined, however this isn't compatible with GCC
>> mark_decl_preserved handling, since mark_decl_preserved is called
>> emitted before the local symbols are defined in the assembly output
>> file.
>>
>> GAS should at least validate that the symbol named in the .retain
>> directive does end up as a symbol though.
>>
> Don't add .retain.

Why?  I don't see why you find it so objectionable.


jeff
H.J. Lu Nov. 6, 2020, 11:29 p.m. UTC | #26
On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
>
>
> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> >> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> >>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> >>>> .retain is ill-defined.   For example,
> >>>>
> >>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> >>>> static int xyzzy __attribute__((__used__));
> >>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> >>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> >>>> .file "x.c"
> >>>> .text
> >>>> .retain xyzzy  <<<<<<<<< What does it do?
> >>>> .local xyzzy
> >>>> .comm xyzzy,4,4
> >>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> >>>> .section .note.GNU-stack,"",@progbits
> >>>> [hjl@gnu-cfl-2 gcc]$
> >>> To answer that question: it's up to the assembler, but for ELF
> >>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> >>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> >>> We both know this isn't rocket science with binutils.
> >> Indeed, and my patch handles it trivially:
> >> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> >>
> >>   +void
> >>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> >>   .... snip ....
> >>   +  sym = get_sym_from_input_line_and_check ();
> >>   +  symbol_get_obj (sym)->retain = 1;
> >>
> >>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> >>     }
> >>        }
> >>
> >>   +  if (symbol_get_obj (symp)->retain)
> >>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> >>   +
> >>      /* Double check weak symbols.  */
> >>      if (S_IS_WEAK (symp))
> >>        {
> >>
> >> We could check that the symbol named in the .retain directive has
> >> already been defined, however this isn't compatible with GCC
> >> mark_decl_preserved handling, since mark_decl_preserved is called
> >> emitted before the local symbols are defined in the assembly output
> >> file.
> >>
> >> GAS should at least validate that the symbol named in the .retain
> >> directive does end up as a symbol though.
> >>
> > Don't add .retain.
>
> Why?  I don't see why you find it so objectionable.
>

An ELF symbol directive should operate on symbol table:

http://www.sco.com/developers/gabi/latest/ch4.symtab.html

not the section flags where the symbol is defined.
Jeff Law Nov. 6, 2020, 11:37 p.m. UTC | #27
On 11/6/20 4:29 PM, H.J. Lu wrote:
> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
>>
>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
>>> <jozef.l@mittosystems.com> wrote:
>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>>>> .retain is ill-defined.   For example,
>>>>>>
>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
>>>>>> static int xyzzy __attribute__((__used__));
>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
>>>>>> .file "x.c"
>>>>>> .text
>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
>>>>>> .local xyzzy
>>>>>> .comm xyzzy,4,4
>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
>>>>>> .section .note.GNU-stack,"",@progbits
>>>>>> [hjl@gnu-cfl-2 gcc]$
>>>>> To answer that question: it's up to the assembler, but for ELF
>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
>>>>> We both know this isn't rocket science with binutils.
>>>> Indeed, and my patch handles it trivially:
>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>>>>
>>>>   +void
>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
>>>>   .... snip ....
>>>>   +  sym = get_sym_from_input_line_and_check ();
>>>>   +  symbol_get_obj (sym)->retain = 1;
>>>>
>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
>>>>     }
>>>>        }
>>>>
>>>>   +  if (symbol_get_obj (symp)->retain)
>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
>>>>   +
>>>>      /* Double check weak symbols.  */
>>>>      if (S_IS_WEAK (symp))
>>>>        {
>>>>
>>>> We could check that the symbol named in the .retain directive has
>>>> already been defined, however this isn't compatible with GCC
>>>> mark_decl_preserved handling, since mark_decl_preserved is called
>>>> emitted before the local symbols are defined in the assembly output
>>>> file.
>>>>
>>>> GAS should at least validate that the symbol named in the .retain
>>>> directive does end up as a symbol though.
>>>>
>>> Don't add .retain.
>> Why?  I don't see why you find it so objectionable.
>>
> An ELF symbol directive should operate on symbol table:
>
> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
>
> not the section flags where the symbol is defined.

I agree in general, but I think this is one of those cases where it's
not so clear.  And what you're talking about is an implementation detail.


jeff
H.J. Lu Nov. 6, 2020, 11:45 p.m. UTC | #28
On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
>
>
> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> >>
> >> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> >>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> >>> <jozef.l@mittosystems.com> wrote:
> >>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> >>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> >>>>>> .retain is ill-defined.   For example,
> >>>>>>
> >>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> >>>>>> static int xyzzy __attribute__((__used__));
> >>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> >>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> >>>>>> .file "x.c"
> >>>>>> .text
> >>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> >>>>>> .local xyzzy
> >>>>>> .comm xyzzy,4,4
> >>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> >>>>>> .section .note.GNU-stack,"",@progbits
> >>>>>> [hjl@gnu-cfl-2 gcc]$
> >>>>> To answer that question: it's up to the assembler, but for ELF
> >>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> >>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> >>>>> We both know this isn't rocket science with binutils.
> >>>> Indeed, and my patch handles it trivially:
> >>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> >>>>
> >>>>   +void
> >>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> >>>>   .... snip ....
> >>>>   +  sym = get_sym_from_input_line_and_check ();
> >>>>   +  symbol_get_obj (sym)->retain = 1;
> >>>>
> >>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> >>>>     }
> >>>>        }
> >>>>
> >>>>   +  if (symbol_get_obj (symp)->retain)
> >>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> >>>>   +
> >>>>      /* Double check weak symbols.  */
> >>>>      if (S_IS_WEAK (symp))
> >>>>        {
> >>>>
> >>>> We could check that the symbol named in the .retain directive has
> >>>> already been defined, however this isn't compatible with GCC
> >>>> mark_decl_preserved handling, since mark_decl_preserved is called
> >>>> emitted before the local symbols are defined in the assembly output
> >>>> file.
> >>>>
> >>>> GAS should at least validate that the symbol named in the .retain
> >>>> directive does end up as a symbol though.
> >>>>
> >>> Don't add .retain.
> >> Why?  I don't see why you find it so objectionable.
> >>
> > An ELF symbol directive should operate on symbol table:
> >
> > http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> >
> > not the section flags where the symbol is defined.
>
> I agree in general, but I think this is one of those cases where it's
> not so clear.  And what you're talking about is an implementation detail.

There is no need for such a hack.  The proper thing to do in ELF is
to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
also avoids the question what to do with SHN_COMMON.
Jeff Law Nov. 7, 2020, 12:01 a.m. UTC | #29
On 11/6/20 4:45 PM, H.J. Lu wrote:
> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
>>
>> On 11/6/20 4:29 PM, H.J. Lu wrote:
>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
>>>>> <jozef.l@mittosystems.com> wrote:
>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>>>>>> .retain is ill-defined.   For example,
>>>>>>>>
>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
>>>>>>>> static int xyzzy __attribute__((__used__));
>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
>>>>>>>> .file "x.c"
>>>>>>>> .text
>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
>>>>>>>> .local xyzzy
>>>>>>>> .comm xyzzy,4,4
>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
>>>>>>>> .section .note.GNU-stack,"",@progbits
>>>>>>>> [hjl@gnu-cfl-2 gcc]$
>>>>>>> To answer that question: it's up to the assembler, but for ELF
>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
>>>>>>> We both know this isn't rocket science with binutils.
>>>>>> Indeed, and my patch handles it trivially:
>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>>>>>>
>>>>>>   +void
>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
>>>>>>   .... snip ....
>>>>>>   +  sym = get_sym_from_input_line_and_check ();
>>>>>>   +  symbol_get_obj (sym)->retain = 1;
>>>>>>
>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
>>>>>>     }
>>>>>>        }
>>>>>>
>>>>>>   +  if (symbol_get_obj (symp)->retain)
>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
>>>>>>   +
>>>>>>      /* Double check weak symbols.  */
>>>>>>      if (S_IS_WEAK (symp))
>>>>>>        {
>>>>>>
>>>>>> We could check that the symbol named in the .retain directive has
>>>>>> already been defined, however this isn't compatible with GCC
>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
>>>>>> emitted before the local symbols are defined in the assembly output
>>>>>> file.
>>>>>>
>>>>>> GAS should at least validate that the symbol named in the .retain
>>>>>> directive does end up as a symbol though.
>>>>>>
>>>>> Don't add .retain.
>>>> Why?  I don't see why you find it so objectionable.
>>>>
>>> An ELF symbol directive should operate on symbol table:
>>>
>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
>>>
>>> not the section flags where the symbol is defined.
>> I agree in general, but I think this is one of those cases where it's
>> not so clear.  And what you're talking about is an implementation detail.
> There is no need for such a hack.  The proper thing to do in ELF is
> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> also avoids the question what to do with SHN_COMMON.

I'm not sure that's a good idea either.  Moving symbols into a section
other than they'd normally live doesn't seem all that wise.


Let's face it, there's not a great solution here.  If we mark its
existing section, then everything in that section gets kept.  If we put
the object into a different section than it would normally live, then
that opens a whole new can of worms.


jeff
H.J. Lu Nov. 7, 2020, 12:13 a.m. UTC | #30
On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
>
>
> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> >>
> >> On 11/6/20 4:29 PM, H.J. Lu wrote:
> >>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> >>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> >>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> >>>>> <jozef.l@mittosystems.com> wrote:
> >>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> >>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> >>>>>>>> .retain is ill-defined.   For example,
> >>>>>>>>
> >>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> >>>>>>>> static int xyzzy __attribute__((__used__));
> >>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> >>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> >>>>>>>> .file "x.c"
> >>>>>>>> .text
> >>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> >>>>>>>> .local xyzzy
> >>>>>>>> .comm xyzzy,4,4
> >>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> >>>>>>>> .section .note.GNU-stack,"",@progbits
> >>>>>>>> [hjl@gnu-cfl-2 gcc]$
> >>>>>>> To answer that question: it's up to the assembler, but for ELF
> >>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> >>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> >>>>>>> We both know this isn't rocket science with binutils.
> >>>>>> Indeed, and my patch handles it trivially:
> >>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> >>>>>>
> >>>>>>   +void
> >>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> >>>>>>   .... snip ....
> >>>>>>   +  sym = get_sym_from_input_line_and_check ();
> >>>>>>   +  symbol_get_obj (sym)->retain = 1;
> >>>>>>
> >>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> >>>>>>     }
> >>>>>>        }
> >>>>>>
> >>>>>>   +  if (symbol_get_obj (symp)->retain)
> >>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> >>>>>>   +
> >>>>>>      /* Double check weak symbols.  */
> >>>>>>      if (S_IS_WEAK (symp))
> >>>>>>        {
> >>>>>>
> >>>>>> We could check that the symbol named in the .retain directive has
> >>>>>> already been defined, however this isn't compatible with GCC
> >>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> >>>>>> emitted before the local symbols are defined in the assembly output
> >>>>>> file.
> >>>>>>
> >>>>>> GAS should at least validate that the symbol named in the .retain
> >>>>>> directive does end up as a symbol though.
> >>>>>>
> >>>>> Don't add .retain.
> >>>> Why?  I don't see why you find it so objectionable.
> >>>>
> >>> An ELF symbol directive should operate on symbol table:
> >>>
> >>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> >>>
> >>> not the section flags where the symbol is defined.
> >> I agree in general, but I think this is one of those cases where it's
> >> not so clear.  And what you're talking about is an implementation detail.
> > There is no need for such a hack.  The proper thing to do in ELF is
> > to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > also avoids the question what to do with SHN_COMMON.
>
> I'm not sure that's a good idea either.  Moving symbols into a section
> other than they'd normally live doesn't seem all that wise.

In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
we should place it in an SHF_GNU_RETAIN section.

>
> Let's face it, there's not a great solution here.  If we mark its
> existing section, then everything in that section gets kept.  If we put

FWIW, this is what .retain direct does and is one reason why I object
it.

> the object into a different section than it would normally live, then
> that opens a whole new can of worms.

We should place it in a section which it normally lives in and mark the
section with SHF_GNU_RETAIN.
Jeff Law Nov. 7, 2020, 12:17 a.m. UTC | #31
On 11/6/20 5:13 PM, H.J. Lu wrote:
> On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
>>
>> On 11/6/20 4:45 PM, H.J. Lu wrote:
>>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
>>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
>>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
>>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
>>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
>>>>>>> <jozef.l@mittosystems.com> wrote:
>>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
>>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
>>>>>>>>>> .retain is ill-defined.   For example,
>>>>>>>>>>
>>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
>>>>>>>>>> static int xyzzy __attribute__((__used__));
>>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
>>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
>>>>>>>>>> .file "x.c"
>>>>>>>>>> .text
>>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
>>>>>>>>>> .local xyzzy
>>>>>>>>>> .comm xyzzy,4,4
>>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
>>>>>>>>>> .section .note.GNU-stack,"",@progbits
>>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
>>>>>>>>> To answer that question: it's up to the assembler, but for ELF
>>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
>>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
>>>>>>>>> We both know this isn't rocket science with binutils.
>>>>>>>> Indeed, and my patch handles it trivially:
>>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
>>>>>>>>
>>>>>>>>   +void
>>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
>>>>>>>>   .... snip ....
>>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
>>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
>>>>>>>>
>>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
>>>>>>>>     }
>>>>>>>>        }
>>>>>>>>
>>>>>>>>   +  if (symbol_get_obj (symp)->retain)
>>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
>>>>>>>>   +
>>>>>>>>      /* Double check weak symbols.  */
>>>>>>>>      if (S_IS_WEAK (symp))
>>>>>>>>        {
>>>>>>>>
>>>>>>>> We could check that the symbol named in the .retain directive has
>>>>>>>> already been defined, however this isn't compatible with GCC
>>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
>>>>>>>> emitted before the local symbols are defined in the assembly output
>>>>>>>> file.
>>>>>>>>
>>>>>>>> GAS should at least validate that the symbol named in the .retain
>>>>>>>> directive does end up as a symbol though.
>>>>>>>>
>>>>>>> Don't add .retain.
>>>>>> Why?  I don't see why you find it so objectionable.
>>>>>>
>>>>> An ELF symbol directive should operate on symbol table:
>>>>>
>>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
>>>>>
>>>>> not the section flags where the symbol is defined.
>>>> I agree in general, but I think this is one of those cases where it's
>>>> not so clear.  And what you're talking about is an implementation detail.
>>> There is no need for such a hack.  The proper thing to do in ELF is
>>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
>>> also avoids the question what to do with SHN_COMMON.
>> I'm not sure that's a good idea either.  Moving symbols into a section
>> other than they'd normally live doesn't seem all that wise.
> In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> we should place it in an SHF_GNU_RETAIN section.

Again, that's an implementation detail and it's not clear to me that one
approach is inherently better than the other.


>
>> Let's face it, there's not a great solution here.  If we mark its
>> existing section, then everything in that section gets kept.  If we put
> FWIW, this is what .retain direct does and is one reason why I object
> it.

We could make .retain work with either approach.    I don't see .retain
as a problem at all. 



>
>> the object into a different section than it would normally live, then
>> that opens a whole new can of worms.
> We should place it in a section which it normally lives in and mark the
> section with SHF_GNU_RETAIN.

And why not do that with .retain?  We define its semantics as precisely
what you've written above.  The referenced symbol goes into its usual
section and its section is marked with SHF_GNU_RETAIN.  That seems much
cleaner than having to track all this in the compiler so that it can
twiddle the section flags.


jeff

>
H.J. Lu Nov. 7, 2020, 12:39 a.m. UTC | #32
On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
>
>
> On 11/6/20 5:13 PM, H.J. Lu wrote:
> > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> >>
> >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> >>>>>>> <jozef.l@mittosystems.com> wrote:
> >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> >>>>>>>>>> .retain is ill-defined.   For example,
> >>>>>>>>>>
> >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> >>>>>>>>>> static int xyzzy __attribute__((__used__));
> >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> >>>>>>>>>> .file "x.c"
> >>>>>>>>>> .text
> >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> >>>>>>>>>> .local xyzzy
> >>>>>>>>>> .comm xyzzy,4,4
> >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> >>>>>>>>> We both know this isn't rocket science with binutils.
> >>>>>>>> Indeed, and my patch handles it trivially:
> >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> >>>>>>>>
> >>>>>>>>   +void
> >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> >>>>>>>>   .... snip ....
> >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> >>>>>>>>
> >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> >>>>>>>>     }
> >>>>>>>>        }
> >>>>>>>>
> >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> >>>>>>>>   +
> >>>>>>>>      /* Double check weak symbols.  */
> >>>>>>>>      if (S_IS_WEAK (symp))
> >>>>>>>>        {
> >>>>>>>>
> >>>>>>>> We could check that the symbol named in the .retain directive has
> >>>>>>>> already been defined, however this isn't compatible with GCC
> >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> >>>>>>>> emitted before the local symbols are defined in the assembly output
> >>>>>>>> file.
> >>>>>>>>
> >>>>>>>> GAS should at least validate that the symbol named in the .retain
> >>>>>>>> directive does end up as a symbol though.
> >>>>>>>>
> >>>>>>> Don't add .retain.
> >>>>>> Why?  I don't see why you find it so objectionable.
> >>>>>>
> >>>>> An ELF symbol directive should operate on symbol table:
> >>>>>
> >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> >>>>>
> >>>>> not the section flags where the symbol is defined.
> >>>> I agree in general, but I think this is one of those cases where it's
> >>>> not so clear.  And what you're talking about is an implementation detail.
> >>> There is no need for such a hack.  The proper thing to do in ELF is
> >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> >>> also avoids the question what to do with SHN_COMMON.
> >> I'm not sure that's a good idea either.  Moving symbols into a section
> >> other than they'd normally live doesn't seem all that wise.
> > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > we should place it in an SHF_GNU_RETAIN section.
>
> Again, that's an implementation detail and it's not clear to me that one
> approach is inherently better than the other.
>
>
> >
> >> Let's face it, there's not a great solution here.  If we mark its
> >> existing section, then everything in that section gets kept.  If we put
> > FWIW, this is what .retain direct does and is one reason why I object
> > it.
>
> We could make .retain work with either approach.    I don't see .retain
> as a problem at all.
>
>
>
> >
> >> the object into a different section than it would normally live, then
> >> that opens a whole new can of worms.
> > We should place it in a section which it normally lives in and mark the
> > section with SHF_GNU_RETAIN.
>
> And why not do that with .retain?  We define its semantics as precisely

But the .retain directive implementation being discussed here is different.
One problem with the .retain directive is we can have

.section .data
foo:
...
bar:

.retain bar
...
xxx:
...

What should assembler do with ".retain bar"?

> what you've written above.  The referenced symbol goes into its usual
> section and its section is marked with SHF_GNU_RETAIN.  That seems much
> cleaner than having to track all this in the compiler so that it can
> twiddle the section flags.

When GCC emits a symbol definition, it places the symbol in a section
with proper
attributes which GCC tracks for each symbol.  It  can be extended to track
SHF_GNU_RETAIN.
Jozef Lawrynowicz Nov. 9, 2020, 5:41 p.m. UTC | #33
On Fri, Nov 06, 2020 at 04:39:33PM -0800, H.J. Lu via Gcc-patches wrote:
> On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
> >
> >
> > On 11/6/20 5:13 PM, H.J. Lu wrote:
> > > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> > >>
> > >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> > >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> > >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > >>>>>>> <jozef.l@mittosystems.com> wrote:
> > >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > >>>>>>>>>> .retain is ill-defined.   For example,
> > >>>>>>>>>>
> > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > >>>>>>>>>> static int xyzzy __attribute__((__used__));
> > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> > >>>>>>>>>> .file "x.c"
> > >>>>>>>>>> .text
> > >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> > >>>>>>>>>> .local xyzzy
> > >>>>>>>>>> .comm xyzzy,4,4
> > >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> > >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> > >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> > >>>>>>>>> We both know this isn't rocket science with binutils.
> > >>>>>>>> Indeed, and my patch handles it trivially:
> > >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> > >>>>>>>>
> > >>>>>>>>   +void
> > >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> > >>>>>>>>   .... snip ....
> > >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> > >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> > >>>>>>>>
> > >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> > >>>>>>>>     }
> > >>>>>>>>        }
> > >>>>>>>>
> > >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> > >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> > >>>>>>>>   +
> > >>>>>>>>      /* Double check weak symbols.  */
> > >>>>>>>>      if (S_IS_WEAK (symp))
> > >>>>>>>>        {
> > >>>>>>>>
> > >>>>>>>> We could check that the symbol named in the .retain directive has
> > >>>>>>>> already been defined, however this isn't compatible with GCC
> > >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> > >>>>>>>> emitted before the local symbols are defined in the assembly output
> > >>>>>>>> file.
> > >>>>>>>>
> > >>>>>>>> GAS should at least validate that the symbol named in the .retain
> > >>>>>>>> directive does end up as a symbol though.
> > >>>>>>>>
> > >>>>>>> Don't add .retain.
> > >>>>>> Why?  I don't see why you find it so objectionable.
> > >>>>>>
> > >>>>> An ELF symbol directive should operate on symbol table:
> > >>>>>
> > >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> > >>>>>
> > >>>>> not the section flags where the symbol is defined.
> > >>>> I agree in general, but I think this is one of those cases where it's
> > >>>> not so clear.  And what you're talking about is an implementation detail.
> > >>> There is no need for such a hack.  The proper thing to do in ELF is
> > >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > >>> also avoids the question what to do with SHN_COMMON.
> > >> I'm not sure that's a good idea either.  Moving symbols into a section
> > >> other than they'd normally live doesn't seem all that wise.
> > > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > > we should place it in an SHF_GNU_RETAIN section.
> >
> > Again, that's an implementation detail and it's not clear to me that one
> > approach is inherently better than the other.
> >
> >
> > >
> > >> Let's face it, there's not a great solution here.  If we mark its
> > >> existing section, then everything in that section gets kept.  If we put
> > > FWIW, this is what .retain direct does and is one reason why I object
> > > it.
> >
> > We could make .retain work with either approach.    I don't see .retain
> > as a problem at all.
> >
> >
> >
> > >
> > >> the object into a different section than it would normally live, then
> > >> that opens a whole new can of worms.
> > > We should place it in a section which it normally lives in and mark the
> > > section with SHF_GNU_RETAIN.
> >
> > And why not do that with .retain?  We define its semantics as precisely
> 
> But the .retain directive implementation being discussed here is different.
> One problem with the .retain directive is we can have
> 
> .section .data
> foo:
> ...
> bar:
> 
> .retain bar
> ...
> xxx:
> ...
> 
> What should assembler do with ".retain bar"?
> 
> > what you've written above.  The referenced symbol goes into its usual
> > section and its section is marked with SHF_GNU_RETAIN.  That seems much
> > cleaner than having to track all this in the compiler so that it can
> > twiddle the section flags.
> 
> When GCC emits a symbol definition, it places the symbol in a section
> with proper
> attributes which GCC tracks for each symbol.  It  can be extended to track
> SHF_GNU_RETAIN.

The attached patch is rough around the edges but shows my approach for
marking unnamed sections as retained, by converting them to named
sections.

I figure we don't have to wrap every usage of SECTION_RETAIN in
HAVE_GAS_SECTION_RETAIN as long as any set of SECTION_RETAIN in the
flags field is wrapped in the macro.

I think a flag to turn off the behavior (in the same way the behavior is
disabled if !defined(HAVE_GAS_SECTION_RETAIN)) would be beneficial,
I haven't added that yet.

Decls that would go in comm_section, tls_comm_section and sometimes
lcomm_section do not get retained as we can't apply the retain section
flag to these symbols. Given these go in one big common block, and
contain uninitialized data, I don't think there is a valid use case for
which these types of symbols need to be retained, but are not referenced
by the program. So I've avoided converting them to .bss or anything like
that.

Some targets alias lcomm_section for bss_section, so we can retain
sections for that case.

So far bootstrap and light testing on x86_64-pc-linux-gnu and
arm-none-eabi has shown no problems.

Thanks,
Jozef

> 
> -- 
> H.J.
commit a24999de8a6c40f87f80bfbbe8383caf9f5a3507
Author: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date:   Sun Nov 8 21:36:59 2020 +0000

    used is retained

diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..d5bb48138d3 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1352,6 +1352,12 @@
 #endif
 
 
+/* Define if your assembler supports specifying the retain section flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SECTION_RETAIN
+#endif
+
+
 /* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
    */
 #ifndef USED_FOR_TARGET
diff --git a/gcc/config/arm/unknown-elf.h b/gcc/config/arm/unknown-elf.h
index 9ad2947505f..032539bc047 100644
--- a/gcc/config/arm/unknown-elf.h
+++ b/gcc/config/arm/unknown-elf.h
@@ -88,6 +88,10 @@
     }									\
   while (0)
 
+/* A local-common decl that is not in a named section will be placed in
+   bss_section.  */
+#define LCOMM_SECTION_NAME ".bss"
+
 /* The libgcc udivmod functions may throw exceptions.  If newlib is
    configured to support long longs in I/O, then printf will depend on
    udivmoddi4, which will depend on the exception unwind routines,
diff --git a/gcc/configure b/gcc/configure
index 9d2fd0dc30b..425725b358c 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24235,6 +24235,42 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# Test if the assembler supports the section flag 'R' for specifying a
+# section which should not be garbage collected by the linker.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section retain flag" >&5
+$as_echo_n "checking assembler for section retain flag... " >&6; }
+if ${gcc_cv_as_section_retain_r+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_section_retain_r=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '.section foo1,"aR"
+  .byte 0' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_section_retain_r=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_section_retain_r" >&5
+$as_echo "$gcc_cv_as_section_retain_r" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SECTION_RETAIN `if test $gcc_cv_as_section_retain_r = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
 $as_echo_n "checking assembler for section merging support... " >&6; }
 if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 73034bb902b..ae3fa794c8d 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3221,6 +3221,15 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
   [`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
 [Define if your assembler supports specifying the exclude section flag.])
 
+# Test if the assembler supports the section flag 'R' for specifying a
+# section which should not be garbage collected by the linker.
+gcc_GAS_CHECK_FEATURE([section retain flag], gcc_cv_as_section_retain_r,,,
+ [.section foo1,"aR"
+  .byte 0])
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_RETAIN,
+  [`if test $gcc_cv_as_section_retain_r = yes; then echo 1; else echo 0; fi`],
+[Define if your assembler supports specifying the retain section flag.])
+
 gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
  [elf,2,12,0], [--fatal-warnings],
  [.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/defaults.h b/gcc/defaults.h
index f1a38626624..26bd89bcc68 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -357,6 +357,33 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 #endif
 
+/* These section names define the name of the section used in
+   *_SECTION_ASM_OP macros, used when converting an unnamed or noswitch
+   section to a named section.  */
+#ifndef TEXT_SECTION_NAME
+#define TEXT_SECTION_NAME ".text"
+#endif
+
+#ifndef DATA_SECTION_NAME
+#define DATA_SECTION_NAME ".data"
+#endif
+
+#ifndef READONLY_DATA_SECTION_NAME
+#define READONLY_DATA_SECTION_NAME ".rodata"
+#endif
+
+#ifndef BSS_SECTION_NAME
+#define BSS_SECTION_NAME ".bss"
+#endif
+
+#ifndef SBSS_SECTION_NAME
+#define SBSS_SECTION_NAME ".sbss"
+#endif
+
+#ifndef SDATA_SECTION_NAME
+#define SDATA_SECTION_NAME ".sdata"
+#endif
+
 /* On many systems, different EH table encodings are used under
    difference circumstances.  Some will require runtime relocations;
    some will not.  For those that do not require runtime relocations,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 833320ba7bf..37291321c3a 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7599,6 +7599,47 @@ defined, GCC will assume such a section does not exist.  Do not define
 both this macro and @code{FINI_SECTION_ASM_OP}.
 @end defmac
 
+@defmac TEXT_SECTION_NAME
+A C string constant for the name of the section that TEXT_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.text}.
+@end defmac
+
+@defmac DATA_SECTION_NAME
+A C string constant for the name of the section that DATA_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.data}.
+@end defmac
+
+@defmac READONLY_DATA_SECTION_NAME
+A C string constant for the name of the section that
+READONLY_DATA_SECTION_ASM_OP will switch to.  If you don't define this,
+the default is @code{.rodata}.
+@end defmac
+
+@defmac BSS_SECTION_NAME
+A C string constant for the name of the section that BSS_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.bss}.
+@end defmac
+
+@defmac SDATA_SECTION_NAME
+A C string constant for the name of the section that SDATA_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.sdata}.
+@end defmac
+
+@defmac SBSS_SECTION_NAME
+A C string constant for the name of the section that SBSS_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.sbss}.
+@end defmac
+
+@defmac LCOMM_SECTION_NAME
+A C string constant for the name of the section that a local-common
+symbol would be placed in, as determined by the @code{ASM_OUTPUT*_LOCAL}
+macros.  If these macros do not place local-common symbols in sections,
+leave this undefined.  This affects the section local-common symbols
+marked with the @code{used} attribute are placed in.
+
+This macro is undefined by default.
+@end defmac
+
 @defmac MACH_DEP_SECTION_ASM_FLAG
 If defined, a C expression whose value is a character constant
 containing the flag used to mark a machine-dependent section.  This
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 58109be3693..64dd72c7dd8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4941,6 +4941,47 @@ defined, GCC will assume such a section does not exist.  Do not define
 both this macro and @code{FINI_SECTION_ASM_OP}.
 @end defmac
 
+@defmac TEXT_SECTION_NAME
+A C string constant for the name of the section that TEXT_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.text}.
+@end defmac
+
+@defmac DATA_SECTION_NAME
+A C string constant for the name of the section that DATA_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.data}.
+@end defmac
+
+@defmac READONLY_DATA_SECTION_NAME
+A C string constant for the name of the section that
+READONLY_DATA_SECTION_ASM_OP will switch to.  If you don't define this,
+the default is @code{.rodata}.
+@end defmac
+
+@defmac BSS_SECTION_NAME
+A C string constant for the name of the section that BSS_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.bss}.
+@end defmac
+
+@defmac SDATA_SECTION_NAME
+A C string constant for the name of the section that SDATA_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.sdata}.
+@end defmac
+
+@defmac SBSS_SECTION_NAME
+A C string constant for the name of the section that SBSS_SECTION_ASM_OP
+will switch to.  If you don't define this, the default is @code{.sbss}.
+@end defmac
+
+@defmac LCOMM_SECTION_NAME
+A C string constant for the name of the section that a local-common
+symbol would be placed in, as determined by the @code{ASM_OUTPUT*_LOCAL}
+macros.  If these macros do not place local-common symbols in sections,
+leave this undefined.  This affects the section local-common symbols
+marked with the @code{used} attribute are placed in.
+
+This macro is undefined by default.
+@end defmac
+
 @defmac MACH_DEP_SECTION_ASM_FLAG
 If defined, a C expression whose value is a character constant
 containing the flag used to mark a machine-dependent section.  This
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index bc32a17efcd..674be5ca532 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -4095,11 +4095,6 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
 #define DEBUG_LTO_LINE_STR_SECTION  ".gnu.debuglto_.debug_line_str"
 #endif
 
-/* Standard ELF section names for compiled code and data.  */
-#ifndef TEXT_SECTION_NAME
-#define TEXT_SECTION_NAME	".text"
-#endif
-
 /* Section flags for .debug_str section.  */
 #define DEBUG_STR_SECTION_FLAGS                                 \
   (HAVE_GAS_SHF_MERGE && flag_merge_debug_strings               \
diff --git a/gcc/output.h b/gcc/output.h
index 2f2f1697fd8..08cf0aca5f8 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,8 @@ extern void no_asm_to_stream (FILE *);
 #define SECTION_COMMON   0x800000	/* contains common data */
 #define SECTION_RELRO	 0x1000000	/* data is readonly after relocation processing */
 #define SECTION_EXCLUDE  0x2000000	/* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000	/* subsequent bits reserved for target */
+#define SECTION_RETAIN   0x4000000	/* retained by the linker, SHF_GNU_RETAIN */
+#define SECTION_MACH_DEP 0x8000000	/* subsequent bits reserved for target */
 
 /* This SECTION_STYLE is used for unnamed sections that we can switch
    to using a special assembler directive.  */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 00000000000..4f2cee6a36b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target section_retain } */
+/* { dg-final { scan-assembler ".text,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata,\"aR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections.  */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 00000000000..e37c8d8e6cf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target section_retain } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm2,\"awR\"" { target arm-*-* } } } */
+/* { dg-options "-ffunction-sections -fdata-sections" } */
+
+#include "attr-used-3.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 60ebbb39f9d..7d3753948ca 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -380,6 +380,15 @@ proc check_effective_target_noinit { } {
     return 0
 }
 
+# The "R" flag to the assembler .section directive is only supported by some targets.
+# This proc returns 1 if it's supported, 0 if it's not.
+
+proc check_effective_target_section_retain { } {
+    return [check_no_compiler_messages section_retain_available object {
+       __asm__(".section .text.foo,\"axR\",%progbits");
+    }]
+}
+
 ###############################
 # proc check_visibility_available { what_kind }
 ###############################
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 435c7b348a5..dd01dc713ba 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -314,6 +314,14 @@ get_section (const char *name, unsigned int flags, tree decl,
           sect->common.flags |= SECTION_NOTYPE;
           flags |= SECTION_NOTYPE;
         }
+      /* It is fine if one of the sections has SECTION_RETAIN and the other
+	 doesn't.  The requirement to retain may only present itself after a
+	 section has been declared.  */
+      if ((sect->common.flags ^ flags) & SECTION_RETAIN)
+	{
+	  sect->common.flags |= SECTION_RETAIN;
+	  flags |= SECTION_RETAIN;
+	}
       if ((sect->common.flags & ~SECTION_DECLARED) != flags
 	  && ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
 	{
@@ -624,6 +632,61 @@ default_function_section (tree decl, enum node_frequency freq,
     }
 }
 
+/* Generate a named section that has the same name as the noswitch or unnamed
+   section SECT.  */
+static section *
+convert_to_named_section (section *sect)
+{
+  unsigned int flags;
+  const char *name = NULL;
+
+  if (SECTION_STYLE (sect) == SECTION_NAMED)
+    return sect;
+
+  /* Pretend the flags came from a decl and unset SECTION_DECLARED and
+     SECTION_STYLE_MASK.  */
+  flags = sect->common.flags & ~(SECTION_DECLARED | SECTION_STYLE_MASK);
+
+  if (sect == text_section)
+    name = TEXT_SECTION_NAME;
+  else if (sect == data_section)
+    name = DATA_SECTION_NAME;
+  else if (sect == readonly_data_section)
+    name = READONLY_DATA_SECTION_NAME;
+  else if (sect == bss_section
+	   || sect == bss_noswitch_section)
+    name = BSS_SECTION_NAME;
+  else if (sect == sbss_section)
+    name = SBSS_SECTION_NAME;
+  else if (sect == sdata_section)
+    name = SDATA_SECTION_NAME;
+  else if (sect == comm_section
+	   || sect == tls_comm_section)
+    {
+      /* These aren't real sections, so they can't be marked with the retain
+	 flag.  */
+      return sect;
+    }
+  else if (sect == lcomm_section)
+    {
+      /* Sometimes lcomm_section corresponds to a real ELF section, other times
+	 only an assembler directive for the symbol name is output.  For the
+	 former case, we can mark the section with the retain flag.  */
+#ifdef LCOMM_SECTION_NAME
+      name = LCOMM_SECTION_NAME;
+      /* The section is not actually common if LCOMM_SECTION_NAME is
+	 defined.  */
+      flags &= ~(SECTION_COMMON);
+#else
+      return sect;
+#endif
+    }
+  else
+    gcc_unreachable ();
+
+  return get_section (name, flags, NULL_TREE);
+}
+
 /* Return the section for function DECL.
 
    If DECL is NULL_TREE, return the text section.  We can be passed
@@ -660,21 +723,24 @@ function_section_1 (tree decl, bool force_cold)
       if (targetm.asm_out.function_section)
 	section = targetm.asm_out.function_section (decl, freq,
 						    startup, exit);
-      if (section)
-	return section;
-      return get_named_section (decl, NULL, 0);
+      if (!section)
+	section = get_named_section (decl, NULL, 0);
     }
   else
-    return targetm.asm_out.select_section
-	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
-	     symtab_node::get (decl)->definition_alignment ());
+    section = targetm.asm_out.select_section
+      (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
+       symtab_node::get (decl)->definition_alignment ());
 #else
   if (targetm.asm_out.function_section)
     section = targetm.asm_out.function_section (decl, freq, startup, exit);
-  if (section)
-    return section;
-  return hot_function_section (decl);
+  if (!section)
+    section = hot_function_section (decl);
+#endif
+#if HAVE_GAS_SECTION_RETAIN
+  if (DECL_PRESERVE_P (decl))
+    section->common.flags |= SECTION_RETAIN;
 #endif
+  return section;
 }
 
 /* Return the section for function DECL.
@@ -2267,11 +2333,19 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   if (TREE_PUBLIC (decl))
     maybe_assemble_visibility (decl);
 
+  sect = get_variable_section (decl, false);
+
   if (DECL_PRESERVE_P (decl))
-    targetm.asm_out.mark_decl_preserved (name);
+    {
+      targetm.asm_out.mark_decl_preserved (name);
+#if HAVE_GAS_SECTION_RETAIN
+      if (SECTION_STYLE (sect) != SECTION_NAMED)
+	sect = convert_to_named_section (sect);
+      sect->common.flags |= SECTION_RETAIN;
+#endif
+    }
 
   /* First make the assembler name(s) global if appropriate.  */
-  sect = get_variable_section (decl, false);
   if (TREE_PUBLIC (decl)
       && (sect->common.flags & SECTION_COMMON) == 0)
     globalize_decl (decl);
@@ -6624,6 +6698,11 @@ default_section_type_flags (tree decl, const char *name, int reloc)
   if (decl && VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
     flags |= SECTION_TLS | SECTION_WRITE;
 
+#if HAVE_GAS_SECTION_RETAIN
+  if (decl && DECL_PRESERVE_P (decl))
+    flags |= SECTION_RETAIN;
+#endif
+
   if (strcmp (name, ".bss") == 0
       || strncmp (name, ".bss.", 5) == 0
       || strncmp (name, ".gnu.linkonce.b.", 16) == 0
@@ -6743,6 +6822,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
       if (flags & SECTION_MACH_DEP)
 	*f++ = MACH_DEP_SECTION_ASM_FLAG;
 #endif
+      if (flags & SECTION_RETAIN)
+	*f++ = 'R';
       *f = '\0';
     }
 
@@ -7635,12 +7716,23 @@ output_section_asm_op (const void *directive)
   fprintf (asm_out_file, "%s\n", (const char *) directive);
 }
 
-/* Emit assembly code to switch to section NEW_SECTION.  Do nothing if
-   the current section is NEW_SECTION.  */
+/* Emit assembly code to switch to section MAYBE_NEW_SECTION.
+   Convert the section to a named section if required.
+   Do nothing if the current section is NEW_SECTION.  */
 
 void
-switch_to_section (section *new_section)
+switch_to_section (section *maybe_new_section)
 {
+  section *new_section;
+
+  if (maybe_new_section->common.flags & SECTION_RETAIN
+      && SECTION_STYLE (maybe_new_section) != SECTION_NAMED)
+    /* SECTION_RETAIN sections must be converted to named so the "R" flag can
+       be emitted in the section directive.  */
+    new_section = convert_to_named_section (maybe_new_section);
+  else
+    new_section = maybe_new_section;
+
   if (in_section == new_section)
     return;
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 140a98594d..ffb75f7919 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1897,14 +1897,15 @@ struct output_elf_obj_tdata
   bfd_boolean flags_init;
 };
 
-/* Indicate if the bfd contains SHF_GNU_MBIND sections or symbols that
-   have the STT_GNU_IFUNC symbol type or STB_GNU_UNIQUE binding.  Used
-   to set the osabi field in the ELF header structure.  */
+/* Indicate if the bfd contains SHF_GNU_MBIND/SHF_GNU_RETAIN sections or
+   symbols that have the STT_GNU_IFUNC symbol type or STB_GNU_UNIQUE
+   binding.  Used to set the osabi field in the ELF header structure.  */
 enum elf_gnu_osabi
 {
   elf_gnu_osabi_mbind = 1 << 0,
   elf_gnu_osabi_ifunc = 1 << 1,
   elf_gnu_osabi_unique = 1 << 2,
+  elf_gnu_osabi_retain = 1 << 3,
 };
 
 typedef struct elf_section_list
@@ -2034,7 +2035,7 @@ struct elf_obj_tdata
   ENUM_BITFIELD (dynamic_lib_link_class) dyn_lib_class : 4;
 
   /* Whether the bfd uses OS specific bits that require ELFOSABI_GNU.  */
-  ENUM_BITFIELD (elf_gnu_osabi) has_gnu_osabi : 3;
+  ENUM_BITFIELD (elf_gnu_osabi) has_gnu_osabi : 4;
 
   /* Whether if the bfd contains the GNU_PROPERTY_NO_COPY_ON_PROTECTED
      property.  */
diff --git a/bfd/elf.c b/bfd/elf.c
index 9d7cbd52e0..8ec21d7705 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1066,9 +1066,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       /* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
 	 but binutils as of 2019-07-23 did not set the EI_OSABI header
 	 byte.  */
-    case ELFOSABI_NONE:
     case ELFOSABI_GNU:
     case ELFOSABI_FREEBSD:
+      if ((hdr->sh_flags & SHF_GNU_RETAIN) != 0)
+	elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_retain;
+      /* Fall through */
+    case ELFOSABI_NONE:
       if ((hdr->sh_flags & SHF_GNU_MBIND) != 0)
 	elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind;
       break;
@@ -12454,8 +12457,8 @@ _bfd_elf_final_write_processing (bfd *abfd)
     i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
 
   /* Set the osabi field to ELFOSABI_GNU if the binary contains
-     SHF_GNU_MBIND sections or symbols of STT_GNU_IFUNC type or
-     STB_GNU_UNIQUE binding.  */
+     SHF_GNU_MBIND or SHF_GNU_RETAIN sections or symbols of STT_GNU_IFUNC type
+     or STB_GNU_UNIQUE binding.  */
   if (elf_tdata (abfd)->has_gnu_osabi != 0)
     {
       if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
@@ -12464,11 +12467,17 @@ _bfd_elf_final_write_processing (bfd *abfd)
 	       && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
 	{
 	  if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind)
-	    _bfd_error_handler (_("GNU_MBIND section is unsupported"));
+	    _bfd_error_handler (_("GNU_MBIND section is supported only by GNU "
+				  "and FreeBSD targets"));
 	  if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_ifunc)
-	    _bfd_error_handler (_("symbol type STT_GNU_IFUNC is unsupported"));
+	    _bfd_error_handler (_("symbol type STT_GNU_IFUNC is supported "
+				  "only by GNU and FreeBSD targets"));
 	  if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_unique)
-	    _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is unsupported"));
+	    _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is supported "
+				  "only by GNU and FreeBSD targets"));
+	  if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_retain)
+	    _bfd_error_handler (_("GNU_RETAIN section is supported "
+				  "only by GNU and FreeBSD targets"));
 	  bfd_set_error (bfd_error_sorry);
 	  return FALSE;
 	}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e23d189b98..346424cb55 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10733,6 +10733,14 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       extsymoff = symtab_hdr->sh_info;
     }
 
+  /* Enable GNU OSABI features in the output BFD that are used in the input
+     BFD.  */
+  if (bed->elf_osabi == ELFOSABI_NONE
+      || bed->elf_osabi == ELFOSABI_GNU
+      || bed->elf_osabi == ELFOSABI_FREEBSD)
+    elf_tdata (output_bfd)->has_gnu_osabi
+      |= elf_tdata (input_bfd)->has_gnu_osabi;
+
   /* Read the local symbols.  */
   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   if (isymbuf == NULL && locsymcount != 0)
@@ -14103,7 +14111,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 			    == SHT_FINI_ARRAY)))
 		|| (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
 		    && elf_next_in_group (o) == NULL
-		    && elf_linked_to_section (o) == NULL)))
+		    && elf_linked_to_section (o) == NULL)
+		|| ((elf_tdata (sub)->has_gnu_osabi & elf_gnu_osabi_retain)
+		    && (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 35e4e303e1..32c264d74e 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -7,6 +7,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.
+
 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 03cfc97464..372bb0e578 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5996,6 +5996,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)
@@ -6028,7 +6030,6 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_TLS:		sindex = 9; break;
 	    case SHF_EXCLUDE:		sindex = 18; break;
 	    case SHF_COMPRESSED:	sindex = 20; break;
-	    case SHF_GNU_MBIND:		sindex = 24; break;
 
 	    default:
 	      sindex = -1;
@@ -6080,10 +6081,28 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 		  if (flag == SHF_PPC_VLE)
 		    sindex = 25;
 		  break;
+		default:
+		  break;
+		}
 
+	      switch (filedata->file_header.e_ident[EI_OSABI])
+		{
+		case ELFOSABI_GNU:
+		case ELFOSABI_FREEBSD:
+		  if (flag == SHF_GNU_RETAIN)
+		    sindex = 26;
+		  /* Fall through */
+		case ELFOSABI_NONE:
+		  if (flag == SHF_GNU_MBIND)
+		    /* We should not recognize SHF_GNU_MBIND for
+		       ELFOSABI_NONE, but binutils as of 2019-07-23 did
+		       not set the EI_OSABI header byte.  */
+		    sindex = 24;
+		  break;
 		default:
 		  break;
 		}
+	      break;
 	    }
 
 	  if (sindex != -1)
@@ -6126,7 +6145,6 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 	    case SHF_TLS:		*p = 'T'; break;
 	    case SHF_EXCLUDE:		*p = 'E'; break;
 	    case SHF_COMPRESSED:	*p = 'C'; break;
-	    case SHF_GNU_MBIND:		*p = 'D'; break;
 
 	    default:
 	      if ((filedata->file_header.e_machine == EM_X86_64
@@ -6136,14 +6154,37 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
 		*p = 'l';
 	      else if (filedata->file_header.e_machine == EM_ARM
 		       && flag == SHF_ARM_PURECODE)
-		  *p = 'y';
+		*p = 'y';
 	      else if (filedata->file_header.e_machine == EM_PPC
 		       && flag == SHF_PPC_VLE)
-		  *p = 'v';
+		*p = 'v';
 	      else if (flag & SHF_MASKOS)
 		{
-		  *p = 'o';
-		  sh_flags &= ~ SHF_MASKOS;
+		  switch (filedata->file_header.e_ident[EI_OSABI])
+		    {
+		    case ELFOSABI_GNU:
+		    case ELFOSABI_FREEBSD:
+		      if (flag == SHF_GNU_RETAIN)
+			{
+			  *p = 'R';
+			  break;
+			}
+		      /* Fall through */
+		    case ELFOSABI_NONE:
+		      if (flag == SHF_GNU_MBIND)
+			{
+			  /* We should not recognize SHF_GNU_MBIND for
+			     ELFOSABI_NONE, but binutils as of 2019-07-23 did
+			     not set the EI_OSABI header byte.  */
+			  *p = 'D';
+			  break;
+			}
+		      /* Fall through */
+		    default:
+		      *p = 'o';
+		      sh_flags &= ~SHF_MASKOS;
+		      break;
+		    }
 		}
 	      else if (flag & SHF_MASKPROC)
 		{
diff --git a/binutils/testsuite/binutils-all/readelf-maskos-1a.d b/binutils/testsuite/binutils-all/readelf-maskos-1a.d
new file mode 100644
index 0000000000..7b27358599
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf-maskos-1a.d
@@ -0,0 +1,10 @@
+#name: Unknown SHF_MASKOS value in section
+#source: readelf-maskos.s
+#notarget: [supports_gnu_osabi] msp430-*-elf visium-*-elf
+#xfail: arm-*-elf
+#readelf: -S --wide
+# PR26722 for the arm-*-elf XFAIL
+
+#...
+  \[[ 0-9]+\] .data.retain_var.*WAo.*
+#pass
diff --git a/binutils/testsuite/binutils-all/readelf-maskos-1b.d b/binutils/testsuite/binutils-all/readelf-maskos-1b.d
new file mode 100644
index 0000000000..2cbb58a73b
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf-maskos-1b.d
@@ -0,0 +1,12 @@
+#name: -t (section details) for unknown SHF_MASKOS value in section
+#source: readelf-maskos.s
+#notarget: [supports_gnu_osabi] msp430-*-elf visium-*-elf
+#xfail: arm-*-elf
+#readelf: -S -t --wide
+# PR26722 for the arm-*-elf XFAIL
+
+#...
+  \[[ 0-9]+\] .data.retain_var
+       PROGBITS +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +(1|2|4|8)
+       \[00200003\]: WRITE, ALLOC, OS \(00200000\)
+#pass
diff --git a/binutils/testsuite/binutils-all/readelf-maskos.s b/binutils/testsuite/binutils-all/readelf-maskos.s
new file mode 100644
index 0000000000..d671119bca
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf-maskos.s
@@ -0,0 +1,11 @@
+  .section	.data.retain_var,"0x200003"
+	.global	retain_var
+	.type	retain_var, %object
+retain_var:
+	.long	2
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 1fb36ae5c4..9d1d496e5c 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -364,8 +364,15 @@ 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 "retain1a"
+    run_dump_test "retain1b"
+    run_dump_test "readelf-maskos-1a"
+    run_dump_test "readelf-maskos-1b"
+}
 
 # 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.s b/binutils/testsuite/binutils-all/retain1.s
new file mode 100644
index 0000000000..f7716faabe
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, %object
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, %object
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, %object
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, %object
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, %object
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, %object
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, %function
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, %object
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, %object
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, %object
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, %object
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, %object
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, %object
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, %function
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, %function
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, %object
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, %object
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, %object
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/binutils/testsuite/binutils-all/retain1a.d b/binutils/testsuite/binutils-all/retain1a.d
new file mode 100644
index 0000000000..6397ac52ae
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1a.d
@@ -0,0 +1,18 @@
+#name: readelf SHF_GNU_RETAIN
+#source: retain1.s
+#target: [supports_gnu_osabi]
+#readelf: -S --wide
+
+#...
+  \[[ 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/retain1b.d b/binutils/testsuite/binutils-all/retain1b.d
new file mode 100644
index 0000000000..12bc388ba1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1b.d
@@ -0,0 +1,46 @@
+#name: -t (section details) for readelf SHF_GNU_RETAIN
+#source: retain1.s
+#target: [supports_gnu_osabi]
+#readelf: -S -t --wide
+
+#...
+  \[[ 0-9]+\] .bss.retain0
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .bss.retain1
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .data.retain2
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .bss.sretain0
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .bss.sretain1
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .data.sretain2
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .text.fnretain1
+#...
+       \[0+200006\]: ALLOC, EXEC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .bss.lsretain0
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .bss.lsretain1
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#...
+  \[[ 0-9]+\] .data.lsretain2
+#...
+       \[0+200003\]: WRITE, ALLOC, GNU_RETAIN
+#pass
diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index b9a1e6e4bc..a43639bafb 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -195,13 +195,15 @@ proc match_target { target } {
 
 # True if the ELF target supports setting the ELF header OSABI field
 # to ELFOSABI_GNU or ELFOSABI_FREEBSD, a requirement for STT_GNU_IFUNC
-# symbol and SHF_GNU_MBIND section support.
+# symbol and SHF_GNU_MBIND or SHF_GNU_RETAIN section support.
 #
 # This generally depends on the target OS only, however there are a
 # number of exceptions for bare metal targets as follows.  The MSP430
 # and Visium targets set OSABI to ELFOSABI_STANDALONE.  Likewise
 # non-EABI ARM targets set OSABI to ELFOSABI_ARM
 #
+# Non-Linux HPPA defaults to ELFOSABI_HPUX.
+#
 # Note that some TI C6X targets use ELFOSABI_C6000_* but one doesn't,
 # so we don't try to sort out tic6x here.  (The effect is that linker
 # testcases will generally need to exclude tic6x or use a -m option.)
@@ -227,6 +229,7 @@ proc supports_gnu_osabi {} {
     }
     if { [istarget "arm*-*-*"]
 	 || [istarget "msp430-*-*"]
+	 || [istarget "hppa-unknown-elf"]
 	 || [istarget "visium-*-*"] } {
 	return 0
     }
diff --git a/gas/NEWS b/gas/NEWS
index 41cc668e61..41b1d9dde3 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -44,6 +44,11 @@
 
 * Configure with --enable-x86-used-note by default for Linux/x86.
 
+* Add support for the SHF_GNU_RETAIN flag, which can be applied to
+  sections using the "R" flag in the .section directive.
+  SHF_GNU_RETAIN specifies that the section should not be garbage
+  collected by the linker.  It requires the GNU or FreeBSD ELF OSABIs.
+
 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 f061ea61f3..8d3c36955e 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -861,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;
@@ -890,8 +893,32 @@ obj_elf_parse_section_letters (char *str, size_t len,
 	      if (ISDIGIT (*str))
 		{
 		  char * end;
+		  struct elf_backend_data *bed;
+		  bfd_vma numeric_flags = strtoul (str, &end, 0);
+
+		  attr |= numeric_flags;
+
+		  bed = (struct elf_backend_data *)
+		    get_elf_backend_data (stdoutput);
+
+		  if (bed->elf_osabi == ELFOSABI_NONE
+		      || bed->elf_osabi == ELFOSABI_STANDALONE
+		      || bed->elf_osabi == ELFOSABI_GNU
+		      || bed->elf_osabi == ELFOSABI_FREEBSD)
+		    {
+		      /* Add flags in the SHF_MASKOS range to gnu_attr for
+			 OSABIs that support those flags.
+			 Also adding the flags for ELFOSABI_{NONE,STANDALONE}
+			 allows them to be validated later in obj_elf_section.
+			 We can't just always set these bits in gnu_attr for
+			 all OSABIs, since Binutils does not recognize all
+			 SHF_MASKOS bits for non-GNU OSABIs.  It's therefore
+			 possible that numeric flags are being used to set bits
+			 in the SHF_MASKOS range for those targets, and we
+			 don't want assembly to fail in those situations.  */
+		      *gnu_attr |= (numeric_flags & SHF_MASKOS);
+		    }
 
-		  attr |= strtoul (str, & end, 0);
 		  /* Update str and len, allowing for the fact that
 		     we will execute str++ and len-- below.  */
 		  end --;
@@ -1387,26 +1414,37 @@ obj_elf_section (int push)
  done:
   demand_empty_rest_of_line ();
 
-  obj_elf_change_section (name, type, attr, entsize, &match, linkonce,
-			  push);
-
-  if ((gnu_attr & SHF_GNU_MBIND) != 0)
+  if ((gnu_attr & (SHF_GNU_MBIND | SHF_GNU_RETAIN)) != 0)
     {
       struct elf_backend_data *bed;
+      bfd_boolean mbind_p = (gnu_attr & SHF_GNU_MBIND) != 0;
 
-      if ((attr & SHF_ALLOC) == 0)
+      if (mbind_p && (attr & SHF_ALLOC) == 0)
 	as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
 
       bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
-      if (bed->elf_osabi == ELFOSABI_NONE)
-	bed->elf_osabi = ELFOSABI_GNU;
-      else if (bed->elf_osabi != ELFOSABI_GNU
-	       && bed->elf_osabi != ELFOSABI_FREEBSD)
-	as_bad (_("GNU_MBIND section is supported only by GNU "
-		  "and FreeBSD targets"));
-      elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+
+      if (bed->elf_osabi != ELFOSABI_GNU
+	  && bed->elf_osabi != ELFOSABI_FREEBSD
+	  && bed->elf_osabi != ELFOSABI_NONE)
+	as_bad (_("%s section is supported only by GNU and FreeBSD targets"),
+		mbind_p ? "GNU_MBIND" : "GNU_RETAIN");
+      else
+	{
+	  if (bed->elf_osabi == ELFOSABI_NONE)
+	    bed->elf_osabi = ELFOSABI_GNU;
+
+	  if (mbind_p)
+	    elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+	  if ((gnu_attr & SHF_GNU_RETAIN) != 0)
+	    elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_retain;
+
+	  attr |= gnu_attr;
+	}
     }
-  elf_section_flags (now_seg) |= gnu_attr;
+
+  obj_elf_change_section (name, type, attr, entsize, &match, linkonce,
+			  push);
 
   if (linked_to_section_index != -1UL)
     {
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 4d5294552a..e92432a8bd 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -6657,6 +6657,9 @@ section is a member of a section group
 section is used for thread-local-storage
 @item ?
 section is a member of the previously-current section's group, if any
+@item R
+retained section (apply SHF_GNU_RETAIN to prevent linker garbage
+collection, GNU ELF extension)
 @item @code{<number>}
 a numeric value indicating the bits to be set in the ELF section header's flags
 field.  Note - if one or more of the alphabetic characters described above is
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 9d75154483..49d5a47959 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -261,8 +261,11 @@ if { [is_elf_format] } then {
     run_dump_test "section19"
     run_dump_test "section20"
     run_dump_test "section21"
+    run_dump_test "section22"
+    run_dump_test "section23a"
+    run_dump_test "section23b"
+    run_dump_test "section24"
     run_dump_test "sh-link-zero"
-
     run_dump_test "dwarf2-1" $dump_opts
     run_dump_test "dwarf2-2" $dump_opts
     run_dump_test "dwarf2-3" $dump_opts
diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d
index 554a791f1d..6aa7b088b1 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\)
+[ 	]*\[.*fedff030\]: 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\)
+[ 	]*\[.*fedf0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
 [ 	]*\[.*\][ 	]+.data.foo
 [ 	]*LOUSER\+0x7f000000[ 	].*
 [ 	]*\[0+003\]: WRITE, ALLOC
diff --git a/gas/testsuite/gas/elf/section10.s b/gas/testsuite/gas/elf/section10.s
index 29f1184523..d52b3458fb 100644
--- a/gas/testsuite/gas/elf/section10.s
+++ b/gas/testsuite/gas/elf/section10.s
@@ -7,7 +7,7 @@
 	.word 2
 
 	# Make sure that specifying further arguments to .sections is still supported
-	.section sec3, "0xfefff000MS", %progbits, 32
+	.section sec3, "0xfedff000MS", %progbits, 32
 	.word 3
 
 	# Make sure that extra flags can be set for well known sections as well.
@@ -19,7 +19,7 @@
 	.word 5
 
 	# Test both together, with a quoted type value.
-	.section sec5, "0xfeff0000", "0x80000009"
+	.section sec5, "0xfedf0000", "0x80000009"
 	.word 6
 
 	# Test that declaring an extended version of a known special section works.
diff --git a/gas/testsuite/gas/elf/section22.d b/gas/testsuite/gas/elf/section22.d
new file mode 100644
index 0000000000..8aa7fcfc34
--- /dev/null
+++ b/gas/testsuite/gas/elf/section22.d
@@ -0,0 +1,19 @@
+#readelf: -h -S --wide
+#name: SHF_GNU_RETAIN sections 22
+#notarget: ![supports_gnu_osabi]
+
+#...
+ +OS/ABI: +UNIX - GNU
+#...
+  \[..\] .text.discard0[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX.*
+#...
+  \[..\] .data.discard1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+#...
+  \[..\] .bss.discard2[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  WA.*
+#...
+  \[..\] .bss.retain0[ 	]+NOBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#...
+  \[..\] .data.retain1[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#...
+  \[..\] .text.retain2[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.*
+#pass
diff --git a/gas/testsuite/gas/elf/section22.s b/gas/testsuite/gas/elf/section22.s
new file mode 100644
index 0000000000..66ed990e57
--- /dev/null
+++ b/gas/testsuite/gas/elf/section22.s
@@ -0,0 +1,34 @@
+	.section	.text.discard0,"ax",%progbits
+	.global	discard0
+	.type	discard0, %function
+discard0:
+	.word	0
+
+	.section	.data.discard1,"aw"
+	.global	discard1
+	.type	discard1, %object
+discard1:
+	.word	1
+
+	.section	.bss.discard2,"aw"
+	.global	discard2
+	.type	discard2, %object
+discard2:
+	.zero	2
+
+	.section	.bss.retain0,"awR",%nobits
+	.global	retain0
+	.type	retain0, %object
+retain0:
+	.zero	2
+
+	.section	.data.retain1,"awR",%progbits
+	.type	retain1, %object
+retain1:
+	.word	1
+
+	.section	.text.retain2,"axR",%progbits
+	.global	retain2
+	.type	retain2, %function
+retain2:
+	.word	0
diff --git a/gas/testsuite/gas/elf/section23.s b/gas/testsuite/gas/elf/section23.s
new file mode 100644
index 0000000000..d671119bca
--- /dev/null
+++ b/gas/testsuite/gas/elf/section23.s
@@ -0,0 +1,11 @@
+  .section	.data.retain_var,"0x200003"
+	.global	retain_var
+	.type	retain_var, %object
+retain_var:
+	.long	2
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/gas/testsuite/gas/elf/section23a.d b/gas/testsuite/gas/elf/section23a.d
new file mode 100644
index 0000000000..2e413e1cec
--- /dev/null
+++ b/gas/testsuite/gas/elf/section23a.d
@@ -0,0 +1,10 @@
+#name: SHF_GNU_RETAIN set with numeric flag value in .section
+#source: section23.s
+#target: [supports_gnu_osabi]
+#readelf: -h -S --wide
+
+#...
+ +OS/ABI: +UNIX - GNU
+#...
+  \[..\] .data.retain_var[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#pass
diff --git a/gas/testsuite/gas/elf/section23b.d b/gas/testsuite/gas/elf/section23b.d
new file mode 100644
index 0000000000..c85200e5ff
--- /dev/null
+++ b/gas/testsuite/gas/elf/section23b.d
@@ -0,0 +1,6 @@
+#name: SHF_GNU_RETAIN set with numeric flag value in .section for non-GNU OSABI target
+#source: section23.s
+#error_output: section23b.err
+#target: msp430-*-elf visium-*-elf
+
+# This test only runs for targets which set ELFOSABI_STANDALONE.
diff --git a/gas/testsuite/gas/elf/section23b.err b/gas/testsuite/gas/elf/section23b.err
new file mode 100644
index 0000000000..83de60c397
--- /dev/null
+++ b/gas/testsuite/gas/elf/section23b.err
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:1: Error: GNU_RETAIN section is supported only by GNU and FreeBSD targets
diff --git a/gas/testsuite/gas/elf/section24.d b/gas/testsuite/gas/elf/section24.d
new file mode 100644
index 0000000000..5ee4aee3af
--- /dev/null
+++ b/gas/testsuite/gas/elf/section24.d
@@ -0,0 +1,18 @@
+#name: Warn for SHF_GNU_RETAIN set on existing section
+#notarget: ![supports_gnu_osabi] rx-*-*
+#readelf: -h -S --wide
+#warning_output: section24.l
+# rx-*-* does not automatically create a ".text" section when starting assembly.
+
+#...
+ +OS/ABI: +UNIX - GNU
+#...
+  \[..\] .text[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX .*
+#...
+  \[..\] .text[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR .*
+#...
+  \[..\] .text.foo[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR .*
+#...
+  \[..\] .text.bar[ 	]+PROGBITS[ 	]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00  AX .*
+#pass
+
diff --git a/gas/testsuite/gas/elf/section24.l b/gas/testsuite/gas/elf/section24.l
new file mode 100644
index 0000000000..e0ea36078c
--- /dev/null
+++ b/gas/testsuite/gas/elf/section24.l
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:4: Warning: ignoring changed section attributes for .text
+[^:]*:20: Warning: ignoring changed section attributes for .text.foo
+[^:]*:30: Warning: ignoring changed section attributes for .text.bar
diff --git a/gas/testsuite/gas/elf/section24.s b/gas/testsuite/gas/elf/section24.s
new file mode 100644
index 0000000000..deaff0a323
--- /dev/null
+++ b/gas/testsuite/gas/elf/section24.s
@@ -0,0 +1,32 @@
+/* The default .text section automatically created by the assembler does not
+   have the SHF_GNU_RETAIN flag set, so the "R" flag cannot be used with that,
+   or any other, default section.  */
+	.section	.text,"axR",%progbits
+retain_bad:
+	.word 0
+
+/* A unique .text section with SHF_GNU_RETAIN applied can be created.  */
+	.section	.text,"axR",%progbits,unique,0
+retain_good:
+	.word 0
+
+/* SHF_GNU_RETAIN can be applied to a new section.  */
+	.section	.text.foo,"axR",%progbits
+foo_retain:
+	.word 0
+
+/* If the section is used again without SHF_GNU_RETAIN, a warning should be
+   emitted.  */
+	.section	.text.foo,"ax",%progbits
+foo:
+	.word 0
+
+	.section	.text.bar,"ax",%progbits
+bar:
+	.word 0
+
+/* SHF_GNU_RETAIN cannot be applied to a section which was already explicitly
+   declared without SHF_GNU_RETAIN set.  */
+	.section	.text.bar,"axR",%progbits
+bar_retain:
+	.word 0
diff --git a/include/elf/common.h b/include/elf/common.h
index b3c30e0e2f..a17cafcc70 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 81c44191d2..bb23010dad 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -23,6 +23,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.
+
 Changes in 2.35:
 
 * X86 NaCl target support is removed.
diff --git a/ld/ld.texi b/ld/ld.texi
index 48e78aecdb..40c209d914 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1805,6 +1805,9 @@ 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.
+
 @kindex --print-gc-sections
 @kindex --no-print-gc-sections
 @cindex garbage collection
@@ -5265,6 +5268,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.
+
 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 f2ff0397c7..bd06ab0d39 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -119,6 +119,17 @@ if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
     set ASFLAGS "$ASFLAGS -mx86-used-note=no"
 }
 
+# Build libraries required for SHF_GNU_RETAIN tests.
+if { [check_gc_sections_available] && [supports_gnu_osabi] } {
+    run_ld_link_tests [list \
+	[list "Build libretain5.a" "" "" "" \
+	    {retain5lib.s} {} "libretain5.a"] \
+	[list "Build libretain6.a" "" "" "" \
+	    {retain6lib.s} {} "libretain6.a"] \
+	]
+}
+
+
 set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
 foreach t $test_list {
     # We need to strip the ".d", but can leave the dirname.
diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s
new file mode 100644
index 0000000000..f7716faabe
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1.s
@@ -0,0 +1,104 @@
+	.global	discard0
+	.section	.bss.discard0,"aw"
+	.type	discard0, %object
+discard0:
+	.zero	2
+
+	.global	discard1
+	.section	.bss.discard1,"aw"
+	.type	discard1, %object
+discard1:
+	.zero	2
+
+	.global	discard2
+	.section	.data.discard2,"aw"
+	.type	discard2, %object
+discard2:
+	.word	1
+
+	.section	.bss.sdiscard0,"aw"
+	.type	sdiscard0, %object
+sdiscard0:
+	.zero	2
+
+	.section	.bss.sdiscard1,"aw"
+	.type	sdiscard1, %object
+sdiscard1:
+	.zero	2
+
+	.section	.data.sdiscard2,"aw"
+	.type	sdiscard2, %object
+sdiscard2:
+	.word	1
+
+	.section	.text.fndiscard0,"ax"
+	.global	fndiscard0
+	.type	fndiscard0, %function
+fndiscard0:
+	.word 0
+
+	.global	retain0
+	.section	.bss.retain0,"awR"
+	.type	retain0, %object
+retain0:
+	.zero	2
+
+	.global	retain1
+	.section	.bss.retain1,"awR"
+	.type	retain1, %object
+retain1:
+	.zero	2
+
+	.global	retain2
+	.section	.data.retain2,"awR"
+	.type	retain2, %object
+retain2:
+	.word	1
+
+	.section	.bss.sretain0,"awR"
+	.type	sretain0, %object
+sretain0:
+	.zero	2
+
+	.section	.bss.sretain1,"awR"
+	.type	sretain1, %object
+sretain1:
+	.zero	2
+
+	.section	.data.sretain2,"aRw"
+	.type	sretain2, %object
+sretain2:
+	.word	1
+
+	.section	.text.fnretain1,"Rax"
+	.global	fnretain1
+	.type	fnretain1, %function
+fnretain1:
+	.word	0
+
+	.section	.text.fndiscard2,"ax"
+	.global	fndiscard2
+	.type	fndiscard2, %function
+fndiscard2:
+	.word	0
+
+	.section	.bss.lsretain0,"awR"
+	.type	lsretain0.2, %object
+lsretain0.2:
+	.zero	2
+
+	.section	.bss.lsretain1,"aRw"
+	.type	lsretain1.1, %object
+lsretain1.1:
+	.zero	2
+
+	.section	.data.lsretain2,"aRw"
+	.type	lsretain2.0, %object
+lsretain2.0:
+	.word	1
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain1a.d b/ld/testsuite/ld-elf/retain1a.d
new file mode 100644
index 0000000000..29adb5d2c9
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1a.d
@@ -0,0 +1,27 @@
+#name: SHF_GNU_RETAIN 1a
+#source: retain1.s
+#ld: -e _start --gc-sections
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#DUMPPROG: nm
+
+#...
+[0-9a-f]+ . fnretain1
+#...
+[0-9a-f]+ . lsretain0.2
+#...
+[0-9a-f]+ . lsretain1.1
+#...
+[0-9a-f]+ . lsretain2.0
+#...
+[0-9a-f]+ . retain0
+#...
+[0-9a-f]+ . retain1
+#...
+[0-9a-f]+ . retain2
+#...
+[0-9a-f]+ . sretain0
+#...
+[0-9a-f]+ . sretain1
+#...
+[0-9a-f]+ . sretain2
+#pass
diff --git a/ld/testsuite/ld-elf/retain1b.d b/ld/testsuite/ld-elf/retain1b.d
new file mode 100644
index 0000000000..b1cafc9d1c
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1b.d
@@ -0,0 +1,10 @@
+#name: SHF_GNU_RETAIN 1b
+#source: retain1.s
+#ld: -e _start --gc-sections
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ . .*discard.*
+#...
diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d
new file mode 100644
index 0000000000..1a63f51aab
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.d
@@ -0,0 +1,5 @@
+#name: SHF_GNU_RETAIN 2 (remove SHF_GNU_RETAIN sections by placing in /DISCARD/)
+#source: retain1.s
+#ld: -e _start -Map=retain2.map --gc-sections --script=retain2.ld
+#map: retain2.map
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
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.d b/ld/testsuite/ld-elf/retain3.d
new file mode 100644
index 0000000000..3c81a88e51
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.d
@@ -0,0 +1,11 @@
+#name: SHF_GNU_RETAIN 3 (keep sections referenced by retained sections)
+#source: retain3.s
+#ld: -e _start --gc-sections
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#DUMPPROG: nm
+
+#...
+[0-9a-f]+ . bar
+#...
+[0-9a-f]+ . foo
+#pass
diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s
new file mode 100644
index 0000000000..ce315cbaa6
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.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, %function
+foo:
+	.word 0
+
+	.section	.text.bar,"axR"
+	.global	bar
+	.type	bar, %function
+bar:
+	.long foo
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain4.d b/ld/testsuite/ld-elf/retain4.d
new file mode 100644
index 0000000000..b423fb9584
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain4.d
@@ -0,0 +1,9 @@
+#name: SHF_GNU_RETAIN 4 (keep orphaned sections when not discarding)
+#source: retain4.s
+#ld: -e _start --gc-sections --orphan-handling=place
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#DUMPPROG: nm
+
+#...
+[0-9a-f]+ . orphaned_fn
+#pass
diff --git a/ld/testsuite/ld-elf/retain4.s b/ld/testsuite/ld-elf/retain4.s
new file mode 100644
index 0000000000..9f350cd3b2
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain4.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	orphaned_fn
+	.type	orphaned_fn, %function
+orphaned_fn:
+	.word 0
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain5.d b/ld/testsuite/ld-elf/retain5.d
new file mode 100644
index 0000000000..86e85f8da5
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5.d
@@ -0,0 +1,11 @@
+#name: SHF_GNU_RETAIN 5 (don't pull SHF_GNU_RETAIN section out of lib)
+#source: retain5main.s
+#ld: --gc-sections -e _start --print-gc-sections -Ltmpdir -lretain5 -Map=retain5.map
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#map: retain5.map
+#DUMPPROG: nm
+
+#failif
+#...
+[0-9a-f]+ . foo
+#...
diff --git a/ld/testsuite/ld-elf/retain5.map b/ld/testsuite/ld-elf/retain5.map
new file mode 100644
index 0000000000..6b97c2a220
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5.map
@@ -0,0 +1,5 @@
+# Check that the library was actually loaded to catch any false PASS.
+
+#...
+LOAD tmpdir/libretain5.a
+#pass
diff --git a/ld/testsuite/ld-elf/retain5lib.s b/ld/testsuite/ld-elf/retain5lib.s
new file mode 100644
index 0000000000..4e83731719
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5lib.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, %function
+foo:
+	.long undefined_sym
diff --git a/ld/testsuite/ld-elf/retain5main.s b/ld/testsuite/ld-elf/retain5main.s
new file mode 100644
index 0000000000..89a7784d13
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5main.s
@@ -0,0 +1,5 @@
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain6a.d b/ld/testsuite/ld-elf/retain6a.d
new file mode 100644
index 0000000000..aa93117ae7
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6a.d
@@ -0,0 +1,13 @@
+#name: SHF_GNU_RETAIN 6a (pull section out of lib required by SHF_GNU_RETAIN section)
+#source: retain6main.s
+#ld: --gc-sections -e _start -u bar -Ltmpdir -lretain6
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#DUMPPROG: nm
+
+#...
+[0-9a-f]+ . bar
+#...
+[0-9a-f]+ . retain_from_lib
+#...
+[0-9a-f]+ . retained_fn
+#pass
diff --git a/ld/testsuite/ld-elf/retain6b.d b/ld/testsuite/ld-elf/retain6b.d
new file mode 100644
index 0000000000..f29ba71dd9
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6b.d
@@ -0,0 +1,10 @@
+#name: SHF_GNU_RETAIN 6b (pull section out of lib required by SHF_GNU_RETAIN section)
+#source: retain6main.s
+#ld: --gc-sections -e _start -u bar -Ltmpdir -lretain6
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#DUMPPROG: nm
+
+#failif
+#...
+[0-9a-f]+ . .*discard.*
+#...
diff --git a/ld/testsuite/ld-elf/retain6lib.s b/ld/testsuite/ld-elf/retain6lib.s
new file mode 100644
index 0000000000..a393dbac61
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6lib.s
@@ -0,0 +1,17 @@
+	.section	.text.bar,"ax"
+	.global	bar
+	.type	bar, %function
+bar:
+	.word 0
+
+	.section	.text.retain_from_lib,"axR"
+	.global	retain_from_lib
+	.type	retain_from_lib, %function
+retain_from_lib:
+	.word 0
+
+	.section	.text.discard_from_lib,"ax"
+	.global	discard_from_lib
+	.type	discard_from_lib, %function
+discard_from_lib:
+	.word 0
diff --git a/ld/testsuite/ld-elf/retain6main.s b/ld/testsuite/ld-elf/retain6main.s
new file mode 100644
index 0000000000..a66c5b3247
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6main.s
@@ -0,0 +1,13 @@
+/* Undefined symbol reference in retained section .text.retained_fn requires
+   symbol definition to be pulled out of library.  */
+	.section	.text.retained_fn,"axR"
+	.global	retained_fn
+	.type	retained_fn, %function
+retained_fn:
+	.long bar
+
+	.section	.text._start,"ax"
+	.global	_start
+	.type	_start, %function
+_start:
+	.word 0
H.J. Lu Nov. 9, 2020, 6:36 p.m. UTC | #34
On Mon, Nov 9, 2020 at 9:41 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Fri, Nov 06, 2020 at 04:39:33PM -0800, H.J. Lu via Gcc-patches wrote:
> > On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
> > >
> > >
> > > On 11/6/20 5:13 PM, H.J. Lu wrote:
> > > > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> > > >>
> > > >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > > >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> > > >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > > >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> > > >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > > >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > > >>>>>>> <jozef.l@mittosystems.com> wrote:
> > > >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > > >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > >>>>>>>>>> .retain is ill-defined.   For example,
> > > >>>>>>>>>>
> > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > >>>>>>>>>> static int xyzzy __attribute__((__used__));
> > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> > > >>>>>>>>>> .file "x.c"
> > > >>>>>>>>>> .text
> > > >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> > > >>>>>>>>>> .local xyzzy
> > > >>>>>>>>>> .comm xyzzy,4,4
> > > >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > > >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> > > >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> > > >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > > >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> > > >>>>>>>>> We both know this isn't rocket science with binutils.
> > > >>>>>>>> Indeed, and my patch handles it trivially:
> > > >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> > > >>>>>>>>
> > > >>>>>>>>   +void
> > > >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> > > >>>>>>>>   .... snip ....
> > > >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> > > >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> > > >>>>>>>>
> > > >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> > > >>>>>>>>     }
> > > >>>>>>>>        }
> > > >>>>>>>>
> > > >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> > > >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> > > >>>>>>>>   +
> > > >>>>>>>>      /* Double check weak symbols.  */
> > > >>>>>>>>      if (S_IS_WEAK (symp))
> > > >>>>>>>>        {
> > > >>>>>>>>
> > > >>>>>>>> We could check that the symbol named in the .retain directive has
> > > >>>>>>>> already been defined, however this isn't compatible with GCC
> > > >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> > > >>>>>>>> emitted before the local symbols are defined in the assembly output
> > > >>>>>>>> file.
> > > >>>>>>>>
> > > >>>>>>>> GAS should at least validate that the symbol named in the .retain
> > > >>>>>>>> directive does end up as a symbol though.
> > > >>>>>>>>
> > > >>>>>>> Don't add .retain.
> > > >>>>>> Why?  I don't see why you find it so objectionable.
> > > >>>>>>
> > > >>>>> An ELF symbol directive should operate on symbol table:
> > > >>>>>
> > > >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> > > >>>>>
> > > >>>>> not the section flags where the symbol is defined.
> > > >>>> I agree in general, but I think this is one of those cases where it's
> > > >>>> not so clear.  And what you're talking about is an implementation detail.
> > > >>> There is no need for such a hack.  The proper thing to do in ELF is
> > > >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > > >>> also avoids the question what to do with SHN_COMMON.
> > > >> I'm not sure that's a good idea either.  Moving symbols into a section
> > > >> other than they'd normally live doesn't seem all that wise.
> > > > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > > > we should place it in an SHF_GNU_RETAIN section.
> > >
> > > Again, that's an implementation detail and it's not clear to me that one
> > > approach is inherently better than the other.
> > >
> > >
> > > >
> > > >> Let's face it, there's not a great solution here.  If we mark its
> > > >> existing section, then everything in that section gets kept.  If we put
> > > > FWIW, this is what .retain direct does and is one reason why I object
> > > > it.
> > >
> > > We could make .retain work with either approach.    I don't see .retain
> > > as a problem at all.
> > >
> > >
> > >
> > > >
> > > >> the object into a different section than it would normally live, then
> > > >> that opens a whole new can of worms.
> > > > We should place it in a section which it normally lives in and mark the
> > > > section with SHF_GNU_RETAIN.
> > >
> > > And why not do that with .retain?  We define its semantics as precisely
> >
> > But the .retain directive implementation being discussed here is different.
> > One problem with the .retain directive is we can have
> >
> > .section .data
> > foo:
> > ...
> > bar:
> >
> > .retain bar
> > ...
> > xxx:
> > ...
> >
> > What should assembler do with ".retain bar"?
> >
> > > what you've written above.  The referenced symbol goes into its usual
> > > section and its section is marked with SHF_GNU_RETAIN.  That seems much
> > > cleaner than having to track all this in the compiler so that it can
> > > twiddle the section flags.
> >
> > When GCC emits a symbol definition, it places the symbol in a section
> > with proper
> > attributes which GCC tracks for each symbol.  It  can be extended to track
> > SHF_GNU_RETAIN.
>
> The attached patch is rough around the edges but shows my approach for
> marking unnamed sections as retained, by converting them to named
> sections.
>
> I figure we don't have to wrap every usage of SECTION_RETAIN in
> HAVE_GAS_SECTION_RETAIN as long as any set of SECTION_RETAIN in the
> flags field is wrapped in the macro.
>
> I think a flag to turn off the behavior (in the same way the behavior is
> disabled if !defined(HAVE_GAS_SECTION_RETAIN)) would be beneficial,
> I haven't added that yet.
>
> Decls that would go in comm_section, tls_comm_section and sometimes
> lcomm_section do not get retained as we can't apply the retain section
> flag to these symbols. Given these go in one big common block, and
> contain uninitialized data, I don't think there is a valid use case for
> which these types of symbols need to be retained, but are not referenced
> by the program. So I've avoided converting them to .bss or anything like
> that.
>
> Some targets alias lcomm_section for bss_section, so we can retain
> sections for that case.
>
> So far bootstrap and light testing on x86_64-pc-linux-gnu and
> arm-none-eabi has shown no problems.
>

Binutils change looks OK.  But GCC changes look too intrusive.
Also SHF_GNU_RETAIN can't be used on Solaris since ld on
Solaris may not support it.

Can you improve

https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain

to do what you need?
Jozef Lawrynowicz Nov. 9, 2020, 7:56 p.m. UTC | #35
On Mon, Nov 09, 2020 at 10:36:07AM -0800, H.J. Lu via Gcc-patches wrote:
> On Mon, Nov 9, 2020 at 9:41 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Fri, Nov 06, 2020 at 04:39:33PM -0800, H.J. Lu via Gcc-patches wrote:
> > > On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
> > > >
> > > >
> > > > On 11/6/20 5:13 PM, H.J. Lu wrote:
> > > > > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> > > > >>
> > > > >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > > > >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> > > > >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > > > >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> > > > >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > > > >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > > > >>>>>>> <jozef.l@mittosystems.com> wrote:
> > > > >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > > > >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > >>>>>>>>>> .retain is ill-defined.   For example,
> > > > >>>>>>>>>>
> > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > > >>>>>>>>>> static int xyzzy __attribute__((__used__));
> > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> > > > >>>>>>>>>> .file "x.c"
> > > > >>>>>>>>>> .text
> > > > >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> > > > >>>>>>>>>> .local xyzzy
> > > > >>>>>>>>>> .comm xyzzy,4,4
> > > > >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > > > >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> > > > >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> > > > >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > > > >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> > > > >>>>>>>>> We both know this isn't rocket science with binutils.
> > > > >>>>>>>> Indeed, and my patch handles it trivially:
> > > > >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> > > > >>>>>>>>
> > > > >>>>>>>>   +void
> > > > >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> > > > >>>>>>>>   .... snip ....
> > > > >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> > > > >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> > > > >>>>>>>>
> > > > >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> > > > >>>>>>>>     }
> > > > >>>>>>>>        }
> > > > >>>>>>>>
> > > > >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> > > > >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> > > > >>>>>>>>   +
> > > > >>>>>>>>      /* Double check weak symbols.  */
> > > > >>>>>>>>      if (S_IS_WEAK (symp))
> > > > >>>>>>>>        {
> > > > >>>>>>>>
> > > > >>>>>>>> We could check that the symbol named in the .retain directive has
> > > > >>>>>>>> already been defined, however this isn't compatible with GCC
> > > > >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> > > > >>>>>>>> emitted before the local symbols are defined in the assembly output
> > > > >>>>>>>> file.
> > > > >>>>>>>>
> > > > >>>>>>>> GAS should at least validate that the symbol named in the .retain
> > > > >>>>>>>> directive does end up as a symbol though.
> > > > >>>>>>>>
> > > > >>>>>>> Don't add .retain.
> > > > >>>>>> Why?  I don't see why you find it so objectionable.
> > > > >>>>>>
> > > > >>>>> An ELF symbol directive should operate on symbol table:
> > > > >>>>>
> > > > >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> > > > >>>>>
> > > > >>>>> not the section flags where the symbol is defined.
> > > > >>>> I agree in general, but I think this is one of those cases where it's
> > > > >>>> not so clear.  And what you're talking about is an implementation detail.
> > > > >>> There is no need for such a hack.  The proper thing to do in ELF is
> > > > >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > > > >>> also avoids the question what to do with SHN_COMMON.
> > > > >> I'm not sure that's a good idea either.  Moving symbols into a section
> > > > >> other than they'd normally live doesn't seem all that wise.
> > > > > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > > > > we should place it in an SHF_GNU_RETAIN section.
> > > >
> > > > Again, that's an implementation detail and it's not clear to me that one
> > > > approach is inherently better than the other.
> > > >
> > > >
> > > > >
> > > > >> Let's face it, there's not a great solution here.  If we mark its
> > > > >> existing section, then everything in that section gets kept.  If we put
> > > > > FWIW, this is what .retain direct does and is one reason why I object
> > > > > it.
> > > >
> > > > We could make .retain work with either approach.    I don't see .retain
> > > > as a problem at all.
> > > >
> > > >
> > > >
> > > > >
> > > > >> the object into a different section than it would normally live, then
> > > > >> that opens a whole new can of worms.
> > > > > We should place it in a section which it normally lives in and mark the
> > > > > section with SHF_GNU_RETAIN.
> > > >
> > > > And why not do that with .retain?  We define its semantics as precisely
> > >
> > > But the .retain directive implementation being discussed here is different.
> > > One problem with the .retain directive is we can have
> > >
> > > .section .data
> > > foo:
> > > ...
> > > bar:
> > >
> > > .retain bar
> > > ...
> > > xxx:
> > > ...
> > >
> > > What should assembler do with ".retain bar"?
> > >
> > > > what you've written above.  The referenced symbol goes into its usual
> > > > section and its section is marked with SHF_GNU_RETAIN.  That seems much
> > > > cleaner than having to track all this in the compiler so that it can
> > > > twiddle the section flags.
> > >
> > > When GCC emits a symbol definition, it places the symbol in a section
> > > with proper
> > > attributes which GCC tracks for each symbol.  It  can be extended to track
> > > SHF_GNU_RETAIN.
> >
> > The attached patch is rough around the edges but shows my approach for
> > marking unnamed sections as retained, by converting them to named
> > sections.
> >
> > I figure we don't have to wrap every usage of SECTION_RETAIN in
> > HAVE_GAS_SECTION_RETAIN as long as any set of SECTION_RETAIN in the
> > flags field is wrapped in the macro.
> >
> > I think a flag to turn off the behavior (in the same way the behavior is
> > disabled if !defined(HAVE_GAS_SECTION_RETAIN)) would be beneficial,
> > I haven't added that yet.
> >
> > Decls that would go in comm_section, tls_comm_section and sometimes
> > lcomm_section do not get retained as we can't apply the retain section
> > flag to these symbols. Given these go in one big common block, and
> > contain uninitialized data, I don't think there is a valid use case for
> > which these types of symbols need to be retained, but are not referenced
> > by the program. So I've avoided converting them to .bss or anything like
> > that.
> >
> > Some targets alias lcomm_section for bss_section, so we can retain
> > sections for that case.
> >
> > So far bootstrap and light testing on x86_64-pc-linux-gnu and
> > arm-none-eabi has shown no problems.
> >
> 
> Binutils change looks OK.  But GCC changes look too intrusive.
> Also SHF_GNU_RETAIN can't be used on Solaris since ld on
> Solaris may not support it.

I see Solaris ELF OSABI doesn't get set in bfd/elf32-i386.c because:

  /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
     objects won't be recognized.  */
  #undef ELF_OSABI

Since GNU OSABI support is implied for ELFOSABI_NONE, I guess there
needs to be an exception for the "R" section flag support where we check
if the target OS is Solaris.

> 
> Can you improve
> 
> https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain
> 
> to do what you need?

I don't want "used" to implicitly create named sections for decls which
would otherwise just be placed in the standard .text/.data/.rodata/.bss
sections.

Unless we just ignore the requirement to "retain" for unnamed sections,
something like my patch is needed where we transform assembler output
from
  .text -> .section .text,"axR"
or
  .bss  -> .section .bss,"awR"
  etc.

Jozef
> 
> -- 
> H.J.
H.J. Lu Nov. 9, 2020, 8:31 p.m. UTC | #36
On Mon, Nov 9, 2020 at 11:56 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Mon, Nov 09, 2020 at 10:36:07AM -0800, H.J. Lu via Gcc-patches wrote:
> > On Mon, Nov 9, 2020 at 9:41 AM Jozef Lawrynowicz
> > <jozef.l@mittosystems.com> wrote:
> > >
> > > On Fri, Nov 06, 2020 at 04:39:33PM -0800, H.J. Lu via Gcc-patches wrote:
> > > > On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
> > > > >
> > > > >
> > > > > On 11/6/20 5:13 PM, H.J. Lu wrote:
> > > > > > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> > > > > >>
> > > > > >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > > > > >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> > > > > >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > > > > >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> > > > > >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > > > > >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > > > > >>>>>>> <jozef.l@mittosystems.com> wrote:
> > > > > >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > > > > >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > > >>>>>>>>>> .retain is ill-defined.   For example,
> > > > > >>>>>>>>>>
> > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > > > >>>>>>>>>> static int xyzzy __attribute__((__used__));
> > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> > > > > >>>>>>>>>> .file "x.c"
> > > > > >>>>>>>>>> .text
> > > > > >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> > > > > >>>>>>>>>> .local xyzzy
> > > > > >>>>>>>>>> .comm xyzzy,4,4
> > > > > >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > > > > >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> > > > > >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> > > > > >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > > > > >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> > > > > >>>>>>>>> We both know this isn't rocket science with binutils.
> > > > > >>>>>>>> Indeed, and my patch handles it trivially:
> > > > > >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> > > > > >>>>>>>>
> > > > > >>>>>>>>   +void
> > > > > >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> > > > > >>>>>>>>   .... snip ....
> > > > > >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> > > > > >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> > > > > >>>>>>>>
> > > > > >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> > > > > >>>>>>>>     }
> > > > > >>>>>>>>        }
> > > > > >>>>>>>>
> > > > > >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> > > > > >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> > > > > >>>>>>>>   +
> > > > > >>>>>>>>      /* Double check weak symbols.  */
> > > > > >>>>>>>>      if (S_IS_WEAK (symp))
> > > > > >>>>>>>>        {
> > > > > >>>>>>>>
> > > > > >>>>>>>> We could check that the symbol named in the .retain directive has
> > > > > >>>>>>>> already been defined, however this isn't compatible with GCC
> > > > > >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> > > > > >>>>>>>> emitted before the local symbols are defined in the assembly output
> > > > > >>>>>>>> file.
> > > > > >>>>>>>>
> > > > > >>>>>>>> GAS should at least validate that the symbol named in the .retain
> > > > > >>>>>>>> directive does end up as a symbol though.
> > > > > >>>>>>>>
> > > > > >>>>>>> Don't add .retain.
> > > > > >>>>>> Why?  I don't see why you find it so objectionable.
> > > > > >>>>>>
> > > > > >>>>> An ELF symbol directive should operate on symbol table:
> > > > > >>>>>
> > > > > >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> > > > > >>>>>
> > > > > >>>>> not the section flags where the symbol is defined.
> > > > > >>>> I agree in general, but I think this is one of those cases where it's
> > > > > >>>> not so clear.  And what you're talking about is an implementation detail.
> > > > > >>> There is no need for such a hack.  The proper thing to do in ELF is
> > > > > >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > > > > >>> also avoids the question what to do with SHN_COMMON.
> > > > > >> I'm not sure that's a good idea either.  Moving symbols into a section
> > > > > >> other than they'd normally live doesn't seem all that wise.
> > > > > > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > > > > > we should place it in an SHF_GNU_RETAIN section.
> > > > >
> > > > > Again, that's an implementation detail and it's not clear to me that one
> > > > > approach is inherently better than the other.
> > > > >
> > > > >
> > > > > >
> > > > > >> Let's face it, there's not a great solution here.  If we mark its
> > > > > >> existing section, then everything in that section gets kept.  If we put
> > > > > > FWIW, this is what .retain direct does and is one reason why I object
> > > > > > it.
> > > > >
> > > > > We could make .retain work with either approach.    I don't see .retain
> > > > > as a problem at all.
> > > > >
> > > > >
> > > > >
> > > > > >
> > > > > >> the object into a different section than it would normally live, then
> > > > > >> that opens a whole new can of worms.
> > > > > > We should place it in a section which it normally lives in and mark the
> > > > > > section with SHF_GNU_RETAIN.
> > > > >
> > > > > And why not do that with .retain?  We define its semantics as precisely
> > > >
> > > > But the .retain directive implementation being discussed here is different.
> > > > One problem with the .retain directive is we can have
> > > >
> > > > .section .data
> > > > foo:
> > > > ...
> > > > bar:
> > > >
> > > > .retain bar
> > > > ...
> > > > xxx:
> > > > ...
> > > >
> > > > What should assembler do with ".retain bar"?
> > > >
> > > > > what you've written above.  The referenced symbol goes into its usual
> > > > > section and its section is marked with SHF_GNU_RETAIN.  That seems much
> > > > > cleaner than having to track all this in the compiler so that it can
> > > > > twiddle the section flags.
> > > >
> > > > When GCC emits a symbol definition, it places the symbol in a section
> > > > with proper
> > > > attributes which GCC tracks for each symbol.  It  can be extended to track
> > > > SHF_GNU_RETAIN.
> > >
> > > The attached patch is rough around the edges but shows my approach for
> > > marking unnamed sections as retained, by converting them to named
> > > sections.
> > >
> > > I figure we don't have to wrap every usage of SECTION_RETAIN in
> > > HAVE_GAS_SECTION_RETAIN as long as any set of SECTION_RETAIN in the
> > > flags field is wrapped in the macro.
> > >
> > > I think a flag to turn off the behavior (in the same way the behavior is
> > > disabled if !defined(HAVE_GAS_SECTION_RETAIN)) would be beneficial,
> > > I haven't added that yet.
> > >
> > > Decls that would go in comm_section, tls_comm_section and sometimes
> > > lcomm_section do not get retained as we can't apply the retain section
> > > flag to these symbols. Given these go in one big common block, and
> > > contain uninitialized data, I don't think there is a valid use case for
> > > which these types of symbols need to be retained, but are not referenced
> > > by the program. So I've avoided converting them to .bss or anything like
> > > that.
> > >
> > > Some targets alias lcomm_section for bss_section, so we can retain
> > > sections for that case.
> > >
> > > So far bootstrap and light testing on x86_64-pc-linux-gnu and
> > > arm-none-eabi has shown no problems.
> > >
> >
> > Binutils change looks OK.  But GCC changes look too intrusive.
> > Also SHF_GNU_RETAIN can't be used on Solaris since ld on
> > Solaris may not support it.
>
> I see Solaris ELF OSABI doesn't get set in bfd/elf32-i386.c because:
>
>   /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
>      objects won't be recognized.  */
>   #undef ELF_OSABI
>
> Since GNU OSABI support is implied for ELFOSABI_NONE, I guess there
> needs to be an exception for the "R" section flag support where we check
> if the target OS is Solaris.

GNU ld on Solaris should support SHF_GNU_RETAIN.

> >
> > Can you improve
> >
> > https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain
> >
> > to do what you need?
>
> I don't want "used" to implicitly create named sections for decls which
> would otherwise just be placed in the standard .text/.data/.rodata/.bss
> sections.
>
> Unless we just ignore the requirement to "retain" for unnamed sections,
> something like my patch is needed where we transform assembler output
> from
>   .text -> .section .text,"axR"
> or
>   .bss  -> .section .bss,"awR"
>   etc.
>

Please checkout

https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain
Jozef Lawrynowicz Nov. 10, 2020, 2:40 p.m. UTC | #37
On Mon, Nov 09, 2020 at 12:31:09PM -0800, H.J. Lu via Gcc-patches wrote:
> On Mon, Nov 9, 2020 at 11:56 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > On Mon, Nov 09, 2020 at 10:36:07AM -0800, H.J. Lu via Gcc-patches wrote:
> > > On Mon, Nov 9, 2020 at 9:41 AM Jozef Lawrynowicz
> > > <jozef.l@mittosystems.com> wrote:
> > > >
> > > > On Fri, Nov 06, 2020 at 04:39:33PM -0800, H.J. Lu via Gcc-patches wrote:
> > > > > On Fri, Nov 6, 2020 at 4:17 PM Jeff Law <law@redhat.com> wrote:
> > > > > >
> > > > > >
> > > > > > On 11/6/20 5:13 PM, H.J. Lu wrote:
> > > > > > > On Fri, Nov 6, 2020 at 4:01 PM Jeff Law <law@redhat.com> wrote:
> > > > > > >>
> > > > > > >> On 11/6/20 4:45 PM, H.J. Lu wrote:
> > > > > > >>> On Fri, Nov 6, 2020 at 3:37 PM Jeff Law <law@redhat.com> wrote:
> > > > > > >>>> On 11/6/20 4:29 PM, H.J. Lu wrote:
> > > > > > >>>>> On Fri, Nov 6, 2020 at 3:22 PM Jeff Law <law@redhat.com> wrote:
> > > > > > >>>>>> On 11/5/20 7:34 AM, H.J. Lu via Gcc-patches wrote:
> > > > > > >>>>>>> On Thu, Nov 5, 2020 at 3:37 AM Jozef Lawrynowicz
> > > > > > >>>>>>> <jozef.l@mittosystems.com> wrote:
> > > > > > >>>>>>>> On Thu, Nov 05, 2020 at 06:21:21AM -0500, Hans-Peter Nilsson wrote:
> > > > > > >>>>>>>>> On Wed, 4 Nov 2020, H.J. Lu wrote:
> > > > > > >>>>>>>>>> .retain is ill-defined.   For example,
> > > > > > >>>>>>>>>>
> > > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat /tmp/x.c
> > > > > > >>>>>>>>>> static int xyzzy __attribute__((__used__));
> > > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ ./xgcc -B./ -S /tmp/x.c -fcommon
> > > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$ cat x.s
> > > > > > >>>>>>>>>> .file "x.c"
> > > > > > >>>>>>>>>> .text
> > > > > > >>>>>>>>>> .retain xyzzy  <<<<<<<<< What does it do?
> > > > > > >>>>>>>>>> .local xyzzy
> > > > > > >>>>>>>>>> .comm xyzzy,4,4
> > > > > > >>>>>>>>>> .ident "GCC: (GNU) 11.0.0 20201103 (experimental)"
> > > > > > >>>>>>>>>> .section .note.GNU-stack,"",@progbits
> > > > > > >>>>>>>>>> [hjl@gnu-cfl-2 gcc]$
> > > > > > >>>>>>>>> To answer that question: it's up to the assembler, but for ELF
> > > > > > >>>>>>>>> and SHF_GNU_RETAIN, it seems obvious it'd tell the assembler to
> > > > > > >>>>>>>>> set SHF_GNU_RETAIN for the section where the symbol ends up.
> > > > > > >>>>>>>>> We both know this isn't rocket science with binutils.
> > > > > > >>>>>>>> Indeed, and my patch handles it trivially:
> > > > > > >>>>>>>> https://sourceware.org/pipermail/binutils/2020-November/113993.html
> > > > > > >>>>>>>>
> > > > > > >>>>>>>>   +void
> > > > > > >>>>>>>>   +obj_elf_retain (int arg ATTRIBUTE_UNUSED)
> > > > > > >>>>>>>>   .... snip ....
> > > > > > >>>>>>>>   +  sym = get_sym_from_input_line_and_check ();
> > > > > > >>>>>>>>   +  symbol_get_obj (sym)->retain = 1;
> > > > > > >>>>>>>>
> > > > > > >>>>>>>>   @@ -2624,6 +2704,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
> > > > > > >>>>>>>>     }
> > > > > > >>>>>>>>        }
> > > > > > >>>>>>>>
> > > > > > >>>>>>>>   +  if (symbol_get_obj (symp)->retain)
> > > > > > >>>>>>>>   +    elf_section_flags (S_GET_SEGMENT (symp)) |= SHF_GNU_RETAIN;
> > > > > > >>>>>>>>   +
> > > > > > >>>>>>>>      /* Double check weak symbols.  */
> > > > > > >>>>>>>>      if (S_IS_WEAK (symp))
> > > > > > >>>>>>>>        {
> > > > > > >>>>>>>>
> > > > > > >>>>>>>> We could check that the symbol named in the .retain directive has
> > > > > > >>>>>>>> already been defined, however this isn't compatible with GCC
> > > > > > >>>>>>>> mark_decl_preserved handling, since mark_decl_preserved is called
> > > > > > >>>>>>>> emitted before the local symbols are defined in the assembly output
> > > > > > >>>>>>>> file.
> > > > > > >>>>>>>>
> > > > > > >>>>>>>> GAS should at least validate that the symbol named in the .retain
> > > > > > >>>>>>>> directive does end up as a symbol though.
> > > > > > >>>>>>>>
> > > > > > >>>>>>> Don't add .retain.
> > > > > > >>>>>> Why?  I don't see why you find it so objectionable.
> > > > > > >>>>>>
> > > > > > >>>>> An ELF symbol directive should operate on symbol table:
> > > > > > >>>>>
> > > > > > >>>>> http://www.sco.com/developers/gabi/latest/ch4.symtab.html
> > > > > > >>>>>
> > > > > > >>>>> not the section flags where the symbol is defined.
> > > > > > >>>> I agree in general, but I think this is one of those cases where it's
> > > > > > >>>> not so clear.  And what you're talking about is an implementation detail.
> > > > > > >>> There is no need for such a hack.  The proper thing to do in ELF is
> > > > > > >>> to place such a symbol in a section with SHF_GNU_RETAIN flag.   This
> > > > > > >>> also avoids the question what to do with SHN_COMMON.
> > > > > > >> I'm not sure that's a good idea either.  Moving symbols into a section
> > > > > > >> other than they'd normally live doesn't seem all that wise.
> > > > > > > In ELF, a symbol must be defined in a section.  If we want to keep a symbol,
> > > > > > > we should place it in an SHF_GNU_RETAIN section.
> > > > > >
> > > > > > Again, that's an implementation detail and it's not clear to me that one
> > > > > > approach is inherently better than the other.
> > > > > >
> > > > > >
> > > > > > >
> > > > > > >> Let's face it, there's not a great solution here.  If we mark its
> > > > > > >> existing section, then everything in that section gets kept.  If we put
> > > > > > > FWIW, this is what .retain direct does and is one reason why I object
> > > > > > > it.
> > > > > >
> > > > > > We could make .retain work with either approach.    I don't see .retain
> > > > > > as a problem at all.
> > > > > >
> > > > > >
> > > > > >
> > > > > > >
> > > > > > >> the object into a different section than it would normally live, then
> > > > > > >> that opens a whole new can of worms.
> > > > > > > We should place it in a section which it normally lives in and mark the
> > > > > > > section with SHF_GNU_RETAIN.
> > > > > >
> > > > > > And why not do that with .retain?  We define its semantics as precisely
> > > > >
> > > > > But the .retain directive implementation being discussed here is different.
> > > > > One problem with the .retain directive is we can have
> > > > >
> > > > > .section .data
> > > > > foo:
> > > > > ...
> > > > > bar:
> > > > >
> > > > > .retain bar
> > > > > ...
> > > > > xxx:
> > > > > ...
> > > > >
> > > > > What should assembler do with ".retain bar"?
> > > > >
> > > > > > what you've written above.  The referenced symbol goes into its usual
> > > > > > section and its section is marked with SHF_GNU_RETAIN.  That seems much
> > > > > > cleaner than having to track all this in the compiler so that it can
> > > > > > twiddle the section flags.
> > > > >
> > > > > When GCC emits a symbol definition, it places the symbol in a section
> > > > > with proper
> > > > > attributes which GCC tracks for each symbol.  It  can be extended to track
> > > > > SHF_GNU_RETAIN.
> > > >
> > > > The attached patch is rough around the edges but shows my approach for
> > > > marking unnamed sections as retained, by converting them to named
> > > > sections.
> > > >
> > > > I figure we don't have to wrap every usage of SECTION_RETAIN in
> > > > HAVE_GAS_SECTION_RETAIN as long as any set of SECTION_RETAIN in the
> > > > flags field is wrapped in the macro.
> > > >
> > > > I think a flag to turn off the behavior (in the same way the behavior is
> > > > disabled if !defined(HAVE_GAS_SECTION_RETAIN)) would be beneficial,
> > > > I haven't added that yet.
> > > >
> > > > Decls that would go in comm_section, tls_comm_section and sometimes
> > > > lcomm_section do not get retained as we can't apply the retain section
> > > > flag to these symbols. Given these go in one big common block, and
> > > > contain uninitialized data, I don't think there is a valid use case for
> > > > which these types of symbols need to be retained, but are not referenced
> > > > by the program. So I've avoided converting them to .bss or anything like
> > > > that.
> > > >
> > > > Some targets alias lcomm_section for bss_section, so we can retain
> > > > sections for that case.
> > > >
> > > > So far bootstrap and light testing on x86_64-pc-linux-gnu and
> > > > arm-none-eabi has shown no problems.
> > > >
> > >
> > > Binutils change looks OK.  But GCC changes look too intrusive.
> > > Also SHF_GNU_RETAIN can't be used on Solaris since ld on
> > > Solaris may not support it.
> >
> > I see Solaris ELF OSABI doesn't get set in bfd/elf32-i386.c because:
> >
> >   /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
> >      objects won't be recognized.  */
> >   #undef ELF_OSABI
> >
> > Since GNU OSABI support is implied for ELFOSABI_NONE, I guess there
> > needs to be an exception for the "R" section flag support where we check
> > if the target OS is Solaris.
> 
> GNU ld on Solaris should support SHF_GNU_RETAIN.
> 
> > >
> > > Can you improve
> > >
> > > https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain
> > >
> > > to do what you need?
> >
> > I don't want "used" to implicitly create named sections for decls which
> > would otherwise just be placed in the standard .text/.data/.rodata/.bss
> > sections.
> >
> > Unless we just ignore the requirement to "retain" for unnamed sections,
> > something like my patch is needed where we transform assembler output
> > from
> >   .text -> .section .text,"axR"
> > or
> >   .bss  -> .section .bss,"awR"
> >   etc.
> >
> 
> Please checkout
> 
> https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/elf/shf_retain

Ah yes, using the prefix the section would have if it were named is a
much simpler solution.

For arm-none-eabi we are losing the "R" flag on data/bss/rodata at opt
levels above -O0 though, this is because SECTION2_RETAIN is not being
set on object_block sections.

Can you add me to that gitlab project so I can submit a merge request
for the fix for this please?

Also in the merge request are new tests and fixes to existing tests, my
new tests go in gcc.c-torture so we catch any other issues from building
at different optimization levels.

I'm going to resubmit my latest Binutils patch once I've put it through
the Binutils tests for ELF targets again.

Thanks,
Jozef
> 
> -- 
> H.J.
diff mbox series

Patch

diff --git a/gcc/config.in b/gcc/config.in
index 3657c46f349..8ef075a0ff3 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1346,6 +1346,12 @@ 
 #endif
 
 
+/* Define if your assembler supports the .retain directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_RETAIN
+#endif
+
+
 /* Define if your assembler supports specifying the exclude section flag. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GAS_SECTION_EXCLUDE
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 74a3eafda6b..fab7b0e8ea4 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -474,3 +474,10 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #undef TARGET_LIBC_HAS_FUNCTION
 #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
+
+/* If the assembler supports the .retain directive for saving a symbol
+   from linker garbage collection, define this macro.  */
+#if HAVE_GAS_RETAIN
+#undef TARGET_ASM_MARK_DECL_PRESERVED
+#define TARGET_ASM_MARK_DECL_PRESERVED default_elf_mark_decl_preserved
+#endif
diff --git a/gcc/configure b/gcc/configure
index abff47d30eb..37488eac25d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24223,6 +24223,41 @@  cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# Test if the assembler supports the .retain directive for saving a symbol from
+# linker garbage collection.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for retain directive" >&5
+$as_echo_n "checking assembler for retain directive... " >&6; }
+if ${gcc_cv_as_retain_r+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_retain_r=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '.retain retain_sym' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_retain_r=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_retain_r" >&5
+$as_echo "$gcc_cv_as_retain_r" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_RETAIN `if test $gcc_cv_as_retain_r = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
 $as_echo_n "checking assembler for section merging support... " >&6; }
 if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 26a5d8e3619..08b38d894a3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3216,6 +3216,14 @@  AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
   [`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
 [Define if your assembler supports specifying the exclude section flag.])
 
+# Test if the assembler supports the .retain directive for saving a symbol from
+# linker garbage collection.
+gcc_GAS_CHECK_FEATURE([retain directive], gcc_cv_as_retain_r,,,
+ [.retain retain_sym])
+AC_DEFINE_UNQUOTED(HAVE_GAS_RETAIN,
+  [`if test $gcc_cv_as_retain_r = yes; then echo 1; else echo 0; fi`],
+[Define if your assembler supports the .retain directive.])
+
 gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
  [elf,2,12,0], [--fatal-warnings],
  [.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 62549b02452..4f77a5c0229 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3810,6 +3810,9 @@  When applied to a member function of a C++ class template, the
 attribute also means that the function is instantiated if the
 class itself is instantiated.
 
+As a GNU ELF extension, functions with this attribute will not be
+garbage collected by the linker.
+
 @item visibility ("@var{visibility_type}")
 @cindex @code{visibility} function attribute
 This attribute affects the linkage of the declaration to which it is attached.
@@ -7269,6 +7272,9 @@  When applied to a static data member of a C++ class template, the
 attribute also means that the member is instantiated if the
 class itself is instantiated.
 
+As a GNU ELF extension, variables with this attribute will not be
+garbage collected by the linker.
+
 @item vector_size (@var{bytes})
 @cindex @code{vector_size} variable attribute
 This attribute specifies the vector size for the type of the declared
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 49316a5d0ff..7fe77e7f09e 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2551,6 +2551,9 @@  Target supports @option{-pie}, @option{-fpie} and @option{-fPIE}.
 @item rdynamic
 Target supports @option{-rdynamic}.
 
+@item retain
+Target supports the @code{.retain} assembler directive.
+
 @item scalar_all_fma
 Target supports all four fused multiply-add optabs for both @code{float}
 and @code{double}.  These optabs are: @code{fma_optab}, @code{fms_optab},
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 97437e8274f..b074b2ff75b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8773,7 +8773,7 @@  library function is given by @var{symref}, which is a @code{symbol_ref}.
 @deftypefn {Target Hook} void TARGET_ASM_MARK_DECL_PRESERVED (const char *@var{symbol})
 This target hook is a function to output to @var{asm_out_file} an assembler
 directive to annotate @var{symbol} as used.  The Darwin target uses the
-.no_dead_code_strip directive.
+.no_dead_code_strip directive, and ELF targets use the .retain directive.
 @end deftypefn
 
 @defmac ASM_OUTPUT_LABELREF (@var{stream}, @var{name})
diff --git a/gcc/output.h b/gcc/output.h
index eb253c50329..c0eba372c5d 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -609,6 +609,10 @@  extern void default_elf_init_array_asm_out_constructor (rtx, int);
 extern void default_elf_fini_array_asm_out_destructor (rtx, int);
 extern int maybe_assemble_visibility (tree);
 
+#if HAVE_GAS_RETAIN
+void default_elf_mark_decl_preserved (const char *);
+#endif
+
 extern int default_address_cost (rtx, machine_mode, addr_space_t, bool);
 
 /* Stack usage.  */
diff --git a/gcc/target.def b/gcc/target.def
index ed2da154e30..12164792b00 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -737,7 +737,7 @@  DEFHOOK
 (mark_decl_preserved,
  "This target hook is a function to output to @var{asm_out_file} an assembler\n\
 directive to annotate @var{symbol} as used.  The Darwin target uses the\n\
-.no_dead_code_strip directive.",
+.no_dead_code_strip directive, and ELF targets use the .retain directive.",
  void, (const char *symbol),
  hook_void_constcharptr)
 
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b53a9..cf1d25a5b27 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@  void foo()
 }
 
 /* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\\.retain\t\.*xyzzy" { target retain } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705aaa77..65a2f029698 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,5 @@  static void function_declaration_after(void) __attribute__((__used__));
 
 /* { dg-final { scan-assembler "function_declaration_before" } } */
 /* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\\.retain\t\.*function_declaration_before" { target retain } } } */
+/* { dg-final { scan-assembler "\\.retain\t\.*function_declaration_after" { target retain } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 8439720baea..7c0e925f7b4 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -380,6 +380,15 @@  proc check_effective_target_noinit { } {
     return 0
 }
 
+# The .retain assembler directive is only supported by some targets.
+# This proc returns 1 if it's supported, 0 if it's not.
+
+proc check_effective_target_retain { } {
+    return [check_no_compiler_messages retain_available object {
+	__asm__(".retain used_var");
+    }]
+}
+
 ###############################
 # proc check_visibility_available { what_kind }
 ###############################
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ea0b59cf44a..c38640456c4 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -8276,6 +8276,19 @@  default_elf_fini_array_asm_out_destructor (rtx symbol, int priority)
   assemble_addr_to_section (symbol, sec);
 }
 
+
+#if HAVE_GAS_RETAIN
+/* Implement TARGET_ASM_MARK_DECL_PRESERVED for ELF targets that support the
+   .retain assembler directive.  */
+void
+default_elf_mark_decl_preserved (const char *name)
+{
+  fprintf (asm_out_file, "\t.retain\t");
+  assemble_name (asm_out_file, name);
+  fputc ('\n', asm_out_file);
+}
+#endif
+
 /* Default TARGET_ASM_OUTPUT_IDENT hook.
 
    This is a bit of a cheat.  The real default is a no-op, but this