aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2005-04-08 11:47:59 +0000
committerPaul Brook <paul@codesourcery.com>2005-04-08 11:47:59 +0000
commit8f6277f5c0ba5af896745b5da1674493da61aa0d (patch)
tree9c879412d04af7f663cc8cdffbf7d86595613a7b /bfd
parentf8569bd74f5ab0cc704174a92d8197cb9f7d717c (diff)
downloadgdb-8f6277f5c0ba5af896745b5da1674493da61aa0d.zip
gdb-8f6277f5c0ba5af896745b5da1674493da61aa0d.tar.gz
gdb-8f6277f5c0ba5af896745b5da1674493da61aa0d.tar.bz2
2005-04-08 Paul Brook <paul@codesourcery.com>
* elf32-arm.c (ARM2THUMB_GLUE_SIZE): Rename... (ARM2THUMB_STATIC_GLUE_SIZE): ... to this. (ARM2THUMB_PIC_GLUE_SIZE): Define. (a2t1p_ldr_insn, a2t2p_add_pc_insn, a2t3p_bx_r12_insn): Add. (elf32_arm_to_thumb_stub): Create PIC stubs. (record_arm_to_thumb_glue): Use different stub size for relocatable images.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elf32-arm.c64
2 files changed, 63 insertions, 11 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index bd49ca0..4723427 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2005-04-08 Paul Brook <paul@codesourcery.com>
+
+ * elf32-arm.c (ARM2THUMB_GLUE_SIZE): Rename...
+ (ARM2THUMB_STATIC_GLUE_SIZE): ... to this.
+ (ARM2THUMB_PIC_GLUE_SIZE): Define.
+ (a2t1p_ldr_insn, a2t2p_add_pc_insn, a2t3p_bx_r12_insn): Add.
+ (elf32_arm_to_thumb_stub): Create PIC stubs.
+ (record_arm_to_thumb_glue): Use different stub size for relocatable
+ images.
+
2005-04-05 Alan Modra <amodra@bigpond.net.au>
* elf64-ppc.c (dec_dynrel_count): New function split out from
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9245bd9..a46713d 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -1636,20 +1636,35 @@ find_arm_glue (struct bfd_link_info *link_info,
return myh;
}
-/* ARM->Thumb glue:
+/* ARM->Thumb glue (static images):
.arm
__func_from_arm:
ldr r12, __func_addr
bx r12
__func_addr:
- .word func @ behave as if you saw a ARM_32 reloc. */
+ .word func @ behave as if you saw a ARM_32 reloc.
-#define ARM2THUMB_GLUE_SIZE 12
+ (relocatable images)
+ .arm
+ __func_from_arm:
+ ldr r12, __func_offset
+ add r12, r12, pc
+ bx r12
+ __func_offset:
+ .word func - .
+ */
+
+#define ARM2THUMB_STATIC_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_PIC_GLUE_SIZE 16
+static const insn32 a2t1p_ldr_insn = 0xe59fc004;
+static const insn32 a2t2p_add_pc_insn = 0xe08cc00f;
+static const insn32 a2t3p_bx_r12_insn = 0xe12fff1c;
+
/* Thumb->ARM: Thumb->(non-interworking aware) ARM
.thumb .thumb
@@ -1769,7 +1784,10 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
free (tmp_name);
- globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
+ if ((link_info->shared || globals->root.is_relocatable_executable))
+ globals->arm_glue_size += ARM2THUMB_PIC_GLUE_SIZE;
+ else
+ globals->arm_glue_size += ARM2THUMB_STATIC_GLUE_SIZE;
return;
}
@@ -2342,15 +2360,39 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
--my_offset;
myh->root.u.def.value = my_offset;
- bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
- s->contents + my_offset);
+ if ((info->shared || globals->root.is_relocatable_executable))
+ {
+ /* For relocatable objects we can't use absolute addresses,
+ so construct the address from a relative offset. */
+ /* TODO: If the offset is small it's probably worth
+ constructing the address with adds. */
+ bfd_put_32 (output_bfd, (bfd_vma) a2t1p_ldr_insn,
+ s->contents + my_offset);
+ bfd_put_32 (output_bfd, (bfd_vma) a2t2p_add_pc_insn,
+ s->contents + my_offset + 4);
+ bfd_put_32 (output_bfd, (bfd_vma) a2t3p_bx_r12_insn,
+ s->contents + my_offset + 8);
+ /* Adjust the offset by 4 for the position of the add,
+ and 8 for the pipeline offset. */
+ ret_offset = (val - (s->output_offset
+ + s->output_section->vma
+ + my_offset + 12))
+ | 1;
+ bfd_put_32 (output_bfd, ret_offset,
+ s->contents + my_offset + 12);
+ }
+ else
+ {
+ 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,
- s->contents + my_offset + 4);
+ bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_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,
- s->contents + my_offset + 8);
+ /* It's a thumb address. Add the low order bit. */
+ bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
+ s->contents + my_offset + 8);
+ }
}
BFD_ASSERT (my_offset <= globals->arm_glue_size);