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
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 @@
11 +/* ARM->Thumb glue (PIC version):
16 + add r12, r12, pc @ pc is __func_addr, so r12 is func
19 - .word func @ behave as if you saw a ARM_32 reloc. */
20 + .word func-.+1 @ offset to actual function, low bit set */
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;
31 /* Thumb->ARM: Thumb->(non-interworking aware) ARM
35 if ((my_offset & 0x01) == 0x01)
37 + long int ret_offset;
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);
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);
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);
55 + /* Calculate the offset to the actual function. */
57 + /* Address of destination of the stub. */
58 + ((bfd_signed_vma) val)
60 + /* Offset from the start of the current section
61 + to the start of the stubs. */
63 + /* Offset of the start of this stub from the start of the stubs. */
65 + /* Address of the start of the current section. */
66 + + s->output_section->vma)
67 + /* The word is 12 bytes into the stub. */
69 + /* The destination is a thumb function so the bottom bit must be set. */
72 + bfd_put_32 (output_bfd, (bfd_vma) ret_offset,
73 + s->contents + my_offset + 12);
76 BFD_ASSERT (my_offset <= globals->arm_glue_size);