[PATCH] Support SHF_GNU_RETAIN ELF section flag
Jozef Lawrynowicz
jozef.l@mittosystems.com
Wed Sep 23 12:13:48 GMT 2020
More information about the Binutils mailing list
Wed Sep 23 12:13:48 GMT 2020
- Previous message (by thread): [PATCH] Support SHF_GNU_RETAIN ELF section flag
- Next message (by thread): [PATCH] Support SHF_GNU_RETAIN ELF section flag
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Attached a revised patch: - Removed mmix-*-* XFAILs - Fixed SHF_GNU_RETAIN being clobbered when using the .section directive without the "R" flag, after the section has previously been marked with SHF_GNU_RETAIN. Added tests for this behavior. Thanks, Jozef On Tue, Sep 22, 2020 at 09:29:33PM +0100, Jozef Lawrynowicz wrote: > The attached patch adds support for the new SHF_GNU_RETAIN ELF section > flag, which was discussed on the GNU gABI mailing list here: > https://sourceware.org/pipermail/gnu-gabi/2020q3/000429.html > > The flag is GNU-specific so uses a bit in the SHF_MASKOS mask. > Its precise definition is as follows: > > ======================================================================= > Section Attribute Flags > +-------------------------------------+ > | Name | Value | > +-------------------------------------+ > | SHF_GNU_RETAIN | 0x200000 (1 << 21) | > +-------------------------------------+ > > SHF_GNU_RETAIN > The link editor should not garbage collect the section if it is > unused. > > ======================================================================= > > The overall intention for this new flag is to enable a new "retain" > attribute to be applied to declarations of functions and data in the > source code. This attribute can be used to ensure the definition > associated with the declaration is present in the linked output file, > even if linker garbage collection would normally remove the containing > section because it is unused. > > The new ".retain" assembler directive can be used to apply > SHF_GNU_RETAIN to a section. GCC will emit this directive when > assembling definitions of functions and data that have had the "retain" > attribute applied. > > Note that there is *not* a direct mapping of SHF_GNU_RETAIN to the BFD > section flag SEC_KEEP. SEC_KEEP would prevent the user being able to > explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/, > which could be necessary in some situations. > > I successfully regtested the patch for the Binutils, GAS and LD > testsuites for the following CPUs, applying the "-elf" suffix when > configuring: > aarch64 alpha arc arm avr bfin bpf cr16 cris crx csky d10v d30v dlx > epiphany fr30 frv ft32 h8300 hppa i386 ia64 ia64-vms ip2k iq2000 lm32 > m32c m32r m68hc11 m68hc12 m68k mcore mep metag microblaze mips mmix > moxie msp430 mt nds32 nfp nios2 or1k pj ppc pru riscv rl78 rx s12z > s390 score sh sparc spu tic6x tilegx tilepro v850 vax visium wasm32 > x86-64 x86 xc16x xgate xstormy16 xtensa z80 > > The new tests are passing for all targets except mmix-elf. This target > has a lot of LD failures, particularly --gc-sections doesn't appear to > have any effect. I don't know anything about the target, but I wonder if > it should be added to the hard-coded list of targets that doesn't > support --gc-sections. I have therefore XFAIL'd the new LD tests for > this target. > > I also regtested for i386-pe, to ensure there was no spill-over of the > new functionality into any non-ELF areas. > > Ok to apply? > > Thanks, > Jozef -------------- next part -------------- >From 862a04415e1b490b4561fe5a44c9fa4120c50825 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz <jozef.l@mittosystems.com> Date: Tue, 22 Sep 2020 21:00:35 +0100 Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag The GNU-specific SHF_GNU_RETAIN ELF section flag is defined as follows: ======================================================================= Section Attribute Flags +-------------------------------------+ | Name | Value | +-------------------------------------+ | SHF_GNU_RETAIN | 0x200000 (1 << 21) | +-------------------------------------+ SHF_GNU_RETAIN The link editor should not garbage collect the section if it is unused. ======================================================================= The new ".retain" assembler directive can be used to apply SHF_GNU_RETAIN to a section. Note that there is not a direct mapping of SHF_GNU_RETAIN to the BFD section flag SEC_KEEP. SEC_KEEP would prevent the user being able to explicitly remove an SHF_GNU_RETAIN section by placing it in /DISCARD/. bfd/ChangeLog: 2020-09-22 Jozef Lawrynowicz <jozef.l@mittosystems.com> * elflink.c (bfd_elf_gc_sections): gc_mark the section if SHF_GNU_RETAIN is set. binutils/ChangeLog: 2020-09-22 Jozef Lawrynowicz <jozef.l@mittosystems.com> * NEWS: Announce SHF_GNU_RETAIN. * readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN. * testsuite/binutils-all/readelf.exp: Run new test. Don't run run_dump_test when there isn't an assembler available. * testsuite/binutils-all/retain1.d: New test. * testsuite/binutils-all/retain1.s: New test. gas/ChangeLog: 2020-09-22 Jozef Lawrynowicz <jozef.l@mittosystems.com> * NEWS: Announce .retain directive and SHF_GNU_RETAIN. * config/obj-elf.c (elf_pseudo_table): Add "retain". (obj_elf_retain): New. (obj_elf_parse_section_letters): Handle 'R' flag. * doc/as.texi: Document .retain directive. (Section): Document 'R' flag. * testsuite/gas/elf/elf.exp: Run new tests. * testsuite/gas/elf/retain1.d: New test. * testsuite/gas/elf/retain1.s: New test. * testsuite/gas/elf/retain2.d: New test. * testsuite/gas/elf/retain2.l: New test. * testsuite/gas/elf/retain2.s: New test. * testsuite/gas/elf/retain3.d: New test. * testsuite/gas/elf/retain3.s: New test. * testsuite/gas/elf/section10.d: Adjust test. include/ChangeLog: 2020-09-22 Jozef Lawrynowicz <jozef.l@mittosystems.com> * elf/common.h (SHF_GNU_RETAIN): Define. ld/ChangeLog: 2020-09-22 Jozef Lawrynowicz <jozef.l@mittosystems.com> * NEWS: Announce SHF_GNU_RETAIN. * ld.texi (garbage collection): Document SHF_GNU_RETAIN. (Output Section Discarding): Likewise. * testsuite/ld-elf/elf.exp: Run new tests. * testsuite/ld-elf/retain1.msg: New test. * testsuite/ld-elf/retain1.s: New test. * testsuite/ld-elf/retain2.d: New test. * testsuite/ld-elf/retain2.ld: New test. * testsuite/ld-elf/retain2.map: New test. * testsuite/ld-elf/retain3.msg: New test. * testsuite/ld-elf/retain3.s: New test. * testsuite/ld-elf/retain4.s: New test. * testsuite/ld-elf/retain5.s: New test. * testsuite/ld-elf/retain6lib.s: New test. * testsuite/ld-elf/retain6main.s: New test. * testsuite/ld-elf/retain7.msg: New test. * testsuite/ld-elf/retain7lib.s: New test. * testsuite/ld-elf/retain7main.s: New test. --- bfd/elflink.c | 3 +- binutils/NEWS | 4 + binutils/readelf.c | 4 + binutils/testsuite/binutils-all/readelf.exp | 6 +- binutils/testsuite/binutils-all/retain1.d | 17 +++ binutils/testsuite/binutils-all/retain1.s | 114 ++++++++++++++++++++ gas/NEWS | 4 + gas/config/obj-elf.c | 71 +++++++++++- gas/doc/as.texi | 20 ++++ gas/testsuite/gas/elf/elf.exp | 7 ++ gas/testsuite/gas/elf/retain1.d | 24 +++++ gas/testsuite/gas/elf/retain1.s | 114 ++++++++++++++++++++ gas/testsuite/gas/elf/retain2.d | 3 + gas/testsuite/gas/elf/retain2.l | 3 + gas/testsuite/gas/elf/retain2.s | 7 ++ gas/testsuite/gas/elf/retain3.d | 24 +++++ gas/testsuite/gas/elf/retain3.s | 104 ++++++++++++++++++ gas/testsuite/gas/elf/retain4.d | 6 ++ gas/testsuite/gas/elf/retain4.s | 20 ++++ gas/testsuite/gas/elf/retain5.d | 6 ++ gas/testsuite/gas/elf/retain5.s | 18 ++++ gas/testsuite/gas/elf/section10.d | 4 +- include/elf/common.h | 1 + ld/NEWS | 4 + ld/ld.texi | 8 ++ ld/testsuite/ld-elf/elf.exp | 33 ++++++ ld/testsuite/ld-elf/retain1.msg | 9 ++ ld/testsuite/ld-elf/retain1.s | 114 ++++++++++++++++++++ ld/testsuite/ld-elf/retain2.d | 6 ++ ld/testsuite/ld-elf/retain2.ld | 7 ++ ld/testsuite/ld-elf/retain2.map | 32 ++++++ ld/testsuite/ld-elf/retain3.msg | 9 ++ ld/testsuite/ld-elf/retain3.s | 104 ++++++++++++++++++ ld/testsuite/ld-elf/retain4.s | 19 ++++ ld/testsuite/ld-elf/retain5.s | 13 +++ ld/testsuite/ld-elf/retain6lib.s | 6 ++ ld/testsuite/ld-elf/retain6main.s | 5 + ld/testsuite/ld-elf/retain7.msg | 1 + ld/testsuite/ld-elf/retain7lib.s | 17 +++ ld/testsuite/ld-elf/retain7main.s | 13 +++ 40 files changed, 977 insertions(+), 7 deletions(-) create mode 100644 binutils/testsuite/binutils-all/retain1.d create mode 100644 binutils/testsuite/binutils-all/retain1.s create mode 100644 gas/testsuite/gas/elf/retain1.d create mode 100644 gas/testsuite/gas/elf/retain1.s create mode 100644 gas/testsuite/gas/elf/retain2.d create mode 100644 gas/testsuite/gas/elf/retain2.l create mode 100644 gas/testsuite/gas/elf/retain2.s create mode 100644 gas/testsuite/gas/elf/retain3.d create mode 100644 gas/testsuite/gas/elf/retain3.s create mode 100644 gas/testsuite/gas/elf/retain4.d create mode 100644 gas/testsuite/gas/elf/retain4.s create mode 100644 gas/testsuite/gas/elf/retain5.d create mode 100644 gas/testsuite/gas/elf/retain5.s create mode 100644 ld/testsuite/ld-elf/retain1.msg create mode 100644 ld/testsuite/ld-elf/retain1.s create mode 100644 ld/testsuite/ld-elf/retain2.d create mode 100644 ld/testsuite/ld-elf/retain2.ld create mode 100644 ld/testsuite/ld-elf/retain2.map create mode 100644 ld/testsuite/ld-elf/retain3.msg create mode 100644 ld/testsuite/ld-elf/retain3.s create mode 100644 ld/testsuite/ld-elf/retain4.s create mode 100644 ld/testsuite/ld-elf/retain5.s create mode 100644 ld/testsuite/ld-elf/retain6lib.s create mode 100644 ld/testsuite/ld-elf/retain6main.s create mode 100644 ld/testsuite/ld-elf/retain7.msg create mode 100644 ld/testsuite/ld-elf/retain7lib.s create mode 100644 ld/testsuite/ld-elf/retain7main.s diff --git a/bfd/elflink.c b/bfd/elflink.c index 0e339f3c1e..6d1a1c5105 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -13977,7 +13977,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) || (elf_section_data (o)->this_hdr.sh_type == SHT_FINI_ARRAY))) || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE - && elf_next_in_group (o) == NULL ))) + && elf_next_in_group (o) == NULL) + || (elf_section_flags (o) & SHF_GNU_RETAIN))) { if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) return FALSE; diff --git a/binutils/NEWS b/binutils/NEWS index c0dc73d7d8..6c7d3f3953 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -4,6 +4,10 @@ symbol names. In addition the --demangle=<style>, --no-demangle, --recurse-limit and --no-recurse-limit options are also now availale. +* Add support for the SHF_GNU_RETAIN ELF section flag. + This flag specifies that the section should not be garbage collected by the + linker if it is unused. + Changes in 2.35: * Changed readelf's display of symbol names when wide mode is not enabled. diff --git a/binutils/readelf.c b/binutils/readelf.c index cb4208f7b9..00502f7058 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -5977,6 +5977,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") }, /* VLE specific. */ /* 25 */ { STRING_COMMA_LEN ("VLE") }, + /* GNU specific. */ + /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") }, }; if (do_section_details) @@ -6010,6 +6012,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) case SHF_EXCLUDE: sindex = 18; break; case SHF_COMPRESSED: sindex = 20; break; case SHF_GNU_MBIND: sindex = 24; break; + case SHF_GNU_RETAIN: sindex = 26; break; default: sindex = -1; @@ -6108,6 +6111,7 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) case SHF_EXCLUDE: *p = 'E'; break; case SHF_COMPRESSED: *p = 'C'; break; case SHF_GNU_MBIND: *p = 'D'; break; + case SHF_GNU_RETAIN: *p = 'R'; break; default: if ((filedata->file_header.e_machine == EM_X86_64 diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp index 1fb36ae5c4..6dea09e305 100644 --- a/binutils/testsuite/binutils-all/readelf.exp +++ b/binutils/testsuite/binutils-all/readelf.exp @@ -364,8 +364,12 @@ readelf_wi_test readelf_compressed_wa_test readelf_dump_test -run_dump_test "pr25543" +# These dump tests require an assembler. +if {[which $AS] != 0} then { + run_dump_test "pr25543" + run_dump_test "retain1" +} # PR 13482 - Check for off-by-one errors when dumping .note sections. if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then { diff --git a/binutils/testsuite/binutils-all/retain1.d b/binutils/testsuite/binutils-all/retain1.d new file mode 100644 index 0000000000..35d7373cc1 --- /dev/null +++ b/binutils/testsuite/binutils-all/retain1.d @@ -0,0 +1,17 @@ +#source: retain1.s +#readelf: -S --wide +#name: readelf SHF_GNU_RETAIN + +#... + \[[ 0-9]+\] .bss.retain0.*WAR.* + \[[ 0-9]+\] .bss.retain1.*WAR.* + \[[ 0-9]+\] .data.retain2.*WAR.* + \[[ 0-9]+\] .bss.sretain0.*WAR.* + \[[ 0-9]+\] .bss.sretain1.*WAR.* + \[[ 0-9]+\] .data.sretain2.*WAR.* + \[[ 0-9]+\] .text.fnretain1.*AXR.* +#... + \[[ 0-9]+\] .bss.lsretain0.*WAR.* + \[[ 0-9]+\] .bss.lsretain1.*WAR.* + \[[ 0-9]+\] .data.lsretain2.*WAR.* +#pass diff --git a/binutils/testsuite/binutils-all/retain1.s b/binutils/testsuite/binutils-all/retain1.s new file mode 100644 index 0000000000..e799ff72ec --- /dev/null +++ b/binutils/testsuite/binutils-all/retain1.s @@ -0,0 +1,114 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, STT_OBJECT +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, STT_OBJECT +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, STT_OBJECT +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, STT_OBJECT +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, STT_OBJECT +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, STT_OBJECT +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, STT_FUNC +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"aw" + .type retain0, STT_OBJECT + .retain .bss.retain0 +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"aw" + .type retain1, STT_OBJECT + .retain .bss.retain1 +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"aw" + .type retain2, STT_OBJECT + .retain .data.retain2 +retain2: + .word 1 + + .section .bss.sretain0,"aw" + .type sretain0, STT_OBJECT + .retain .bss.sretain0 +sretain0: + .zero 2 + + .section .bss.sretain1,"aw" + .type sretain1, STT_OBJECT + .retain .bss.sretain1 +sretain1: + .zero 2 + + .section .data.sretain2,"aw" + .type sretain2, STT_OBJECT + .retain .data.sretain2 +sretain2: + .word 1 + + .section .text.fnretain1,"ax" + .global fnretain1 + .type fnretain1, STT_FUNC + .retain .text.fnretain1 +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, STT_FUNC +fndiscard2: + .word 0 + + .section .bss.lsretain0,"aw" + .type lsretain0.2, STT_OBJECT + .retain .bss.lsretain0 +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aw" + .type lsretain1.1, STT_OBJECT + .retain .bss.lsretain1 +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aw" + .type lsretain2.0, STT_OBJECT + .retain .data.lsretain2 +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/gas/NEWS b/gas/NEWS index 66afd0357b..0d63fad7b3 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -9,6 +9,10 @@ * Configure with --enable-x86-used-note by default for Linux/x86. +* Add support for the .retain directive, which applies the ELF SHF_GNU_RETAIN + flag to the specified section. This flag specifies the section should not be + garbage collected by the linker if it is unused. + Changes in 2.35: * X86 NaCl target support is removed. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 9e39707801..5e384f2c58 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -78,6 +78,7 @@ static void obj_elf_gnu_attribute (int); static void obj_elf_tls_common (int); static void obj_elf_lcomm (int); static void obj_elf_struct (int); +static void obj_elf_retain (int); static const pseudo_typeS elf_pseudo_table[] = { @@ -119,6 +120,9 @@ static const pseudo_typeS elf_pseudo_table[] = /* A GNU extension for object attributes. */ {"gnu_attribute", obj_elf_gnu_attribute, 0}, + /* A GNU extension for preventing linker garbage collection of sections. */ + {"retain", obj_elf_retain, 0}, + /* These are used for dwarf. */ {"2byte", cons, 2}, {"4byte", cons, 4}, @@ -802,9 +806,15 @@ obj_elf_change_section (const char *name, as_bad (_("changed section attributes for %s"), name); } else - /* FIXME: Maybe we should consider removing a previously set - processor or application specific attribute as suspicious ? */ - elf_section_flags (sec) = attr; + { + /* Don't clobber SHF_GNU_RETAIN if it has been previously set on + the section. */ + attr |= (elf_section_flags (sec) & SHF_GNU_RETAIN); + + /* FIXME: Maybe we should consider removing a previously set + processor or application specific attribute as suspicious ? */ + elf_section_flags (sec) = attr; + } if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize) as_bad (_("changed section entity size for %s"), name); @@ -857,6 +867,9 @@ obj_elf_parse_section_letters (char *str, size_t len, case 'd': *gnu_attr |= SHF_GNU_MBIND; break; + case 'R': + *gnu_attr |= SHF_GNU_RETAIN; + break; case '?': *is_clone = TRUE; break; @@ -1986,6 +1999,58 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED) obj_elf_vendor_attribute (OBJ_ATTR_GNU); } +/* Parse a ".retain [name]" directive. + The SHF_GNU_RETAIN flag should be applied to the section named "name". + If "name" is omitted, apply the flag to the current section being + assembled. */ +static void +obj_elf_retain (int ignored ATTRIBUTE_UNUSED) +{ + const char *name; + symbolS *secsym; + asection *bfdsec; + + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + { + /* Handle the case when "name" isn't specified. */ + name = now_seg->name; + if (name == NULL) + { + as_bad (_("\".retain\" directive not within a section")); + ignore_rest_of_line (); + return; + } + } + else + { + /* The "name" argument has been given, validate it. */ + name = obj_elf_section_name (); + secsym = symbol_find (name); + if (secsym == NULL) + { + as_bad (_("section '%s' has not been declared"), name); + ignore_rest_of_line (); + return; + } + else if (secsym != NULL + && !symbol_section_p (secsym)) + { + as_bad (_("'%s' is not a section name, expected " + "\".retain [name]\""), name); + ignore_rest_of_line (); + return; + } + } + demand_empty_rest_of_line (); + + bfdsec = bfd_get_section_by_name (stdoutput, name); + if (bfdsec != NULL) + elf_section_flags (bfdsec) |= SHF_GNU_RETAIN; + else + as_bad (_("Couldn't find BFD section for %s\n"), name); +} + void elf_obj_read_begin_hook (void) { diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 112eaf810c..68afaa6aae 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -4468,6 +4468,7 @@ Some machine configurations provide additional directives. * Quad:: @code{.quad @var{bignums}} * Reloc:: @code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]} * Rept:: @code{.rept @var{count}} +* Retain:: @code{.retain [@var{name}]} * Sbttl:: @code{.sbttl "@var{subheading}"} @ifset COFF * Scl:: @code{.scl @var{class}} @@ -6468,6 +6469,22 @@ is equivalent to assembling A count of zero is allowed, but nothing is generated. Negative counts are not allowed and if encountered will be treated as if they were zero. +@ifset ELF +@node Retain +@section @code{.retain [@var{name}]} + +@cindex @code{retain} directive +@cindex SHF_GNU_RETAIN + +Apply the @code{SHF_GNU_RETAIN} flag to the section named @var{name}. +If @var{name} is omitted, apply the flag to the current section being +assembled. + +The @code{SHF_GNU_RETAIN} flag specifies that the section should not be +garbage collected by the linker if it is unused. + +@end ifset + @node Sbttl @section @code{.sbttl "@var{subheading}"} @@ -6546,6 +6563,9 @@ ignored. (For compatibility with the ELF version) section is not readable (meaningful for PE targets) @item 0-9 single-digit power-of-two section alignment (GNU extension) +@item R +retained section (apply SHF_GNU_RETAIN to prevent linker garbage +collection, GNU ELF extension) @end table If no flags are specified, the default flags depend upon the section name. If diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 8520421ba3..c0dfdf504f 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -307,6 +307,13 @@ if { [is_elf_format] } then { run_dump_test "strtab" + # Tests for the .retain directive/SHF_GNU_RETAIN. + run_dump_test "retain1" + run_dump_test "retain2" + run_dump_test "retain3" + run_dump_test "retain4" + run_dump_test "retain5" + run_dump_test "bignums" run_dump_test "section-symbol-redef" diff --git a/gas/testsuite/gas/elf/retain1.d b/gas/testsuite/gas/elf/retain1.d new file mode 100644 index 0000000000..439a60ca21 --- /dev/null +++ b/gas/testsuite/gas/elf/retain1.d @@ -0,0 +1,24 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 1 + +#... + \[..\] .bss.discard0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.discard1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.discard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sdiscard0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sdiscard1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.sdiscard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .text.fndiscard0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* + \[..\] .bss.retain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.retain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.retain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sretain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sretain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.sretain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .text.fnretain1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* + \[..\] .text.fndiscard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* +#... + \[..\] .bss.lsretain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.lsretain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.lsretain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#pass diff --git a/gas/testsuite/gas/elf/retain1.s b/gas/testsuite/gas/elf/retain1.s new file mode 100644 index 0000000000..e799ff72ec --- /dev/null +++ b/gas/testsuite/gas/elf/retain1.s @@ -0,0 +1,114 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, STT_OBJECT +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, STT_OBJECT +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, STT_OBJECT +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, STT_OBJECT +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, STT_OBJECT +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, STT_OBJECT +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, STT_FUNC +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"aw" + .type retain0, STT_OBJECT + .retain .bss.retain0 +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"aw" + .type retain1, STT_OBJECT + .retain .bss.retain1 +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"aw" + .type retain2, STT_OBJECT + .retain .data.retain2 +retain2: + .word 1 + + .section .bss.sretain0,"aw" + .type sretain0, STT_OBJECT + .retain .bss.sretain0 +sretain0: + .zero 2 + + .section .bss.sretain1,"aw" + .type sretain1, STT_OBJECT + .retain .bss.sretain1 +sretain1: + .zero 2 + + .section .data.sretain2,"aw" + .type sretain2, STT_OBJECT + .retain .data.sretain2 +sretain2: + .word 1 + + .section .text.fnretain1,"ax" + .global fnretain1 + .type fnretain1, STT_FUNC + .retain .text.fnretain1 +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, STT_FUNC +fndiscard2: + .word 0 + + .section .bss.lsretain0,"aw" + .type lsretain0.2, STT_OBJECT + .retain .bss.lsretain0 +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aw" + .type lsretain1.1, STT_OBJECT + .retain .bss.lsretain1 +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aw" + .type lsretain2.0, STT_OBJECT + .retain .data.lsretain2 +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/gas/testsuite/gas/elf/retain2.d b/gas/testsuite/gas/elf/retain2.d new file mode 100644 index 0000000000..ca58b250b6 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.d @@ -0,0 +1,3 @@ +#name: SHF_GNU_RETAIN 2 +#error_output: retain2.l +#skip: hppa-*-* diff --git a/gas/testsuite/gas/elf/retain2.l b/gas/testsuite/gas/elf/retain2.l new file mode 100644 index 0000000000..5a44012567 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.l @@ -0,0 +1,3 @@ +[^:]*: Assembler messages: +[^:]*:1: Error: section '.data.foo' has not been declared +[^:]*:7: Error: 'myvar' is not a section name, expected ".retain \[name\]" diff --git a/gas/testsuite/gas/elf/retain2.s b/gas/testsuite/gas/elf/retain2.s new file mode 100644 index 0000000000..75eb26d7f7 --- /dev/null +++ b/gas/testsuite/gas/elf/retain2.s @@ -0,0 +1,7 @@ +.retain ".data.foo" +.section .data,"aw" +.global myvar +.type myvar, STT_OBJECT +myvar: + .byte 2 +.retain "myvar" diff --git a/gas/testsuite/gas/elf/retain3.d b/gas/testsuite/gas/elf/retain3.d new file mode 100644 index 0000000000..2d5ca68086 --- /dev/null +++ b/gas/testsuite/gas/elf/retain3.d @@ -0,0 +1,24 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 3 (use flags set on .section directive) + +#... + \[..\] .bss.discard0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.discard1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.discard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sdiscard0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .bss.sdiscard1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .data.sdiscard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WA.* + \[..\] .text.fndiscard0[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* + \[..\] .bss.retain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.retain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.retain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sretain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.sretain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.sretain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .text.fnretain1[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* + \[..\] .text.fndiscard2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX.* +#... + \[..\] .bss.lsretain0[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .bss.lsretain1[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* + \[..\] .data.lsretain2[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR.* +#pass diff --git a/gas/testsuite/gas/elf/retain3.s b/gas/testsuite/gas/elf/retain3.s new file mode 100644 index 0000000000..065399ec6f --- /dev/null +++ b/gas/testsuite/gas/elf/retain3.s @@ -0,0 +1,104 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, STT_OBJECT +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, STT_OBJECT +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, STT_OBJECT +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, STT_OBJECT +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, STT_OBJECT +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, STT_OBJECT +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, STT_FUNC +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"awR" + .type retain0, STT_OBJECT +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"awR" + .type retain1, STT_OBJECT +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"awR" + .type retain2, STT_OBJECT +retain2: + .word 1 + + .section .bss.sretain0,"awR" + .type sretain0, STT_OBJECT +sretain0: + .zero 2 + + .section .bss.sretain1,"awR" + .type sretain1, STT_OBJECT +sretain1: + .zero 2 + + .section .data.sretain2,"aRw" + .type sretain2, STT_OBJECT +sretain2: + .word 1 + + .section .text.fnretain1,"Rax" + .global fnretain1 + .type fnretain1, STT_FUNC +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, STT_FUNC +fndiscard2: + .word 0 + + .section .bss.lsretain0,"awR" + .type lsretain0.2, STT_OBJECT +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aRw" + .type lsretain1.1, STT_OBJECT +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aRw" + .type lsretain2.0, STT_OBJECT +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/gas/testsuite/gas/elf/retain4.d b/gas/testsuite/gas/elf/retain4.d new file mode 100644 index 0000000000..eacad20635 --- /dev/null +++ b/gas/testsuite/gas/elf/retain4.d @@ -0,0 +1,6 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 4 (switch to SHF_GNU_RETAIN section without "R" flag) + +#... + \[..\] .text.foo[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* +#pass diff --git a/gas/testsuite/gas/elf/retain4.s b/gas/testsuite/gas/elf/retain4.s new file mode 100644 index 0000000000..48aeae2a11 --- /dev/null +++ b/gas/testsuite/gas/elf/retain4.s @@ -0,0 +1,20 @@ +/* SHF_GNU_RETAIN should not be clobbered when switching to a section without + explicitly specifying the flag. */ + .section .text.foo,"axR" + .global foo + .type foo, STT_FUNC +foo: + .word 0 + + .section .text.foo,"ax" + .global bar + .type bar, STT_FUNC +bar: + .word 0 + + .section .text.main,"ax" + .global main + .type main, STT_FUNC +main: + .word 0 + diff --git a/gas/testsuite/gas/elf/retain5.d b/gas/testsuite/gas/elf/retain5.d new file mode 100644 index 0000000000..9edbfad710 --- /dev/null +++ b/gas/testsuite/gas/elf/retain5.d @@ -0,0 +1,6 @@ +#readelf: -S --wide +#name: SHF_GNU_RETAIN 5 (apply "R" flag to existing section) + +#... + \[..\] .text.foo[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR.* +#pass diff --git a/gas/testsuite/gas/elf/retain5.s b/gas/testsuite/gas/elf/retain5.s new file mode 100644 index 0000000000..c2957a7db4 --- /dev/null +++ b/gas/testsuite/gas/elf/retain5.s @@ -0,0 +1,18 @@ +/* Applying the "R" flag to an existing section should apply SHF_GNU_RETAIN. */ + .section .text.foo,"ax" + .global foo + .type foo, STT_FUNC +foo: + .word 0 + + .section .text.foo,"axR" + .global bar + .type bar, STT_FUNC +bar: + .word 0 + + .section .text.main,"ax" + .global main + .type main, STT_FUNC +main: + .word 0 diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d index 554a791f1d..ef91d7d086 100644 --- a/gas/testsuite/gas/elf/section10.d +++ b/gas/testsuite/gas/elf/section10.d @@ -18,7 +18,7 @@ #... [ ]*\[.*\][ ]+sec3 [ ]*PROGBITS.* -[ ]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) +[ ]*\[.*fefff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) #... [ ]*\[.*\][ ]+sec4 [ ]*LOOS\+0x11[ ].* @@ -26,7 +26,7 @@ #... [ ]*\[.*\][ ]+sec5 [ ]*LOUSER\+0x9[ ].* -[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ef00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) +[ ]*\[.*feff0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) [ ]*\[.*\][ ]+.data.foo [ ]*LOUSER\+0x7f000000[ ].* [ ]*\[0+003\]: WRITE, ALLOC diff --git a/include/elf/common.h b/include/elf/common.h index 805058146a..364c58a7de 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -554,6 +554,7 @@ /* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */ #define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ #define SHF_GNU_BUILD_NOTE (1 << 20) /* Section contains GNU BUILD ATTRIBUTE notes. */ +#define SHF_GNU_RETAIN (1 << 21) /* Section should not be garbage collected by the linker. */ #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ /* This used to be implemented as a processor specific section flag. diff --git a/ld/NEWS b/ld/NEWS index 695348141b..1c3cc9d20a 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -13,6 +13,10 @@ unless you are working on a project that has its own analogue of symbol tables that are not reflected in the ELF symtabs. +* Add support for the SHF_GNU_RETAIN ELF section flag. + This flag specifies that the section should not be garbage collected by the + linker if it is unused. + Changes in 2.35: * X86 NaCl target support is removed. diff --git a/ld/ld.texi b/ld/ld.texi index 7d961c3bb8..5daffbeb5f 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1781,6 +1781,10 @@ specified either by one of the options @samp{--entry}, @samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY} command in the linker script. +As a GNU extension, ELF input sections marked with the +@code{SHF_GNU_RETAIN} flag will not be garbage collected if they are +unused. + @kindex --print-gc-sections @kindex --no-print-gc-sections @cindex garbage collection @@ -5226,6 +5230,10 @@ The special output section name @samp{/DISCARD/} may be used to discard input sections. Any input sections which are assigned to an output section named @samp{/DISCARD/} are not included in the output file. +This can be used to discard input sections marked with the ELF flag +@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker +garbage collection when they are unused. + Note, sections that match the @samp{/DISCARD/} output section will be discarded even if they are in an ELF section group which has other members which are not being discarded. This is deliberate. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index c0d67d80d2..9046bc870a 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -225,6 +225,39 @@ if [check_gc_sections_available] { {pr25490-6.s} \ [list [list "readelf" {-SW} $pr25490_6_exp]] \ "pr25490-6.exe"] \ + [list "SHF_GNU_RETAIN 1" \ + "--gc-sections -e _start --print-gc-sections" "" "" \ + {retain1.s} \ + {{ ld retain1.msg }} \ + "retain1.exe"] \ + [list "SHF_GNU_RETAIN 3 (use flags set on .section directive)" \ + "--gc-sections -e _start --print-gc-sections" "" "" \ + {retain3.s} \ + {{ ld retain3.msg }} \ + "retain3.exe"] \ + [list "SHF_GNU_RETAIN 4 (keep sections referenced by retained sections)" \ + "--gc-sections -e _start --print-gc-sections" "" "" \ + {retain4.s} {} \ + "retain4.exe"] \ + [list "SHF_GNU_RETAIN 5 (keep orphaned sections when not discarding)" \ + "--gc-sections -e _start --print-gc-sections --orphan-handling=place" "" "" \ + {retain5.s} {} \ + "retain5.exe"] \ + [list "Build libretain6.a" \ + "" "" "" \ + {retain6lib.s} {} "libretain6.a"] \ + [list "SHF_GNU_RETAIN 6 (don't pull SHF_GNU_RETAIN section out of lib)" \ + "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain6" "" \ + {retain6main.s} {} \ + "retain6.exe"] \ + [list "Build libretain7.a" \ + "" "" "" \ + {retain7lib.s} {} "libretain7.a"] \ + [list "SHF_GNU_RETAIN 7 (pull section out of lib required by SHF_GNU_RETAIN section)" \ + "--gc-sections -e _start --print-gc-sections" "-Ltmpdir -lretain7" "" \ + {retain7main.s} \ + {{ ld retain7.msg }} \ + "retain7.exe"] \ ] } diff --git a/ld/testsuite/ld-elf/retain1.msg b/ld/testsuite/ld-elf/retain1.msg new file mode 100644 index 0000000000..9a265c980f --- /dev/null +++ b/ld/testsuite/ld-elf/retain1.msg @@ -0,0 +1,9 @@ +.*: removing unused section '.bss.discard0' in file.* +.*: removing unused section '.bss.discard1' in file.* +.*: removing unused section '.data.discard2' in file.* +.*: removing unused section '.bss.sdiscard0' in file.* +.*: removing unused section '.bss.sdiscard1' in file.* +.*: removing unused section '.data.sdiscard2' in file.* +.*: removing unused section '.text.fndiscard0' in file.* +.*: removing unused section '.text.fndiscard2' in file.* +#pass diff --git a/ld/testsuite/ld-elf/retain1.s b/ld/testsuite/ld-elf/retain1.s new file mode 100644 index 0000000000..e799ff72ec --- /dev/null +++ b/ld/testsuite/ld-elf/retain1.s @@ -0,0 +1,114 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, STT_OBJECT +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, STT_OBJECT +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, STT_OBJECT +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, STT_OBJECT +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, STT_OBJECT +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, STT_OBJECT +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, STT_FUNC +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"aw" + .type retain0, STT_OBJECT + .retain .bss.retain0 +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"aw" + .type retain1, STT_OBJECT + .retain .bss.retain1 +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"aw" + .type retain2, STT_OBJECT + .retain .data.retain2 +retain2: + .word 1 + + .section .bss.sretain0,"aw" + .type sretain0, STT_OBJECT + .retain .bss.sretain0 +sretain0: + .zero 2 + + .section .bss.sretain1,"aw" + .type sretain1, STT_OBJECT + .retain .bss.sretain1 +sretain1: + .zero 2 + + .section .data.sretain2,"aw" + .type sretain2, STT_OBJECT + .retain .data.sretain2 +sretain2: + .word 1 + + .section .text.fnretain1,"ax" + .global fnretain1 + .type fnretain1, STT_FUNC + .retain .text.fnretain1 +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, STT_FUNC +fndiscard2: + .word 0 + + .section .bss.lsretain0,"aw" + .type lsretain0.2, STT_OBJECT + .retain .bss.lsretain0 +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aw" + .type lsretain1.1, STT_OBJECT + .retain .bss.lsretain1 +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aw" + .type lsretain2.0, STT_OBJECT + .retain .data.lsretain2 +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain2.d b/ld/testsuite/ld-elf/retain2.d new file mode 100644 index 0000000000..9834d58297 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.d @@ -0,0 +1,6 @@ +# Test that sections marked with SHF_GNU_RETAIN can be removed by placing them +# in /DISCARD/. +# source: retain1.s +# ld: -e _start -Map=retain2.map --gc-sections --script=retain2.ld +# map: retain2.map +# skip: mep-*-* dlx-*-* d30v-*-* pj-*-* pru-*-* xgate-*-* s12z-*-* diff --git a/ld/testsuite/ld-elf/retain2.ld b/ld/testsuite/ld-elf/retain2.ld new file mode 100644 index 0000000000..8ef982753c --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.ld @@ -0,0 +1,7 @@ +SECTIONS +{ + /DISCARD/ : + { + *(.text.fnretain1) + } +} diff --git a/ld/testsuite/ld-elf/retain2.map b/ld/testsuite/ld-elf/retain2.map new file mode 100644 index 0000000000..4028aa1f58 --- /dev/null +++ b/ld/testsuite/ld-elf/retain2.map @@ -0,0 +1,32 @@ +# Test that .text.fnretain1, which has the SHF_GNU_RETAIN flag, can still be +# explicitly discarded from the output file. + +#... +Discarded input sections + + .text.* +#... + .data.* +#... + .bss.* +#... + .bss.discard0.* +#... + .bss.discard1.* +#... + .data.discard2.* +#... + .bss.sdiscard0.* +#... + .bss.sdiscard1.* +#... + .data.sdiscard2.* +#... + .text.fndiscard0.* +#... + .text.fnretain1.* +#... + .text.fndiscard2.* +#... +Memory Configuration +#pass diff --git a/ld/testsuite/ld-elf/retain3.msg b/ld/testsuite/ld-elf/retain3.msg new file mode 100644 index 0000000000..9a265c980f --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.msg @@ -0,0 +1,9 @@ +.*: removing unused section '.bss.discard0' in file.* +.*: removing unused section '.bss.discard1' in file.* +.*: removing unused section '.data.discard2' in file.* +.*: removing unused section '.bss.sdiscard0' in file.* +.*: removing unused section '.bss.sdiscard1' in file.* +.*: removing unused section '.data.sdiscard2' in file.* +.*: removing unused section '.text.fndiscard0' in file.* +.*: removing unused section '.text.fndiscard2' in file.* +#pass diff --git a/ld/testsuite/ld-elf/retain3.s b/ld/testsuite/ld-elf/retain3.s new file mode 100644 index 0000000000..065399ec6f --- /dev/null +++ b/ld/testsuite/ld-elf/retain3.s @@ -0,0 +1,104 @@ + .global discard0 + .section .bss.discard0,"aw" + .type discard0, STT_OBJECT +discard0: + .zero 2 + + .global discard1 + .section .bss.discard1,"aw" + .type discard1, STT_OBJECT +discard1: + .zero 2 + + .global discard2 + .section .data.discard2,"aw" + .type discard2, STT_OBJECT +discard2: + .word 1 + + .section .bss.sdiscard0,"aw" + .type sdiscard0, STT_OBJECT +sdiscard0: + .zero 2 + + .section .bss.sdiscard1,"aw" + .type sdiscard1, STT_OBJECT +sdiscard1: + .zero 2 + + .section .data.sdiscard2,"aw" + .type sdiscard2, STT_OBJECT +sdiscard2: + .word 1 + + .section .text.fndiscard0,"ax" + .global fndiscard0 + .type fndiscard0, STT_FUNC +fndiscard0: + .word 0 + + .global retain0 + .section .bss.retain0,"awR" + .type retain0, STT_OBJECT +retain0: + .zero 2 + + .global retain1 + .section .bss.retain1,"awR" + .type retain1, STT_OBJECT +retain1: + .zero 2 + + .global retain2 + .section .data.retain2,"awR" + .type retain2, STT_OBJECT +retain2: + .word 1 + + .section .bss.sretain0,"awR" + .type sretain0, STT_OBJECT +sretain0: + .zero 2 + + .section .bss.sretain1,"awR" + .type sretain1, STT_OBJECT +sretain1: + .zero 2 + + .section .data.sretain2,"aRw" + .type sretain2, STT_OBJECT +sretain2: + .word 1 + + .section .text.fnretain1,"Rax" + .global fnretain1 + .type fnretain1, STT_FUNC +fnretain1: + .word 0 + + .section .text.fndiscard2,"ax" + .global fndiscard2 + .type fndiscard2, STT_FUNC +fndiscard2: + .word 0 + + .section .bss.lsretain0,"awR" + .type lsretain0.2, STT_OBJECT +lsretain0.2: + .zero 2 + + .section .bss.lsretain1,"aRw" + .type lsretain1.1, STT_OBJECT +lsretain1.1: + .zero 2 + + .section .data.lsretain2,"aRw" + .type lsretain2.0, STT_OBJECT +lsretain2.0: + .word 1 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain4.s b/ld/testsuite/ld-elf/retain4.s new file mode 100644 index 0000000000..080a5dfc2e --- /dev/null +++ b/ld/testsuite/ld-elf/retain4.s @@ -0,0 +1,19 @@ +/* The retention of bar should also prevent foo from being gc'ed, since bar + references foo. */ + .section .text.foo,"ax" + .global foo + .type foo, STT_FUNC +foo: + .word 0 + + .section .text.bar,"axR" + .global bar + .type bar, STT_FUNC +bar: + .long foo + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain5.s b/ld/testsuite/ld-elf/retain5.s new file mode 100644 index 0000000000..5ffadad694 --- /dev/null +++ b/ld/testsuite/ld-elf/retain5.s @@ -0,0 +1,13 @@ +/* A section which doesn't match any linker script input section rules but + has SHF_GNU_RETAIN applied should not be garbage collected. */ + .section .orphaned_section,"axR" + .global foo + .type foo, STT_FUNC +foo: + .word 0 + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain6lib.s b/ld/testsuite/ld-elf/retain6lib.s new file mode 100644 index 0000000000..4de7adea3d --- /dev/null +++ b/ld/testsuite/ld-elf/retain6lib.s @@ -0,0 +1,6 @@ +/* The link will fail if foo is included because undefined_sym is not defined. */ + .section .text.foo,"axR" + .global foo + .type foo, STT_FUNC +foo: + .long undefined_sym diff --git a/ld/testsuite/ld-elf/retain6main.s b/ld/testsuite/ld-elf/retain6main.s new file mode 100644 index 0000000000..7c722481e8 --- /dev/null +++ b/ld/testsuite/ld-elf/retain6main.s @@ -0,0 +1,5 @@ + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 diff --git a/ld/testsuite/ld-elf/retain7.msg b/ld/testsuite/ld-elf/retain7.msg new file mode 100644 index 0000000000..c21e3b9d75 --- /dev/null +++ b/ld/testsuite/ld-elf/retain7.msg @@ -0,0 +1 @@ +.*: removing unused section '.text.discard_from_lib' in file.* diff --git a/ld/testsuite/ld-elf/retain7lib.s b/ld/testsuite/ld-elf/retain7lib.s new file mode 100644 index 0000000000..2aebf32bd0 --- /dev/null +++ b/ld/testsuite/ld-elf/retain7lib.s @@ -0,0 +1,17 @@ + .section .text.bar,"ax" + .global bar + .type bar, STT_FUNC +bar: + .word 0 + + .section .text.retain_from_lib,"axR" + .global retain_from_lib + .type retain_from_lib, STT_FUNC +retain_from_lib: + .word 0 + + .section .text.discard_from_lib,"ax" + .global discard_from_lib + .type discard_from_lib, STT_FUNC +discard_from_lib: + .word 0 diff --git a/ld/testsuite/ld-elf/retain7main.s b/ld/testsuite/ld-elf/retain7main.s new file mode 100644 index 0000000000..d8ce70e718 --- /dev/null +++ b/ld/testsuite/ld-elf/retain7main.s @@ -0,0 +1,13 @@ +/* Undefined symbol reference in retained section .text.foo requires symbol + definition to be pulled out of library. */ + .section .text.foo,"axR" + .global foo + .type foo, STT_FUNC +foo: + .long bar + + .section .text._start,"ax" + .global _start + .type _start, STT_FUNC +_start: + .word 0 -- 2.28.0
- Previous message (by thread): [PATCH] Support SHF_GNU_RETAIN ELF section flag
- Next message (by thread): [PATCH] Support SHF_GNU_RETAIN ELF section flag
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list