bfd/ChangeLog
authorTerry Guo <terry.guo@arm.com>
Thu, 21 Aug 2014 10:00:35 +0000 (18:00 +0800)
committerTerry Guo <terry.guo@arm.com>
Thu, 21 Aug 2014 10:00:35 +0000 (18:00 +0800)
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.

ld/testsuite/ChangeLog
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.

bfd/ChangeLog
bfd/elf32-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/farcall-cond-thumb-arm.d [new file with mode: 0644]
ld/testsuite/ld-arm/farcall-cond-thumb-arm.s [new file with mode: 0644]
ld/testsuite/ld-arm/jump-reloc-veneers-cond-long-backward.d [new file with mode: 0644]
ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d [new file with mode: 0644]
ld/testsuite/ld-arm/jump-reloc-veneers-cond-short-backward.d [new file with mode: 0644]
ld/testsuite/ld-arm/jump-reloc-veneers-cond-short.d [new file with mode: 0644]
ld/testsuite/ld-arm/jump-reloc-veneers-cond.s [new file with mode: 0644]

index 6dd80be..81da6e3 100644 (file)
@@ -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
index 73b5fb0..89d51c1 100644 (file)
@@ -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
index 3345d2c..6ef84a0 100644 (file)
@@ -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
index 677e7b2..f971afc 100644 (file)
@@ -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 (file)
index 0000000..0b0172b
--- /dev/null
@@ -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 (file)
index 0000000..809f2fc
--- /dev/null
@@ -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 (file)
index 0000000..ee0709a
--- /dev/null
@@ -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 (file)
index 0000000..276a24e
--- /dev/null
@@ -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 (file)
index 0000000..d05425b
--- /dev/null
@@ -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 (file)
index 0000000..08c2212
--- /dev/null
@@ -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 (file)
index 0000000..83f969c
--- /dev/null
@@ -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