summaryrefslogtreecommitdiffstats
path: root/recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch')
-rw-r--r--recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch76
1 files changed, 76 insertions, 0 deletions
diff --git a/recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch b/recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
new file mode 100644
index 0000000000..59d8035f7d
--- /dev/null
+++ b/recipes/binutils/binutils-2.16/binutils-2.16-thumb-glue.patch
@@ -0,0 +1,76 @@
+# The ARM->Thumb glue uses an ldr of the target function address, this
+# simply doesn't work for PIC code, changed to use 4 word PIC glue
+#
+--- binutils-2.16/.pc/binutils-2.16-thumb-glue.patch/bfd/elf32-arm.c 2005-09-18 03:52:15.465165051 -0700
++++ binutils-2.16/bfd/elf32-arm.c 2005-09-18 03:52:33.546302825 -0700
+@@ -1493,19 +1493,20 @@
+ return myh;
+ }
+
+-/* ARM->Thumb glue:
++/* ARM->Thumb glue (PIC version):
+
+ .arm
+ __func_from_arm:
+ ldr r12, __func_addr
++ add r12, r12, pc @ pc is __func_addr, so r12 is func
+ bx r12
+ __func_addr:
+- .word func @ behave as if you saw a ARM_32 reloc. */
++ .word func-.+1 @ offset to actual function, low bit set */
+
+-#define ARM2THUMB_GLUE_SIZE 12
+-static const insn32 a2t1_ldr_insn = 0xe59fc000;
+-static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
+-static const insn32 a2t3_func_addr_insn = 0x00000001;
++#define ARM2THUMB_GLUE_SIZE 16
++static const insn32 a2t1_ldr_insn = 0xe59fc004;
++static const insn32 a2t2_add_r12_insn = 0xe08fc00c;
++static const insn32 a2t3_bx_r12_insn = 0xe12fff1c;
+
+ /* Thumb->ARM: Thumb->(non-interworking aware) ARM
+
+@@ -2187,6 +2188,8 @@
+
+ if ((my_offset & 0x01) == 0x01)
+ {
++ long int ret_offset;
++
+ if (sym_sec != NULL
+ && sym_sec->owner != NULL
+ && !INTERWORK_FLAG (sym_sec->owner))
+@@ -2203,12 +2206,31 @@
+ bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
+ s->contents + my_offset);
+
+- bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
++ bfd_put_32 (output_bfd, (bfd_vma) a2t2_add_r12_insn,
+ s->contents + my_offset + 4);
+
+- /* It's a thumb address. Add the low order bit. */
+- bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
++ bfd_put_32 (output_bfd, (bfd_vma) a2t3_bx_r12_insn,
+ s->contents + my_offset + 8);
++
++ /* Calculate the offset to the actual function. */
++ ret_offset =
++ /* Address of destination of the stub. */
++ ((bfd_signed_vma) val)
++ - ((bfd_signed_vma)
++ /* Offset from the start of the current section
++ to the start of the stubs. */
++ (s->output_offset
++ /* Offset of the start of this stub from the start of the stubs. */
++ + my_offset
++ /* Address of the start of the current section. */
++ + s->output_section->vma)
++ /* The word is 12 bytes into the stub. */
++ + 12
++ /* The destination is a thumb function so the bottom bit must be set. */
++ - 1);
++
++ bfd_put_32 (output_bfd, (bfd_vma) ret_offset,
++ s->contents + my_offset + 12);
+ }
+
+ BFD_ASSERT (my_offset <= globals->arm_glue_size);