From ecd12bc14d85421fcf992cda5af1d534cc8736e0 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 19 Jan 2010 13:50:55 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 9 ++++++++ bfd/elfcode.h | 17 +++++++++++++-- bfd/elfcore.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 18019121d29..3f68528bf58 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2010-01-19 Daisuke Hatayama + Alan Modra + + * 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. + 2010-01-19 Matthew Gretton-Dann * elf32-arm.c (elf32_arm_howto_table_1): Correct bitsize of diff --git a/bfd/elfcode.h b/bfd/elfcode.h index ecdc2de5b46..07ad3c92e51 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -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)) diff --git a/bfd/elfcore.h b/bfd/elfcore.h index c51c575606d..168c81ae21b 100644 --- a/bfd/elfcore.h +++ b/bfd/elfcore.h @@ -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; -- 2.30.2