[PATCH 1/5] readelf: Consolidate get_[32|64]bit_section_headers

H.J. Lu hjl.tools@gmail.com
Thu Jul 9 12:40:48 GMT 2026


Consolidate get_32bit_section_headers and get_64bit_section_headers into
get_section_headers.  Use BYTE_GET_SIZE to retrieve external ELF section
header fields.

	PR binutils/34356
	* elfcomm.h (BYTE_GET_SIZE): New.
	* readelf.c (get_32bit_section_headers): Moved to ...
	(get_section_headers): This.  Use BYTE_GET_SIZE to retrieve
	external ELF section header fields.
	(get_64bit_section_headers): Removed.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 binutils/elfcomm.h |   6 ++
 binutils/readelf.c | 146 ++++++++++++---------------------------------
 2 files changed, 43 insertions(+), 109 deletions(-)

diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h
index 953bc3d1bc3..30d6e3bf732 100644
--- a/binutils/elfcomm.h
+++ b/binutils/elfcomm.h
@@ -43,6 +43,12 @@ extern uint64_t byte_get_big_endian (const unsigned char *, unsigned int);
 #define BYTE_GET(field)		byte_get (field, sizeof (field))
 #define BYTE_GET_SIGNED(field)	byte_get_signed (field, sizeof (field))
 
+#define BYTE_GET_SIZE(var, ptr, size) \
+  { \
+    (var) = byte_get (ptr, (size)); \
+    ptr += (size); \
+  }
+
 /* This is just a bit of syntatic sugar.  */
 #define streq(a,b)	  (strcmp ((a), (b)) == 0)
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 0938fe64b22..16480340b4d 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -7984,14 +7984,13 @@ validate_section_info (Elf_Internal_Shdr *internal,
    messages if the load fails.  */
 
 static bool
-get_32bit_section_headers (Filedata * filedata, bool probe)
+get_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;
+  if (filedata->section_headers != NULL)
+    return true;
+
+  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)
@@ -8003,18 +8002,27 @@ get_32bit_section_headers (Filedata * filedata, bool probe)
   if (filedata->file_header.e_shoff == 0)
     return false;
 
-  if (size < sizeof * shdrs)
+  unsigned int sizeof_External_Shdr;
+  if (is_32bit_elf)
+    sizeof_External_Shdr = sizeof (Elf32_External_Shdr);
+  else
+    sizeof_External_Shdr = sizeof (Elf64_External_Shdr);
+
+  if (size < sizeof_External_Shdr)
     {
       if (! probe)
-	error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n"));
+	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 (! probe && size > sizeof_External_Shdr)
+    warn (_("The e_shentsize field in the ELF header is larger "
+	    "than the size of an ELF section header\n"));
+
+  void *shdrs = get_data (NULL, filedata, filedata->file_header.e_shoff,
+			  size, num,
+			  probe ? NULL : _("section headers"));
   if (shdrs == NULL)
     return false;
 
@@ -8031,96 +8039,28 @@ get_32bit_section_headers (Filedata * filedata, bool probe)
   filedata->orig_section_headers = (Elf_Internal_Shdr **)
     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);
-      validate_section_info (internal, orig_internal, i, filedata,
-			     false, probe);
-    }
-
-  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"));
+  void *ptr = shdrs;
+  uint32_t elf_class_size = is_32bit_elf ? 4 : 8;
 
-  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;
-    }
-
-  filedata->orig_section_headers = (Elf_Internal_Shdr **)
-    xcalloc2 (num, sizeof (Elf_Internal_Shdr *));
+  Elf_Internal_Shdr *internal;
+  Elf_Internal_Shdr **orig_internal;
+  unsigned int i;
 
   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);
+      BYTE_GET_SIZE (internal->sh_name, ptr, 4);
+      BYTE_GET_SIZE (internal->sh_type, ptr, 4);
+      BYTE_GET_SIZE (internal->sh_flags, ptr, elf_class_size);
+      BYTE_GET_SIZE (internal->sh_addr, ptr, elf_class_size);
+      BYTE_GET_SIZE (internal->sh_offset, ptr, elf_class_size);
+      BYTE_GET_SIZE (internal->sh_size, ptr, elf_class_size);
+      BYTE_GET_SIZE (internal->sh_link, ptr, 4);
+      BYTE_GET_SIZE (internal->sh_info, ptr, 4);
+      BYTE_GET_SIZE (internal->sh_addralign, ptr, elf_class_size);
+      BYTE_GET_SIZE (internal->sh_entsize, ptr, elf_class_size);
       validate_section_info (internal, orig_internal, i, filedata,
 			     false, probe);
     }
@@ -8129,18 +8069,6 @@ get_64bit_section_headers (Filedata * filedata, bool probe)
   return true;
 }
 
-static bool
-get_section_headers (Filedata *filedata, bool probe)
-{
-  if (filedata->section_headers != NULL)
-    return true;
-
-  if (is_32bit_elf)
-    return get_32bit_section_headers (filedata, probe);
-  else
-    return get_64bit_section_headers (filedata, probe);
-}
-
 static Elf_Internal_Sym *
 get_32bit_elf_symbols (Filedata *filedata,
 		       Elf_Internal_Shdr *section,
-- 
2.55.0



More information about the Binutils mailing list