aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2012-05-16 03:35:29 +0000
committerAlan Modra <amodra@gmail.com>2012-05-16 03:35:29 +0000
commiteee3b786492c6a4564515f3a0ae4029645d73a01 (patch)
treed02095282fd5fd217aabbc5891744263da81464f
parent83e56e63c27c2d5293ae41d06a150c5a411f249f (diff)
downloadfsf-binutils-gdb-eee3b786492c6a4564515f3a0ae4029645d73a01.zip
fsf-binutils-gdb-eee3b786492c6a4564515f3a0ae4029645d73a01.tar.gz
fsf-binutils-gdb-eee3b786492c6a4564515f3a0ae4029645d73a01.tar.bz2
PR ld/13962
PR ld/7023 * elf.c (bfd_section_from_shdr): Fail when .dynsym sh_info is out of range. As a special case, fix sh_info for zero sh_size. Do the same for .symtab.
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf.c20
2 files changed, 27 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 05bc0de..34bee4f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2012-05-16 Alan Modra <amodra@gmail.com>
+
+ PR ld/13962
+ PR ld/7023
+ * elf.c (bfd_section_from_shdr): Fail when .dynsym sh_info is
+ out of range. As a special case, fix sh_info for zero sh_size.
+ Do the same for .symtab.
+
2012-05-15 James Murray <jsm@jsm-net.demon.co.uk>
Stephane Carrez <stcarrez@nerim.fr>
diff --git a/bfd/elf.c b/bfd/elf.c
index 9481c0e..7acf142 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1646,7 +1646,15 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
- return FALSE;
+ {
+ if (hdr->sh_size != 0)
+ return FALSE;
+ /* Some assemblers erroneously set sh_info to one with a
+ zero sh_size. ld sees this as a global symbol count
+ of (unsigned) -1. Fix it here. */
+ hdr->sh_info = 0;
+ return TRUE;
+ }
BFD_ASSERT (elf_onesymtab (abfd) == 0);
elf_onesymtab (abfd) = shindex;
elf_tdata (abfd)->symtab_hdr = *hdr;
@@ -1699,6 +1707,16 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
+ if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+ {
+ if (hdr->sh_size != 0)
+ return FALSE;
+ /* Some linkers erroneously set sh_info to one with a
+ zero sh_size. ld sees this as a global symbol count
+ of (unsigned) -1. Fix it here. */
+ hdr->sh_info = 0;
+ return TRUE;
+ }
BFD_ASSERT (elf_dynsymtab (abfd) == 0);
elf_dynsymtab (abfd) = shindex;
elf_tdata (abfd)->dynsymtab_hdr = *hdr;