]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / binutils / binutils-2.16 / binutils-2.16-thumb-glue.patch
1 # The ARM->Thumb glue uses an ldr of the target function address, this
2 # simply doesn't work for PIC code, changed to use 4 word PIC glue
3 #
4 --- binutils-2.16/.pc/binutils-2.16-thumb-glue.patch/bfd/elf32-arm.c    2005-09-18 03:52:15.465165051 -0700
5 +++ binutils-2.16/bfd/elf32-arm.c       2005-09-18 03:52:33.546302825 -0700
6 @@ -1493,19 +1493,20 @@
7    return myh;
8  }
9  
10 -/* ARM->Thumb glue:
11 +/* ARM->Thumb glue (PIC version):
12  
13     .arm
14     __func_from_arm:
15     ldr r12, __func_addr
16 +   add r12, r12, pc      @ pc is __func_addr, so r12 is func
17     bx  r12
18     __func_addr:
19 -   .word func    @ behave as if you saw a ARM_32 reloc.  */
20 +   .word func-.+1        @ offset to actual function, low bit set  */
21  
22 -#define ARM2THUMB_GLUE_SIZE 12
23 -static const insn32 a2t1_ldr_insn = 0xe59fc000;
24 -static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
25 -static const insn32 a2t3_func_addr_insn = 0x00000001;
26 +#define ARM2THUMB_GLUE_SIZE 16
27 +static const insn32 a2t1_ldr_insn = 0xe59fc004;
28 +static const insn32 a2t2_add_r12_insn = 0xe08fc00c;
29 +static const insn32 a2t3_bx_r12_insn = 0xe12fff1c;
30  
31  /* Thumb->ARM:                          Thumb->(non-interworking aware) ARM
32  
33 @@ -2187,6 +2188,8 @@
34  
35    if ((my_offset & 0x01) == 0x01)
36      {
37 +      long int ret_offset;
38 +
39        if (sym_sec != NULL
40           && sym_sec->owner != NULL
41           && !INTERWORK_FLAG (sym_sec->owner))
42 @@ -2203,12 +2206,31 @@
43        bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
44                   s->contents + my_offset);
45  
46 -      bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
47 +      bfd_put_32 (output_bfd, (bfd_vma) a2t2_add_r12_insn,
48                   s->contents + my_offset + 4);
49  
50 -      /* It's a thumb address.  Add the low order bit.  */
51 -      bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
52 +      bfd_put_32 (output_bfd, (bfd_vma) a2t3_bx_r12_insn,
53                   s->contents + my_offset + 8);
54 +
55 +      /* Calculate the offset to the actual function. */
56 +      ret_offset =
57 +       /* Address of destination of the stub.  */
58 +       ((bfd_signed_vma) val)
59 +       - ((bfd_signed_vma)
60 +          /* Offset from the start of the current section
61 +             to the start of the stubs.  */
62 +          (s->output_offset
63 +           /* Offset of the start of this stub from the start of the stubs.  */
64 +           + my_offset
65 +           /* Address of the start of the current section.  */
66 +           + s->output_section->vma)
67 +          /* The word is 12 bytes into the stub.  */
68 +          + 12
69 +          /* The destination is a thumb function so the bottom bit must be set. */
70 +          - 1);
71 +
72 +      bfd_put_32 (output_bfd, (bfd_vma) ret_offset,
73 +                 s->contents + my_offset + 12);
74      }
75  
76    BFD_ASSERT (my_offset <= globals->arm_glue_size);