2008-03-07 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Sat, 8 Mar 2008 01:20:39 +0000 (01:20 +0000)
committerPaul Brook <paul@codesourcery.com>
Sat, 8 Mar 2008 01:20:39 +0000 (01:20 +0000)
bfd/
* elf32-arm.c (elf32_arm_howto_table_1): Fix bitmasks for MOVW and
MOVT relocations.
(elf32_arm_final_link_relocate): Fix off by one MOVW/MOVT sign
extension.
(elf32_arm_relocate_section): Handle MOVW and MOVT
relocations.  Improve safety check for other weird relocations.
(elf32_arm_check_relocs): Only set h->needs_plt for branch/call
relocations.

gas/
* config/tc-arm.c (md_apply_fix): Use correct offset range.

ld/testsuite/
* ld-arm/arm-elf.exp (armelftests): Add movw-merge and arm-app-movw.
* ld-arm/arm-app-movw.s: New test.
* ld-arm/arm-app.r: Update expected output.
* ld-arm/movw-merge.d: New test.
* ld-arm/movw-merge.s: New test.

bfd/ChangeLog
bfd/elf32-arm.c
gas/ChangeLog
gas/config/tc-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-app-movw.s [new file with mode: 0644]
ld/testsuite/ld-arm/arm-app.r
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/movw-merge.d [new file with mode: 0644]
ld/testsuite/ld-arm/movw-merge.s [new file with mode: 0644]

index 6490fcf43929a05b0c51a511aceb4c6b7067a361..73c6a77c3b2d19d59b56077dc6ba42f23b2d5d92 100644 (file)
@@ -1,3 +1,14 @@
+2008-03-07  Paul Brook  <paul@codesourcery.com>
+
+       * elf32-arm.c (elf32_arm_howto_table_1): Fix bitmasks for MOVW and
+       MOVT relocations.
+       (elf32_arm_final_link_relocate): Fix off by one MOVW/MOVT sign
+       extension.
+       (elf32_arm_relocate_section): Handle MOVW and MOVT
+       relocations.  Improve safety check for other weird relocations.
+       (elf32_arm_check_relocs): Only set h->needs_plt for branch/call
+       relocations.
+
 2008-03-03  Bob Wilson  <bob.wilson@acm.org>
        
        * xtensa-isa.c (xtensa_isa_num_pipe_stages): Make max_stage static and
index 6f66a7150dff32e7e481dfca56dd60494e841385..687d9cd33a595328892fe9792bc88405e4f307b2 100644 (file)
@@ -696,8 +696,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_MOVW_ABS_NC",   /* name */
         FALSE,                 /* partial_inplace */
-        0x0000ffff,            /* src_mask */
-        0x0000ffff,            /* dst_mask */
+        0x000f0fff,            /* src_mask */
+        0x000f0fff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   HOWTO (R_ARM_MOVT_ABS,       /* type */
@@ -710,8 +710,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_MOVT_ABS",      /* name */
         FALSE,                 /* partial_inplace */
-        0x0000ffff,            /* src_mask */
-        0x0000ffff,            /* dst_mask */
+        0x000f0fff,            /* src_mask */
+        0x000f0fff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   HOWTO (R_ARM_MOVW_PREL_NC,   /* type */
@@ -724,8 +724,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_MOVW_PREL_NC",  /* name */
         FALSE,                 /* partial_inplace */
-        0x0000ffff,            /* src_mask */
-        0x0000ffff,            /* dst_mask */
+        0x000f0fff,            /* src_mask */
+        0x000f0fff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   HOWTO (R_ARM_MOVT_PREL,      /* type */
@@ -738,8 +738,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_MOVT_PREL",     /* name */
         FALSE,                 /* partial_inplace */
-        0x0000ffff,            /* src_mask */
-        0x0000ffff,            /* dst_mask */
+        0x000f0fff,            /* src_mask */
+        0x000f0fff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   HOWTO (R_ARM_THM_MOVW_ABS_NC,        /* type */
@@ -5916,7 +5916,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        if (globals->use_rel)
          {
            addend = ((insn >> 4) & 0xf000) | (insn & 0xfff);
-           signed_addend = (addend ^ 0x10000) - 0x10000;
+           signed_addend = (addend ^ 0x8000) - 0x8000;
          }
 
        value += signed_addend;
@@ -5966,7 +5966,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                   | ((insn >> 15) & 0x0800)
                   | ((insn >> 4)  & 0x0700)
                   | (insn         & 0x00ff);
-           signed_addend = (addend ^ 0x10000) - 0x10000;
+           signed_addend = (addend ^ 0x8000) - 0x8000;
          }
 
        value += signed_addend;
@@ -6548,34 +6548,85 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                  asection *msec;
                  bfd_vma addend, value;
 
-                 if (howto->rightshift)
+                 switch (r_type)
                    {
-                     (*_bfd_error_handler)
-                       (_("%B(%A+0x%lx): %s relocation against SEC_MERGE section"),
-                        input_bfd, input_section,
-                        (long) rel->r_offset, howto->name);
-                     return FALSE;
-                   }
+                   case R_ARM_MOVW_ABS_NC:
+                   case R_ARM_MOVT_ABS:
+                     value = bfd_get_32 (input_bfd, contents + rel->r_offset);
+                     addend = ((value & 0xf0000) >> 4) | (value & 0xfff);
+                     addend = (addend ^ 0x8000) - 0x8000;
+                     break;
 
-                 value = bfd_get_32 (input_bfd, contents + rel->r_offset);
+                   case R_ARM_THM_MOVW_ABS_NC:
+                   case R_ARM_THM_MOVT_ABS:
+                     value = bfd_get_16 (input_bfd, contents + rel->r_offset)
+                             << 16;
+                     value |= bfd_get_16 (input_bfd,
+                                          contents + rel->r_offset + 2);
+                     addend = ((value & 0xf7000) >> 4) | (value & 0xff)
+                              | ((value & 0x04000000) >> 15);
+                     addend = (addend ^ 0x8000) - 0x8000;
+                     break;
 
-                 /* Get the (signed) value from the instruction.  */
-                 addend = value & howto->src_mask;
-                 if (addend & ((howto->src_mask + 1) >> 1))
-                   {
-                     bfd_signed_vma mask;
+                   default:
+                     if (howto->rightshift
+                         || (howto->src_mask & (howto->src_mask + 1)))
+                       {
+                         (*_bfd_error_handler)
+                           (_("%B(%A+0x%lx): %s relocation against SEC_MERGE section"),
+                            input_bfd, input_section,
+                            (long) rel->r_offset, howto->name);
+                         return FALSE;
+                       }
+
+                     value = bfd_get_32 (input_bfd, contents + rel->r_offset);
 
-                     mask = -1;
-                     mask &= ~ howto->src_mask;
-                     addend |= mask;
+                     /* Get the (signed) value from the instruction.  */
+                     addend = value & howto->src_mask;
+                     if (addend & ((howto->src_mask + 1) >> 1))
+                       {
+                         bfd_signed_vma mask;
+
+                         mask = -1;
+                         mask &= ~ howto->src_mask;
+                         addend |= mask;
+                       }
+                     break;
                    }
+
                  msec = sec;
                  addend =
                    _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend)
                    - relocation;
                  addend += msec->output_section->vma + msec->output_offset;
-                 value = (value & ~ howto->dst_mask) | (addend & howto->dst_mask);
-                 bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+
+                 /* Cases here must match those in the preceeding
+                    switch statement.  */
+                 switch (r_type)
+                   {
+                   case R_ARM_MOVW_ABS_NC:
+                   case R_ARM_MOVT_ABS:
+                     value = (value & 0xfff0f000) | ((addend & 0xf000) << 4)
+                             | (addend & 0xfff);
+                     bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                     break;
+
+                   case R_ARM_THM_MOVW_ABS_NC:
+                   case R_ARM_THM_MOVT_ABS:
+                     value = (value & 0xfbf08f00) | ((addend & 0xf700) << 4)
+                             | (addend & 0xff) | ((addend & 0x0800) << 15);
+                     bfd_put_16 (input_bfd, value >> 16,
+                                 contents + rel->r_offset);
+                     bfd_put_16 (input_bfd, value,
+                                 contents + rel->r_offset + 2);
+                     break;
+
+                   default:
+                     value = (value & ~ howto->dst_mask)
+                             | (addend & howto->dst_mask);
+                     bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                     break;
+                   }
                }
            }
          else
@@ -7663,6 +7714,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
   asection *sreloc;
   bfd_vma *local_got_offsets;
   struct elf32_arm_link_hash_table *htab;
+  bfd_boolean needs_plt;
 
   if (info->relocatable)
     return TRUE;
@@ -7804,10 +7856,6 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
              break;
            /* Fall through */
 
-         case R_ARM_ABS32:
-         case R_ARM_ABS32_NOI:
-         case R_ARM_REL32:
-         case R_ARM_REL32_NOI:
          case R_ARM_PC24:
          case R_ARM_PLT32:
          case R_ARM_CALL:
@@ -7816,6 +7864,13 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          case R_ARM_THM_CALL:
          case R_ARM_THM_JUMP24:
          case R_ARM_THM_JUMP19:
+           needs_plt = 1;
+           goto normal_reloc;
+
+         case R_ARM_ABS32:
+         case R_ARM_ABS32_NOI:
+         case R_ARM_REL32:
+         case R_ARM_REL32_NOI:
          case R_ARM_MOVW_ABS_NC:
          case R_ARM_MOVT_ABS:
          case R_ARM_MOVW_PREL_NC:
@@ -7824,6 +7879,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          case R_ARM_THM_MOVT_ABS:
          case R_ARM_THM_MOVW_PREL_NC:
          case R_ARM_THM_MOVT_PREL:
+           needs_plt = 0;
+         normal_reloc:
+
            /* Should the interworking branches be listed here?  */
            if (h != NULL)
              {
@@ -7840,11 +7898,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                   refers to is in a different object.  We can't tell for
                   sure yet, because something later might force the
                   symbol local.  */
-               if (r_type != R_ARM_ABS32
-                    && r_type != R_ARM_REL32
-                    && r_type != R_ARM_ABS32_NOI
-                    && r_type != R_ARM_REL32_NOI
-                    && r_type != R_ARM_ABS12)
+               if (needs_plt)
                  h->needs_plt = 1;
 
                /* If we create a PLT entry, this relocation will reference
index bb8a91eae0e95a3ba6e7b991c93eb3c382394a7e..b360a4b00addd575159b685d2c8461f002a6833e 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-07  Paul Brook  <paul@codesourcery.com>
+
+       * config/tc-arm.c (md_apply_fix): Use correct offset range.
+
 2008-03-07  Alan Modra  <amodra@bigpond.net.au>
 
        * config/tc-ppc.c (ppc_setup_opcodes): Tidy.  Add code to test
index 48fb1522f80980ef9eb9e695a19c2b72185dbc83..161b644ccbe65539fbcad55736f127811c0425f5 100644 (file)
@@ -18804,7 +18804,7 @@ md_apply_fix (fixS *    fixP,
          /* REL format relocations are limited to a 16-bit addend.  */
          if (!fixP->fx_done)
            {
-             if (value < -0x1000 || value > 0xffff)
+             if (value < -0x8000 || value > 0x7fff)
                  as_bad_where (fixP->fx_file, fixP->fx_line,
                                _("offset out of range"));
            }
index 91eb52f99d1ff9093b0ad8d73b7bf9b3ff552a5d..a30eba94338793bedc7ecabc4a997913b984062d 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-07  Paul Brook  <paul@codesourcery.com>
+
+       * ld-arm/arm-elf.exp (armelftests): Add movw-merge and arm-app-movw.
+       * ld-arm/arm-app-movw.s: New test.
+       * ld-arm/arm-app.r: Update expected output.
+       * ld-arm/movw-merge.d: New test.
+       * ld-arm/movw-merge.s: New test.
+
 2008-03-01  Alan Modra  <amodra@bigpond.net.au>
 
        * ld-powerpc/relbrlt.d: Update.  Also check .branch_lt section.
diff --git a/ld/testsuite/ld-arm/arm-app-movw.s b/ld/testsuite/ld-arm/arm-app-movw.s
new file mode 100644 (file)
index 0000000..55ced97
--- /dev/null
@@ -0,0 +1,11 @@
+       .text
+       .globl _start
+_start:
+       movw    r0, #:lower16:data_obj
+       movt    r0, #:upper16:data_obj
+       movw    r0, #:lower16:lib_func1
+       movt    r0, #:upper16:lib_func1
+
+       .globl app_func2
+app_func2:
+       bx      lr
index a24939281b59105770e62e2130548cb63ef65b91..4b25e70c0343c2e8e587647c47b3559dff6ca098 100644 (file)
@@ -1,5 +1,5 @@
 
-tmpdir/arm-app:     file format elf32-(little|big)arm
+tmpdir/arm-app.*:     file format elf32-(little|big)arm
 
 DYNAMIC RELOCATION RECORDS
 OFFSET   TYPE              VALUE 
index 3f2b69c1ac685d68add9b82338bb8c762142b50e..7c6ee2134fbab990d297e59912e25271452722f2 100644 (file)
@@ -176,6 +176,12 @@ set armelftests {
     {"ARMv4 interworking" "-static -T arm.ld --fix-v4bx-interworking" "--fix-v4bx -meabi=4" {armv4-bx.s}
      {{objdump -d armv4-bx.d}}
      "armv4-bx"}
+    {"MOVW/MOVT and merged sections" "-T arm.ld" "" {movw-merge.s}
+     {{objdump -dw movw-merge.d}}
+     "movw-merge"}
+    {"MOVW/MOVT against shared libraries" "tmpdir/arm-lib.so" "" {arm-app-movw.s}
+     {{objdump -Rw arm-app.r}}
+     "arm-app-movw"}
 }
 
 run_ld_link_tests $armelftests
diff --git a/ld/testsuite/ld-arm/movw-merge.d b/ld/testsuite/ld-arm/movw-merge.d
new file mode 100644 (file)
index 0000000..2df4737
--- /dev/null
@@ -0,0 +1,13 @@
+
+.*:     file format.*
+
+Disassembly of section .text:
+
+00008000 <[^>]*>:
+    8000:      e3080013        movw    r0, #32787      ; 0x8013
+    8004:      e3400000        movt    r0, #0  ; 0x0
+
+00008008 <[^>]*>:
+    8008:      f248 0013       movw    r0, #32787      ; 0x8013
+    800c:      f2c0 0000       movt    r0, #0  ; 0x0
+
diff --git a/ld/testsuite/ld-arm/movw-merge.s b/ld/testsuite/ld-arm/movw-merge.s
new file mode 100644 (file)
index 0000000..17c70a5
--- /dev/null
@@ -0,0 +1,20 @@
+       .arch armv7-a
+       .syntax unified
+       .text
+       .global _start
+       .type   _start, %function
+_start:
+       movw    r0, #:lower16:.LC0
+       movt    r0, #:upper16:.LC0
+       .thumb
+       .global tfunc
+       .type   tfunc, %function
+tfunc:
+       movw    r0, #:lower16:.LC0
+       movt    r0, #:upper16:.LC0
+
+       .section        .rodata.str1.4,"aMS",%progbits,1
+       .align  2
+       .ascii "pad"
+.LC0:
+       .ascii  "inner: cont \000"