aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-arm.c41
-rw-r--r--ld/testsuite/ChangeLog12
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp35
-rw-r--r--ld/testsuite/ld-arm/farcall-cond-thumb-arm.d18
-rw-r--r--ld/testsuite/ld-arm/farcall-cond-thumb-arm.s27
-rw-r--r--ld/testsuite/ld-arm/jump-reloc-veneers-cond-long-backward.d24
-rw-r--r--ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d24
-rw-r--r--ld/testsuite/ld-arm/jump-reloc-veneers-cond-short-backward.d13
-rw-r--r--ld/testsuite/ld-arm/jump-reloc-veneers-cond-short.d13
-rw-r--r--ld/testsuite/ld-arm/jump-reloc-veneers-cond.s12
11 files changed, 220 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6dd80be..81da6e3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-21 Tony Wang <tony.wang@arm.com>
+
+ * elf32-arm.c (elf32_arm_final_link_relocate): Implement
+ the veneer routine for R_ARM_THM_JUMP19.
+ (arm_type_of_stub): Add conditional clause for R_ARM_THM_JUMP19
+ (elf32_arm_size_stub): Ditto.
+
2014-08-20 Roland McGrath <mcgrathr@google.com>
PR ld/17277
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 73b5fb0..89d51c1 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2283,6 +2283,8 @@ static const bfd_vma elf32_arm_nacl_plt_entry [] =
#define THM_MAX_BWD_BRANCH_OFFSET (-(1 << 22) + 4)
#define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
+#define THM2_MAX_FWD_COND_BRANCH_OFFSET (((1 << 20) -2) + 4)
+#define THM2_MAX_BWD_COND_BRANCH_OFFSET (-(1 << 20) + 4)
enum stub_insn_type
{
@@ -3667,7 +3669,8 @@ arm_type_of_stub (struct bfd_link_info *info,
/* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
are considering a function call relocation. */
- if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
+ if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
+ || r_type == R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
branch_type = ST_BRANCH_TO_THUMB;
@@ -3711,7 +3714,7 @@ arm_type_of_stub (struct bfd_link_info *info,
branch_offset = (bfd_signed_vma)(destination - location);
if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
- || r_type == R_ARM_THM_TLS_CALL)
+ || r_type == R_ARM_THM_TLS_CALL || r_type == R_ARM_THM_JUMP19)
{
/* Handle cases where:
- this call goes too far (different Thumb/Thumb2 max
@@ -3727,10 +3730,15 @@ arm_type_of_stub (struct bfd_link_info *info,
|| (thumb2
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
+ || (thumb2
+ && (branch_offset > THM2_MAX_FWD_COND_BRANCH_OFFSET
+ || (branch_offset < THM2_MAX_BWD_COND_BRANCH_OFFSET))
+ && (r_type == R_ARM_THM_JUMP19))
|| (branch_type == ST_BRANCH_TO_ARM
&& (((r_type == R_ARM_THM_CALL
|| r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx)
- || (r_type == R_ARM_THM_JUMP24))
+ || (r_type == R_ARM_THM_JUMP24)
+ || (r_type == R_ARM_THM_JUMP19))
&& !use_plt))
{
if (branch_type == ST_BRANCH_TO_THUMB)
@@ -5347,7 +5355,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* For historical reasons, use the existing names for
ARM-to-Thumb and Thumb-to-ARM stubs. */
if ((r_type == (unsigned int) R_ARM_THM_CALL
- || r_type == (unsigned int) R_ARM_THM_JUMP24)
+ || r_type == (unsigned int) R_ARM_THM_JUMP24
+ || r_type == (unsigned int) R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
sprintf (stub_entry->output_name,
THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
@@ -9125,6 +9134,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_signed_vma reloc_signed_max = 0xffffe;
bfd_signed_vma reloc_signed_min = -0x100000;
bfd_signed_vma signed_check;
+ enum elf32_arm_stub_type stub_type = arm_stub_none;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct elf32_arm_link_hash_entry *hash;
/* Need to refetch the addend, reconstruct the top three bits,
and squish the two 11 bit pieces together. */
@@ -9156,8 +9168,25 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
*unresolved_reloc_p = FALSE;
}
- /* ??? Should handle interworking? GCC might someday try to
- use this for tail calls. */
+ hash = (struct elf32_arm_link_hash_entry *)h;
+
+ stub_type = arm_type_of_stub (info, input_section, rel,
+ st_type, &branch_type,
+ hash, value, sym_sec,
+ input_bfd, sym_name);
+ if (stub_type != arm_stub_none)
+ {
+ stub_entry = elf32_arm_get_stub_entry (input_section,
+ sym_sec, h,
+ rel, globals,
+ stub_type);
+ if (stub_entry != NULL)
+ {
+ value = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
+ }
+ }
relocation = value + signed_addend;
relocation -= (input_section->output_section->vma
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 3345d2c..6ef84a0 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2014-08-21 Tony Wang <tony.wang@arm.com>
+
+ * ld-arm/jump-reloc-veneers-cond.s: New test.
+ * ld-arm/farcall-cond-thumb-arm.s: Ditto.
+ * ld-arm/jump-reloc-veneers-cond-short.d: Expected output
+ for target without a veneer generation.
+ * ld-arm/jump-reloc-veneers-cond-long.d: Expected output
+ for target with a veneer generation.
+ * ld-arm/farcall-cond-thumb-arm.d: Expected output for
+ inter working veneer generation.
+ * ld-arm/arm-elf.exp: Add tests for conditional branch veneer.
+
2014-08-20 Roland McGrath <mcgrathr@google.com>
PR ld/17277
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 677e7b2..f971afc 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -453,6 +453,16 @@ set armeabitests_nonacl {
{{objdump -d farcall-thumb-arm-pic-veneer.d}}
"farcall-thumb-arm-pic-veneer"}
+ {"Thumb-ARM farcall cond" "-Ttext 0x8000 --section-start .foo=0x118000" "" "-W" {farcall-cond-thumb-arm.s}
+ {{objdump -d farcall-cond-thumb-arm.d}}
+ "farcall-cond-thumb-arm"}
+ {"Thumb-ARM farcall cond (BE8)" "-Ttext 0x8000 --section-start .foo=0x118000 -EB --be8" "" "-W -EB" {farcall-cond-thumb-arm.s}
+ {{objdump -d farcall-cond-thumb-arm.d}}
+ "farcall-cond-thumb-arm-be8"}
+ {"Thumb-ARM farcall cond (BE)" "-Ttext 0x8000 --section-start .foo=0x118000 -EB" "" "-W -EB" {farcall-cond-thumb-arm.s}
+ {{objdump -d farcall-cond-thumb-arm.d}}
+ "farcall-cond-thumb-arm-be"}
+
{"Multiple farcalls" "-Ttext 0x1000 --section-start .foo=0x2002020" "" "" {farcall-mix.s}
{{objdump -d farcall-mix.d}}
"farcall-mix"}
@@ -551,6 +561,31 @@ set armeabitests_nonacl {
{{objdump -d jump-reloc-veneers-long.d}}
"jump-reloc-veneers-long"}
+ {"R_ARM_THM_JUMP19 Relocation veneers: Short"
+ "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
+ "-march=armv7-m -mthumb"
+ {jump-reloc-veneers-cond.s}
+ {{objdump -d jump-reloc-veneers-cond-short.d}}
+ "jump-reloc-veneers-cond-short"}
+ {"R_ARM_THM_JUMP19 Relocation veneers: Long"
+ "--section-start destsect=0x00108004 --section-start .text=0x8000" ""
+ "-march=armv7-m -mthumb"
+ {jump-reloc-veneers-cond.s}
+ {{objdump -d jump-reloc-veneers-cond-long.d}}
+ "jump-reloc-veneers-cond-long"}
+ {"R_ARM_THM_JUMP19 Relocation veneers: Short backward"
+ "--section-start destsect=0x8004 --section-start .text=0x108000" ""
+ "-march=armv7-m -mthumb"
+ {jump-reloc-veneers-cond.s}
+ {{objdump -d jump-reloc-veneers-cond-short-backward.d}}
+ "jump-reloc-veneers-cond-short-backward"}
+ {"R_ARM_THM_JUMP19 Relocation veneers: Long backward"
+ "--section-start destsect=0x8002 --section-start .text=0x108000" ""
+ "-march=armv7-m -mthumb"
+ {jump-reloc-veneers-cond.s}
+ {{objdump -d jump-reloc-veneers-cond-long-backward.d}}
+ "jump-reloc-veneers-cond-long-backward"}
+
{"Default group size" "-Ttext 0x1000 --section-start .foo=0x2003020" "" "" {farcall-group.s farcall-group2.s}
{{objdump -d farcall-group.d}}
"farcall-group-default"}
diff --git a/ld/testsuite/ld-arm/farcall-cond-thumb-arm.d b/ld/testsuite/ld-arm/farcall-cond-thumb-arm.d
new file mode 100644
index 0000000..0b0172b
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-cond-thumb-arm.d
@@ -0,0 +1,18 @@
+.*: file format .*
+
+Disassembly of section .text:
+
+00008000 <_start>:
+ 8000: f050 a002 bne.w 58008 <__bar_from_thumb>
+ \.\.\.
+ 58004: f040 8000 bne.w 58008 <__bar_from_thumb>
+
+00058008 <__bar_from_thumb>:
+ 58008: 4778 bx pc
+ 5800a: 46c0 nop ; \(mov r8, r8\)
+ 5800c: ea02fffb b 118000 <bar>
+
+Disassembly of section .foo:
+
+00118000 <bar>:
+ 118000: e12fff1e bx lr
diff --git a/ld/testsuite/ld-arm/farcall-cond-thumb-arm.s b/ld/testsuite/ld-arm/farcall-cond-thumb-arm.s
new file mode 100644
index 0000000..809f2fc
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-cond-thumb-arm.s
@@ -0,0 +1,27 @@
+@ Test to ensure that a Thumb to ARM call exceeding 4Mb generates a stub.
+@ Check that we can generate two types of stub in the same section.
+
+ .global _start
+ .syntax unified
+
+@ We will place the section .text at 0x1c01010.
+
+ .text
+ .thumb_func
+_start:
+ .global bar
+ bne bar
+@ This call is close enough to generate a "short branch" stub
+@ or no stub if blx is available.
+ .space 0x050000
+ bne bar
+
+@ We will place the section .foo at 0x2001014.
+
+ .section .foo, "xa"
+
+ .arm
+ .type bar, %function
+bar:
+ bx lr
+
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long-backward.d b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long-backward.d
new file mode 100644
index 0000000..ee0709a
--- /dev/null
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long-backward.d
@@ -0,0 +1,24 @@
+
+.*: file format.*
+
+
+Disassembly of section destsect:
+
+00008002 <[^>]*>:
+ 8002: f7ff fffe bl 8002 <dest>
+
+Disassembly of section .text:
+
+001080.. <[^>]*>:
+ 1080..: f040 8002 bne.w 108008 <__dest_veneer>
+ 1080..: 0000 movs r0, r0
+ ...
+
+001080.. <[^>]*>:
+ 1080..: b401 push {r0}
+ 1080..: 4802 ldr r0, \[pc, #8\] ; \(108014 <__dest_veneer\+0xc>\)
+ 1080..: 4684 mov ip, r0
+ 1080..: bc01 pop {r0}
+ 1080..: 4760 bx ip
+ 1080..: bf00 nop
+ 1080..: 00008003 .word 0x00008003
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d
new file mode 100644
index 0000000..276a24e
--- /dev/null
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d
@@ -0,0 +1,24 @@
+
+.*: file format.*
+
+
+Disassembly of section destsect:
+
+00108004 <[^>]*>:
+ 108004: f7ff fffe bl 108004 <dest>
+
+Disassembly of section .text:
+
+000080.. <[^>]*>:
+ 80..: (8002f040|f0408002) .word 0x(8002f040|f0408002)
+ 80..: 0000 movs r0, r0
+ ...
+
+000080.. <[^>]*>:
+ 80..: b401 push {r0}
+ 80..: 4802 ldr r0, \[pc, #8\] ; \(80.. <__dest_veneer\+0xc>\)
+ 80..: 4684 mov ip, r0
+ 80..: bc01 pop {r0}
+ 80..: 4760 bx ip
+ 80..: bf00 nop
+ 80..: 00108005 .word 0x00108005
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short-backward.d b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short-backward.d
new file mode 100644
index 0000000..d05425b
--- /dev/null
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short-backward.d
@@ -0,0 +1,13 @@
+
+.*: file format.*
+
+
+Disassembly of section destsect:
+
+00008004 <[^>]*>:
+ 8004: f7ff fffe bl 8004 <dest>
+
+Disassembly of section .text:
+
+001080.. <_start>:
+ 1080..: f440 8000 bne.w 8004 <dest>
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short.d b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short.d
new file mode 100644
index 0000000..08c2212
--- /dev/null
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-short.d
@@ -0,0 +1,13 @@
+
+.*: file format.*
+
+
+Disassembly of section destsect:
+
+00108002 <[^>]*>:
+ 108002: f7ff fffe bl 108002 <dest>
+
+Disassembly of section .text:
+
+000080.. <[^>]*>:
+ 80..: f07f afff bne.w 108002 <dest>
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond.s b/ld/testsuite/ld-arm/jump-reloc-veneers-cond.s
new file mode 100644
index 0000000..83f969c
--- /dev/null
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond.s
@@ -0,0 +1,12 @@
+ .text
+ .syntax unified
+ .thumb_func
+ .global _start
+ .type _start,%function
+_start:
+ bne dest
+
+ .section destsect, "x"
+ .thumb_func
+dest:
+ bl dest