]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas/ELF: re-work SHF_GNU_* handling
authorJan Beulich <jbeulich@suse.com>
Fri, 15 Aug 2025 10:18:34 +0000 (12:18 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 15 Aug 2025 10:18:34 +0000 (12:18 +0200)
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.

gas/config/obj-elf.c
gas/config/tc-alpha.c
gas/config/tc-i386.c
gas/config/tc-ia64.c
gas/config/tc-mep.c
gas/config/tc-ppc.c
gas/testsuite/gas/elf/bad-section-flag.err

index a209a9be7d6395f3f56c5007ae98cba82d9117e3..4e774dcd7d992d865577eb803bebadf59816f6b6 100644 (file)
@@ -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,
index 9558425d8f8f1373304a0132e6af3d58bc655ca8..7ba85a6777021dd4ce4e784c1a4a059be7e3eb8c 100644 (file)
@@ -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;
 }
 
index 8fb8a7ee372e8eeeca96696f7e13412970b30df8..11f409526e32a8c25fa2eaf4a6aeaa75b7299bfc 100644 (file)
@@ -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;
 }
 
index 88f956388607c1aa9c0ce20d8575395f48592c9d..58e2c7158fa8efb9c3cddd8af358d72a4dff5440 100644 (file)
@@ -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;
 }
 
index 14691861bcfb9c8651b16854361eac22b26ee8ea..16ea2800e3aa7546177a09191fc4176699c0b1af 100644 (file)
@@ -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;
 }
 
index 9b3aaabfa0af81639c82149b17311359e6fe88f2..0816c38ea4ddc49a45c13452feaacab5c2fd511a 100644 (file)
@@ -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 */
index 6099c4f5f6762c3ef5548f98c6043d4051686cdb..919d13f17cf0df67a0ffa42ca57d24a9cd998617 100644 (file)
@@ -1,2 +1,2 @@
 .*: Assembler messages:
-.*:1: Fatal error: .*
+.*:1: Error: unrecognized [.]section attribute: .*