diff options
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 7 | ||||
-rw-r--r-- | bfd/elf32-arm.c | 14 | ||||
-rw-r--r-- | bfd/elflink.c | 21 |
4 files changed, 41 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9841e5d..7cbe0a2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2009-03-13 Nick Clifton <nickc@redhat.com> + + PR 9934 + * elf-bfd.h (NUM_SHDR_ENTRIES): Cope with an empty section. + * elflink.c (elf_link_read_relocs_from_section): Use + NUM_SHDR_ENTRIES. Gracefully handle the case where there are + relocs but no symbol table. + * elf32-arm.c (elf32_arm_check_relocs): Likewise. + 2009-03-12 H.J. Lu <hongjiu.lu@intel.com> PR ld/9938 diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 7b8fa69..865388c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -31,8 +31,11 @@ /* The number of entries in a section is its size divided by the size of a single entry. This is normally only applicable to reloc and - symbol table sections. */ -#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_size / (shdr)->sh_entsize) + symbol table sections. + PR 9934: It is possible to have relocations that do not refer to + symbols, thus it is also possible to have a relocation section in + an object file, but no symbol table. */ +#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_entsize > 0 ? (shdr)->sh_size / (shdr)->sh_entsize : 0) /* If size isn't specified as 64 or 32, NAME macro should fail. */ #ifndef NAME diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index f534290..226434a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -9597,6 +9597,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, bfd_vma *local_got_offsets; struct elf32_arm_link_hash_table *htab; bfd_boolean needs_plt; + unsigned long nsyms; if (info->relocatable) return TRUE; @@ -9620,7 +9621,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, symtab_hdr = & elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); - + nsyms = NUM_SHDR_ENTRIES (symtab_hdr); + rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { @@ -9633,14 +9635,18 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, r_type = ELF32_R_TYPE (rel->r_info); r_type = arm_real_reloc_type (htab, r_type); - if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) + if (r_symndx >= nsyms + /* PR 9934: It is possible to have relocations that do not + refer to symbols, thus it is also possible to have an + object file containing relocations but no symbol table. */ + && (r_symndx > 0 || nsyms > 0)) { (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd, - r_symndx); + r_symndx); return FALSE; } - if (r_symndx < symtab_hdr->sh_info) + if (nsyms == 0 || r_symndx < symtab_hdr->sh_info) h = NULL; else { diff --git a/bfd/elflink.c b/bfd/elflink.c index d0e4534..c635cb0 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2202,7 +2202,7 @@ elf_link_read_relocs_from_section (bfd *abfd, return FALSE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - nsyms = symtab_hdr->sh_size / symtab_hdr->sh_entsize; + nsyms = NUM_SHDR_ENTRIES (symtab_hdr); bed = get_elf_backend_data (abfd); @@ -2228,11 +2228,24 @@ elf_link_read_relocs_from_section (bfd *abfd, r_symndx = ELF32_R_SYM (irela->r_info); if (bed->s->arch_size == 64) r_symndx >>= 24; - if ((size_t) r_symndx >= nsyms) + if (nsyms > 0) + { + if ((size_t) r_symndx >= nsyms) + { + (*_bfd_error_handler) + (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)" + " for offset 0x%lx in section `%A'"), + abfd, sec, + (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } + else if (r_symndx != 0) { (*_bfd_error_handler) - (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)" - " for offset 0x%lx in section `%A'"), + (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'" + " when the object file has no symbol table"), abfd, sec, (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset); bfd_set_error (bfd_error_bad_value); |