* elf-hppa.h (elf_hppa_final_link_relocate): Add check to ensure that
authorDave Anglin <dave.anglin@nrc.ca>
Sun, 25 Jan 2009 23:05:20 +0000 (23:05 +0000)
committerDave Anglin <dave.anglin@nrc.ca>
Sun, 25 Jan 2009 23:05:20 +0000 (23:05 +0000)
branch targets can be reached for R_PARISC_PCREL22F, R_PARISC_PCREL17F
and R_PARISC_PCREL12F relocations.

bfd/ChangeLog
bfd/elf-hppa.h

index 7fe0dce4f52b05023a6f0a58142d8a962fb502db..705b5b69fd3fa60c04a29a146e800260fa9569ad 100644 (file)
@@ -1,3 +1,9 @@
+2009-01-25  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * elf-hppa.h (elf_hppa_final_link_relocate): Add check to ensure that
+       branch targets can be reached for R_PARISC_PCREL22F, R_PARISC_PCREL17F
+       and R_PARISC_PCREL12F relocations.
+
 2009-01-24  Alan Modra  <amodra@bigpond.net.au>
 
        PR 6022
index 0aff4ccc711d041c9b8e4cd2baeee28a8a01b034..b371c0e6af351ddf0bada4d83a7dc9add4795921 100644 (file)
@@ -1606,10 +1606,11 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                              bfd_vma value,
                              struct bfd_link_info *info,
                              asection *sym_sec,
-                             struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
+                             struct elf_link_hash_entry *h,
                              struct elf64_hppa_dyn_hash_entry *dyn_h)
 {
   int insn;
+  bfd_vma max_branch_offset = 0;
   bfd_vma offset = rel->r_offset;
   bfd_signed_vma addend = rel->r_addend;
   reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
@@ -1629,7 +1630,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
        Note for a call to a function defined in another dynamic library
        we want to redirect the call to a stub.  */
 
-    /* Random PC relative relocs.  */
+    /* PC relative relocs without an implicit offset.  */
     case R_PARISC_PCREL21L:
     case R_PARISC_PCREL14R:
     case R_PARISC_PCREL14F:
@@ -1684,6 +1685,27 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
        value -= (offset + input_section->output_offset
                  + input_section->output_section->vma);
 
+       if (r_type == (unsigned int) R_PARISC_PCREL22F)
+         max_branch_offset = (1 << (22-1)) << 2;
+       else if (r_type == (unsigned int) R_PARISC_PCREL17F)
+         max_branch_offset = (1 << (17-1)) << 2;
+       else if (r_type == (unsigned int) R_PARISC_PCREL12F)
+         max_branch_offset = (1 << (12-1)) << 2;
+
+       /* Make sure we can reach the branch target.  */
+       if (max_branch_offset != 0
+           && value + addend + max_branch_offset >= 2*max_branch_offset)
+         {
+           (*_bfd_error_handler)
+             (_("%B(%A+0x%lx): cannot reach %s"),
+             input_bfd,
+             input_section,
+             offset,
+             h->root.root.string);
+           bfd_set_error (bfd_error_bad_value);
+           return bfd_reloc_notsupported;
+         }
+
        /* Adjust for any field selectors.  */
        if (r_type == R_PARISC_PCREL17R)
          value = hppa_field_adjust (value, -8 + addend, e_rsel);