* elf32-sh.c (sh_elf_relocate_section): Only relocation
authorDJ Delorie <dj@redhat.com>
Tue, 13 Mar 2001 04:43:40 +0000 (04:43 +0000)
committerDJ Delorie <dj@redhat.com>
Tue, 13 Mar 2001 04:43:40 +0000 (04:43 +0000)
R_SH_DIR8WP* relocs if they're against external symbols, else
they're just for relaxing.  Validate the reloc values.

bfd/ChangeLog
bfd/elf32-sh.c

index 99506d1..dc6ff2d 100644 (file)
@@ -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.
index 0e6be9b..6d7bc2e 100644 (file)
@@ -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);