From cbac6da160859cd4ffbfc85d06774d1962f5faa3 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 1 Oct 2020 11:49:04 +0100 Subject: [PATCH] Support SHF_GNU_RETAIN ELF section flag The SHF_GNU_RETAIN section flag is an extension to the GNU ELF OSABI. It 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-10-02 H.J. Lu Jozef Lawrynowicz * 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 (bfd_elf_gc_sections): gc_mark the section if SHF_GNU_RETAIN is set. binutils/ChangeLog: 2020-10-02 Jozef Lawrynowicz * NEWS: Announce SHF_GNU_RETAIN. * 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 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-10-02 H.J. Lu Jozef Lawrynowicz * 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. Handle numeric flag values within the SHF_MASKOS range. (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: Don't test SHF_GNU_RETAIN bit of section flag. * testsuite/gas/elf/section10.s: Don't set SHF_GNU_RETAIN bit of section flag. * 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. include/ChangeLog: 2020-10-02 Jozef Lawrynowicz * elf/common.h (SHF_GNU_RETAIN): Define. ld/ChangeLog: 2020-10-02 Jozef Lawrynowicz H.J. Lu * 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 | 17 +++- bfd/elflink.c | 4 +- binutils/NEWS | 4 + binutils/readelf.c | 21 +++- 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 | 65 +++++++++--- gas/config/obj-elf.h | 3 +- gas/doc/as.texi | 3 + gas/testsuite/gas/elf/elf.exp | 3 + gas/testsuite/gas/elf/section10.d | 4 +- gas/testsuite/gas/elf/section10.s | 4 +- gas/testsuite/gas/elf/section22.d | 19 ++++ gas/testsuite/gas/elf/section22.s | 34 +++++++ gas/testsuite/gas/elf/section23.s | 11 +++ gas/testsuite/gas/elf/section23a.d | 11 +++ gas/testsuite/gas/elf/section23b.d | 6 ++ gas/testsuite/gas/elf/section23b.err | 2 + 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 +++ 47 files changed, 822 insertions(+), 29 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 gas/testsuite/gas/elf/section23.s create mode 100644 gas/testsuite/gas/elf/section23a.d create mode 100644 gas/testsuite/gas/elf/section23b.d create mode 100644 gas/testsuite/gas/elf/section23b.err 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..5daf8ec0f5 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; @@ -12476,11 +12479,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 b6937293e8..6efd181a32 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -14102,7 +14102,9 @@ 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_tdata (sub)->has_gnu_osabi & elf_gnu_osabi_retain + && elf_section_flags (o) & SHF_GNU_RETAIN))) { if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) return FALSE; diff --git a/binutils/NEWS b/binutils/NEWS index c0dc73d7d8..6c7d3f3953 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -4,6 +4,10 @@ symbol names. In addition the --demangle=