From: Jan Beulich Date: Fri, 15 Aug 2025 10:18:34 +0000 (+0200) Subject: gas/ELF: re-work SHF_GNU_* handling X-Git-Tag: gdb-17-branchpoint~304 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4984ab44f82bd0b05d0c6ca5182d21e5ace8cf3a;p=thirdparty%2Fbinutils-gdb.git gas/ELF: re-work SHF_GNU_* handling Indicate to obj_elf_parse_section_letters() whether to recognize GNU- specific flags by conditionally passing NULL in place of a pointer to the GNU attributes. This way wrong use of d and R can be diagnosed just like any other use of unrecognized letters. Furthermore adjust the md_elf_section_letter() interface: Have targets merely return the extra letters they support. There's no point having them customize the entire diagnostic. Even more so that additions in common code would then reflecting in every target's diagnostic as well, which - as can be seen - wasn't always properly done. There's also no reason for wrong letters to be a fatal error; switch to as_bad() while making other adjustments there. While making the target specific adjustments, also drop IA-64's dead handling of 'o' (SHF_LINK_ORDER), which has been covered by common code for a long time. Also re-arrange the switch() in obj_elf_parse_section_letters() to be alphabetically sorted again. --- diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index a209a9be7d6..4e774dcd7d9 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -896,6 +896,11 @@ obj_elf_parse_section_letters (char *str, size_t len, } } break; + case 'd': + if (gnu_attr == NULL) + goto unrecognized; + *gnu_attr |= SHF_GNU_MBIND; + break; case 'e': attr |= SHF_EXCLUDE; break; @@ -908,33 +913,33 @@ obj_elf_parse_section_letters (char *str, size_t len, case 'x': attr |= SHF_EXECINSTR; break; + case 'G': + attr |= SHF_GROUP; + break; case 'M': attr |= SHF_MERGE; break; + case 'R': + if (gnu_attr == NULL) + goto unrecognized; + *gnu_attr |= SHF_GNU_RETAIN; + break; case 'S': attr |= SHF_STRINGS; break; - case 'G': - attr |= SHF_GROUP; - break; case 'T': attr |= SHF_TLS; break; - case 'd': - *gnu_attr |= SHF_GNU_MBIND; - break; - case 'R': - *gnu_attr |= SHF_GNU_RETAIN; - break; case '?': *is_clone = true; break; default: + unrecognized: { - const char *bad_msg = _("unrecognized .section attribute:" - " want a,e,o,w,x,M,S,G,T or number"); + const char *md_extra = ""; + #ifdef md_elf_section_letter - bfd_vma md_attr = md_elf_section_letter (*str, &bad_msg); + bfd_vma md_attr = md_elf_section_letter (*str, &md_extra); if (md_attr != (bfd_vma) -1) attr |= md_attr; else @@ -942,21 +947,14 @@ obj_elf_parse_section_letters (char *str, size_t len, if (ISDIGIT (*str)) { char * end; - const struct elf_backend_data *bed; bfd_vma numeric_flags = strtoul (str, &end, 0); attr |= numeric_flags; - bed = get_elf_backend_data (stdoutput); - - if (bed->elf_osabi == ELFOSABI_NONE - || bed->elf_osabi == ELFOSABI_GNU - || bed->elf_osabi == ELFOSABI_FREEBSD) + if (gnu_attr != NULL) { /* Add flags in the SHF_MASKOS range to gnu_attr for OSABIs that support those flags. - Also adding the flags for ELFOSABI_NONE 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 @@ -972,10 +970,18 @@ obj_elf_parse_section_letters (char *str, size_t len, len -= (end - str); str = end; } - else if (!attr && !*gnu_attr && (*str == '+' || *str == '-')) + else if (!*inherit && !attr + && (gnu_attr == NULL || !*gnu_attr) + && (*str == '+' || *str == '-')) *inherit = *str == '+' ? 1 : -1; else - as_fatal ("%s", bad_msg); + { + as_bad (_("unrecognized .section attribute: want %s%s%s,? or number"), + gnu_attr != NULL ? "a,d,e,o,w,x,G,M,R,S,T" + : "a,e,o,w,x,G,M,S,T", + md_extra != NULL ? "," : "", md_extra); + return attr; + } } break; } @@ -1260,8 +1266,16 @@ obj_elf_section (int push) ignore_rest_of_line (); return; } + + const struct elf_backend_data *bed = get_elf_backend_data (stdoutput); attr = obj_elf_parse_section_letters (beg, strlen (beg), &is_clone, - &inherit, &gnu_attr); + &inherit, + bed->elf_osabi == ELFOSABI_NONE + || (bed->elf_osabi + == ELFOSABI_GNU) + || (bed->elf_osabi + == ELFOSABI_FREEBSD) + ? &gnu_attr : NULL); if (inherit > 0) attr |= elf_section_flags (now_seg); @@ -1571,28 +1585,17 @@ obj_elf_section (int push) if ((gnu_attr & (SHF_GNU_MBIND | SHF_GNU_RETAIN)) != 0) { - const struct elf_backend_data *bed; bool mbind_p = (gnu_attr & SHF_GNU_MBIND) != 0; if (mbind_p && (attr & SHF_ALLOC) == 0) as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name); - bed = get_elf_backend_data (stdoutput); + 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; - 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 (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; - } + attr |= gnu_attr; } change_section (name, type, attr, entsize, &match, linkonce, push, diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index 9558425d8f8..7ba85a67770 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -5306,12 +5306,12 @@ select_gp_value (void) /* Map 's' to SHF_ALPHA_GPREL. */ bfd_vma -alpha_elf_section_letter (int letter, const char **ptr_msg) +alpha_elf_section_letter (int letter, const char **extra) { if (letter == 's') return SHF_ALPHA_GPREL; - *ptr_msg = _("bad .section directive: want a,s,w,x,M,S,G,T in string"); + *extra = "s"; return -1; } diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8fb8a7ee372..11f409526e3 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -18669,17 +18669,15 @@ i386_solaris_fix_up_eh_frame (segT sec) /* For ELF on x86-64, add support for SHF_X86_64_LARGE. */ bfd_vma -x86_64_section_letter (int letter, const char **ptr_msg) +x86_64_section_letter (int letter, const char **extra) { if (flag_code == CODE_64BIT) { if (letter == 'l') return SHF_X86_64_LARGE; - *ptr_msg = _("bad .section directive: want a,l,w,x,M,S,G,T in string"); + *extra = "l"; } - else - *ptr_msg = _("bad .section directive: want a,w,x,M,S,G,T in string"); return -1; } diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 88f95638860..58e2c7158fa 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -853,20 +853,20 @@ set_section (char *name) /* Map 's' to SHF_IA_64_SHORT. */ bfd_vma -ia64_elf_section_letter (int letter, const char **ptr_msg) +ia64_elf_section_letter (int letter, const char **extra) { if (letter == 's') return SHF_IA_64_SHORT; - else if (letter == 'o') - return SHF_LINK_ORDER; #ifdef TE_VMS else if (letter == 'O') return SHF_IA_64_VMS_OVERLAID; else if (letter == 'g') return SHF_IA_64_VMS_GLOBAL; + *extra = "g,s,O"; +#else + *extra = "s"; #endif - *ptr_msg = _("bad .section directive: want a,o,s,w,x,M,S,G,T in string"); return -1; } diff --git a/gas/config/tc-mep.c b/gas/config/tc-mep.c index 14691861bcf..16ea2800e3a 100644 --- a/gas/config/tc-mep.c +++ b/gas/config/tc-mep.c @@ -2081,12 +2081,12 @@ mep_fix_adjustable (fixS *fixP) } bfd_vma -mep_elf_section_letter (int letter, const char **ptrmsg) +mep_elf_section_letter (int letter, const char **extra) { if (letter == 'v') return SHF_MEP_VLIW; - *ptrmsg = _("bad .section directive: want a,v,w,x,M,S in string"); + *extra = "v"; return -1; } diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 9b3aaabfa0a..0816c38ea4d 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -4171,12 +4171,12 @@ ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type) } bfd_vma -ppc_elf_section_letter (int letter, const char **ptrmsg) +ppc_elf_section_letter (int letter, const char **extra) { if (letter == 'v') return SHF_PPC_VLE; - *ptrmsg = _("bad .section directive: want a,e,v,w,x,M,S,G,T in string"); + *extra = "v"; return -1; } #endif /* OBJ_ELF */ diff --git a/gas/testsuite/gas/elf/bad-section-flag.err b/gas/testsuite/gas/elf/bad-section-flag.err index 6099c4f5f67..919d13f17cf 100644 --- a/gas/testsuite/gas/elf/bad-section-flag.err +++ b/gas/testsuite/gas/elf/bad-section-flag.err @@ -1,2 +1,2 @@ .*: Assembler messages: -.*:1: Fatal error: .* +.*:1: Error: unrecognized [.]section attribute: .*