From e95de06338c51f03d29a7fe5d2f1c374054c9e44 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Tue, 17 Oct 2006 15:46:21 +0000 Subject: [PATCH] bfd/ * elf32-arm.c (elf32_arm_howto_table_1): Change offset for R_THM_CALL to 25 and remove FIXME comment. (using_thumb2): New function. (elf32_arm_final_link_relocate): Cope with Thumb-2 BL encoding. include/ * elf/arm.h: Define TAG_CPU_ARCH_* constants. ld/testsuite/ * ld-arm/arm-elf.exp: Add thumb1-bl, thumb2-bl, thumb2-bl-as-thumb1-bad and thumb2-bl-bad tests. * ld-arm/thumb1-bl.d: New. * ld-arm/thumb1-bl.s: New. * ld-arm/thumb2-bl-as-thumb1-bad.d: New. * ld-arm/thumb2-bl-as-thumb1-bad.s: New. * ld-arm/thumb2-bl-bad.d: New. * ld-arm/thumb2-bl-bad.s: New. * ld-arm/thumb2-bl.d: New. * ld-arm/thumb2-bl.s: New. --- bfd/ChangeLog | 7 +++ bfd/elf32-arm.c | 61 +++++++++++++++---- include/ChangeLog | 4 ++ include/elf/arm.h | 13 ++++ ld/testsuite/ChangeLog | 13 ++++ ld/testsuite/ld-arm/arm-elf.exp | 8 +++ ld/testsuite/ld-arm/thumb1-bl.d | 11 ++++ ld/testsuite/ld-arm/thumb1-bl.s | 22 +++++++ ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d | 4 ++ ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s | 22 +++++++ ld/testsuite/ld-arm/thumb2-bl-bad.d | 4 ++ ld/testsuite/ld-arm/thumb2-bl-bad.s | 22 +++++++ ld/testsuite/ld-arm/thumb2-bl.d | 11 ++++ ld/testsuite/ld-arm/thumb2-bl.s | 23 +++++++ 14 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 ld/testsuite/ld-arm/thumb1-bl.d create mode 100644 ld/testsuite/ld-arm/thumb1-bl.s create mode 100644 ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d create mode 100644 ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s create mode 100644 ld/testsuite/ld-arm/thumb2-bl-bad.d create mode 100644 ld/testsuite/ld-arm/thumb2-bl-bad.s create mode 100644 ld/testsuite/ld-arm/thumb2-bl.d create mode 100644 ld/testsuite/ld-arm/thumb2-bl.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f7bae6c61a..db2662f7b2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2006-10-17 Mark Shinwell + + * elf32-arm.c (elf32_arm_howto_table_1): Change offset for + R_THM_CALL to 25 and remove FIXME comment. + (using_thumb2): New function. + (elf32_arm_final_link_relocate): Cope with Thumb-2 BL encoding. + 2006-10-17 Mark Shinwell * elf32-arm.c (elf32_arm_final_link_relocate): Add cases diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index c2ef9b1463..c2e51c1976 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -217,11 +217,10 @@ static reloc_howto_type elf32_arm_howto_table_1[] = 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* FIXME: Has two more bits of offset in Thumb32. */ HOWTO (R_ARM_THM_CALL, /* type */ 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 23, /* bitsize */ + 25, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed,/* complain_on_overflow */ @@ -3534,6 +3533,14 @@ identify_add_or_sub(bfd_vma insn) return 0; } +/* Determine if we're dealing with a Thumb-2 object. */ + +static int using_thumb2 (struct elf32_arm_link_hash_table *globals) +{ + int arch = elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch); + return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7; +} + /* Perform a relocation as part of a final link. */ static bfd_reloc_status_type @@ -4056,22 +4063,33 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* Thumb BL (branch long instruction). */ { bfd_vma relocation; + bfd_vma reloc_sign; bfd_boolean overflow = FALSE; bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data); bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2); - bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift; - bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + bfd_signed_vma reloc_signed_max; + bfd_signed_vma reloc_signed_min; bfd_vma check; bfd_signed_vma signed_check; + int bitsize; + int thumb2 = using_thumb2 (globals); - /* Need to refetch the addend and squish the two 11 bit pieces - together. */ + /* Fetch the addend. We use the Thumb-2 encoding (backwards compatible + with Thumb-1) involving the J1 and J2 bits. */ if (globals->use_rel) { - bfd_vma upper = upper_insn & 0x7ff; - bfd_vma lower = lower_insn & 0x7ff; - upper = (upper ^ 0x400) - 0x400; /* Sign extend. */ - addend = (upper << 12) | (lower << 1); + bfd_vma s = (upper_insn & (1 << 10)) >> 10; + bfd_vma upper = upper_insn & 0x3ff; + bfd_vma lower = lower_insn & 0x7ff; + bfd_vma j1 = (lower_insn & (1 << 13)) >> 13; + bfd_vma j2 = (lower_insn & (1 << 11)) >> 11; + bfd_vma i1 = j1 ^ s ? 0 : 1; + bfd_vma i2 = j2 ^ s ? 0 : 1; + + addend = (i1 << 23) | (i2 << 22) | (upper << 12) | (lower << 1); + /* Sign extend. */ + addend = (addend | ((s ? 0 : 1) << 24)) - (1 << 24); + signed_addend = addend; } @@ -4148,6 +4166,15 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, else signed_check = check | ~((bfd_vma) -1 >> howto->rightshift); + /* Calculate the permissable maximum and minimum values for + this relocation according to whether we're relocating for + Thumb-2 or not. */ + bitsize = howto->bitsize; + if (!thumb2) + bitsize -= 2; + reloc_signed_max = ((1 << (bitsize - 1)) - 1) >> howto->rightshift; + reloc_signed_min = ~reloc_signed_max; + /* Assumes two's complement. */ if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) overflow = TRUE; @@ -4159,9 +4186,17 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, 1 of the base address. */ relocation = (relocation + 2) & ~ 3; - /* Put RELOCATION back into the insn. */ - upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); - lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); + /* Put RELOCATION back into the insn. Assumes two's complement. + We use the Thumb-2 encoding, which is safe even if dealing with + a Thumb-1 instruction by virtue of our overflow check above. */ + reloc_sign = (signed_check < 0) ? 1 : 0; + upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) + | ((relocation >> 12) & 0x3ff) + | (reloc_sign << 10); + lower_insn = (lower_insn & ~(bfd_vma) 0x2fff) + | (((!((relocation >> 23) & 1)) ^ reloc_sign) << 13) + | (((!((relocation >> 22) & 1)) ^ reloc_sign) << 11) + | ((relocation >> 1) & 0x7ff); /* Put the relocated value back in the object file: */ bfd_put_16 (input_bfd, upper_insn, hit_data); diff --git a/include/ChangeLog b/include/ChangeLog index 6c09101860..564efeaec7 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2006-10-17 Mark Shinwell + + * elf/arm.h: Define TAG_CPU_ARCH_* constants. + 2006-09-17 Mei Ligang * dis-asm.h: Add prototypes for Score disassembler routines. diff --git a/include/elf/arm.h b/include/elf/arm.h index 6b7297733e..890ef8d7e7 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -84,6 +84,19 @@ #define PF_ARM_PI 0x20000000 /* Segment is position-independent. */ #define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */ +/* Values for the Tag_CPU_arch EABI attribute. */ +#define TAG_CPU_ARCH_PRE_V4 0 +#define TAG_CPU_ARCH_V4 1 +#define TAG_CPU_ARCH_V4T 2 +#define TAG_CPU_ARCH_V5T 3 +#define TAG_CPU_ARCH_V5TE 4 +#define TAG_CPU_ARCH_V5TEJ 5 +#define TAG_CPU_ARCH_V6 6 +#define TAG_CPU_ARCH_V6KZ 7 +#define TAG_CPU_ARCH_V6T2 8 +#define TAG_CPU_ARCH_V6K 9 +#define TAG_CPU_ARCH_V7 10 + /* Relocation types. */ START_RELOC_NUMBERS (elf_arm_reloc_type) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 36d20a347b..5ced8e4935 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2006-10-17 Mark Shinwell + + * ld-arm/arm-elf.exp: Add thumb1-bl, thumb2-bl, + thumb2-bl-as-thumb1-bad and thumb2-bl-bad tests. + * ld-arm/thumb1-bl.d: New. + * ld-arm/thumb1-bl.s: New. + * ld-arm/thumb2-bl-as-thumb1-bad.d: New. + * ld-arm/thumb2-bl-as-thumb1-bad.s: New. + * ld-arm/thumb2-bl-bad.d: New. + * ld-arm/thumb2-bl-bad.s: New. + * ld-arm/thumb2-bl.d: New. + * ld-arm/thumb2-bl.s: New. + 2006-10-17 Alan Modra * ld-arm/mixed-app.sym, ld-cris/ldsym1.d, ld-cris/libdso-12.d, diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index eee320433c..af94c8776d 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -62,6 +62,12 @@ set armelftests { {"Group relocations" "-Ttext 0x8000 --section-start zero=0x0 --section-start alpha=0xeef0 --section-start beta=0xffeef0" "" {group-relocs.s} {{objdump -Dr group-relocs.d}} "group-relocs"} + {"Thumb-1 BL" "-Ttext 0x1000 --section-start .foo=0x401000" "" {thumb1-bl.s} + {{objdump -dr thumb1-bl.d}} + "thumb1-bl"} + {"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" {thumb2-bl.s} + {{objdump -dr thumb2-bl.d}} + "thumb2-bl"} {"Simple non-PIC shared library" "-shared" "" {arm-lib.s} {{objdump -fdw arm-lib.d} {objdump -Rw arm-lib.r}} "arm-lib.so"} @@ -146,4 +152,6 @@ run_dump_test "group-relocs-alu-bad" run_dump_test "group-relocs-ldr-bad" run_dump_test "group-relocs-ldrs-bad" run_dump_test "group-relocs-ldc-bad" +run_dump_test "thumb2-bl-as-thumb1-bad" +run_dump_test "thumb2-bl-bad" diff --git a/ld/testsuite/ld-arm/thumb1-bl.d b/ld/testsuite/ld-arm/thumb1-bl.d new file mode 100644 index 0000000000..09d70959b6 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb1-bl.d @@ -0,0 +1,11 @@ + +.*thumb1-bl: file format elf32-.*arm + +Disassembly of section .text: + +00001000 <_start>: + 1000: f3ff fffe bl 401000 +Disassembly of section .foo: + +00401000 : + 401000: 4770 bx lr diff --git a/ld/testsuite/ld-arm/thumb1-bl.s b/ld/testsuite/ld-arm/thumb1-bl.s new file mode 100644 index 0000000000..cdecaa484b --- /dev/null +++ b/ld/testsuite/ld-arm/thumb1-bl.s @@ -0,0 +1,22 @@ +@ Test to ensure that a Thumb-1 BL works. + + .arch armv5t + .global _start + .syntax unified + +@ We will place the section .text at 0x1000. + + .text + .thumb_func + +_start: + bl bar + +@ We will place the section .foo at 0x401000. + + .section .foo, "xa" + .thumb_func + +bar: + bx lr + diff --git a/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d new file mode 100644 index 0000000000..749b58f566 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.d @@ -0,0 +1,4 @@ +#name: Thumb-2-as-Thumb-1 BL failure test +#source: thumb2-bl-as-thumb1-bad.s +#ld: -Ttext 0x1000 --section-start .foo=0x401004 +#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar' diff --git a/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s new file mode 100644 index 0000000000..dae5d43972 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl-as-thumb1-bad.s @@ -0,0 +1,22 @@ +@ Test to ensure that a Thumb-1 BL with a Thumb-2-only offset fails. + + .arch armv5t + .global _start + .syntax unified + +@ We will place the section .text at 0x1000. + + .text + .thumb_func + +_start: + bl bar + +@ We will place the section .foo at 0x401004. + + .section .foo, "xa" + .thumb_func + +bar: + bx lr + diff --git a/ld/testsuite/ld-arm/thumb2-bl-bad.d b/ld/testsuite/ld-arm/thumb2-bl-bad.d new file mode 100644 index 0000000000..0fc6e043e1 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl-bad.d @@ -0,0 +1,4 @@ +#name: Thumb-2 BL failure test +#source: thumb2-bl-bad.s +#ld: -Ttext 0x1000 --section-start .foo=0x1001004 +#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar' diff --git a/ld/testsuite/ld-arm/thumb2-bl-bad.s b/ld/testsuite/ld-arm/thumb2-bl-bad.s new file mode 100644 index 0000000000..63e3fe7e72 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl-bad.s @@ -0,0 +1,22 @@ +@ Test to ensure that a Thumb-2 BL with an oversize offset fails. + + .arch armv7 + .global _start + .syntax unified + +@ We will place the section .text at 0x1000. + + .text + .thumb_func + +_start: + bl bar + +@ We will place the section .foo at 0x1001004. + + .section .foo, "xa" + .thumb_func + +bar: + bx lr + diff --git a/ld/testsuite/ld-arm/thumb2-bl.d b/ld/testsuite/ld-arm/thumb2-bl.d new file mode 100644 index 0000000000..bdfb9b79b7 --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl.d @@ -0,0 +1,11 @@ + +.*thumb2-bl: file format elf32-.*arm + +Disassembly of section .text: + +00001000 <_start>: + 1000: f3ff d7fe bl 1001000 +Disassembly of section .foo: + +01001000 : + 1001000: 4770 bx lr diff --git a/ld/testsuite/ld-arm/thumb2-bl.s b/ld/testsuite/ld-arm/thumb2-bl.s new file mode 100644 index 0000000000..ddb1cd33fc --- /dev/null +++ b/ld/testsuite/ld-arm/thumb2-bl.s @@ -0,0 +1,23 @@ +@ Test to ensure that a Thumb-2 BL works with an offset that is +@ not permissable for Thumb-1. + + .arch armv7 + .global _start + .syntax unified + +@ We will place the section .text at 0x1000. + + .text + .thumb_func + +_start: + bl bar + +@ We will place the section .foo at 0x1001000. + + .section .foo, "xa" + .thumb_func + +bar: + bx lr +