This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Fix handling of ELF objects without section header table
- From: Jakub Jelinek <jakub at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 18 Jun 2002 11:03:13 +0200
- Subject: [PATCH] Fix handling of ELF objects without section header table
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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