[RFC][PATCH v2 0/4] readelf and libbfd: Add Extended Numbering Support for ELF corefiles
Alan Modra
amodra@gmail.com
Tue Jan 19 13:52:00 GMT 2010
This is the patch I applied. Handles e_phnum extension in executables
as well as cores, and differs from your version in the treatment of
e_phnum == 0xffff with the first section header sh_info zero. For
backwards compatibility, I think this ought to be taken as 0xffff
program headers, not zero (or 4G) program headers.
include/elf/
2010-01-19 Daisuke Hatayama <d.hatayama@jp.fujitsu.com>
* common.h (PN_XNUM): Define.
bfd/
2010-01-19 Daisuke Hatayama <d.hatayama@jp.fujitsu.com>
Alan Modra <amodra@gmail.com>
* elfcode.h (elf_swap_ehdr_out): Handle e_phnum > 0xffff.
(elf_object_p): Read e_phnum extension.
(elf_write_shdrs_and_ehdr): Write e_phnum extension.
* elfcore.h (elf_core_file_p): Read e_phnum extension. Sanity check
that we can read last program header.
binutils/
2010-01-19 Daisuke Hatayama <d.hatayama@jp.fujitsu.com>
Alan Modra <amodra@gmail.com>
* readelf.c (process_file_header): Handle e_phnum extension.
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.118
diff -u -p -r1.118 common.h
--- include/elf/common.h 18 Dec 2009 16:21:51 -0000 1.118
+++ include/elf/common.h 19 Jan 2010 13:46:23 -0000
@@ -1,6 +1,6 @@
/* ELF support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
@@ -405,6 +405,9 @@
#define EV_NONE 0 /* Invalid ELF version */
#define EV_CURRENT 1 /* Current version */
+/* Value for e_phnum. */
+#define PN_XNUM 0xffff /* Extended numbering */
+
/* Values for program header, p_type field. */
#define PT_NULL 0 /* Program header table entry unused */
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.98
diff -u -p -r1.98 elfcode.h
--- bfd/elfcode.h 28 Sep 2009 09:45:33 -0000 1.98
+++ bfd/elfcode.h 19 Jan 2010 12:04:15 -0000
@@ -1,6 +1,6 @@
/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
@@ -279,7 +279,10 @@ elf_swap_ehdr_out (bfd *abfd,
H_PUT_32 (abfd, src->e_flags, dst->e_flags);
H_PUT_16 (abfd, src->e_ehsize, dst->e_ehsize);
H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
- H_PUT_16 (abfd, src->e_phnum, dst->e_phnum);
+ tmp = src->e_phnum;
+ if (tmp > PN_XNUM)
+ tmp = PN_XNUM;
+ H_PUT_16 (abfd, tmp, dst->e_phnum);
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
tmp = src->e_shnum;
if (tmp >= (SHN_LORESERVE & 0xffff))
@@ -701,6 +704,14 @@ elf_object_p (bfd *abfd)
goto got_wrong_format_error;
}
+ /* And program headers. */
+ if (i_ehdrp->e_phnum == PN_XNUM && i_shdr.sh_info != 0)
+ {
+ i_ehdrp->e_phnum = i_shdr.sh_info;
+ if (i_ehdrp->e_phnum != i_shdr.sh_info)
+ goto got_wrong_format_error;
+ }
+
/* Sanity check that we can read all of the section headers.
It ought to be good enough to just read the last one. */
if (i_ehdrp->e_shnum != 1)
@@ -1072,6 +1083,8 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
/* Some fields in the first section header handle overflow of ehdr
fields. */
+ if (i_ehdrp->e_phnum >= PN_XNUM)
+ i_shdrp[0]->sh_info = i_ehdrp->e_phnum;
if (i_ehdrp->e_shnum >= (SHN_LORESERVE & 0xffff))
i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
if (i_ehdrp->e_shstrndx >= (SHN_LORESERVE & 0xffff))
Index: bfd/elfcore.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcore.h,v
retrieving revision 1.29
diff -u -p -r1.29 elfcore.h
--- bfd/elfcore.h 9 Sep 2009 21:38:57 -0000 1.29
+++ bfd/elfcore.h 19 Jan 2010 12:04:15 -0000
@@ -1,6 +1,6 @@
/* ELF core file support for BFD.
Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2010 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -184,6 +184,61 @@ elf_core_file_p (bfd *abfd)
if (i_ehdrp->e_phentsize != sizeof (Elf_External_Phdr))
goto wrong;
+ /* If the program header count is PN_XNUM(0xffff), the actual
+ count is in the first section header. */
+ if (i_ehdrp->e_shoff != 0 && i_ehdrp->e_phnum == PN_XNUM)
+ {
+ Elf_External_Shdr x_shdr;
+ Elf_Internal_Shdr i_shdr;
+ bfd_signed_vma where = i_ehdrp->e_shoff;
+
+ if (where != (file_ptr) where)
+ goto wrong;
+
+ /* Seek to the section header table in the file. */
+ if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
+ goto fail;
+
+ /* Read the first section header at index 0, and convert to internal
+ form. */
+ if (bfd_bread (&x_shdr, sizeof (x_shdr), abfd) != sizeof (x_shdr))
+ goto fail;
+ elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
+
+ if (i_shdr.sh_info != 0)
+ {
+ i_ehdrp->e_phnum = i_shdr.sh_info;
+ if (i_ehdrp->e_phnum != i_shdr.sh_info)
+ goto wrong;
+ }
+ }
+
+ /* Sanity check that we can read all of the program headers.
+ It ought to be good enough to just read the last one. */
+ if (i_ehdrp->e_phnum > 1)
+ {
+ Elf_External_Phdr x_phdr;
+ Elf_Internal_Phdr i_phdr;
+ bfd_signed_vma where;
+
+ /* Check that we don't have a totally silly number of
+ program headers. */
+ if (i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (x_phdr)
+ || i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (i_phdr))
+ goto wrong;
+
+ where = i_ehdrp->e_phoff + (i_ehdrp->e_phnum - 1) * sizeof (x_phdr);
+ if (where != (file_ptr) where)
+ goto wrong;
+ if ((bfd_size_type) where <= i_ehdrp->e_phoff)
+ goto wrong;
+
+ if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
+ goto fail;
+ if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
+ goto fail;
+ }
+
/* Move to the start of the program headers. */
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
goto wrong;
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.480
diff -u -p -r1.480 readelf.c
--- binutils/readelf.c 11 Jan 2010 14:45:41 -0000 1.480
+++ binutils/readelf.c 19 Jan 2010 13:30:27 -0000
@@ -3340,8 +3340,13 @@ process_file_header (void)
(long) elf_header.e_ehsize);
printf (_(" Size of program headers: %ld (bytes)\n"),
(long) elf_header.e_phentsize);
- printf (_(" Number of program headers: %ld\n"),
+ printf (_(" Number of program headers: %ld"),
(long) elf_header.e_phnum);
+ if (section_headers != NULL
+ && elf_header.e_phnum == PN_XNUM
+ && section_headers[0].sh_info != 0)
+ printf (_(" (%ld)"), (long) section_headers[0].sh_info);
+ putc ('\n', stdout);
printf (_(" Size of section headers: %ld (bytes)\n"),
(long) elf_header.e_shentsize);
printf (_(" Number of section headers: %ld"),
@@ -3362,6 +3367,9 @@ process_file_header (void)
if (section_headers != NULL)
{
+ if (elf_header.e_phnum == PN_XNUM
+ && section_headers[0].sh_info != 0)
+ elf_header.e_phnum = section_headers[0].sh_info;
if (elf_header.e_shnum == SHN_UNDEF)
elf_header.e_shnum = section_headers[0].sh_size;
if (elf_header.e_shstrndx == (SHN_XINDEX & 0xffff))
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list