This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix handling of ELF objects without section header table


Hi!

The 64K+ sections patches caused segfaults and weird data shown when
handling files with no section header table at all.
http://www.caldera.com/developers/gabi/2001-04-24/ch4.eheader.html
says:
   e_shoff
           This member holds the section header table's file offset in bytes. If the file has no section header table, this
           member holds zero.
...
   e_shnum
           This member holds the number of entries in the section header table. Thus the product of e_shentsize and e_shnum
           gives the section header table's size in bytes. If a file has no section header table, e_shnum holds the value
           zero.

           If the number of sections is greater than or equal to SHN_LORESERVE (0xff00), this member has the value zero and
           the actual number of section header table entries is contained in the sh_size field of the section header at index
           0. (Otherwise, the sh_size member of the initial entry contains 0.)

>From this, I think the right behaviour is:
e_shoff == 0 && e_shnum == 0 -> no sections
e_shoff != 0 && e_shnum == 0 -> e_shnum = ((ElfW(Shdr) *)(char *)ehdrp + e_shoff)->sh_size
				(and if even that is 0, no sections)
otherwise e_shnum is the number of sections.

Here is a patch, ok to commit?

I've also a check for e_shoff != 0 to e_shstrndx handling, although using
e_shstrndx != 0 if e_shnum == 0 is probably a bug, it happens in real world files
(I got one from Red Hat bugzilla report) and we don't need it for anything anyway
if there is no section table.

2002-06-18  Jakub Jelinek  <jakub@redhat.com>

binutils/
	* readelf.c (get_file_header): Only read the first section header if
	e_shoff is non-zero.

bfd/
	* elfcode.h (elf_object_p): Sanity check eh_shoff == 0 implies
	e_shnum == 0.
	Only read the first section header if e_shoff is non-zero.
	Don't consider e_shstrndx if there are no sections.

--- binutils/readelf.c.jj	Tue Jun 18 09:59:35 2002
+++ binutils/readelf.c	Tue Jun 18 10:40:57 2002
@@ -9711,12 +9711,15 @@ get_file_header (file)
       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
     }
 
-  /* There may be some extensions in the first section header.  Don't
-     bomb if we can't read it.  */
-  if (is_32bit_elf)
-    get_32bit_section_headers (file, 1);
-  else
-    get_64bit_section_headers (file, 1);
+  if (elf_header.e_shoff)
+    {
+      /* There may be some extensions in the first section header.  Don't
+	 bomb if we can't read it.  */
+      if (is_32bit_elf)
+	get_32bit_section_headers (file, 1);
+      else
+	get_64bit_section_headers (file, 1);
+    }
 
   return 1;
 }
--- bfd/elfcode.h.jj	Tue Jun 18 09:58:53 2002
+++ bfd/elfcode.h	Tue Jun 18 11:03:00 2002
@@ -624,6 +624,10 @@ elf_object_p (abfd)
   if (i_ehdrp->e_shentsize != sizeof (x_shdr) && i_ehdrp->e_shnum != 0)
     goto got_wrong_format_error;
 
+  /* Further sanity check.  */
+  if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0)
+    goto got_wrong_format_error;
+
   ebd = get_elf_backend_data (abfd);
 
   /* Check that the ELF e_machine field matches what this particular
@@ -677,25 +681,28 @@ elf_object_p (abfd)
   /* Remember the entry point specified in the ELF file header.  */
   bfd_set_start_address (abfd, i_ehdrp->e_entry);
 
-  /* Seek to the section header table in the file.  */
-  if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
-    goto got_no_match;
-
-  /* Read the first section header at index 0, and convert to internal
-     form.  */
-  if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
-      != sizeof (x_shdr))
-    goto got_no_match;
-  elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
-
-  /* If the section count is zero, the actual count is in the first
-     section header.  */
-  if (i_ehdrp->e_shnum == SHN_UNDEF)
-    i_ehdrp->e_shnum = i_shdr.sh_size;
-
-  /* And similarly for the string table index.  */
-  if (i_ehdrp->e_shstrndx == SHN_XINDEX)
-    i_ehdrp->e_shstrndx = i_shdr.sh_link;
+  if (i_ehdrp->e_shoff != 0)
+    {
+      /* Seek to the section header table in the file.  */
+      if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
+	goto got_no_match;
+
+      /* Read the first section header at index 0, and convert to internal
+	 form.  */
+      if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
+	  != sizeof (x_shdr))
+	goto got_no_match;
+      elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
+
+      /* If the section count is zero, the actual count is in the first
+	 section header.  */
+      if (i_ehdrp->e_shnum == SHN_UNDEF)
+	i_ehdrp->e_shnum = i_shdr.sh_size;
+
+      /* And similarly for the string table index.  */
+      if (i_ehdrp->e_shstrndx == SHN_XINDEX)
+	i_ehdrp->e_shstrndx = i_shdr.sh_link;
+    }
 
   /* Allocate space for a copy of the section header table in
      internal form.  */
@@ -751,7 +758,7 @@ elf_object_p (abfd)
 	}
     }
 
-  if (i_ehdrp->e_shstrndx)
+  if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff)
     {
       if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx))
 	goto got_no_match;
@@ -789,7 +796,7 @@ elf_object_p (abfd)
      bfd_section_from_shdr with it (since this particular strtab is
      used to find all of the ELF section names.) */
 
-  if (i_ehdrp->e_shstrndx != 0)
+  if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff)
     {
       unsigned int num_sec;
 

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]