diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/elf32-sh.c | 42 |
2 files changed, 43 insertions, 5 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 99506d1..dc6ff2d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2001-03-12 DJ Delorie <dj@redhat.com> + + * elf32-sh.c (sh_elf_relocate_section): Only relocation + R_SH_DIR8WP* relocs if they're against external symbols, else + they're just for relaxing. Validate the reloc values. + 2001-03-12 Stefan Geuken <mail@stefan-geuken.de> * binary.c (bfd_external_binary_architecture): Declare. diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index 0e6be9b..6d7bc2e 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -3029,14 +3029,46 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, break; case R_SH_IND12W: + relocation -= 4; + goto final_link_relocate; + 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; + /* If the reloc is against the start of this section, then + the assembler has already taken care of it and the reloc + is here only to assist in relaxing. If the reloc is not + against the start of this section, then it's against an + external symbol and we must deal with it ourselves. */ + if (input_section->output_section->vma + input_section->output_offset + != relocation) + { + int disp = (relocation + - input_section->output_section->vma + - input_section->output_offset + - rel->r_offset); + int mask = 0; + switch (r_type) + { + case R_SH_DIR8WPN: + case R_SH_DIR8WPZ: mask = 1; break; + case R_SH_DIR8WPL: mask = 3; break; + default: mask = 0; break; + } + if (disp & mask) + { + ((*_bfd_error_handler) + (_("%s: 0x%lx: fatal: unaligned branch target for relax-support relocation"), + bfd_get_filename (input_section->owner), + (unsigned long) rel->r_offset)); + bfd_set_error (bfd_error_bad_value); + return false; + } + relocation -= 4; + goto final_link_relocate; + } + r = bfd_reloc_ok; + break; default: bfd_set_error (bfd_error_bad_value); |