[PATCH v2 3/5] readelf: fold get_{32,64}bit_elf_symbols()

Jan Beulich <[email protected]> Fri, 31 Jul 2026 14:11:18 +0200
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
PR binutils/34356

They're identical except for the types used and the order of fields
processed. The latter doesn't matter for correctness, and the former can
be addressed by compiling the same code twice.
---
v2: Use new file readelf-nn.c.

--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -7871,250 +7871,14 @@ get_section_headers (Filedata *filedata,
 }
 
 static Elf_Internal_Sym *
-get_32bit_elf_symbols (Filedata *filedata,
-		       Elf_Internal_Shdr *section,
-		       uint64_t *num_syms_return)
-{
-  uint64_t number = 0;
-  Elf32_External_Sym * esyms = NULL;
-  Elf_External_Sym_Shndx * shndx = NULL;
-  Elf_Internal_Sym * isyms = NULL;
-  Elf_Internal_Sym * psym;
-  unsigned int j;
-  elf_section_list * entry;
-
-  if (section->sh_size == 0)
-    {
-      if (num_syms_return != NULL)
-	* num_syms_return = 0;
-      return NULL;
-    }
-
-  /* Run some sanity checks first.  */
-  if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size)
-    {
-      error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"),
-	     printable_section_name (filedata, section),
-	     section->sh_entsize);
-      goto exit_point;
-    }
-
-  if (section->sh_size > filedata->file_size)
-    {
-      error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"),
-	     printable_section_name (filedata, section),
-	     section->sh_size);
-      goto exit_point;
-    }
-
-  number = section->sh_size / section->sh_entsize;
-
-  if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
-    {
-      error (_("Size (%#" PRIx64 ") of section %s "
-	       "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"),
-	     section->sh_size,
-	     printable_section_name (filedata, section),
-	     section->sh_entsize);
-      goto exit_point;
-    }
-
-  esyms = (Elf32_External_Sym *) get_data (NULL, filedata, section->sh_offset, 1,
-                                           section->sh_size, _("symbols"));
-  if (esyms == NULL)
-    goto exit_point;
-
-  shndx = NULL;
-  for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next)
-    {
-      if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers))
-	continue;
-
-      if (shndx != NULL)
-	{
-	  error (_("Multiple symbol table index sections associated with the same symbol section\n"));
-	  free (shndx);
-	}
-
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
-						   entry->hdr->sh_offset,
-						   1, entry->hdr->sh_size,
-						   _("symbol table section indices"));
-      if (shndx == NULL)
-	goto exit_point;
-
-      /* PR17531: file: heap-buffer-overflow */
-      if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-	{
-	  error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"),
-		 printable_section_name (filedata, entry->hdr),
-		 entry->hdr->sh_size,
-		 section->sh_size);
-	  goto exit_point;
-	}
-    }
-
-  isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
-
-  if (isyms == NULL)
-    {
-      error (_("Out of memory reading %" PRIu64 " symbols\n"), number);
-      goto exit_point;
-    }
-
-  for (j = 0, psym = isyms; j < number; j++, psym++)
-    {
-      psym->st_name  = BYTE_GET (esyms[j].st_name);
-      psym->st_value = BYTE_GET (esyms[j].st_value);
-      psym->st_size  = BYTE_GET (esyms[j].st_size);
-      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
-      if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
-	psym->st_shndx
-	  = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
-      else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
-	psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
-      psym->st_info  = BYTE_GET (esyms[j].st_info);
-      psym->st_other = BYTE_GET (esyms[j].st_other);
-    }
-
- exit_point:
-  free (shndx);
-  free (esyms);
-
-  if (num_syms_return != NULL)
-    * num_syms_return = isyms == NULL ? 0 : number;
-
-  return isyms;
-}
-
-static Elf_Internal_Sym *
-get_64bit_elf_symbols (Filedata *filedata,
-		       Elf_Internal_Shdr *section,
-		       uint64_t *num_syms_return)
-{
-  uint64_t number = 0;
-  Elf64_External_Sym * esyms = NULL;
-  Elf_External_Sym_Shndx * shndx = NULL;
-  Elf_Internal_Sym * isyms = NULL;
-  Elf_Internal_Sym * psym;
-  unsigned int j;
-  elf_section_list * entry;
-
-  if (section->sh_size == 0)
-    {
-      if (num_syms_return != NULL)
-	* num_syms_return = 0;
-      return NULL;
-    }
-
-  /* Run some sanity checks first.  */
-  if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size)
-    {
-      error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"),
-	     printable_section_name (filedata, section),
-	     section->sh_entsize);
-      goto exit_point;
-    }
-
-  if (section->sh_size > filedata->file_size)
-    {
-      error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"),
-	     printable_section_name (filedata, section),
-	     section->sh_size);
-      goto exit_point;
-    }
-
-  number = section->sh_size / section->sh_entsize;
-
-  if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
-    {
-      error (_("Size (%#" PRIx64 ") of section %s "
-	       "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"),
-	     section->sh_size,
-	     printable_section_name (filedata, section),
-	     section->sh_entsize);
-      goto exit_point;
-    }
-
-  esyms = (Elf64_External_Sym *) get_data (NULL, filedata, section->sh_offset, 1,
-                                           section->sh_size, _("symbols"));
-  if (!esyms)
-    goto exit_point;
-
-  shndx = NULL;
-  for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next)
-    {
-      if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers))
-	continue;
-
-      if (shndx != NULL)
-	{
-	  error (_("Multiple symbol table index sections associated with the same symbol section\n"));
-	  free (shndx);
-	}
-
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
-						   entry->hdr->sh_offset,
-						   1, entry->hdr->sh_size,
-						   _("symbol table section indices"));
-      if (shndx == NULL)
-	goto exit_point;
-
-      /* PR17531: file: heap-buffer-overflow */
-      if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-	{
-	  error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"),
-		 printable_section_name (filedata, entry->hdr),
-		 entry->hdr->sh_size,
-		 section->sh_size);
-	  goto exit_point;
-	}
-    }
-
-  isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
-
-  if (isyms == NULL)
-    {
-      error (_("Out of memory reading %" PRIu64 " symbols\n"), number);
-      goto exit_point;
-    }
-
-  for (j = 0, psym = isyms; j < number; j++, psym++)
-    {
-      psym->st_name  = BYTE_GET (esyms[j].st_name);
-      psym->st_info  = BYTE_GET (esyms[j].st_info);
-      psym->st_other = BYTE_GET (esyms[j].st_other);
-      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
-
-      if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
-	psym->st_shndx
-	  = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
-      else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
-	psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
-
-      psym->st_value = BYTE_GET (esyms[j].st_value);
-      psym->st_size  = BYTE_GET (esyms[j].st_size);
-    }
-
- exit_point:
-  free (shndx);
-  free (esyms);
-
-  if (num_syms_return != NULL)
-    * num_syms_return = isyms == NULL ? 0 : number;
-
-  return isyms;
-}
-
-static Elf_Internal_Sym *
 get_elf_symbols (Filedata *filedata,
 		 Elf_Internal_Shdr *section,
 		 uint64_t *num_syms_return)
 {
   if (is_32bit_elf)
-    return get_32bit_elf_symbols (filedata, section, num_syms_return);
+    return Elf32_get_symbols (filedata, section, num_syms_return);
   else
-    return get_64bit_elf_symbols (filedata, section, num_syms_return);
+    return Elf64_get_symbols (filedata, section, num_syms_return);
 }
 
 static const char *
--- a/binutils/readelf-nn.c
+++ b/binutils/readelf-nn.c
@@ -162,4 +162,122 @@ ElfXX(_get_section_headers) (Filedata *
   return true;
 }
 
+static Elf_Internal_Sym *
+ElfXX(_get_symbols) (Filedata *filedata, const Elf_Internal_Shdr *section,
+		     uint64_t *num_syms_return)
+{
+  uint64_t number = 0;
+  ElfXX(_External_Sym) * esyms = NULL;
+  Elf_External_Sym_Shndx * shndx = NULL;
+  Elf_Internal_Sym * isyms = NULL;
+  Elf_Internal_Sym * psym;
+  unsigned int j;
+  elf_section_list * entry;
+
+  if (section->sh_size == 0)
+    {
+      if (num_syms_return != NULL)
+	* num_syms_return = 0;
+      return NULL;
+    }
+
+  /* Run some sanity checks first.  */
+  if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size)
+    {
+      error (_("Section %s has an invalid sh_entsize of %#" PRIx64 "\n"),
+	     printable_section_name (filedata, section),
+	     section->sh_entsize);
+      goto exit_point;
+    }
+
+  if (section->sh_size > filedata->file_size)
+    {
+      error (_("Section %s has an invalid sh_size of %#" PRIx64 "\n"),
+	     printable_section_name (filedata, section),
+	     section->sh_size);
+      goto exit_point;
+    }
+
+  number = section->sh_size / section->sh_entsize;
+
+  if (number * sizeof (*esyms) > section->sh_size + 1)
+    {
+      error (_("Size (%#" PRIx64 ") of section %s "
+	       "is not a multiple of its sh_entsize (%#" PRIx64 ")\n"),
+	     section->sh_size,
+	     printable_section_name (filedata, section),
+	     section->sh_entsize);
+      goto exit_point;
+    }
+
+  esyms = get_data (NULL, filedata, section->sh_offset, 1, section->sh_size,
+		    _("symbols"));
+  if (esyms == NULL)
+    goto exit_point;
+
+  shndx = NULL;
+  for (entry = filedata->symtab_shndx_list; entry != NULL; entry = entry->next)
+    {
+      if (entry->hdr->sh_link != (size_t) (section - filedata->section_headers))
+	continue;
+
+      if (shndx != NULL)
+	{
+	  error (_("Multiple symbol table index sections associated with the same symbol section\n"));
+	  free (shndx);
+	}
+
+      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
+						   entry->hdr->sh_offset,
+						   1, entry->hdr->sh_size,
+						   _("symbol table section indices"));
+      if (shndx == NULL)
+	goto exit_point;
+
+      /* PR17531: file: heap-buffer-overflow */
+      if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+	{
+	  error (_("Index section %s has an sh_size of %#" PRIx64 " - expected %#" PRIx64 "\n"),
+		 printable_section_name (filedata, entry->hdr),
+		 entry->hdr->sh_size,
+		 section->sh_size);
+	  goto exit_point;
+	}
+    }
+
+  isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
+
+  if (isyms == NULL)
+    {
+      error (_("Out of memory reading %" PRIu64 " symbols\n"), number);
+      goto exit_point;
+    }
+
+  for (j = 0, psym = isyms; j < number; j++, psym++)
+    {
+      psym->st_name  = BYTE_GET (esyms[j].st_name);
+      psym->st_value = BYTE_GET (esyms[j].st_value);
+      psym->st_size  = BYTE_GET (esyms[j].st_size);
+      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+
+      if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
+	psym->st_shndx
+	  = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
+      else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
+	psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
+
+      psym->st_info  = BYTE_GET (esyms[j].st_info);
+      psym->st_other = BYTE_GET (esyms[j].st_other);
+    }
+
+ exit_point:
+  free (shndx);
+  free (esyms);
+
+  if (num_syms_return != NULL)
+    * num_syms_return = isyms == NULL ? 0 : number;
+
+  return isyms;
+}
+
 #undef ElfXX