[binutils-gdb] readelf: fold get_{32,64}bit_section_headers()

Jan Beulich jbeulich@sourceware.org
Fri Aug 14 08:58:48 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=75e32f7588d09b0a99835647c5d560675909d462

commit 75e32f7588d09b0a99835647c5d560675909d462
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Aug 14 10:54:35 2026 +0200

    readelf: fold get_{32,64}bit_section_headers()
    
    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.

Diff:
---
 binutils/readelf-nn.c |  75 +++++++++++++++++++++++
 binutils/readelf.c    | 160 ++------------------------------------------------
 2 files changed, 81 insertions(+), 154 deletions(-)

diff --git a/binutils/readelf-nn.c b/binutils/readelf-nn.c
index 07639d7881f..f86f6eeeb78 100644
--- a/binutils/readelf-nn.c
+++ b/binutils/readelf-nn.c
@@ -87,4 +87,79 @@ ElfXX(_get_program_headers) (Filedata * filedata, Elf_Internal_Phdr * pheaders)
   return true;
 }
 
+/* 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
+ElfXX(_get_section_headers) (Filedata * filedata, bool probe)
+{
+  ElfXX(_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 = 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_offset    = BYTE_GET (shdrs[i].sh_offset);
+      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
+      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
+      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
+      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
+      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
+      if (!probe)
+	validate_section_info (internal, orig_internal, i, filedata);
+    }
+
+  free (shdrs);
+  return true;
+}
+
 #undef ElfXX
diff --git a/binutils/readelf.c b/binutils/readelf.c
index e34db4d0cca..31cb14a06b0 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -3469,6 +3469,10 @@ get_dynamic_type (Filedata * filedata, unsigned long type)
     }
 }
 
+static void
+validate_section_info (Elf_Internal_Shdr *, Elf_Internal_Shdr **,
+		       unsigned int, Filedata *);
+
 #define ElfXX(n) Elf32 ## n
 #include "readelf-nn.c"
 #define ElfXX(n) Elf64 ## n
@@ -7855,158 +7859,6 @@ validate_section_info (Elf_Internal_Shdr *internal,
     }
 }
 
-/* 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)
-{
-  Elf32_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 = (Elf32_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_offset    = BYTE_GET (shdrs[i].sh_offset);
-      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
-      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
-      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
-      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
-      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
-      if (!probe)
-	validate_section_info (internal, orig_internal, i, filedata);
-    }
-
-  free (shdrs);
-  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);
-    }
-
-  free (shdrs);
-  return true;
-}
-
 static bool
 get_section_headers (Filedata *filedata, bool probe)
 {
@@ -8014,9 +7866,9 @@ get_section_headers (Filedata *filedata, bool probe)
     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 *


More information about the Binutils-cvs mailing list