* libxcoff.h (struct xcoff_backend_data_rec): Constify src param
[binutils-gdb.git] / bfd / coff-arm.c
index 95e65cd43cddf0332abeae1f80eb91fe74e283ee..bfedfdbc68af007e7af1c07637e2487108949275 100644 (file)
@@ -1,5 +1,6 @@
 /* BFD back-end for ARM COFF files.
-   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -853,6 +854,7 @@ coff_arm_reloc_type_lookup (abfd, code)
       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9,  ARM_THUMB9);
       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23);
+      ASTD (BFD_RELOC_THUMB_PCREL_BLX,      ARM_THUMB23);
 #endif
     default: return (CONST struct reloc_howto_struct *) 0;
     }
@@ -992,7 +994,6 @@ insert_thumb_branch (br_insn, rel_off)
 
   return br_insn;
 }
-
 \f
 static struct coff_link_hash_entry *
 find_thumb_glue (info, name, input_bfd)
@@ -1243,12 +1244,18 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
         {
           if (info->relocateable)
             continue;
-#if 0  /* We must not ignore the symbol value.  If the symbol is
-         within the same section, the relocation should have already
-         been fixed, but if it is not, we'll be handed a reloc into
-         the beginning of the symbol's section, so we must not cancel
-         out the symbol's value, otherwise we'll be adding it in
-         twice.  */
+         /* FIXME - it is not clear which targets need this next test
+            and which do not.  It is known that it is needed for the
+            VxWorks and EPOC-PE targets, but it is also known that it
+            was supressed for other ARM targets.  This ought to be
+            sorted out one day.  */
+#ifdef ARM_COFF_BUGFIX
+         /* We must not ignore the symbol value.  If the symbol is
+            within the same section, the relocation should have already
+            been fixed, but if it is not, we'll be handed a reloc into
+            the beginning of the symbol's section, so we must not cancel
+            out the symbol's value, otherwise we'll be adding it in
+            twice.  */
           if (sym != NULL && sym->n_scnum != 0)
             addend += sym->n_value;
 #endif
@@ -1588,18 +1595,18 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
 
              BFD_ASSERT (size == 4);
 
-              /* howto->pc_relative should be TRUE for type 14 BRANCH23 */
+              /* howto->pc_relative should be TRUE for type 14 BRANCH23 */
               relocation -= (input_section->output_section->vma
                              + input_section->output_offset);
 
-              /* howto->pcrel_offset should be TRUE for type 14 BRANCH23 */
+              /* howto->pcrel_offset should be TRUE for type 14 BRANCH23 */
               relocation -= address;
 
              /* No need to negate the relocation with BRANCH23.  */
              /* howto->complain_on_overflow == complain_overflow_signed for BRANCH23.  */
              /* howto->rightshift == 1 */
-             /* Drop unwanted bits from the value we are relocating to.  */
 
+             /* Drop unwanted bits from the value we are relocating to.  */
              check = relocation >> howto->rightshift;
 
              /* If this is a signed value, the rightshift just dropped
@@ -1613,13 +1620,9 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
 
              /* Get the value from the object file.  */
              if (bfd_big_endian (input_bfd))
-               {
-                 add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
-               }
+               add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
              else
-               {
-                 add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
-               }
+               add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
 
              /* Get the value from the object file with an appropriate sign.
                 The expression involving howto->src_mask isolates the upper
@@ -1629,18 +1632,16 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                 can not get the upper bit, but that does not matter since
                 signed_add needs no adjustment to become negative in that
                 case.  */
-
              signed_add = add;
 
              if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
                signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
 
+             /* howto->bitpos == 0 */
              /* Add the value from the object file, shifted so that it is a
                 straight number.  */
-             /* howto->bitpos == 0 */
-
              signed_check += signed_add;
-             relocation += signed_add;
+             relocation   += signed_add;
 
              BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
 
@@ -1649,21 +1650,26 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                  || signed_check < reloc_signed_min)
                overflow = true;
 
-             /* Put RELOCATION into the correct bits:  */
-
+             /* For the BLX(1) instruction remove bit 0 of the adjusted offset.
+                Bit 0 can only be set if the upper insn is at a half-word boundary,
+                since the destination address, an ARM instruction, must always be
+                on a word boundary.  The semantics of the BLX (1) instruction,
+                however, are that bit 0 in the offset must always be 0, and the
+                corresponding bit 1 in the target address will be set from bit
+                1 of the source address.  */
+             if ((x & 0x18000000) == 0x08000000)
+               relocation &= ~0x2;
+
+             /* Put the relocation into the correct bits.  */
              if (bfd_big_endian (input_bfd))
-               {
-                 relocation = (((relocation & 0xffe) >> 1)  | ((relocation << 4) & 0x07ff0000));
-               }
+               relocation = (((relocation & 0xffe) >> 1)  | ((relocation << 4) & 0x07ff0000));
              else
-               {
-                 relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
-               }
+               relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
 
-             /* Add RELOCATION to the correct bits of X:  */
+             /* Add the relocation to the correct bits of X.  */
              x = ((x & ~howto->dst_mask) | relocation);
 
-             /* Put the relocated value back in the object file:  */
+             /* Put the relocated value back in the object file.  */
              bfd_put_32 (input_bfd, x, location);
 
              rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;
@@ -2435,8 +2441,8 @@ coff_arm_copy_private_bfd_data (src, dest)
 }
 
 /* Note:  the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
*must* match the definitions in gcc/config/arm/coff.h and semi.h */
-#define LOCAL_LABEL_PREFIX "."
  *must* match the definitions in gcc/config/arm/{coff|semi|aout}.h.  */
+#define LOCAL_LABEL_PREFIX ""
 #ifndef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX "_"
 #endif
@@ -2536,11 +2542,13 @@ coff_arm_final_link_postscript (abfd, pfinfo)
 #define TARGET_UNDERSCORE 0
 #endif
 
+#ifndef EXTRA_S_FLAGS
 #ifdef COFF_WITH_PE
 #define EXTRA_S_FLAGS (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
 #else
 #define EXTRA_S_FLAGS 0
 #endif
+#endif
 
 /* Forward declaration for use initialising alternative_target field.  */
 extern const bfd_target TARGET_BIG_SYM ;
@@ -2548,4 +2556,3 @@ extern const bfd_target TARGET_BIG_SYM ;
 /* Target vectors.  */
 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM)
 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM)
-