[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