diff options
author | Alan Modra <amodra@gmail.com> | 2019-07-23 17:54:42 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-07-23 18:22:02 +0930 |
commit | df3a023bd614133fe69afb02cd0e8f3e590a36a9 (patch) | |
tree | 396b62a6d24352b88221af7749348cdfbcd5a9a3 | |
parent | 06f44071ccbeca33fff70b928b71d95a15982740 (diff) | |
download | gdb-df3a023bd614133fe69afb02cd0e8f3e590a36a9.zip gdb-df3a023bd614133fe69afb02cd0e8f3e590a36a9.tar.gz gdb-df3a023bd614133fe69afb02cd0e8f3e590a36a9.tar.bz2 |
SHF_GNU_MBIND requires ELFOSABI_GNU
When SHF_GNU_MBIND was added in the SHF_LOOS to SHF_HIOS range, it
should have required ELFOSABI_GNU since these flags are already in use
by other OSes. HPUX SHF_HP_TLS in fact has the same value. That
means no place in binutils should test SHF_GNU_MBIND without first
checking OSABI, and SHF_GNU_MBIND should not be set without also
setting OSABI. At least, that's the ideal, but the patch accepts
SHF_GNU_MBIND on ELFOSABI_NONE object files since gas didn't always
set OSABI. However, to reinforce the fact that SHF_GNU_MBIND isn't
proper without a non-zero OSABI, readelf will display the flag as
LOOS+0 if OSABI isn't set.
The clash with SHF_HP_TLS means that hppa64-linux either has that flag
on .tbss sections or supports GNU_MBIND, not both. (hppa64-linux
users, if there are any, may have noticed that GNU ld since 2017
mysteriously aligned their .tbss sections to a 4k boundary. That was
one consequence of SHF_HP_TLS being blindly interpreted as
SHF_GNU_MBIND.) Since it seems that binutils, gdb, gcc, glibc, and
the linux kernel don't care about SHF_HP_TLS I took that flag out of
.tbss for hppa64-linux.
bfd/
* elf-bfd.h (enum elf_gnu_osabi): Add elf_gnu_osabi_mbind.
* elf.c (_bfd_elf_make_section_from_shdr): Set elf_gnu_osabi_mbind.
(get_program_header_size): Formatting. Only test SH_GNU_MBIND
when elf_gnu_osabi_mbind is set.
(_bfd_elf_map_sections_to_segments): Likewise.
(_bfd_elf_init_private_section_data): Likewise.
(_bfd_elf_final_write_processing): Update comment.
* elf64-hppa.c (elf64_hppa_special_sections): Move .tbss entry.
(elf_backend_special_sections): Define without .tbss for linux.
binutils/
* readelf.c (get_parisc_segment_type): Split off hpux entries..
(get_ia64_segment_type): ..and these..
(get_hpux_segment_type): ..to here.
(get_segment_type): Condition GNU_MBIND on osabi. Use
get_hpux_segment_type.
(get_symbol_binding): Do not print UNIQUE for ELFOSABI_NONE.
(get_symbol_type): Do not print IFUNC for ELFOSABI_NONE.
gas/
* config/obj-elf.c (obj_elf_change_section): Don't emit a fatal
error for non-SHF_ALLOC SHF_GNU_MBIND here.
(obj_elf_parse_section_letters): Return SHF_GNU_MBIND in new
gnu_attr param.
(obj_elf_section): Adjust obj_elf_parse_section_letters call.
Formatting. Set SHF_GNU_MBIND and elf_osabi from gnu_attr.
Emit normal error for non-SHF_ALLOC SHF_GNU_MBIND and wrong osabi.
(obj_elf_type): Set elf_osabi for ifunc.
* testsuite/gas/elf/section12a.d: xfail msp430 and hpux.
* testsuite/gas/elf/section12b.d: Likewise.
* testsuite/gas/elf/section13.d: Likewise.
* testsuite/gas/elf/section13.l: Adjust expected error.
ld/
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Condition
SHF_GNU_MBIND on osabi. Set output elf_gnu_osabi_mbind.
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 7 | ||||
-rw-r--r-- | bfd/elf.c | 80 | ||||
-rw-r--r-- | bfd/elf64-hppa.c | 4 | ||||
-rw-r--r-- | binutils/ChangeLog | 10 | ||||
-rw-r--r-- | binutils/readelf.c | 99 | ||||
-rw-r--r-- | gas/ChangeLog | 15 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 69 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section12a.d | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section12b.d | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section13.d | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/section13.l | 2 | ||||
-rw-r--r-- | ld/ChangeLog | 5 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 2 |
14 files changed, 205 insertions, 108 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3a19099..0b6dff6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,17 @@ 2019-07-23 Alan Modra <amodra@gmail.com> + * elf-bfd.h (enum elf_gnu_osabi): Add elf_gnu_osabi_mbind. + * elf.c (_bfd_elf_make_section_from_shdr): Set elf_gnu_osabi_mbind. + (get_program_header_size): Formatting. Only test SH_GNU_MBIND + when elf_gnu_osabi_mbind is set. + (_bfd_elf_map_sections_to_segments): Likewise. + (_bfd_elf_init_private_section_data): Likewise. + (_bfd_elf_final_write_processing): Update comment. + * elf64-hppa.c (elf64_hppa_special_sections): Move .tbss entry. + (elf_backend_special_sections): Define without .tbss for linux. + +2019-07-23 Alan Modra <amodra@gmail.com> + * elf-bfd.h (enum elf_gnu_osabi): Rename from elf_gnu_symbols. Remove none, any, all enums. (struct elf_obj_tdata): Rename has_gnu_symbols field to has_gnu_osabi. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 134496e..01beac6 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1809,11 +1809,12 @@ struct output_elf_obj_tdata bfd_boolean flags_init; }; -/* Indicate if the bfd contains 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 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, }; @@ -1067,6 +1067,19 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, if ((hdr->sh_flags & SHF_EXCLUDE) != 0) flags |= SEC_EXCLUDE; + switch (elf_elfheader (abfd)->e_ident[EI_OSABI]) + { + /* 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_MBIND) != 0) + elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind; + break; + } + if ((flags & SEC_ALLOC) == 0) { /* The debugging sections appear to be recognized only by name, @@ -4425,31 +4438,32 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info) bed = get_elf_backend_data (abfd); - if ((abfd->flags & D_PAGED) != 0) - { - /* Add a PT_GNU_MBIND segment for each mbind section. */ - unsigned int page_align_power = bfd_log2 (bed->commonpagesize); - for (s = abfd->sections; s != NULL; s = s->next) - if (elf_section_flags (s) & SHF_GNU_MBIND) - { - if (elf_section_data (s)->this_hdr.sh_info - > PT_GNU_MBIND_NUM) - { - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: GNU_MBIN section `%pA' has invalid sh_info field: %d"), - abfd, s, elf_section_data (s)->this_hdr.sh_info); - continue; - } - /* Align mbind section to page size. */ - if (s->alignment_power < page_align_power) - s->alignment_power = page_align_power; - segs ++; - } - } - - /* Let the backend count up any program headers it might need. */ - if (bed->elf_backend_additional_program_headers) + if ((abfd->flags & D_PAGED) != 0 + && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0) + { + /* Add a PT_GNU_MBIND segment for each mbind section. */ + unsigned int page_align_power = bfd_log2 (bed->commonpagesize); + for (s = abfd->sections; s != NULL; s = s->next) + if (elf_section_flags (s) & SHF_GNU_MBIND) + { + if (elf_section_data (s)->this_hdr.sh_info > PT_GNU_MBIND_NUM) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: GNU_MBIND section `%pA' has invalid " + "sh_info field: %d"), + abfd, s, elf_section_data (s)->this_hdr.sh_info); + continue; + } + /* Align mbind section to page size. */ + if (s->alignment_power < page_align_power) + s->alignment_power = page_align_power; + segs ++; + } + } + + /* Let the backend count up any program headers it might need. */ + if (bed->elf_backend_additional_program_headers) { int a; @@ -5045,11 +5059,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) pm = &m->next; } - if (first_mbind && (abfd->flags & D_PAGED) != 0) + if (first_mbind + && (abfd->flags & D_PAGED) != 0 + && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0) for (s = first_mbind; s != NULL; s = s->next) if ((elf_section_flags (s) & SHF_GNU_MBIND) != 0 - && (elf_section_data (s)->this_hdr.sh_info - <= PT_GNU_MBIND_NUM)) + && elf_section_data (s)->this_hdr.sh_info <= PT_GNU_MBIND_NUM) { /* Mandated PF_R. */ unsigned long p_flags = PF_R; @@ -7665,7 +7680,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd, & (SHF_MASKOS | SHF_MASKPROC)); /* Copy sh_info from input for mbind section. */ - if (elf_section_flags (isec) & SHF_GNU_MBIND) + if ((elf_tdata (ibfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0 + && elf_section_flags (isec) & SHF_GNU_MBIND) elf_section_data (osec)->this_hdr.sh_info = elf_section_data (isec)->this_hdr.sh_info; @@ -12118,9 +12134,9 @@ _bfd_elf_final_write_processing (bfd *abfd, if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE) i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; - /* To make things simpler for the loader on Linux systems we set the - osabi field to ELFOSABI_GNU if the binary contains symbols of - the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding. */ + /* 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. */ if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE && elf_tdata (abfd)->has_gnu_osabi) i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU; diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 9f6a513..7781158 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -3954,13 +3954,13 @@ elf64_hppa_relocate_section (bfd *output_bfd, static const struct bfd_elf_special_section elf64_hppa_special_sections[] = { + { STRING_COMMA_LEN (".tbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS }, { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT }, { STRING_COMMA_LEN (".dlt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT }, { STRING_COMMA_LEN (".sdata"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT }, { STRING_COMMA_LEN (".sbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT }, - { STRING_COMMA_LEN (".tbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS }, { NULL, 0, 0, 0, 0 } }; @@ -4088,5 +4088,7 @@ const struct elf_size_info hppa64_elf_size_info = #define ELF_OSABI ELFOSABI_GNU #undef elf64_bed #define elf64_bed elf64_hppa_linux_bed +#undef elf_backend_special_sections +#define elf_backend_special_sections (elf64_hppa_special_sections + 1) #include "elf64-target.h" diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 7bbb9d3..e329c40 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,15 @@ 2019-07-23 Alan Modra <amodra@gmail.com> + * readelf.c (get_parisc_segment_type): Split off hpux entries.. + (get_ia64_segment_type): ..and these.. + (get_hpux_segment_type): ..to here. + (get_segment_type): Condition GNU_MBIND on osabi. Use + get_hpux_segment_type. + (get_symbol_binding): Do not print UNIQUE for ELFOSABI_NONE. + (get_symbol_type): Do not print IFUNC for ELFOSABI_NONE. + +2019-07-23 Alan Modra <amodra@gmail.com> + * testsuite/binutils-all/objcopy.exp (elf64): Correct object file used to set this variable. diff --git a/binutils/readelf.c b/binutils/readelf.c index 5e8fe82..1ba4bcb 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -3879,22 +3879,6 @@ get_parisc_segment_type (unsigned long type) { switch (type) { - case PT_HP_TLS: return "HP_TLS"; - case PT_HP_CORE_NONE: return "HP_CORE_NONE"; - case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; - case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; - case PT_HP_CORE_COMM: return "HP_CORE_COMM"; - case PT_HP_CORE_PROC: return "HP_CORE_PROC"; - case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; - case PT_HP_CORE_STACK: return "HP_CORE_STACK"; - case PT_HP_CORE_SHM: return "HP_CORE_SHM"; - case PT_HP_CORE_MMF: return "HP_CORE_MMF"; - case PT_HP_PARALLEL: return "HP_PARALLEL"; - case PT_HP_FASTBIND: return "HP_FASTBIND"; - case PT_HP_OPT_ANNOT: return "HP_OPT_ANNOT"; - case PT_HP_HSL_ANNOT: return "HP_HSL_ANNOT"; - case PT_HP_STACK: return "HP_STACK"; - case PT_HP_CORE_UTSNAME: return "HP_CORE_UTSNAME"; case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT"; case PT_PARISC_UNWIND: return "PARISC_UNWIND"; case PT_PARISC_WEAKORDER: return "PARISC_WEAKORDER"; @@ -3909,10 +3893,6 @@ get_ia64_segment_type (unsigned long type) { case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT"; case PT_IA_64_UNWIND: return "IA_64_UNWIND"; - case PT_HP_TLS: return "HP_TLS"; - case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT"; - case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT"; - case PT_IA_64_HP_STACK: return "HP_STACK"; default: return NULL; } } @@ -3928,6 +3908,44 @@ get_tic6x_segment_type (unsigned long type) } static const char * +get_hpux_segment_type (unsigned long type, unsigned e_machine) +{ + if (e_machine == EM_PARISC) + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_HP_CORE_NONE: return "HP_CORE_NONE"; + case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; + case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; + case PT_HP_CORE_COMM: return "HP_CORE_COMM"; + case PT_HP_CORE_PROC: return "HP_CORE_PROC"; + case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; + case PT_HP_CORE_STACK: return "HP_CORE_STACK"; + case PT_HP_CORE_SHM: return "HP_CORE_SHM"; + case PT_HP_CORE_MMF: return "HP_CORE_MMF"; + case PT_HP_PARALLEL: return "HP_PARALLEL"; + case PT_HP_FASTBIND: return "HP_FASTBIND"; + case PT_HP_OPT_ANNOT: return "HP_OPT_ANNOT"; + case PT_HP_HSL_ANNOT: return "HP_HSL_ANNOT"; + case PT_HP_STACK: return "HP_STACK"; + case PT_HP_CORE_UTSNAME: return "HP_CORE_UTSNAME"; + default: return NULL; + } + + if (e_machine == EM_IA_64) + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT"; + case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT"; + case PT_IA_64_HP_STACK: return "HP_STACK"; + default: return NULL; + } + + return NULL; +} + +static const char * get_solaris_segment_type (unsigned long type) { switch (type) @@ -3965,12 +3983,7 @@ get_segment_type (Filedata * filedata, unsigned long p_type) case PT_GNU_PROPERTY: return "GNU_PROPERTY"; default: - if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI) - { - sprintf (buff, "GNU_MBIND+%#lx", - p_type - PT_GNU_MBIND_LO); - } - else if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) + if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) { const char * result; @@ -4011,24 +4024,28 @@ get_segment_type (Filedata * filedata, unsigned long p_type) } else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) { - const char * result; + const char * result = NULL; - switch (filedata->file_header.e_machine) + switch (filedata->file_header.e_ident[EI_OSABI]) { - case EM_PARISC: - result = get_parisc_segment_type (p_type); + case ELFOSABI_GNU: + case ELFOSABI_FREEBSD: + if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI) + { + sprintf (buff, "GNU_MBIND+%#lx", p_type - PT_GNU_MBIND_LO); + result = buff; + } break; - case EM_IA_64: - result = get_ia64_segment_type (p_type); + case ELFOSABI_HPUX: + result = get_hpux_segment_type (p_type, + filedata->file_header.e_machine); + break; + case ELFOSABI_SOLARIS: + result = get_solaris_segment_type (p_type); break; default: - if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) - result = get_solaris_segment_type (p_type); - else - result = NULL; break; } - if (result != NULL) return result; @@ -11052,9 +11069,7 @@ get_symbol_binding (Filedata * filedata, unsigned int binding) else if (binding >= STB_LOOS && binding <= STB_HIOS) { if (binding == STB_GNU_UNIQUE - && (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU - /* GNU is still using the default value 0. */ - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_NONE)) + && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU) return "UNIQUE"; snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding); } @@ -11106,9 +11121,7 @@ get_symbol_type (Filedata * filedata, unsigned int type) if (type == STT_GNU_IFUNC && (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_FREEBSD - /* GNU is still using the default value 0. */ - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_NONE)) + || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)) return "IFUNC"; snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type); diff --git a/gas/ChangeLog b/gas/ChangeLog index 47938f7..19ca464 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,20 @@ 2019-07-23 Alan Modra <amodra@gmail.com> + * config/obj-elf.c (obj_elf_change_section): Don't emit a fatal + error for non-SHF_ALLOC SHF_GNU_MBIND here. + (obj_elf_parse_section_letters): Return SHF_GNU_MBIND in new + gnu_attr param. + (obj_elf_section): Adjust obj_elf_parse_section_letters call. + Formatting. Set SHF_GNU_MBIND and elf_osabi from gnu_attr. + Emit normal error for non-SHF_ALLOC SHF_GNU_MBIND and wrong osabi. + (obj_elf_type): Set elf_osabi for ifunc. + * testsuite/gas/elf/section12a.d: xfail msp430 and hpux. + * testsuite/gas/elf/section12b.d: Likewise. + * testsuite/gas/elf/section13.d: Likewise. + * testsuite/gas/elf/section13.l: Adjust expected error. + +2019-07-23 Alan Modra <amodra@gmail.com> + * testsuite/gas/elf/section12a.d: Don't skip for rx. 2019-07-22 Barnaby Wilks <barnaby.wilks@arm.com> diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index af35fee..fd2c943 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -706,9 +706,6 @@ obj_elf_change_section (const char *name, attr |= ssect->attr; } - if ((attr & (SHF_ALLOC | SHF_GNU_MBIND)) == SHF_GNU_MBIND) - as_fatal (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name); - /* Convert ELF type and flags to BFD flags. */ flags = (SEC_RELOC | ((attr & SHF_WRITE) ? 0 : SEC_READONLY) @@ -785,7 +782,8 @@ obj_elf_change_section (const char *name, } static bfd_vma -obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone) +obj_elf_parse_section_letters (char *str, size_t len, + bfd_boolean *is_clone, bfd_vma *gnu_attr) { bfd_vma attr = 0; *is_clone = FALSE; @@ -819,7 +817,7 @@ obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone) attr |= SHF_TLS; break; case 'd': - attr |= SHF_GNU_MBIND; + *gnu_attr |= SHF_GNU_MBIND; break; case '?': *is_clone = TRUE; @@ -1011,6 +1009,7 @@ obj_elf_section (int push) char *beg; int type, dummy; bfd_vma attr; + bfd_vma gnu_attr; int entsize; int linkonce; subsegT new_subsection = -1; @@ -1041,6 +1040,7 @@ obj_elf_section (int push) return; type = SHT_NULL; attr = 0; + gnu_attr = 0; group_name = NULL; entsize = 0; linkonce = 0; @@ -1077,7 +1077,8 @@ obj_elf_section (int push) ignore_rest_of_line (); return; } - attr |= obj_elf_parse_section_letters (beg, strlen (beg), &is_clone); + attr |= obj_elf_parse_section_letters (beg, strlen (beg), + &is_clone, &gnu_attr); SKIP_WHITESPACE (); if (*input_line_pointer == ',') @@ -1103,14 +1104,14 @@ obj_elf_section (int push) ++input_line_pointer; if (ISDIGIT (* input_line_pointer)) - { - type = strtoul (input_line_pointer, & input_line_pointer, 0); - } + type = strtoul (input_line_pointer, &input_line_pointer, 0); else { c = get_symbol_name (& beg); (void) restore_line_pointer (c); - type = obj_elf_section_type (beg, input_line_pointer - beg, TRUE); + type = obj_elf_section_type (beg, + input_line_pointer - beg, + TRUE); } } else @@ -1177,7 +1178,7 @@ obj_elf_section (int push) } } - if ((attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',') + if ((gnu_attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',') { ++input_line_pointer; SKIP_WHITESPACE (); @@ -1211,7 +1212,8 @@ obj_elf_section (int push) c = get_symbol_name (& beg); (void) restore_line_pointer (c); - attr |= obj_elf_section_word (beg, input_line_pointer - beg, & type); + attr |= obj_elf_section_word (beg, input_line_pointer - beg, + &type); SKIP_WHITESPACE (); } @@ -1226,6 +1228,23 @@ done: obj_elf_change_section (name, type, info, attr, entsize, group_name, linkonce, push); + if ((gnu_attr & SHF_GNU_MBIND) != 0) + { + struct elf_backend_data *bed; + + if ((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_section_flags (now_seg) |= gnu_attr; + if (push && new_subsection != -1) subseg_set (now_seg, new_subsection); } @@ -2032,15 +2051,15 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED) || strcmp (type_name, "10") == 0 || strcmp (type_name, "STT_GNU_IFUNC") == 0) { - const struct elf_backend_data *bed; - - bed = get_elf_backend_data (stdoutput); - if (!(bed->elf_osabi == ELFOSABI_GNU - || bed->elf_osabi == ELFOSABI_FREEBSD - /* GNU is still using the default value 0. */ - || bed->elf_osabi == ELFOSABI_NONE)) - as_bad (_("symbol type \"%s\" is supported only by GNU and FreeBSD targets"), - type_name); + struct elf_backend_data *bed; + + 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 (_("symbol type \"%s\" is supported only by GNU " + "and FreeBSD targets"), type_name); type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION; } else if (strcmp (type_name, "gnu_unique_object") == 0) @@ -2048,14 +2067,12 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED) struct elf_backend_data *bed; bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput); - if (!(bed->elf_osabi == ELFOSABI_GNU - /* GNU is still using the default value 0. */ - || bed->elf_osabi == ELFOSABI_NONE)) + if (bed->elf_osabi == ELFOSABI_NONE) + bed->elf_osabi = ELFOSABI_GNU; + else if (bed->elf_osabi != ELFOSABI_GNU) as_bad (_("symbol type \"%s\" is supported only by GNU targets"), type_name); type = BSF_OBJECT | BSF_GNU_UNIQUE; - /* PR 10549: Always set OSABI field to GNU for objects containing unique symbols. */ - bed->elf_osabi = ELFOSABI_GNU; } #ifdef md_elf_symbol_type else if ((type = md_elf_symbol_type (type_name, sym, elfsym)) != -1) diff --git a/gas/testsuite/gas/elf/section12a.d b/gas/testsuite/gas/elf/section12a.d index 3e04171..2b6aa3e 100644 --- a/gas/testsuite/gas/elf/section12a.d +++ b/gas/testsuite/gas/elf/section12a.d @@ -2,6 +2,8 @@ #as: --no-pad-sections #readelf: -Sg --wide #name: mbind sections +# msp430 and hpux do not support SHF_GNU_MBIND +#xfail: msp430-*-* *-*-hpux* #... \[[ 0-9]+\] \.mbind\.data[ ]+PROGBITS[ ]+0+0 0+[0-9a-f]+ 0+1 00 WAD 0 0 1 diff --git a/gas/testsuite/gas/elf/section12b.d b/gas/testsuite/gas/elf/section12b.d index 717bc1a..fcbb697 100644 --- a/gas/testsuite/gas/elf/section12b.d +++ b/gas/testsuite/gas/elf/section12b.d @@ -2,8 +2,9 @@ #as: --no-pad-sections #objdump: -s #name: mbind section contents -# The RX port annoyingly reorders the sections so that they do not match the sequence expected below. -#skip: rx-*-* +# RX annoyingly reorders the sections so that they do not match the sequence +# expected below. msp430 and hpux do not support SHF_GNU_MBIND +#xfail: rx-*-* msp430-*-* *-*-hpux* #... Contents of section .mbind.data: diff --git a/gas/testsuite/gas/elf/section13.d b/gas/testsuite/gas/elf/section13.d index 940ccec..9f4fe36 100644 --- a/gas/testsuite/gas/elf/section13.d +++ b/gas/testsuite/gas/elf/section13.d @@ -1,2 +1,3 @@ #name: mbind sections without SHF_ALLOC #error_output: section13.l +#xfail: msp430-*-* *-*-hpux* diff --git a/gas/testsuite/gas/elf/section13.l b/gas/testsuite/gas/elf/section13.l index c56b5ae..3ddf54a 100644 --- a/gas/testsuite/gas/elf/section13.l +++ b/gas/testsuite/gas/elf/section13.l @@ -1,2 +1,2 @@ [^:]*: Assembler messages: -[^:]*:1: Fatal error: SHF_ALLOC isn't set for GNU_MBIND section: .mbind.data +[^:]*:1: Error: SHF_ALLOC isn't set for GNU_MBIND section: .mbind.data diff --git a/ld/ChangeLog b/ld/ChangeLog index fd13791..7d7b664 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,10 @@ 2019-07-23 Alan Modra <amodra@gmail.com> + * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Condition + SHF_GNU_MBIND on osabi. Set output elf_gnu_osabi_mbind. + +2019-07-23 Alan Modra <amodra@gmail.com> + * testsuite/ld-elf/size-1.d, * testsuite/ld-elf/size-1.s, * testsuite/ld-elf/size-1.t: New test. diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index f3c6e3a..5cdd1bd 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -2131,6 +2131,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, && elfinput && elfoutput && (s->flags & SEC_ALLOC) != 0 + && (elf_tdata (s->owner)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0 && (elf_section_flags (s) & SHF_GNU_MBIND) != 0) { /* Find the output mbind section with the same type, attributes @@ -2168,6 +2169,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, secname = ".mbind.rodata"; else secname = ".mbind.text"; + elf_tdata (link_info.output_bfd)->has_gnu_osabi |= elf_gnu_osabi_mbind; } /* Look through the script to see where to place this section. The |