summaryrefslogtreecommitdiffstats
path: root/meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch')
-rw-r--r--meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch76
1 files changed, 76 insertions, 0 deletions
diff --git a/meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch b/meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
new file mode 100644
index 0000000000..59d8035f7d
--- /dev/null
+++ b/meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
@@ -0,0 +1,76 @@
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);