[PATCH 2/5] readelf: fold get_{32,64}bit_section_headers()

Jan Beulich <[email protected]> Mon, 27 Jul 2026 11:19:40 +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.

Sadly the placement of the recently added validate_section_info() now
requires a forward declaration.

--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -7368,6 +7368,10 @@ process_file_header (Filedata * filedata
   return true;
 }
 
+static void
+validate_section_info (Elf_Internal_Shdr *, Elf_Internal_Shdr **,
+		       unsigned int, Filedata *);
+
 #define ElfXX(n) Elf32 ## n
 #include "readelf.c"
 #define ElfXX(n) Elf64 ## n
@@ -7909,14 +7913,16 @@ validate_section_info (Elf_Internal_Shdr
     }
 }
 
+#else /* ElfXX */
+
 /* Allocate memory and load the sections headers into FILEDATA->filedata->section_headers.
    If PROBE is true, this is just a probe and we do not generate any error
    messages if the load fails.  */
 
 static bool
-get_32bit_section_headers (Filedata * filedata, bool probe)
+ElfXX(_get_section_headers) (Filedata * filedata, bool probe)
 {
-  Elf32_External_Shdr * shdrs;
+  ElfXX(_External_Shdr) * shdrs;
   Elf_Internal_Shdr *   internal;
   Elf_Internal_Shdr **  orig_internal;
   unsigned int          i;
@@ -7942,9 +7948,8 @@ get_32bit_section_headers (Filedata * fi
   if (!probe && size > sizeof * shdrs)
     warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n"));
 
-  shdrs = (Elf32_External_Shdr *) get_data (NULL, filedata, filedata->file_header.e_shoff,
-                                            size, num,
-					    probe ? NULL : _("section headers"));
+  shdrs = get_data (NULL, filedata, filedata->file_header.e_shoff, size, num,
+		    probe ? NULL : _("section headers"));
   if (shdrs == NULL)
     return false;
 
@@ -7985,81 +7990,9 @@ get_32bit_section_headers (Filedata * fi
   return true;
 }
 
-/* Like get_32bit_section_headers, except that it fetches 64-bit headers.  */
-
-static bool
-get_64bit_section_headers (Filedata * filedata, bool probe)
-{
-  Elf64_External_Shdr *  shdrs;
-  Elf_Internal_Shdr *    internal;
-  Elf_Internal_Shdr **   orig_internal;
-  unsigned int           i;
-  unsigned int           size = filedata->file_header.e_shentsize;
-  unsigned int           num = probe ? 1 : filedata->file_header.e_shnum;
-
-  /* PR binutils/17531: Cope with unexpected section header sizes.  */
-  if (size == 0 || num == 0)
-    return false;
-
-  /* The section header cannot be at the start of the file - that is
-     where the ELF file header is located.  A file with absolutely no
-     sections in it will use a shoff of 0.  */
-  if (filedata->file_header.e_shoff == 0)
-    return false;
-
-  if (size < sizeof * shdrs)
-    {
-      if (! probe)
-	error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n"));
-      return false;
-    }
-
-  if (! probe && size > sizeof * shdrs)
-    warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n"));
-
-  shdrs = (Elf64_External_Shdr *) get_data (NULL, filedata,
-					    filedata->file_header.e_shoff,
-                                            size, num,
-					    probe ? NULL : _("section headers"));
-  if (shdrs == NULL)
-    return false;
-
-  filedata->section_headers = (Elf_Internal_Shdr *)
-    cmalloc (num, sizeof (Elf_Internal_Shdr));
-  if (filedata->section_headers == NULL)
-    {
-      if (! probe)
-	error (_("Out of memory reading %u section headers\n"), num);
-      free (shdrs);
-      return false;
-    }
-
-  if (!probe)
-    filedata->orig_section_headers = xcalloc2 (num,
-					       sizeof (Elf_Internal_Shdr *));
-
-  orig_internal = filedata->orig_section_headers;
-  for (i = 0, internal = filedata->section_headers;
-       i < num;
-       i++, internal++, orig_internal++)
-    {
-      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
-      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
-      internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
-      internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
-      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
-      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
-      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
-      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
-      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
-      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
-      if (!probe)
-	validate_section_info (internal, orig_internal, i, filedata);
-    }
+#endif /* ElfXX */
 
-  free (shdrs);
-  return true;
-}
+#ifndef ElfXX
 
 static bool
 get_section_headers (Filedata *filedata, bool probe)
@@ -8068,9 +8001,9 @@ get_section_headers (Filedata *filedata,
     return true;
 
   if (is_32bit_elf)
-    return get_32bit_section_headers (filedata, probe);
+    return Elf32_get_section_headers (filedata, probe);
   else
-    return get_64bit_section_headers (filedata, probe);
+    return Elf64_get_section_headers (filedata, probe);
 }
 
 static Elf_Internal_Sym *