diff options
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.patch | 76 |
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); | ||
