diff options
55 files changed, 943 insertions, 41 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a06d5a7..a23da61 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + H.J. Lu <hongjiu.lu@intel.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. + (_bfd_elf_final_write_processing): Report if SHF_GNU_RETAIN is + not supported by the OSABI. + Adjust error messages. + * elflink.c (elf_link_input_bfd): Copy enabled has_gnu_osabi bits from + input BFD to output BFD. + (bfd_elf_gc_sections): gc_mark the section if SHF_GNU_RETAIN is set. + 2020-11-16 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com> * cpu-arm.c (processors): Add Cortex-A78C. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 140a9859..ffb75f7 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. */ @@ -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; @@ -12456,8 +12459,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) @@ -12466,11 +12469,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 4b035a2..6cc6361 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10746,6 +10746,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) @@ -14116,7 +14124,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/ChangeLog b/binutils/ChangeLog index 2124c59..e8bcd97 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,19 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + + * NEWS: Announce SHF_GNU_RETAIN support. + * readelf.c (get_elf_section_flags): Handle SHF_GNU_RETAIN. + Recognize SHF_GNU_RETAIN and SHF_GNU_MBIND only for supported OSABIs. + * testsuite/binutils-all/readelf.exp: Run new tests. + 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/readelf-maskos-1a.d: New test. + * testsuite/binutils-all/readelf-maskos-1b.d: New test. + * testsuite/binutils-all/readelf-maskos.s: New test. + * testsuite/binutils-all/retain1.s: New test. + * testsuite/binutils-all/retain1a.d: New test. + * testsuite/binutils-all/retain1b.d: New test. + 2020-11-17 Howard Chu <hyc@symas.com> * ar.c (main): Place the libdeps record in the second archive diff --git a/binutils/NEWS b/binutils/NEWS index 02a19ea..e74b6a2 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -12,6 +12,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 6373852..f6a074b 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 0000000..7b27358 --- /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 0000000..2cbb58a --- /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 0000000..d671119 --- /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 1fb36ae..9d1d496 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 0000000..f7716fa --- /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 0000000..6397ac5 --- /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 0000000..12bc388 --- /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 b9a1e6e..a43639b 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/ChangeLog b/gas/ChangeLog index cdbc1ca..fcfce70 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + H.J. Lu <hongjiu.lu@intel.com> + + * NEWS: Announce SHF_GNU_RETAIN support. + * config/obj-elf.c (obj_elf_change_section): Merge SHF_GNU_RETAIN bit + between section declarations. + (obj_elf_parse_section_letters): Handle 'R' flag. + Handle numeric flag values within the SHF_MASKOS range. + (obj_elf_section): Validate SHF_GNU_RETAIN usage. + * doc/as.texi: Document 'R' flag to .section directive. + * testsuite/gas/elf/elf.exp: Run new tests. + * testsuite/gas/elf/section10.d: Unset SHF_GNU_RETAIN bit. + * testsuite/gas/elf/section10.s: Likewise. + * testsuite/gas/elf/section22.d: New test. + * testsuite/gas/elf/section22.s: New test. + * testsuite/gas/elf/section23.s: New test. + * testsuite/gas/elf/section23a.d: New test. + * testsuite/gas/elf/section23b.d: New test. + * testsuite/gas/elf/section23b.err: New test. + * testsuite/gas/elf/section24.s: New test. + * testsuite/gas/elf/section24a.d: New test. + * testsuite/gas/elf/section24b.d: New test. + 2020-11-13 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com> * NEWS: Update news. @@ -52,6 +52,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 7aed812..54d42d9 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -806,9 +806,17 @@ 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 overwrite a previously set SHF_GNU_RETAIN flag for the + section. The entire section must be marked retained. */ + if ((elf_tdata (stdoutput)->has_gnu_osabi & elf_gnu_osabi_retain) + && ((elf_section_flags (old_sec) & SHF_GNU_RETAIN))) + attr |= 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); @@ -861,6 +869,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 +901,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 +1422,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 278de41..84a7e61 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -6659,6 +6659,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 edacf27..0ba32c7 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -261,8 +261,12 @@ 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 "section24a" + run_dump_test "section24b" 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 554a791..6aa7b08 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 29f1184..d52b345 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 0000000..8aa7fcf --- /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 0000000..66ed990 --- /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 0000000..d671119 --- /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 0000000..2e413e1 --- /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 0000000..c85200e --- /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 0000000..83de60c --- /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.s b/gas/testsuite/gas/elf/section24.s new file mode 100644 index 0000000..adcff4a --- /dev/null +++ b/gas/testsuite/gas/elf/section24.s @@ -0,0 +1,38 @@ + .section .text,"ax",%progbits + .word 0 + .section .data,"aw" + .word 0 + .section .bss,"aw",%nobits + .word 0 + .section .rodata,"a" + .word 0 + +/* Test that we can set the 'R' flag on an existing section. */ + .section .text,"axR",%progbits + .word 0 + .section .data,"awR" + .word 0 + .section .bss,"awR",%nobits + .word 0 + .section .rodata,"aR" + .word 0 + +/* Test that the 'R' flag does not get clobbered when the section is switched + back to. */ + .section .text,"ax",%progbits + .word 0 + .section .data,"aw" + .word 0 + .section .bss,"aw",%nobits + .word 0 + .section .rodata,"a" + .word 0 + + .section .text + .word 0 + .section .data + .word 0 + .section .bss + .word 0 + .section .rodata + .word 0 diff --git a/gas/testsuite/gas/elf/section24a.d b/gas/testsuite/gas/elf/section24a.d new file mode 100644 index 0000000..8f316d3 --- /dev/null +++ b/gas/testsuite/gas/elf/section24a.d @@ -0,0 +1,17 @@ +#name: Merge SHF_GNU_RETAIN for non-unique sections +#notarget: ![supports_gnu_osabi] +#source: section24.s +#readelf: -h -S --wide + +#... + +OS/ABI: +UNIX - GNU +#... + \[..\] .text[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AXR .* +#... + \[..\] .data[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR .* +#... + \[..\] .bss[ ]+NOBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 WAR .* +#... + \[..\] .rodata[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AR .* +#pass + diff --git a/gas/testsuite/gas/elf/section24b.d b/gas/testsuite/gas/elf/section24b.d new file mode 100644 index 0000000..451ec21 --- /dev/null +++ b/gas/testsuite/gas/elf/section24b.d @@ -0,0 +1,10 @@ +#name: Merge SHF_GNU_RETAIN for non-unique sections (check no unmerged) +#notarget: ![supports_gnu_osabi] +#source: section24.s +#readelf: -S --wide + +#failif +#... + \[..\] .(text|data|bss|rodata)[ ]+PROGBITS[ ]+[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 [^R] .* +#pass + diff --git a/include/ChangeLog b/include/ChangeLog index 93d9653..c8163ae 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + + * elf/common.h (SHF_GNU_RETAIN): Define. + 2020-11-16 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com> * opcode/aarch64.h (AARCH64_FEATURE_FLAGM): Add new feature. diff --git a/include/elf/common.h b/include/elf/common.h index fc672de..95a852f 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/ChangeLog b/ld/ChangeLog index 7141182..0e2ddee 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,28 @@ +2020-11-18 Jozef Lawrynowicz <jozef.l@mittosystems.com> + + * NEWS: Announce support for 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. + 2020-11-17 Alan Modra <amodra@gmail.com> PR 26882 @@ -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. @@ -1807,6 +1807,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 @@ -5291,6 +5294,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 f2ff039..6e61c7f 100644 --- a/ld/testsuite/ld-elf/elf.exp +++ b/ld/testsuite/ld-elf/elf.exp @@ -119,6 +119,16 @@ 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 0000000..f7716fa --- /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 0000000..29adb5d --- /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 0000000..b1cafc9 --- /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 0000000..1a63f51 --- /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 0000000..8ef9827 --- /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 0000000..4028aa1 --- /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 0000000..3c81a88 --- /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 0000000..ce315cb --- /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 0000000..b423fb9 --- /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 0000000..f30f121 --- /dev/null +++ b/ld/testsuite/ld-elf/retain4.s @@ -0,0 +1,13 @@ +/* A section that 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 0000000..86e85f8 --- /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 0000000..6b97c2a --- /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 0000000..4e83731 --- /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 0000000..89a7784 --- /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 0000000..aa93117 --- /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 0000000..f29ba71 --- /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 0000000..a393dba --- /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 0000000..a66c5b3 --- /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 |