bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ld bug - thumb code


From: Nick Clifton
Subject: Re: ld bug - thumb code
Date: 11 Sep 2002 17:19:43 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.1

Hi Andy,

> The disassembled thumb image appears to contain a corrupted thunk:
> 
> 00000188 <_ZThn4_N1C1FEv>:
>   188:    3804          sub    r0, #4
>   18a:    e345          b    818 <_ramstart+0x68c>
> since no valid code exists at 818.

It appears that the linker does not correctly handle the
R_ARM_THM_PC11 relocation.  Please try applying the attached patch and
let me know if it fixes the problem for you.  (It does with the test
code you sent to me).

Cheers
        Nick

Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.91
diff -c -3 -p -w -r1.91 elf32-arm.h
*** bfd/elf32-arm.h     27 Aug 2002 11:01:55 -0000      1.91
--- bfd/elf32-arm.h     11 Sep 2002 16:16:21 -0000
*************** elf32_arm_final_link_relocate (howto, in
*** 1501,1533 ****
      case R_ARM_THM_PC11:
        /* Thumb B (branch) instruction).  */
        {
!       bfd_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;
  #endif
!       relocation = value + 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 |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
  
        bfd_put_16 (input_bfd, relocation, hit_data);
--- 1501,1536 ----
      case R_ARM_THM_PC11:
        /* Thumb B (branch) instruction).  */
        {
!       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_signed_vma signed_check;
  
  #ifdef USE_REL
        /* Need to refetch addend.  */
        addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
!       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 + signed_addend;
  
        relocation -= (input_section->output_section->vma
                       + input_section->output_offset
                       + rel->r_offset);
  
!       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);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]