From ebe24dd4f8e4c7c8f34b6b69092d53053b6cd982 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Thu, 26 Feb 2009 15:37:53 +0000 Subject: [PATCH] 2009-02-26 Christophe Lyon bfd/ * elf32-arm.c (stub_reloc_type): Removed. (insn_sequence): Renamed reloc_type field to r_type. (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New stub. (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise. (elf32_arm_stub_long_branch_thumb_only_pic): Likewise. (elf32_arm_stub_type): Add new enum entries for the new stubs. (arm_stub_is_thumb): Catch new stubs. (arm_type_of_stub): Handle new stubs. (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs. (bfd_elf32_arm_process_before_allocation): Remove useless condition. testsuite/ * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs. * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the test is now expected to pass. * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise. * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise. --- bfd/ChangeLog | 14 +++ bfd/elf32-arm.c | 100 +++++++++++++----- ld/testsuite/ChangeLog | 9 +- ld/testsuite/ld-arm/arm-elf.exp | 12 ++- .../ld-arm/farcall-thumb-arm-pic-veneer.d | 25 ++++- .../ld-arm/farcall-thumb-thumb-m-pic-veneer.d | 27 ++++- .../ld-arm/farcall-thumb-thumb-pic-veneer.d | 27 ++++- 7 files changed, 168 insertions(+), 46 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4d3b31b9235..bdd2f802260 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2009-02-26 Christophe Lyon + + * elf32-arm.c (stub_reloc_type): Removed. + (insn_sequence): Renamed reloc_type field to r_type. + (elf32_arm_stub_long_branch_v4t_arm_thumb_pic): New stub. + (elf32_arm_stub_long_branch_v4t_thumb_arm_pic): Likewise. + (elf32_arm_stub_long_branch_thumb_only_pic): Likewise. + (elf32_arm_stub_type): Add new enum entries for the new stubs. + (arm_stub_is_thumb): Catch new stubs. + (arm_type_of_stub): Handle new stubs. + (arm_size_one_stub): Use ARRAY_SIZE. Handle new stubs. + (bfd_elf32_arm_process_before_allocation): Remove useless + condition. + 2009-02-25 H.J. Lu * elf.c (elf_find_function): Use is_function_type to check diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 7499f803524..2527e5e8425 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2018,13 +2018,6 @@ enum stub_insn_type DATA_TYPE }; -enum stub_reloc_type - { - STUB_RELOC_NONE = 0, - STUB_RELOC_ABS, - STUB_RELOC_PIC, - }; - #define THUMB16_INSN(X) {(X), THUMB16_TYPE, R_ARM_NONE, 0} #define THUMB32_INSN(X) {(X), THUMB32_TYPE, R_ARM_NONE, 0} #define ARM_INSN(X) {(X), ARM_TYPE, R_ARM_NONE, 0} @@ -2035,7 +2028,7 @@ typedef struct { bfd_vma data; enum stub_insn_type type; - enum stub_reloc_type reloc_type; + unsigned int r_type; int reloc_addend; } insn_sequence; @@ -2110,6 +2103,39 @@ static const insn_sequence elf32_arm_stub_long_branch_any_thumb_pic[] = DATA_WORD(0, R_ARM_REL32, 0), /* dcd R_ARM_REL32(X) */ }; +/* V4T ARM -> ARM long branch stub, PIC. */ +static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] = + { + ARM_INSN(0xe59fc004), /* ldr ip, [pc, #4] */ + ARM_INSN(0xe08fc00c), /* add ip, pc, ip */ + ARM_INSN(0xe12fff1c), /* bx ip */ + DATA_WORD(0, R_ARM_REL32, 0), /* dcd R_ARM_REL32(X) */ + }; + +/* V4T Thumb -> ARM long branch stub, PIC. */ +static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] = + { + THUMB16_INSN(0x4778), /* bx pc */ + THUMB16_INSN(0x46c0), /* nop */ + ARM_INSN(0xe59fc000), /* ldr ip, [pc, #0] */ + ARM_INSN(0xe08cf00f), /* add pc, ip, pc */ + DATA_WORD(0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */ + }; + +/* Thumb -> Thumb long branch stub, PIC. Used on architectures which + support only this mode, or on V4T where it is expensive to switch + to ARM. */ +static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] = + { + THUMB16_INSN(0xb401), /* push {r0} */ + THUMB16_INSN(0x4802), /* ldr r0, [pc, #8] */ + THUMB16_INSN(0x46fc), /* mov ip, pc */ + THUMB16_INSN(0x4484), /* add ip, r0 */ + THUMB16_INSN(0xbc01), /* pop {r0} */ + THUMB16_INSN(0x4760), /* bx ip */ + DATA_WORD(0, R_ARM_REL32, 4), /* dcd R_ARM_REL32(X) */ + }; + /* Section name for stubs is the associated section name plus this string. */ #define STUB_SUFFIX ".stub" @@ -2124,6 +2150,9 @@ enum elf32_arm_stub_type arm_stub_short_branch_v4t_thumb_arm, arm_stub_long_branch_any_arm_pic, arm_stub_long_branch_any_thumb_pic, + arm_stub_long_branch_v4t_arm_thumb_pic, + arm_stub_long_branch_v4t_thumb_arm_pic, + arm_stub_long_branch_thumb_only_pic, }; struct elf32_arm_stub_hash_entry @@ -2796,6 +2825,8 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type) case arm_stub_long_branch_thumb_only: case arm_stub_long_branch_v4t_thumb_arm: case arm_stub_short_branch_v4t_thumb_arm: + case arm_stub_long_branch_v4t_thumb_arm_pic: + case arm_stub_long_branch_thumb_only_pic: return TRUE; case arm_stub_none: BFD_FAIL (); @@ -2872,8 +2903,8 @@ arm_type_of_stub (struct bfd_link_info *info, ? ((globals->use_blx) /* V5T and above. */ ? arm_stub_long_branch_any_thumb_pic - /* not yet supported on V4T. */ - : arm_stub_none) + /* On V4T, use Thumb code only. */ + : arm_stub_long_branch_thumb_only_pic) /* non-PIC stubs. */ : ((globals->use_blx) @@ -2885,8 +2916,8 @@ arm_type_of_stub (struct bfd_link_info *info, else { stub_type = (info->shared | globals->pic_veneer) - /* PIC stub not yet supported on V4T. */ - ? arm_stub_none + /* PIC stub. */ + ? arm_stub_long_branch_thumb_only_pic /* non-PIC stub. */ : arm_stub_long_branch_thumb_only; } @@ -2909,8 +2940,8 @@ arm_type_of_stub (struct bfd_link_info *info, ? ((globals->use_blx) /* V5T and above. */ ? arm_stub_long_branch_any_arm_pic - /* not yet supported on V4T. */ - : arm_stub_none) + /* V4T PIC stub. */ + : arm_stub_long_branch_v4t_thumb_arm_pic) /* non-PIC stubs. */ : ((globals->use_blx) @@ -2951,7 +2982,12 @@ arm_type_of_stub (struct bfd_link_info *info, { stub_type = (info->shared | globals->pic_veneer) /* PIC stubs. */ - ? arm_stub_long_branch_any_thumb_pic + ? ((globals->use_blx) + /* V5T and above. */ + ? arm_stub_long_branch_any_thumb_pic + /* V4T stub. */ + : arm_stub_long_branch_v4t_arm_thumb_pic) + /* non-PIC stubs. */ : ((globals->use_blx) /* V5T and above. */ @@ -3207,7 +3243,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, put_arm_insn (globals, stub_bfd, template[i].data, loc + size); /* Handle cases where the target is encoded within the instruction. */ - if (template[i].reloc_type == R_ARM_JUMP24) + if (template[i].r_type == R_ARM_JUMP24) { stub_reloc_idx = i; stub_reloc_offset = size; @@ -3241,7 +3277,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, /* Assume there is one and only one entry to relocate in each stub. */ BFD_ASSERT (stub_reloc_idx != -1); - _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].reloc_type), + _bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].r_type), stub_bfd, stub_sec, stub_sec->contents, stub_entry->stub_offset + stub_reloc_offset, sym_value, template[stub_reloc_idx].reloc_addend); @@ -3271,32 +3307,43 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry, { case arm_stub_long_branch_any_any: template = elf32_arm_stub_long_branch_any_any; - template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence); - + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_any); break; case arm_stub_long_branch_v4t_arm_thumb: template = elf32_arm_stub_long_branch_v4t_arm_thumb; - template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb); break; case arm_stub_long_branch_thumb_only: template = elf32_arm_stub_long_branch_thumb_only; - template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only); break; case arm_stub_long_branch_v4t_thumb_arm: template = elf32_arm_stub_long_branch_v4t_thumb_arm; - template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm); break; case arm_stub_short_branch_v4t_thumb_arm: template = elf32_arm_stub_short_branch_v4t_thumb_arm; - template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_short_branch_v4t_thumb_arm); break; case arm_stub_long_branch_any_arm_pic: template = elf32_arm_stub_long_branch_any_arm_pic; - template_size = sizeof (elf32_arm_stub_long_branch_any_arm_pic) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_arm_pic); break; case arm_stub_long_branch_any_thumb_pic: template = elf32_arm_stub_long_branch_any_thumb_pic; - template_size = sizeof (elf32_arm_stub_long_branch_any_thumb_pic) / sizeof (insn_sequence); + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_any_thumb_pic); + break; + case arm_stub_long_branch_v4t_arm_thumb_pic: + template = elf32_arm_stub_long_branch_v4t_arm_thumb_pic; + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_arm_thumb_pic); + break; + case arm_stub_long_branch_v4t_thumb_arm_pic: + template = elf32_arm_stub_long_branch_v4t_thumb_arm_pic; + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm_pic); + break; + case arm_stub_long_branch_thumb_only_pic: + template = elf32_arm_stub_long_branch_thumb_only_pic; + template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic); break; default: BFD_FAIL (); @@ -4647,8 +4694,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd, /* This one is a call from arm code. We need to look up the target of the call. If it is a thumb target, we insert glue. */ - if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC - && !(r_type == R_ARM_CALL && globals->use_blx)) + if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC) record_arm_to_thumb_glue (link_info, h); break; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index a214deaf932..d78062d8b2a 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,6 +1,13 @@ +2009-02-26 Christophe Lyon + + * ld-arm/arm-elf.exp: Add 3 tests for the 3 new stubs. + * ld-arm/farcall-thumb-arm-pic-veneer.d: New expected result, the + test is now expected to pass. + * ld-arm/farcall-thumb-thumb-m-pic-veneer.d: Likewise. + * ld-arm/farcall-thumb-thumb-pic-veneer.d: Likewise. + 2009-02-25 Christophe Lyon - testsuite/ * ld-arm/thumb2-bl-as-thumb1-bad-noeabi.d: Update expected result, as stubs are now generated and the end of the .text section. * ld-arm/thumb2-bl-bad-noeabi.d: Likewise. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index da63b40d1b4..48b2b51ea70 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -296,6 +296,12 @@ set armeabitests { {"Thumb-Thumb farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv5t" {farcall-thumb-thumb.s} {{objdump -d farcall-thumb-thumb-blx-pic-veneer.d}} "farcall-thumb-thumb-blx-pic-veneer"} + {"Thumb-Thumb farcall M profile (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv7m" {farcall-thumb-thumb.s} + {{objdump -d farcall-thumb-thumb-m-pic-veneer.d}} + "farcall-thumb-thumb-m-pic-veneer"} + {"Thumb-Thumb farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-march=armv4t" {farcall-thumb-thumb.s} + {{objdump -d farcall-thumb-thumb-pic-veneer.d}} + "farcall-thumb-thumb-pic-veneer"} {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s} {{objdump -d farcall-thumb-arm.d}} @@ -315,6 +321,9 @@ set armeabitests { {"Thumb-ARM farcall with BLX (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W -march=armv5t" {farcall-thumb-arm.s} {{objdump -d farcall-thumb-arm-blx-pic-veneer.d}} "farcall-thumb-arm-blx-pic-veneer"} + {"Thumb-ARM farcall (PIC veneer)" "-Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer" "-W" {farcall-thumb-arm.s} + {{objdump -d farcall-thumb-arm-pic-veneer.d}} + "farcall-thumb-arm-pic-veneer"} {"Multiple farcalls" "-Ttext 0x1000 --section-start .foo=0x2002020" "" {farcall-mix.s} {{objdump -d farcall-mix.d}} @@ -350,9 +359,6 @@ run_dump_test "attr-merge-wchar-24-nowarn" run_dump_test "attr-merge-wchar-40-nowarn" run_dump_test "attr-merge-wchar-42-nowarn" run_dump_test "attr-merge-wchar-44-nowarn" -run_dump_test "farcall-thumb-thumb-pic-veneer" -run_dump_test "farcall-thumb-thumb-m-pic-veneer" -run_dump_test "farcall-thumb-arm-pic-veneer" run_dump_test "farcall-section" run_dump_test "attr-merge-unknown-1" run_dump_test "attr-merge-unknown-2" diff --git a/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d b/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d index a2c09d29b4c..6ac6e5c0f93 100644 --- a/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d +++ b/ld/testsuite/ld-arm/farcall-thumb-arm-pic-veneer.d @@ -1,5 +1,20 @@ -#name: Thumb-ARM farcall without BLX (PIC veneer) -#source: farcall-thumb-arm.s -#as: -march=armv4t -W -#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer -#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar' +.*: file format .* + +Disassembly of section .text: + +00001000 <_start>: + 1000: f000 f802 bl 1008 <__bar_from_thumb> + 1004: 0000 lsls r0, r0, #0 + ... + +00001008 <__bar_from_thumb>: + 1008: 4778 bx pc + 100a: 46c0 nop \(mov r8, r8\) + 100c: e59fc000 ldr ip, \[pc, #0\] ; 1014 <__bar_from_thumb\+0xc> + 1010: e08cf00f add pc, ip, pc + 1014: 01fffffc .word 0x01fffffc + +Disassembly of section .foo: + +02001014 : + 2001014: e12fff1e bx lr diff --git a/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d b/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d index f8308ff37dd..c96ea3f19a4 100644 --- a/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d +++ b/ld/testsuite/ld-arm/farcall-thumb-thumb-m-pic-veneer.d @@ -1,5 +1,22 @@ -#name: Thumb-Thumb farcall M profile (PIC veneer) -#source: farcall-thumb-thumb.s -#as: -march=armv4t -#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer -#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar' +.*: file format .* + +Disassembly of section .text: + +00001000 <_start>: + 1000: f000 f802 bl 1008 <__bar_veneer> + 1004: 0000 lsls r0, r0, #0 + ... + +00001008 <__bar_veneer>: + 1008: b401 push {r0} + 100a: 4802 ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\) + 100c: 46fc mov ip, pc + 100e: 4484 add ip, r0 + 1010: bc01 pop {r0} + 1012: 4760 bx ip + 1014: 02000005 .word 0x02000005 + +Disassembly of section .foo: + +02001014 : + 2001014: 4770 bx lr diff --git a/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d b/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d index f97671bbf02..c96ea3f19a4 100644 --- a/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d +++ b/ld/testsuite/ld-arm/farcall-thumb-thumb-pic-veneer.d @@ -1,5 +1,22 @@ -#name: Thumb-Thumb farcall without BLX (PIC veneer) -#source: farcall-thumb-thumb.s -#as: -march=armv4t -#ld: -Ttext 0x1000 --section-start .foo=0x2001014 --pic-veneer -#error: .*\(.text\+0x0\): relocation truncated to fit: R_ARM_THM_CALL against `bar' +.*: file format .* + +Disassembly of section .text: + +00001000 <_start>: + 1000: f000 f802 bl 1008 <__bar_veneer> + 1004: 0000 lsls r0, r0, #0 + ... + +00001008 <__bar_veneer>: + 1008: b401 push {r0} + 100a: 4802 ldr r0, \[pc, #8\] \(1014 <__bar_veneer\+0xc>\) + 100c: 46fc mov ip, pc + 100e: 4484 add ip, r0 + 1010: bc01 pop {r0} + 1012: 4760 bx ip + 1014: 02000005 .word 0x02000005 + +Disassembly of section .foo: + +02001014 : + 2001014: 4770 bx lr