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

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.