aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elf-bfd.h7
-rw-r--r--bfd/elf32-arm.c14
-rw-r--r--bfd/elflink.c21
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);