Fix handling of R_ARM_THM_PC11
authorNick Clifton <nickc@redhat.com>
Thu, 12 Sep 2002 13:18:57 +0000 (13:18 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 12 Sep 2002 13:18:57 +0000 (13:18 +0000)
bfd/ChangeLog
bfd/elf32-arm.h

index 8a84296e83c6d68af5740c491c76c82cf6d85356..5b825a2a3f9e74fd61ce5a39cefe4ff39c1baaa0 100644 (file)
@@ -1,3 +1,8 @@
+2002-09-12  Nick Clifton  <nickc@redhat.com>
+
+       * elf32-arm.h (elf32_arm_final_link_relocate): Fix handling of
+       R_ARM_THM_PC11.
+
 2002-09-11  Andrew Haley  <aph@cambridge.redhat.com>
 
        * elf.c (_bfd_elf_find_nearest_line): Check functionname_ptr and
index 5cd94347c31031296e094f6d40597e9c939771fb..e8538ac3ff2ccab5b4362a9e9d9095f571247063 100644 (file)
@@ -1501,33 +1501,36 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
     case R_ARM_THM_PC11:
       /* Thumb B (branch) instruction).  */
       {
-       bfd_vma        relocation;
+       bfd_signed_vma relocation;
        bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
        bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
-       bfd_vma        check;
        bfd_signed_vma signed_check;
 
 #ifdef USE_REL
        /* Need to refetch addend.  */
        addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
-       /* ??? Need to determine shift amount from operand size.  */
-       addend >>= howto->rightshift;
+       if (addend & ((howto->src_mask + 1) >> 1))
+         {
+           signed_addend = -1;
+           signed_addend &= ~ howto->src_mask;
+           signed_addend |= addend;
+         }
+       else
+         signed_addend = addend;
+       /* The value in the insn has been right shifted.  We need to
+          undo this, so that we can perform the address calculation
+          in terms of bytes.  */
+       signed_addend <<= howto->rightshift;
 #endif
-       relocation = value + addend;
+       relocation = value + signed_addend;
 
        relocation -= (input_section->output_section->vma
                       + input_section->output_offset
                       + rel->r_offset);
 
-       check = relocation >> howto->rightshift;
-
-       /* If this is a signed value, the rightshift just
-          dropped leading 1 bits (assuming twos complement).  */
-       if ((bfd_signed_vma) relocation >= 0)
-         signed_check = check;
-       else
-         signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
-
+       relocation >>= howto->rightshift;
+       signed_check = relocation;
+       relocation &= howto->dst_mask;
        relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
 
        bfd_put_16 (input_bfd, relocation, hit_data);