]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
clean-up bfd/elf-attrs.c: move specific-code to parse object attributes v1 into a...
authorMatthieu Longo <matthieu.longo@arm.com>
Thu, 30 Jan 2025 19:09:12 +0000 (19:09 +0000)
committerMatthieu Longo <matthieu.longo@arm.com>
Tue, 4 Mar 2025 11:02:03 +0000 (11:02 +0000)
bfd/elf-attrs.c

index aa6d6284a3d391f59d586ad4f39be23878884c6c..a6a72369afd3674f419f548b6cc12bb6208bb9d4 100644 (file)
@@ -489,160 +489,172 @@ _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, unsigned int tag)
     }
 }
 
+static void
+bfd_elf_parse_attr_section_v1 (bfd *abfd,
+                              Elf_Internal_Shdr * hdr,
+                              bfd_byte *contents)
+{
+  bfd_byte *p = contents;
+  bfd_byte *p_end = p + hdr->sh_size;
+  const char *std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
+
+  while (p_end - p >= 4)
+    {
+      size_t len = p_end - p;
+      size_t namelen;
+      size_t section_len;
+      int vendor;
+
+      section_len = bfd_get_32 (abfd, p);
+      p += 4;
+      if (section_len == 0)
+       break;
+      if (section_len > len)
+       section_len = len;
+      if (section_len <= 4)
+       {
+         _bfd_error_handler
+               (_("%pB: error: attribute section length too small: %ld"),
+                abfd, (long) section_len);
+         break;
+       }
+      section_len -= 4;
+      namelen = strnlen ((char *) p, section_len) + 1;
+      if (namelen >= section_len)
+       break;
+      if (std_sec && strcmp ((char *) p, std_sec) == 0)
+       vendor = OBJ_ATTR_PROC;
+      else if (strcmp ((char *) p, "gnu") == 0)
+       vendor = OBJ_ATTR_GNU;
+      else
+       {
+         /* Other vendor section.  Ignore it.  */
+         p += section_len;
+         continue;
+       }
+
+      p += namelen;
+      section_len -= namelen;
+      while (section_len > 0)
+       {
+         unsigned int tag;
+         unsigned int val;
+         size_t subsection_len;
+         bfd_byte *end, *orig_p;
+
+         orig_p = p;
+         tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end);
+         if (p_end - p >= 4)
+         {
+           subsection_len = bfd_get_32 (abfd, p);
+           p += 4;
+         }
+         else
+         {
+           p = p_end;
+           break;
+         }
+         if (subsection_len > section_len)
+           subsection_len = section_len;
+         section_len -= subsection_len;
+         end = orig_p + subsection_len;
+         if (end < p)
+           break;
+         switch (tag)
+           {
+           case Tag_File:
+             while (p < end)
+               {
+                 int type;
+                 bool ok = false;
+
+                 tag = _bfd_safe_read_leb128 (abfd, &p, false, end);
+                 type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
+                 switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
+                   {
+                   case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
+                     val = _bfd_safe_read_leb128 (abfd, &p, false, end);
+                     ok = elf_add_obj_attr_int_string (abfd, vendor, tag,
+                                                       val, (char *) p,
+                                                       (char *) end);
+                     p += strnlen ((char *) p, end - p);
+                     if (p < end)
+                       p++;
+                     break;
+                   case ATTR_TYPE_FLAG_STR_VAL:
+                     ok = elf_add_obj_attr_string (abfd, vendor, tag,
+                                                   (char *) p,
+                                                   (char *) end);
+                     p += strnlen ((char *) p, end - p);
+                     if (p < end)
+                       p++;
+                     break;
+                   case ATTR_TYPE_FLAG_INT_VAL:
+                     val = _bfd_safe_read_leb128 (abfd, &p, false, end);
+                     ok = bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
+                     break;
+                   default:
+                     abort ();
+                   }
+                 if (!ok)
+                   bfd_perror (_("error adding attribute"));
+               }
+             break;
+           case Tag_Section:
+           case Tag_Symbol:
+             /* Don't have anywhere convenient to attach these.
+                Fall through for now.  */
+           default:
+             /* Ignore things we don't know about.  */
+             p = end;
+             break;
+           }
+       }
+    }
+}
+
 /* Parse an object attributes section.  */
 void
 _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 {
-  bfd_byte *contents;
-  bfd_byte *p;
-  bfd_byte *p_end;
-  const char *std_sec;
-  ufile_ptr filesize;
-
   /* PR 17512: file: 2844a11d.  */
   if (hdr->sh_size == 0)
     return;
 
-  filesize = bfd_get_file_size (abfd);
+  ufile_ptr filesize = bfd_get_file_size (abfd);
   if (filesize != 0 && hdr->sh_size > filesize)
     {
-      /* xgettext:c-format */
       _bfd_error_handler (_("%pB: error: attribute section '%pA' too big: %#llx"),
                          abfd, hdr->bfd_section, (long long) hdr->sh_size);
       bfd_set_error (bfd_error_invalid_operation);
       return;
     }
 
-  contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
-  if (!contents)
+  bfd_byte *data = (bfd_byte *) bfd_malloc (hdr->sh_size);
+  if (!data)
     return;
-  if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
-                                hdr->sh_size))
-    {
-      free (contents);
-      return;
-    }
-  p = contents;
-  p_end = p + hdr->sh_size;
-  std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
 
-  if (*p++ == 'A')
-    {
-      while (p_end - p >= 4)
-       {
-         size_t len = p_end - p;
-         size_t namelen;
-         size_t section_len;
-         int vendor;
-
-         section_len = bfd_get_32 (abfd, p);
-         p += 4;
-         if (section_len == 0)
-           break;
-         if (section_len > len)
-           section_len = len;
-         if (section_len <= 4)
-           {
-             _bfd_error_handler
-               (_("%pB: error: attribute section length too small: %ld"),
-                abfd, (long) section_len);
-             break;
-           }
-         section_len -= 4;
-         namelen = strnlen ((char *) p, section_len) + 1;
-         if (namelen >= section_len)
-           break;
-         if (std_sec && strcmp ((char *) p, std_sec) == 0)
-           vendor = OBJ_ATTR_PROC;
-         else if (strcmp ((char *) p, "gnu") == 0)
-           vendor = OBJ_ATTR_GNU;
-         else
-           {
-             /* Other vendor section.  Ignore it.  */
-             p += section_len;
-             continue;
-           }
+  if (!bfd_get_section_contents (abfd, hdr->bfd_section, data, 0, hdr->sh_size))
+    goto free_data;
 
-         p += namelen;
-         section_len -= namelen;
-         while (section_len > 0)
-           {
-             unsigned int tag;
-             unsigned int val;
-             size_t subsection_len;
-             bfd_byte *end, *orig_p;
-
-             orig_p = p;
-             tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end);
-             if (p_end - p >= 4)
-               {
-                 subsection_len = bfd_get_32 (abfd, p);
-                 p += 4;
-               }
-             else
-               {
-                 p = p_end;
-                 break;
-               }
-             if (subsection_len > section_len)
-               subsection_len = section_len;
-             section_len -= subsection_len;
-             end = orig_p + subsection_len;
-             if (end < p)
-               break;
-             switch (tag)
-               {
-               case Tag_File:
-                 while (p < end)
-                   {
-                     int type;
-                     bool ok = false;
-
-                     tag = _bfd_safe_read_leb128 (abfd, &p, false, end);
-                     type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
-                     switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
-                       {
-                       case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
-                         val = _bfd_safe_read_leb128 (abfd, &p, false, end);
-                         ok = elf_add_obj_attr_int_string (abfd, vendor, tag,
-                                                           val, (char *) p,
-                                                           (char *) end);
-                         p += strnlen ((char *) p, end - p);
-                         if (p < end)
-                           p++;
-                         break;
-                       case ATTR_TYPE_FLAG_STR_VAL:
-                         ok = elf_add_obj_attr_string (abfd, vendor, tag,
-                                                       (char *) p,
-                                                       (char *) end);
-                         p += strnlen ((char *) p, end - p);
-                         if (p < end)
-                           p++;
-                         break;
-                       case ATTR_TYPE_FLAG_INT_VAL:
-                         val = _bfd_safe_read_leb128 (abfd, &p, false, end);
-                         ok = bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
-                         break;
-                       default:
-                         abort ();
-                       }
-                     if (!ok)
-                       bfd_perror (_("error adding attribute"));
-                   }
-                 break;
-               case Tag_Section:
-               case Tag_Symbol:
-                 /* Don't have anywhere convenient to attach these.
-                    Fall through for now.  */
-               default:
-                 /* Ignore things we don't know about.  */
-                 p = end;
-                 break;
-               }
-           }
-       }
-    }
-  free (contents);
+  unsigned char *cursor = data;
+
+  /* The first character is the version of the attributes.
+     Currently only version 'A' is recognised here.  */
+  if (*cursor != 'A')
+  {
+    _bfd_error_handler (_("%pB: error: unknown attributes version '%c'(%d) "
+                         "- expecting 'A'\n"), abfd, *cursor, *cursor);
+    bfd_set_error (bfd_error_wrong_format);
+    goto free_data;
+  }
+
+  ++cursor;
+
+  bfd_elf_parse_attr_section_v1 (abfd, hdr, cursor);
+
+free_data:
+  free (data);
 }
 
 /* Merge common object attributes from IBFD into OBFD.  Raise an error