Add a flag to asection, linker_has_input, and use it to reliably
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index 0e6be9b0151057fa0047c3384b117d5c3df28bbe..6d7bc2eae0fbf1fae044d6f689a3bcc8e4beabf4 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);
This page took 0.023486 seconds and 4 git commands to generate.