summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf32-sh.c43
2 files changed, 28 insertions, 21 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 15e54dff23..4bbb6c0846 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2000-08-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * elf32-sh.c (sh_elf_relocate_section) [R_SH_IND12W,
+ R_SH_DIR8WPN, R_SH_DIR8WPZ, R_SH_DIR8WPL]: Handle them
+ explicitly. Improve validation of r_type.
+
2000-08-21 H.J. Lu <hjl@gnu.org>
* elf32-i386.c (elf_i386_size_dynamic_sections): Zero out the
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index f1e0027761..9e2d8237ca 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -1884,6 +1884,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
continue;
if (r_type < 0
+ || r_type >= R_SH_max
|| (r_type >= (int) R_SH_FIRST_INVALID_RELOC
&& r_type <= (int) R_SH_LAST_INVALID_RELOC))
{
@@ -1891,14 +1892,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
return false;
}
- /* FIXME: This is certainly incorrect. However, it is how the
- COFF linker works. */
- if (r_type != (int) R_SH_DIR32
- && r_type != (int) R_SH_IND12W
- && r_type != (int) R_SH_LOOP_START
- && r_type != (int) R_SH_LOOP_END)
- continue;
-
howto = sh_elf_howto_table + r_type;
/* This is a final link. */
@@ -1907,11 +1900,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
sec = NULL;
if (r_symndx < symtab_hdr->sh_info)
{
- /* There is nothing to be done for an internal IND12W
- relocation. FIXME: This is probably wrong, but it's how
- the COFF relocations work. */
- if (r_type == (int) R_SH_IND12W)
- continue;
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
relocation = (sec->output_section->vma
@@ -1944,22 +1932,34 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
}
}
- /* FIXME: This is how the COFF relocations work. */
- if (r_type == (int) R_SH_IND12W)
- relocation -= 4;
-
switch ((int)r_type)
{
- case (int)R_SH_DIR32:
- addend = rel->r_addend;
- /* Fall through. */
- default:
+ final_link_relocate:
/* COFF relocs don't use the addend. The addend is used for
R_SH_DIR32 to be compatible with other compilers. */
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
relocation, addend);
break;
+
+ case R_SH_IND12W:
+ case R_SH_DIR8WPN:
+ case R_SH_DIR8WPZ:
+ case R_SH_DIR8WPL:
+ /* These should normally be handled by the assembler, but at
+ least IND12W is generated by ourselves, so we must deal
+ with it. */
+ relocation -= 4;
+ goto final_link_relocate;
+
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+
+ case R_SH_DIR32:
+ addend = rel->r_addend;
+ goto final_link_relocate;
+
case R_SH_LOOP_START:
{
static bfd_vma start, end;
@@ -1969,6 +1969,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
r = sh_elf_reloc_loop (r_type, input_bfd, input_section, contents,
rel->r_offset, sec, start, end);
break;
+
case R_SH_LOOP_END:
end = (relocation + rel->r_addend
- (sec->output_section->vma + sec->output_offset));