bfd/
authorNick Clifton <nickc@redhat.com>
Tue, 26 Aug 2008 11:46:41 +0000 (11:46 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 26 Aug 2008 11:46:41 +0000 (11:46 +0000)
        * elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define.
        (elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch.
        (arm_type_of_stub): Handle armv4t short branches. Update
        prototype.
        (arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch.
        (arm_build_one_stub): Likewise.
        (arm_size_one_stub): Likewise.
        (elf32_arm_size_stubs): Use new arm_type_of_stub prototype.
        (arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch.

        ld/testsuite/
        * ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
        * ld-arm/farcall-group2.s: Fix comment.
        * ld-arm/farcall-thumb-arm-short.d: New test.
        * ld-arm/farcall-thumb-arm-short.s: New test.

bfd/ChangeLog
bfd/elf32-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/farcall-group2.s
ld/testsuite/ld-arm/farcall-thumb-arm-short.d [new file with mode: 0644]
ld/testsuite/ld-arm/farcall-thumb-arm-short.s [new file with mode: 0644]

index 5c34381..9ff4b5c 100644 (file)
@@ -1,3 +1,15 @@
+2008-08-25  Christophe Lyon  <christophe.lyon@st.com>
+
+       * elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define.
+       (elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch.
+       (arm_type_of_stub): Handle armv4t short branches. Update
+       prototype.
+       (arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch.
+       (arm_build_one_stub): Likewise.
+       (arm_size_one_stub): Likewise.
+       (elf32_arm_size_stubs): Use new arm_type_of_stub prototype.
+       (arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch.
+
 2008-08-24  Andreas Schwab  <schwab@suse.de>
 
        * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Do proper
index 39ce002..6601c45 100644 (file)
@@ -2045,6 +2045,13 @@ static const bfd_vma arm_thumb_arm_v4t_long_branch_stub[] =
     0x00000000,         /* dcd  R_ARM_ABS32(X) */
   };
 
+static const bfd_vma arm_thumb_arm_v4t_short_branch_stub[] =
+  {
+    0x46c04778,         /* bx   pc */
+                        /* nop   */
+    0xea000000,         /* b    (X) */
+  };
+
 static const bfd_vma arm_pic_long_branch_stub[] =
   {
     0xe59fc000,         /* ldr   r12, [pc] */
@@ -2063,6 +2070,7 @@ enum elf32_arm_stub_type
   arm_thumb_v4t_stub_long_branch,
   arm_thumb_thumb_stub_long_branch,
   arm_thumb_arm_v4t_stub_long_branch,
+  arm_thumb_arm_v4t_stub_short_branch,
   arm_stub_pic_long_branch,
 };
 
@@ -2738,6 +2746,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
     {
     case arm_thumb_thumb_stub_long_branch:
     case arm_thumb_arm_v4t_stub_long_branch:
+    case arm_thumb_arm_v4t_stub_short_branch:
       return TRUE;
     case arm_stub_none:
       BFD_FAIL ();
@@ -2756,7 +2765,10 @@ arm_type_of_stub (struct bfd_link_info *info,
                  const Elf_Internal_Rela *rel,
                  unsigned char st_type,
                  struct elf32_arm_link_hash_entry *hash,
-                 bfd_vma destination)
+                 bfd_vma destination,
+                 asection *sym_sec,
+                 bfd *input_bfd,
+                 const char *name)
 {
   bfd_vma location;
   bfd_signed_vma branch_offset;
@@ -2826,6 +2838,16 @@ arm_type_of_stub (struct bfd_link_info *info,
          else
            {
              /* Thumb to arm.  */
+             if (sym_sec != NULL
+                 && sym_sec->owner != NULL
+                 && !INTERWORK_FLAG (sym_sec->owner))
+               {
+                 (*_bfd_error_handler)
+                   (_("%B(%s): warning: interworking not enabled.\n"
+                      "  first occurrence: %B: Thumb call to ARM"),
+                    sym_sec->owner, input_bfd, name);
+               }
+
              stub_type = (info->shared | globals->pic_veneer)
                ? ((globals->use_blx)
                   ? arm_stub_pic_long_branch
@@ -2833,6 +2855,12 @@ arm_type_of_stub (struct bfd_link_info *info,
                : (globals->use_blx)
                ? arm_stub_long_branch
                : arm_thumb_arm_v4t_stub_long_branch;
+
+             /* Handle v4t short branches.  */
+             if ((stub_type == arm_thumb_arm_v4t_stub_long_branch)
+                 && (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET)
+                 && (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET))
+               stub_type = arm_thumb_arm_v4t_stub_short_branch;
            }
        }
     }
@@ -2841,8 +2869,19 @@ arm_type_of_stub (struct bfd_link_info *info,
       if (st_type == STT_ARM_TFUNC)
        {
          /* Arm to thumb.  */
-         /* We have an extra 2-bytes reach because of the mode change
-            (bit 24 (H) of BLX encoding).  */
+
+         if (sym_sec != NULL
+             && sym_sec->owner != NULL
+             && !INTERWORK_FLAG (sym_sec->owner))
+           {
+             (*_bfd_error_handler)
+               (_("%B(%s): warning: interworking not enabled.\n"
+                  "  first occurrence: %B: Thumb call to ARM"),
+                sym_sec->owner, input_bfd, name);
+           }
+
+         /* We have an extra 2-bytes reach because of
+            the mode change (bit 24 (H) of BLX encoding).  */
          if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
              || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
              || !globals->use_blx)
@@ -3098,6 +3137,10 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
       template =  arm_thumb_arm_v4t_long_branch_stub;
       template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      template =  arm_thumb_arm_v4t_short_branch_stub;
+      template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+      break;
     case arm_stub_pic_long_branch:
       template = arm_pic_long_branch_stub;
       template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3147,6 +3190,19 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
                                stub_bfd, stub_sec, stub_sec->contents,
                                stub_entry->stub_offset + 16, sym_value, 0);
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      {
+       long int rel_offset;
+       static const insn32 t2a3_b_insn = 0xea000000;
+
+       rel_offset = sym_value - (stub_addr + 8 + 4);
+
+       put_arm_insn (globals, stub_bfd,
+                     (bfd_vma) t2a3_b_insn | ((rel_offset >> 2) & 0x00FFFFFF),
+                     loc + 4);
+      }
+      break;
+
     case arm_stub_pic_long_branch:
       /* We want the value relative to the address 8 bytes from the
         start of the stub.  */
@@ -3197,6 +3253,10 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
       template =  arm_thumb_arm_v4t_long_branch_stub;
       template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      template =  arm_thumb_arm_v4t_short_branch_stub;
+      template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
+      break;
     case arm_stub_pic_long_branch:
       template = arm_pic_long_branch_stub;
       template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
@@ -3603,7 +3663,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
                  /* Determine what (if any) linker stub is needed.  */
                  stub_type = arm_type_of_stub (info, section, irela, st_type,
-                                               hash, destination);
+                                               hash, destination, sym_sec,
+                                               input_bfd, sym_name);
                  if (stub_type == arm_stub_none)
                    continue;
 
@@ -11205,6 +11266,12 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
        return FALSE;
       break;
+    case arm_thumb_arm_v4t_stub_short_branch:
+      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
+       return FALSE;
+      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
+       return FALSE;
+      break;
     case arm_stub_pic_long_branch:
       if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
        return FALSE;
index 117f5b7..a2c3050 100644 (file)
@@ -1,3 +1,10 @@
+2008-08-26  Nick Clifton  <nickc@redhat.com>
+
+       * ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
+       * ld-arm/farcall-group2.s: Fix comment.
+       * ld-arm/farcall-thumb-arm-short.d: New test.
+       * ld-arm/farcall-thumb-arm-short.s: New test.
+
 2008-08-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * ld-x86-64/dwarfreloc.exp, ld-x86-64/dwarfreloc.rd,
index c01c795..6075e68 100644 (file)
@@ -207,7 +207,7 @@ set armeabitests {
      {"Thumb-2 BL" "-Ttext 0x1000 --section-start .foo=0x1001000" "" {thumb2-bl.s}
       {{objdump -dr thumb2-bl.d}}
       "thumb2-bl"}
-    
+
     {"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s}
      {{objdump -d armv4-bx.d}}
      "armv4-bx"}
@@ -260,6 +260,9 @@ set armeabitests {
     {"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm.d}}
      "farcall-thumb-arm"}
+    {"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
+     {{objdump -d farcall-thumb-arm-short.d}}
+     "farcall-thumb-arm-short"}
     {"Thumb-ARM farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
      {{objdump -d farcall-thumb-arm-blx.d}}
      "farcall-thumb-arm-blx"}
index 4624804..774869f 100644 (file)
@@ -1,10 +1,7 @@
-
 @ Test to ensure that ARM calls exceeding 32Mb generate stubs.
 
-@ We will place the section .foo at 0x2000.
-
        .text
-myfunc:        
+myfunc:
        bl bar3
        bl bar4
        bl bar5
diff --git a/ld/testsuite/ld-arm/farcall-thumb-arm-short.d b/ld/testsuite/ld-arm/farcall-thumb-arm-short.d
new file mode 100644 (file)
index 0000000..2e7a17a
--- /dev/null
@@ -0,0 +1,14 @@
+.*:     file format .*
+
+Disassembly of section .text:
+
+00001000 <__bar_from_thumb>:
+    1000:      4778            bx      pc
+    1002:      46c0            nop                     \(mov r8, r8\)
+    1004:      ea000402        b       2014 <bar>
+00001008 <_start>:
+    1008:      f7ff fffa       bl      1000 <__bar_from_thumb>
+Disassembly of section .foo:
+
+00002014 <bar>:
+    2014:      e12fff1e        bx      lr
diff --git a/ld/testsuite/ld-arm/farcall-thumb-arm-short.s b/ld/testsuite/ld-arm/farcall-thumb-arm-short.s
new file mode 100644 (file)
index 0000000..1865380
--- /dev/null
@@ -0,0 +1,21 @@
+@ Test to ensure that a Thumb to ARM call within 4Mb does not generate a stub.
+
+       .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 0x2014.
+
+       .section .foo, "xa"
+
+       .arm
+       .type bar, %function
+bar:
+       bx lr
+