[PATCH v2] Support for SHF_GNU_RETAIN ELF Section Flag
Jozef Lawrynowicz
jozef.l@mittosystems.com
Thu Oct 1 10:50:33 GMT 2020
On Wed, Sep 30, 2020 at 03:13:15PM -0700, H.J. Lu via Binutils wrote:
> On Mon, Sep 28, 2020 at 6:28 AM Jozef Lawrynowicz
> <jozef.l@mittosystems.com> wrote:
> >
> > The attached patch is version 2 of the SHF_GNU_RETAIN patch that was
> > previously discussed here:
> > https://sourceware.org/pipermail/binutils/2020-September/113406.html
> >
> > The following changes have been made:
> > - Removed the .retain directive
> > - The assembler will create different input sections for sections with
> > the same name but SHF_GNU_RETAIN set/unset (thanks to H.J. for that).
> > This means the linker will be able to do a better job garbage
> > collecting input sections, as the "retain" attribute applied to a
> > symbol declaration in the source code will not cause other parts of
> > the program that are not required, but are in the same section, to be
> > unnecessarily retained.
> > - Added GNU OSABI handling (also thanks to H.J.).
> >
> > I've successfully regtested the patch for the Binutils, GAS and LD
> > testsuites for the following targets:
> >
> > aarch64-elf arc-elf arm-eabi arm-elf avr-elf bfin-elf cr16-elf cris-elf
> > crx-elf csky-elf d10v-elf d30v-elf dlx-elf epiphany-elf fr30-elf frv-elf
> > ft32-elf h8300-elf hppa-elf i386-elf ip2k-elf iq2000-elf lm32-elf
> > m32c-elf m32r-elf m68hc11-elf m68hc12-elf m68k-elf mcore-elf mep-elf
> > metag-elf microblaze-elf mips-elf moxie-elf msp430-elf mt-elf nios2-elf
> > or1k-elf pj-elf ppc-elf pru-elf riscv-elf rl78-elf rx-elf s12z-elf
> > score-elf sh-elf sparc-elf spu-elf tic6x-elf tilegx-elf tilepro-elf
> > v850-elf visium-elf wasm32-elf xgate-elf xstormy16-elf xtensa-elf
> > z80-elf.
> >
> > The new tests only run for the targets that use the GNU OSABI. From the
> > above list, arm-elf, hppa-elf, msp430-elf, visium-elf do not use the GNU
> > OSABI, so do not support SHF_GNU_RETAIN.
> >
> > Ok to apply?
> >
> > Thanks,
> > Jozef
>
> +# SHF_GNU_RETAIN requires the GNU OSABI.
> +if { [check_gc_sections_available] && [supports_gnu_osabi] } {
> + run_ld_link_tests [list \
> + [list "SHF_GNU_RETAIN 1" \
> + "--gc-sections -e _start --print-gc-sections" "" "" \
> + {retain1.s} \
> + {{ ld retain1.msg }} \
> + "retain1.exe"] \
> + [list "SHF_GNU_RETAIN 3 (keep sections referenced by retained sections)" \
> + "--gc-sections -e _start --print-gc-sections" "" "" \
> + {retain3.s} {} \
> + "retain3.exe"] \
> + [list "SHF_GNU_RETAIN 4 (keep orphaned sections when not discarding)" \
> + "--gc-sections -e _start --print-gc-sections
> --orphan-handling=place" "" "" \
> + {retain4.s} {} \
> + "retain4.exe"] \
> + [list "Build libretain5.a" \
> + "" "" "" \
> + {retain5lib.s} {} "libretain5.a"] \
> + [list "SHF_GNU_RETAIN 5 (don't pull SHF_GNU_RETAIN section out of lib)" \
> + "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain5" "" \
> + {retain5main.s} {} \
> + "retain5.exe"] \
> + [list "Build libretain6.a" \
> + "" "" "" \
> + {retain6lib.s} {} "libretain6.a"] \
> + [list "SHF_GNU_RETAIN 6 (pull section out of lib required by
> SHF_GNU_RETAIN section)" \
> + "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain6" "" \
> + {retain6main.s} \
> + {{ ld retain6.msg }} \
> + "retain6.exe"] \
> + ]
> +}
> +
>
> Can you use *.d files like
>
> retain6.d:
> #ld: --gc-sections --print-gc-sections -e _start
> #warning_output: retain6.l
> #target: [check_gc_sections_available]
>
> instead?
Fixed in the attached patch.
Thanks,
Jozef
>
> --
> H.J.
-------------- next part --------------
>From c089da6a64f293e1fc15cdf31e647b4f04af62b4 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Thu, 1 Oct 2020 11:49:04 +0100
Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag
The GNU-specific SHF_GNU_RETAIN ELF section flag is defined as follows:
=======================================================================
Section Attribute Flags
+-------------------------------------+
| Name | Value |
+-------------------------------------+
| SHF_GNU_RETAIN | 0x200000 (1 << 21) |
+-------------------------------------+
SHF_GNU_RETAIN
The link editor should not garbage collect the section if it is
unused.
=======================================================================
Note that there is not a direct mapping of SHF_GNU_RETAIN to the BFD
section flag SEC_KEEP. This would prevent the user being able to
explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/.
bfd/ChangeLog:
2020-09-28 H.J. Lu <hongjiu.lu@intel.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* elf-bfd.h (enum elf_gnu_osabi): Add elf_gnu_osabi_retain.
(struct elf_obj_tdata): Increase has_gnu_osabi to 4 bits.
* elf.c (_bfd_elf_make_section_from_shdr): Set elf_gnu_osabi_retain
for SHF_GNU_RETAIN.
* elflink.c (bfd_elf_gc_sections): gc_mark the section if
SHF_GNU_RETAIN is set.
binutils/ChangeLog:
2020-09-28 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* NEWS: Announce SHF_GNU_RETAIN.
* readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN.
* testsuite/binutils-all/readelf.exp: Run new test.
Don't run run_dump_test when there isn't an assembler available.
* testsuite/lib/binutils-common.exp (supports_gnu_osabi): Adjust
comment.
* testsuite/binutils-all/retain1.d: New test.
* testsuite/binutils-all/retain1.s: New test.
gas/ChangeLog:
2020-09-28 H.J. Lu <hongjiu.lu@intel.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* NEWS: Announce SHF_GNU_RETAIN.
* config/obj-elf.c (SEC_ASSEMBLER_SHF_MASK): New.
(get_section): Use SEC_ASSEMBLER_SHF_MASK.
(obj_elf_change_section): Update struct member name.
(obj_elf_parse_section_letters): Handle 'R' flag.
(obj_elf_section): Set elf_gnu_osabi_retain
for SHF_GNU_RETAIN.
* config/obj-elf.h (struct elf_section_match): Adjust "info" member
name to "sh_info". Add "sh_flags" member.
* doc/as.texi (Section): Document 'R' flag.
* testsuite/gas/elf/elf.exp: Run new tests.
* testsuite/gas/elf/section10.d: Adjust test.
* testsuite/gas/elf/section22.d: New test.
* testsuite/gas/elf/section22.s: New test.
include/ChangeLog:
2020-09-28 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* elf/common.h (SHF_GNU_RETAIN): Define.
ld/ChangeLog:
2020-09-28 Jozef Lawrynowicz <jozef.l@mittosystems.com>
H.J. Lu <hongjiu.lu@intel.com>
* NEWS: Announce SHF_GNU_RETAIN.
* ld.texi (garbage collection): Document SHF_GNU_RETAIN.
(Output Section Discarding): Likewise.
* testsuite/ld-elf/elf.exp: Run new tests.
* testsuite/ld-elf/retain1.s: New test.
* testsuite/ld-elf/retain1a.d: New test.
* testsuite/ld-elf/retain1b.d: New test.
* testsuite/ld-elf/retain2.d: New test.
* testsuite/ld-elf/retain2.ld: New test.
* testsuite/ld-elf/retain2.map: New test.
* testsuite/ld-elf/retain3.d: New test.
* testsuite/ld-elf/retain3.s: New test.
* testsuite/ld-elf/retain4.d: New test.
* testsuite/ld-elf/retain4.s: New test.
* testsuite/ld-elf/retain5.d: New test.
* testsuite/ld-elf/retain5.map: New test.
* testsuite/ld-elf/retain5lib.s: New test.
* testsuite/ld-elf/retain5main.s: New test.
* testsuite/ld-elf/retain6a.d: New test.
* testsuite/ld-elf/retain6b.d: New test.
* testsuite/ld-elf/retain6lib.s: New test.
* testsuite/ld-elf/retain6main.s: New test.
* testsuite/ld-elf/retain7.s: New test.
* testsuite/ld-elf/retain7a.d: New test.
* testsuite/ld-elf/retain7b.d: New test.
---
bfd/elf-bfd.h | 9 +-
bfd/elf.c | 5 +-
bfd/elflink.c | 3 +-
binutils/NEWS | 4 +
binutils/readelf.c | 4 +
binutils/testsuite/binutils-all/readelf.exp | 6 +-
binutils/testsuite/binutils-all/retain1.d | 18 ++++
binutils/testsuite/binutils-all/retain1.s | 104 ++++++++++++++++++++
binutils/testsuite/lib/binutils-common.exp | 5 +-
gas/NEWS | 6 ++
gas/config/obj-elf.c | 39 +++++---
gas/config/obj-elf.h | 3 +-
gas/doc/as.texi | 3 +
gas/testsuite/gas/elf/elf.exp | 1 +
gas/testsuite/gas/elf/section10.d | 4 +-
gas/testsuite/gas/elf/section22.d | 19 ++++
gas/testsuite/gas/elf/section22.s | 34 +++++++
include/elf/common.h | 1 +
ld/NEWS | 4 +
ld/ld.texi | 8 ++
ld/testsuite/ld-elf/elf.exp | 11 +++
ld/testsuite/ld-elf/retain1.s | 104 ++++++++++++++++++++
ld/testsuite/ld-elf/retain1a.d | 28 ++++++
ld/testsuite/ld-elf/retain1b.d | 11 +++
ld/testsuite/ld-elf/retain2.d | 6 ++
ld/testsuite/ld-elf/retain2.ld | 7 ++
ld/testsuite/ld-elf/retain2.map | 32 ++++++
ld/testsuite/ld-elf/retain3.d | 12 +++
ld/testsuite/ld-elf/retain3.s | 19 ++++
ld/testsuite/ld-elf/retain4.d | 10 ++
ld/testsuite/ld-elf/retain4.s | 13 +++
ld/testsuite/ld-elf/retain5.d | 12 +++
ld/testsuite/ld-elf/retain5.map | 5 +
ld/testsuite/ld-elf/retain5lib.s | 6 ++
ld/testsuite/ld-elf/retain5main.s | 5 +
ld/testsuite/ld-elf/retain6a.d | 14 +++
ld/testsuite/ld-elf/retain6b.d | 11 +++
ld/testsuite/ld-elf/retain6lib.s | 17 ++++
ld/testsuite/ld-elf/retain6main.s | 13 +++
ld/testsuite/ld-elf/retain7.s | 104 ++++++++++++++++++++
ld/testsuite/ld-elf/retain7a.d | 28 ++++++
ld/testsuite/ld-elf/retain7b.d | 11 +++
42 files changed, 737 insertions(+), 22 deletions(-)
create mode 100644 binutils/testsuite/binutils-all/retain1.d
create mode 100644 binutils/testsuite/binutils-all/retain1.s
create mode 100644 gas/testsuite/gas/elf/section22.d
create mode 100644 gas/testsuite/gas/elf/section22.s
create mode 100644 ld/testsuite/ld-elf/retain1.s
create mode 100644 ld/testsuite/ld-elf/retain1a.d
create mode 100644 ld/testsuite/ld-elf/retain1b.d
create mode 100644 ld/testsuite/ld-elf/retain2.d
create mode 100644 ld/testsuite/ld-elf/retain2.ld
create mode 100644 ld/testsuite/ld-elf/retain2.map
create mode 100644 ld/testsuite/ld-elf/retain3.d
create mode 100644 ld/testsuite/ld-elf/retain3.s
create mode 100644 ld/testsuite/ld-elf/retain4.d
create mode 100644 ld/testsuite/ld-elf/retain4.s
create mode 100644 ld/testsuite/ld-elf/retain5.d
create mode 100644 ld/testsuite/ld-elf/retain5.map
create mode 100644 ld/testsuite/ld-elf/retain5lib.s
create mode 100644 ld/testsuite/ld-elf/retain5main.s
create mode 100644 ld/testsuite/ld-elf/retain6a.d
create mode 100644 ld/testsuite/ld-elf/retain6b.d
create mode 100644 ld/testsuite/ld-elf/retain6lib.s
create mode 100644 ld/testsuite/ld-elf/retain6main.s
create mode 100644 ld/testsuite/ld-elf/retain7.s
create mode 100644 ld/testsuite/ld-elf/retain7a.d
create mode 100644 ld/testsuite/ld-elf/retain7b.d
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 00594020c9..85a889a97f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1068,9 +1068,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;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index b6937293e8..65b2d6b8aa 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -14102,7 +14102,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|| (elf_section_data (o)->this_hdr.sh_type
== SHT_FINI_ARRAY)))
|| (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
- && elf_next_in_group (o) == NULL )))
+ && elf_next_in_group (o) == NULL)
+ || (elf_section_flags (o) & SHF_GNU_RETAIN)))
{
if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
return FALSE;
diff --git a/binutils/NEWS b/binutils/NEWS
index c0dc73d7d8..6c7d3f3953 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -4,6 +4,10 @@
symbol names. In addition the --demangle=<style>, --no-demangle,
--recurse-limit and --no-recurse-limit options are also now availale.
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+ This flag specifies that the section should not be garbage collected by the
+ linker if it is unused.
+
Changes in 2.35:
* Changed readelf's display of symbol names when wide mode is not enabled.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 9ba4e29a65..d136b750ed 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5977,6 +5977,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
/* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
/* VLE specific. */
/* 25 */ { STRING_COMMA_LEN ("VLE") },
+ /* GNU specific. */
+ /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") },
};
if (do_section_details)
@@ -6010,6 +6012,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
case SHF_EXCLUDE: sindex = 18; break;
case SHF_COMPRESSED: sindex = 20; break;
case SHF_GNU_MBIND: sindex = 24; break;
+ case SHF_GNU_RETAIN: sindex = 26; break;
default:
sindex = -1;
@@ -6108,6 +6111,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags)
case SHF_EXCLUDE: *p = 'E'; break;
case SHF_COMPRESSED: *p = 'C'; break;
case SHF_GNU_MBIND: *p = 'D'; break;
+ case SHF_GNU_RETAIN: *p = 'R'; break;
default:
if ((filedata->file_header.e_machine == EM_X86_64
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 1fb36ae5c4..6dea09e305 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -364,8 +364,12 @@ readelf_wi_test
readelf_compressed_wa_test
readelf_dump_test
-run_dump_test "pr25543"
+# These dump tests require an assembler.
+if {[which $AS] != 0} then {
+ run_dump_test "pr25543"
+ run_dump_test "retain1"
+}
# PR 13482 - Check for off-by-one errors when dumping .note sections.
if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
diff --git a/binutils/testsuite/binutils-all/retain1.d b/binutils/testsuite/binutils-all/retain1.d
new file mode 100644
index 0000000000..01cd32a475
--- /dev/null
+++ b/binutils/testsuite/binutils-all/retain1.d
@@ -0,0 +1,18 @@
+#source: retain1.s
+#readelf: -S --wide
+#name: readelf SHF_GNU_RETAIN
+#notarget: ![supports_gnu_osabi]
+
+#...
+ \[[ 0-9]+\] .bss.retain0.*WAR.*
+ \[[ 0-9]+\] .bss.retain1.*WAR.*
+ \[[ 0-9]+\] .data.retain2.*WAR.*
+ \[[ 0-9]+\] .bss.sretain0.*WAR.*
+ \[[ 0-9]+\] .bss.sretain1.*WAR.*
+ \[[ 0-9]+\] .data.sretain2.*WAR.*
+ \[[ 0-9]+\] .text.fnretain1.*AXR.*
+#...
+ \[[ 0-9]+\] .bss.lsretain0.*WAR.*
+ \[[ 0-9]+\] .bss.lsretain1.*WAR.*
+ \[[ 0-9]+\] .data.lsretain2.*WAR.*
+#pass
diff --git a/binutils/testsuite/binutils-all/retain1.s b/binutils/testsuite/binutils-all/retain1.s
new file mode 100644
index 0000000000..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/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 7ae58506ec..2056967a35 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -16,6 +16,12 @@
* Configure with --enable-x86-used-note by default for Linux/x86.
+* Add support for the "R" flag in the .section directive.
+ This flag requires ELFOSABI_GNU or ELFOSABI_FREEBSD, and applies the
+ ELF SHF_GNU_RETAIN flag to the specified section. This flag specifies
+ the section should not be garbage collected by the linker if it is
+ unused.
+
Changes in 2.35:
* X86 NaCl target support is removed.
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index b1c99020a3..abc3c5d692 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -517,6 +517,10 @@ struct section_stack
static struct section_stack *section_stack;
+/* Create unique input sections for sections with the same name, but different
+ values for the flags in this mask. */
+#define SEC_ASSEMBLER_SHF_MASK SHF_GNU_RETAIN
+
static bfd_boolean
get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
@@ -525,9 +529,12 @@ get_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
const char *group_name = elf_group_name (sec);
const char *linked_to_symbol_name
= sec->map_head.linked_to_symbol_name;
- unsigned int info = elf_section_data (sec)->this_hdr.sh_info;
+ unsigned int sh_info = elf_section_data (sec)->this_hdr.sh_info;
+ bfd_vma sh_flags = (elf_section_data (sec)->this_hdr.sh_flags
+ & SEC_ASSEMBLER_SHF_MASK);
- return (info == match->info
+ return (sh_info == match->sh_info
+ && sh_flags == match->sh_flags
&& ((bfd_section_flags (sec) & SEC_ASSEMBLER_SECTION_ID)
== (match->flags & SEC_ASSEMBLER_SECTION_ID))
&& sec->section_id == match->section_id
@@ -736,7 +743,7 @@ obj_elf_change_section (const char *name,
type = bfd_elf_get_default_section_type (flags);
elf_section_type (sec) = type;
elf_section_flags (sec) = attr;
- elf_section_data (sec)->this_hdr.sh_info = match_p->info;
+ elf_section_data (sec)->this_hdr.sh_info = match_p->sh_info;
/* Prevent SEC_HAS_CONTENTS from being inadvertently set. */
if (type == SHT_NOBITS)
@@ -857,6 +864,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;
@@ -1250,18 +1260,21 @@ obj_elf_section (int push)
if (ISDIGIT (* input_line_pointer))
{
char *t = input_line_pointer;
- match.info = strtoul (input_line_pointer,
+ match.sh_info = strtoul (input_line_pointer,
&input_line_pointer, 0);
- if (match.info == (unsigned int) -1)
+ if (match.sh_info == (unsigned int) -1)
{
as_warn (_("unsupported mbind section info: %s"), t);
- match.info = 0;
+ match.sh_info = 0;
}
}
else
input_line_pointer = save;
}
+ if ((gnu_attr & SHF_GNU_RETAIN) != 0)
+ match.sh_flags |= SHF_GNU_RETAIN;
+
if (*input_line_pointer == ',')
{
char *save = input_line_pointer;
@@ -1352,11 +1365,12 @@ obj_elf_section (int push)
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);
@@ -1364,9 +1378,12 @@ obj_elf_section (int push)
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;
+ as_bad (_("%s section is supported only by GNU and FreeBSD targets"),
+ mbind_p ? "GNU_MBIND" : "GNU_RETAIN");
+ 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;
}
elf_section_flags (now_seg) |= gnu_attr;
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index b39a1a1ab6..6eb0a8ede4 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -106,8 +106,9 @@ struct elf_section_match
{
const char *group_name;
const char *linked_to_symbol_name;
- unsigned int info;
unsigned int section_id;
+ unsigned int sh_info; /* ELF section information. */
+ bfd_vma sh_flags; /* ELF section flags. */
flagword flags;
};
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index b88c1f9997..31c32a8172 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -6559,6 +6559,9 @@ ignored. (For compatibility with the ELF version)
section is not readable (meaningful for PE targets)
@item 0-9
single-digit power-of-two section alignment (GNU extension)
+@item R
+retained section (apply SHF_GNU_RETAIN to prevent linker garbage
+collection, GNU ELF extension)
@end table
If no flags are specified, the default flags depend upon the section name. If
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 135ade24ec..a0ad2d8dd0 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -257,6 +257,7 @@ if { [is_elf_format] } then {
run_dump_test "section19"
run_dump_test "section20"
run_dump_test "section21"
+ run_dump_test "section22"
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..ef91d7d086 100644
--- a/gas/testsuite/gas/elf/section10.d
+++ b/gas/testsuite/gas/elf/section10.d
@@ -18,7 +18,7 @@
#...
[ ]*\[.*\][ ]+sec3
[ ]*PROGBITS.*
-[ ]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
+[ ]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\)
#...
[ ]*\[.*\][ ]+sec4
[ ]*LOOS\+0x11[ ].*
@@ -26,7 +26,7 @@
#...
[ ]*\[.*\][ ]+sec5
[ ]*LOUSER\+0x9[ ].*
-[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
+[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\)
[ ]*\[.*\][ ]+.data.foo
[ ]*LOUSER\+0x7f000000[ ].*
[ ]*\[0+003\]: WRITE, ALLOC
diff --git a/gas/testsuite/gas/elf/section22.d b/gas/testsuite/gas/elf/section22.d
new file mode 100644
index 0000000000..27d9127745
--- /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[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.*
+#...
+ \[..\] .data[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.*
+#...
+ \[..\] .bss[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.*
+#...
+ \[..\] .bss[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#...
+ \[..\] .data[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.*
+#...
+ \[..\] .text[ ]+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..6e2b95c1e8
--- /dev/null
+++ b/gas/testsuite/gas/elf/section22.s
@@ -0,0 +1,34 @@
+ .section .text,"ax",%progbits
+ .global discard0
+ .type discard0, %function
+discard0:
+ .word 0
+
+ .section .data,"aw"
+ .global discard1
+ .type discard1, %object
+discard1:
+ .word 1
+
+ .section .bss,"aw"
+ .global discard2
+ .type discard2, %object
+discard2:
+ .zero 2
+
+ .section .bss,"awR",%nobits
+ .global retain0
+ .type retain0, %object
+retain0:
+ .zero 2
+
+ .section .data,"awR",%progbits
+ .type retain1, %object
+retain1:
+ .word 1
+
+ .section .text,"axR",%progbits
+ .global retain2
+ .type retain2, %function
+retain2:
+ .word 0
diff --git a/include/elf/common.h b/include/elf/common.h
index 571e21af29..c01e562c78 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 e4ae43b257..72cdf0edd3 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -15,6 +15,10 @@
unless you are working on a project that has its own analogue
of symbol tables that are not reflected in the ELF symtabs.
+* Add support for the SHF_GNU_RETAIN ELF section flag.
+ This flag specifies that the section should not be garbage collected by the
+ linker if it is unused.
+
Changes in 2.35:
* X86 NaCl target support is removed.
diff --git a/ld/ld.texi b/ld/ld.texi
index ee592df6c2..526b642d78 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1787,6 +1787,10 @@ specified either by one of the options @samp{--entry},
@samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY}
command in the linker script.
+As a GNU extension, ELF input sections marked with the
+@code{SHF_GNU_RETAIN} flag will not be garbage collected if they are
+unused.
+
@kindex --print-gc-sections
@kindex --no-print-gc-sections
@cindex garbage collection
@@ -5232,6 +5236,10 @@ The special output section name @samp{/DISCARD/} may be used to discard
input sections. Any input sections which are assigned to an output
section named @samp{/DISCARD/} are not included in the output file.
+This can be used to discard input sections marked with the ELF flag
+@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker
+garbage collection when they are unused.
+
Note, sections that match the @samp{/DISCARD/} output section will be
discarded even if they are in an ELF section group which has other
members which are not being discarded. This is deliberate.
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 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..75abb9856c
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1a.d
@@ -0,0 +1,28 @@
+#name: SHF_GNU_RETAIN 1a
+#source: retain1.s
+#ld: -e _start --gc-sections
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..815c0150f5
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain1b.d
@@ -0,0 +1,11 @@
+#name: SHF_GNU_RETAIN 1b
+#source: retain1.s
+#ld: -e _start --gc-sections
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..11efd6ddb8
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain2.d
@@ -0,0 +1,6 @@
+#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
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..911f5b7594
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain3.d
@@ -0,0 +1,12 @@
+#name: SHF_GNU_RETAIN 3 (keep sections referenced by retained sections)
+#source: retain3.s
+#ld: -e _start --gc-sections
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..e94898d681
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain4.d
@@ -0,0 +1,10 @@
+#name: SHF_GNU_RETAIN 4 (keep orphaned sections when not discarding)
+#source: retain4.s
+#ld: -e _start --gc-sections --orphan-handling=place
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..378799599e
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain5.d
@@ -0,0 +1,12 @@
+#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
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..92872deffc
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6a.d
@@ -0,0 +1,14 @@
+#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
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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..a797bf7837
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain6b.d
@@ -0,0 +1,11 @@
+#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
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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
diff --git a/ld/testsuite/ld-elf/retain7.s b/ld/testsuite/ld-elf/retain7.s
new file mode 100644
index 0000000000..2d80947fbd
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7.s
@@ -0,0 +1,104 @@
+ .section .bss,"aw"
+ .global discard0
+ .type discard0, %object
+discard0:
+ .zero 2
+
+ .section .bss,"aw"
+ .global discard1
+ .type discard1, %object
+discard1:
+ .zero 2
+
+ .section .data,"aw"
+ .global discard2
+ .type discard2, %object
+discard2:
+ .word 1
+
+ .section .bss,"aw"
+ .type sdiscard0, %object
+sdiscard0:
+ .zero 2
+
+ .section .bss,"aw"
+ .type sdiscard1, %object
+sdiscard1:
+ .zero 2
+
+ .section .data,"aw"
+ .type sdiscard2, %object
+sdiscard2:
+ .word 1
+
+ .text
+ .global fndiscard0
+ .type fndiscard0, %function
+fndiscard0:
+ .word 0
+
+ .section .bss,"awR"
+ .global retain0
+ .type retain0, %object
+retain0:
+ .zero 2
+
+ .section .bss,"awR"
+ .global retain1
+ .type retain1, %object
+retain1:
+ .zero 2
+
+ .section .data,"awR"
+ .global retain2
+ .type retain2, %object
+retain2:
+ .word 1
+
+ .section .bss,"awR"
+ .type sretain0, %object
+sretain0:
+ .zero 2
+
+ .section .bss,"awR"
+ .type sretain1, %object
+sretain1:
+ .zero 2
+
+ .section .data,"aRw"
+ .type sretain2, %object
+sretain2:
+ .word 1
+
+ .section .text,"Rax"
+ .global fnretain1
+ .type fnretain1, %function
+fnretain1:
+ .word 0
+
+ .section .text,"ax"
+ .global fndiscard2
+ .type fndiscard2, %function
+fndiscard2:
+ .word 0
+
+ .section .bss,"awR"
+ .type lsretain0.2, %object
+lsretain0.2:
+ .zero 2
+
+ .section .bss,"aRw"
+ .type lsretain1.1, %object
+lsretain1.1:
+ .zero 2
+
+ .section .data,"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/retain7a.d b/ld/testsuite/ld-elf/retain7a.d
new file mode 100644
index 0000000000..055bb74da9
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7a.d
@@ -0,0 +1,28 @@
+#name: SHF_GNU_RETAIN 7a (flag applied to default section names)
+#source: retain7.s
+#ld: -e _start --gc-sections
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#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/retain7b.d b/ld/testsuite/ld-elf/retain7b.d
new file mode 100644
index 0000000000..f268047c35
--- /dev/null
+++ b/ld/testsuite/ld-elf/retain7b.d
@@ -0,0 +1,11 @@
+#name: SHF_GNU_RETAIN 7b (flag applied to default section names)
+#source: retain7.s
+#ld: -e _start --gc-sections
+#skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-*
+#notarget: ![supports_gnu_osabi] ![check_gc_sections_available]
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ . .*discard.*
+#...
--
2.28.0
More information about the Binutils
mailing list