2009-01-15 Andrew Stubbs <ams@codesourcery.com>
authorAndrew Stubbs <andrew.stubbs@st.com>
Thu, 15 Jan 2009 18:00:49 +0000 (18:00 +0000)
committerAndrew Stubbs <andrew.stubbs@st.com>
Thu, 15 Jan 2009 18:00:49 +0000 (18:00 +0000)
    Julian Brown   <julian@codesourcery.com>

bfd/
* elf-bfd.h (NUM_KNOWN_OBJ_ATTRIBUTES): Set to 71 to include all known
ARM attributes in ABI 2.07.
* elf32-arm.c (get_secondary_compatible_arch): New function.
(set_secondary_compatible_arch): New function.
(tag_cpu_arch_combine): New function.
(elf32_arm_copy_one_eabi_other_attribute): Delete function.
(elf32_arm_copy_eabi_other_attribute_list): Delete function.
(elf32_arm_merge_eabi_attributes): Rename order_312 to order_021 to
make it fit with order_01243.
Add support for Tag_also_compatible_with,
Tag_CPU_unaligned_access, Tag_T2EE_use, Tag_Virtualization_use,
Tag_MPextension_use, Tag_nodefaults and Tag_conformance.
Improve/tidy up support for Tag_CPU_raw_name, Tag_CPU_name,
Tag_CPU_arch, Tag_ABI_HardFP_use, Tag_VFP_HP_extension,
Tag_ABI_FP_denormal, Tag_ABI_PCS_GOT_use, Tag_ABI_align8_needed,
Tag_VFP_arch and Tag_ABI_FP_16bit_format.
Rework the way unknown attributes are handled.
Defer errors until all attributes have been processed.

gas/
* config/tc-arm.c (cpu_arch): Change ARM_ARCH_V6M to 11.

include/elf/
* arm.h (TAG_CPU_ARCH_V6_M, TAG_CPU_ARCH_V6S_M): New defines.
(MAX_TAG_CPU_ARCH, TAG_CPU_ARCH_V4T_PLUS_V6_M): New defines.
(Tag_NEON_arch): Rename to Tag_Advanced_SIMD_arch to match ARM ABI
version 2.07.
(Tag_undefined39, Tag_nodefaults): New enum values.
(Tag_also_compatible_with, Tag_T2EE_use): Likewise.
(Tag_conformance, Tag_Virtualization_use): Likewise.
(Tag_undefined69, Tag_MPextension_use): Likewise.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-arm.c
gas/ChangeLog
gas/config/tc-arm.c
include/elf/ChangeLog
include/elf/arm.h

index 84426d6a7fd1606f36bfd7861e17fb0c0fe23a67..75c36933a9a3b4c2b3a5f36bab87325444e104a1 100644 (file)
@@ -1,3 +1,25 @@
+2009-01-15  Andrew Stubbs  <ams@codesourcery.com>
+           Julian Brown   <julian@codesourcery.com>
+
+       * elf-bfd.h (NUM_KNOWN_OBJ_ATTRIBUTES): Set to 71 to include all known
+       ARM attributes in ABI 2.07.
+       * elf32-arm.c (get_secondary_compatible_arch): New function.
+       (set_secondary_compatible_arch): New function.
+       (tag_cpu_arch_combine): New function.
+       (elf32_arm_copy_one_eabi_other_attribute): Delete function.
+       (elf32_arm_copy_eabi_other_attribute_list): Delete function.
+       (elf32_arm_merge_eabi_attributes): Rename order_312 to order_021 to
+       make it fit with order_01243.
+       Add support for Tag_also_compatible_with,
+       Tag_CPU_unaligned_access, Tag_T2EE_use, Tag_Virtualization_use,
+       Tag_MPextension_use, Tag_nodefaults and Tag_conformance.
+       Improve/tidy up support for Tag_CPU_raw_name, Tag_CPU_name,
+       Tag_CPU_arch, Tag_ABI_HardFP_use, Tag_VFP_HP_extension,
+       Tag_ABI_FP_denormal, Tag_ABI_PCS_GOT_use, Tag_ABI_align8_needed,
+       Tag_VFP_arch and Tag_ABI_FP_16bit_format.
+       Rework the way unknown attributes are handled.
+       Defer errors until all attributes have been processed.
+
 2009-01-15  Andrew Stubbs  <ams@codesourcery.com>
 
        * elf-attrs.c (bfd_elf_add_obj_attr_compat): Rename to
index 5e13a653d1b5e28e882acbd32f48e8d483b298c3..14825a45cd6dae07d8a502c8ee8884224949d63b 100644 (file)
@@ -1369,7 +1369,7 @@ struct elf_find_verdep_info
 };
 
 /* The maximum number of known object attributes for any target.  */
-#define NUM_KNOWN_OBJ_ATTRIBUTES 33
+#define NUM_KNOWN_OBJ_ATTRIBUTES 71
 
 /* The value of an object attribute.  type & 1 indicates whether there
    is an integer value; type & 2 indicates whether there is a string
index 705d4fc3882cfb8ed5758ad767d2ad71d9085265..ece1a56ccfcb300a175e9f9bc3b9282da1c5df1d 100644 (file)
@@ -8147,31 +8147,207 @@ elf32_arm_obj_attrs_arg_type (int tag)
     return (tag & 1) != 0 ? 2 : 1;
 }
 
+/* Read the architecture from the Tag_also_compatible_with attribute, if any.
+   Returns -1 if no architecture could be read.  */
+
+static int
+get_secondary_compatible_arch (bfd *abfd)
+{
+  obj_attribute *attr =
+    &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with];
+
+  /* Note: the tag and its argument below are uleb128 values, though
+     currently-defined values fit in one byte for each.  */
+  if (attr->s
+      && attr->s[0] == Tag_CPU_arch
+      && (attr->s[1] & 128) != 128
+      && attr->s[2] == 0)
+   return attr->s[1];
+
+  /* This tag is "safely ignorable", so don't complain if it looks funny.  */
+  return -1;
+}
+
+/* Set, or unset, the architecture of the Tag_also_compatible_with attribute.
+   The tag is removed if ARCH is -1.  */
+
 static void
-elf32_arm_copy_one_eabi_other_attribute (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
+set_secondary_compatible_arch (bfd *abfd, int arch)
 {
-  switch (in_list->tag)
-    {
-    case Tag_VFP_HP_extension:
-    case Tag_ABI_FP_16bit_format:
-      bfd_elf_add_obj_attr_int (obfd, OBJ_ATTR_PROC, in_list->tag, in_list->attr.i);
-      break;
+  obj_attribute *attr =
+    &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with];
 
-    default:
-      if ((in_list->tag & 127) < 64)
-       {
-         _bfd_error_handler
-             (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
-         break;
-       }
+  if (arch == -1)
+    {
+      attr->s = NULL;
+      return;
     }
+
+  /* Note: the tag and its argument below are uleb128 values, though
+     currently-defined values fit in one byte for each.  */
+  if (!attr->s)
+    attr->s = bfd_alloc (abfd, 3);
+  attr->s[0] = Tag_CPU_arch;
+  attr->s[1] = arch;
+  attr->s[2] = '\0';
 }
 
-static void 
-elf32_arm_copy_eabi_other_attribute_list (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
-{
-  for (; in_list; in_list = in_list->next )
-    elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
+/* Combine two values for Tag_CPU_arch, taking secondary compatibility tags
+   into account.  */
+
+static int
+tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
+                     int newtag, int secondary_compat)
+{
+#define T(X) TAG_CPU_ARCH_##X
+  int tagl, tagh, result;
+  const int v6t2[] =
+    {
+      T(V6T2),   /* PRE_V4.  */
+      T(V6T2),   /* V4.  */
+      T(V6T2),   /* V4T.  */
+      T(V6T2),   /* V5T.  */
+      T(V6T2),   /* V5TE.  */
+      T(V6T2),   /* V5TEJ.  */
+      T(V6T2),   /* V6.  */
+      T(V7),     /* V6KZ.  */
+      T(V6T2)    /* V6T2.  */
+    };
+  const int v6k[] =
+    {
+      T(V6K),    /* PRE_V4.  */
+      T(V6K),    /* V4.  */
+      T(V6K),    /* V4T.  */
+      T(V6K),    /* V5T.  */
+      T(V6K),    /* V5TE.  */
+      T(V6K),    /* V5TEJ.  */
+      T(V6K),    /* V6.  */
+      T(V6KZ),   /* V6KZ.  */
+      T(V7),     /* V6T2.  */
+      T(V6K)     /* V6K.  */
+    };
+  const int v7[] =
+    {
+      T(V7),     /* PRE_V4.  */
+      T(V7),     /* V4.  */
+      T(V7),     /* V4T.  */
+      T(V7),     /* V5T.  */
+      T(V7),     /* V5TE.  */
+      T(V7),     /* V5TEJ.  */
+      T(V7),     /* V6.  */
+      T(V7),     /* V6KZ.  */
+      T(V7),     /* V6T2.  */
+      T(V7),     /* V6K.  */
+      T(V7)      /* V7.  */
+    };
+  const int v6_m[] =
+    {
+      -1,        /* PRE_V4.  */
+      -1,        /* V4.  */
+      T(V6K),    /* V4T.  */
+      T(V6K),    /* V5T.  */
+      T(V6K),    /* V5TE.  */
+      T(V6K),    /* V5TEJ.  */
+      T(V6K),    /* V6.  */
+      T(V6KZ),   /* V6KZ.  */
+      T(V7),     /* V6T2.  */
+      T(V6K),    /* V6K.  */
+      T(V7),     /* V7.  */
+      T(V6_M)    /* V6_M.  */
+    };
+  const int v6s_m[] =
+    {
+      -1,        /* PRE_V4.  */
+      -1,        /* V4.  */
+      T(V6K),    /* V4T.  */
+      T(V6K),    /* V5T.  */
+      T(V6K),    /* V5TE.  */
+      T(V6K),    /* V5TEJ.  */
+      T(V6K),    /* V6.  */
+      T(V6KZ),   /* V6KZ.  */
+      T(V7),     /* V6T2.  */
+      T(V6K),    /* V6K.  */
+      T(V7),     /* V7.  */
+      T(V6S_M),  /* V6_M.  */
+      T(V6S_M)   /* V6S_M.  */
+    };
+  const int v4t_plus_v6_m[] =
+    {
+      -1,              /* PRE_V4.  */
+      -1,              /* V4.  */
+      T(V4T),          /* V4T.  */
+      T(V5T),          /* V5T.  */
+      T(V5TE),         /* V5TE.  */
+      T(V5TEJ),                /* V5TEJ.  */
+      T(V6),           /* V6.  */
+      T(V6KZ),         /* V6KZ.  */
+      T(V6T2),         /* V6T2.  */
+      T(V6K),          /* V6K.  */
+      T(V7),           /* V7.  */
+      T(V6_M),         /* V6_M.  */
+      T(V6S_M),                /* V6S_M.  */
+      T(V4T_PLUS_V6_M) /* V4T plus V6_M.  */
+    };
+  const int *comb[] =
+    {
+      v6t2,
+      v6k,
+      v7,
+      v6_m,
+      v6s_m,
+      /* Pseudo-architecture.  */
+      v4t_plus_v6_m
+    };
+
+  /* Check we've not got a higher architecture than we know about.  */
+
+  if (oldtag >= MAX_TAG_CPU_ARCH || newtag >= MAX_TAG_CPU_ARCH)
+    {
+      _bfd_error_handler (_("ERROR: %B: Unknown CPU architecture"), ibfd);
+      return -1;
+    }
+
+  /* Override old tag if we have a Tag_also_compatible_with on the output.  */
+
+  if ((oldtag == T(V6_M) && *secondary_compat_out == T(V4T))
+      || (oldtag == T(V4T) && *secondary_compat_out == T(V6_M)))
+    oldtag = T(V4T_PLUS_V6_M);
+
+  /* And override the new tag if we have a Tag_also_compatible_with on the
+     input.  */
+
+  if ((newtag == T(V6_M) && secondary_compat == T(V4T))
+      || (newtag == T(V4T) && secondary_compat == T(V6_M)))
+    newtag = T(V4T_PLUS_V6_M);
+
+  tagl = (oldtag < newtag) ? oldtag : newtag;
+  result = tagh = (oldtag > newtag) ? oldtag : newtag;
+
+  /* Architectures before V6KZ add features monotonically.  */
+  if (tagh <= TAG_CPU_ARCH_V6KZ)
+    return result;
+
+  result = comb[tagh - T(V6T2)][tagl];
+
+  /* Use Tag_CPU_arch == V4T and Tag_also_compatible_with (Tag_CPU_arch V6_M)
+     as the canonical version.  */
+  if (result == T(V4T_PLUS_V6_M))
+    {
+      result = T(V4T);
+      *secondary_compat_out = T(V6_M);
+    }
+  else
+    *secondary_compat_out = -1;
+
+  if (result == -1)
+    {
+      _bfd_error_handler (_("ERROR: %B: Conflicting CPU architectures %d/%d"),
+                         ibfd, oldtag, newtag);
+      return -1;
+    }
+
+  return result;
+#undef T
 }
 
 /* Merge EABI object attributes from IBFD into OBFD.  Raise an error if there
@@ -8184,12 +8360,14 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
   obj_attribute *out_attr;
   obj_attribute_list *in_list;
   obj_attribute_list *out_list;
+  obj_attribute_list **out_listp;
   /* Some tags have 0 = don't care, 1 = strong requirement,
      2 = weak requirement.  */
-  static const int order_312[3] = {3, 1, 2};
+  static const int order_021[3] = {0, 2, 1};
   /* For use with Tag_VFP_arch.  */
   static const int order_01243[5] = {0, 1, 2, 4, 3};
   int i;
+  bfd_boolean result = TRUE;
 
   if (!elf_known_obj_attributes_proc (obfd)[0].i)
     {
@@ -8216,7 +8394,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
          _bfd_error_handler
            (_("ERROR: %B uses VFP register arguments, %B does not"),
             ibfd, obfd);
-         return FALSE;
+         result = FALSE;
        }
     }
 
@@ -8227,12 +8405,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
        {
        case Tag_CPU_raw_name:
        case Tag_CPU_name:
-         /* Use whichever has the greatest architecture requirements.  We
-            won't necessarily have both the above tags, so make sure input
-            name is non-NULL.  */
-         if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i
-             && in_attr[i].s)
-           out_attr[i].s = _bfd_elf_attr_strdup (obfd, in_attr[i].s);
+         /* These are merged after Tag_CPU_arch. */
          break;
 
        case Tag_ABI_optimization_goals:
@@ -8241,38 +8414,148 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
          break;
 
        case Tag_CPU_arch:
+         {
+           int secondary_compat = -1, secondary_compat_out = -1;
+           unsigned int saved_out_attr = out_attr[i].i;
+           static const char *name_table[] = {
+               /* These aren't real CPU names, but we can't guess
+                  that from the architecture version alone.  */
+               "Pre v4",
+               "ARM v4",
+               "ARM v4T",
+               "ARM v5T",
+               "ARM v5TE",
+               "ARM v5TEJ",
+               "ARM v6",
+               "ARM v6KZ",
+               "ARM v6T2",
+               "ARM v6K",
+               "ARM v7",
+               "ARM v6-M",
+               "ARM v6S-M"
+           };
+
+           /* Merge Tag_CPU_arch and Tag_also_compatible_with.  */
+           secondary_compat = get_secondary_compatible_arch (ibfd);
+           secondary_compat_out = get_secondary_compatible_arch (obfd);
+           out_attr[i].i = tag_cpu_arch_combine (ibfd, out_attr[i].i,
+                                                 &secondary_compat_out,
+                                                 in_attr[i].i,
+                                                 secondary_compat);
+           set_secondary_compatible_arch (obfd, secondary_compat_out);
+
+           /* Merge Tag_CPU_name and Tag_CPU_raw_name.  */
+           if (out_attr[i].i == saved_out_attr)
+             ; /* Leave the names alone.  */
+           else if (out_attr[i].i == in_attr[i].i)
+             {
+               /* The output architecture has been changed to match the
+                  input architecture.  Use the input names.  */
+               out_attr[Tag_CPU_name].s = in_attr[Tag_CPU_name].s
+                 ? _bfd_elf_attr_strdup (obfd, in_attr[Tag_CPU_name].s)
+                 : NULL;
+               out_attr[Tag_CPU_raw_name].s = in_attr[Tag_CPU_raw_name].s
+                 ? _bfd_elf_attr_strdup (obfd, in_attr[Tag_CPU_raw_name].s)
+                 : NULL;
+             }
+           else
+             {
+               out_attr[Tag_CPU_name].s = NULL;
+               out_attr[Tag_CPU_raw_name].s = NULL;
+             }
+
+           /* If we still don't have a value for Tag_CPU_name,
+              make one up now.  Tag_CPU_raw_name remains blank.  */
+           if (out_attr[Tag_CPU_name].s == NULL
+               && out_attr[i].i < ARRAY_SIZE (name_table))
+             out_attr[Tag_CPU_name].s =
+               _bfd_elf_attr_strdup (obfd, name_table[out_attr[i].i]);
+         }
+         break;
+
        case Tag_ARM_ISA_use:
        case Tag_THUMB_ISA_use:
        case Tag_WMMX_arch:
-       case Tag_NEON_arch:
-         /* ??? Do NEON and WMMX conflict?  */
+       case Tag_Advanced_SIMD_arch:
+         /* ??? Do Advanced_SIMD (NEON) and WMMX conflict?  */
        case Tag_ABI_FP_rounding:
-       case Tag_ABI_FP_denormal:
        case Tag_ABI_FP_exceptions:
        case Tag_ABI_FP_user_exceptions:
        case Tag_ABI_FP_number_model:
-       case Tag_ABI_align8_preserved:
-       case Tag_ABI_HardFP_use:
+       case Tag_VFP_HP_extension:
+       case Tag_CPU_unaligned_access:
+       case Tag_T2EE_use:
+       case Tag_Virtualization_use:
+       case Tag_MPextension_use:
          /* Use the largest value specified.  */
          if (in_attr[i].i > out_attr[i].i)
            out_attr[i].i = in_attr[i].i;
          break;
 
-       case Tag_CPU_arch_profile:
-         /* Warn if conflicting architecture profiles used.  */
-         if (out_attr[i].i && in_attr[i].i && in_attr[i].i != out_attr[i].i)
+       case Tag_ABI_align8_preserved:
+       case Tag_ABI_PCS_RO_data:
+         /* Use the smallest value specified.  */
+         if (in_attr[i].i < out_attr[i].i)
+           out_attr[i].i = in_attr[i].i;
+         break;
+
+       case Tag_ABI_align8_needed:
+         if ((in_attr[i].i > 0 || out_attr[i].i > 0)
+             && (in_attr[Tag_ABI_align8_preserved].i == 0
+                 || out_attr[Tag_ABI_align8_preserved].i == 0))
            {
+             /* This error message should be enabled once all non-conformant
+                binaries in the toolchain have had the attributes set
+                properly.
              _bfd_error_handler
-               (_("ERROR: %B: Conflicting architecture profiles %c/%c"),
-                ibfd, in_attr[i].i, out_attr[i].i);
-             return FALSE;
+               (_("ERROR: %B: 8-byte data alignment conflicts with %B"),
+                obfd, ibfd);
+             result = FALSE; */
            }
-         if (in_attr[i].i)
+         /* Fall through.  */
+       case Tag_ABI_FP_denormal:
+       case Tag_ABI_PCS_GOT_use:
+         /* Use the "greatest" from the sequence 0, 2, 1, or the largest
+            value if greater than 2 (for future-proofing).  */
+         if ((in_attr[i].i > 2 && in_attr[i].i > out_attr[i].i)
+             || (in_attr[i].i <= 2 && out_attr[i].i <= 2
+                 && order_021[in_attr[i].i] > order_021[out_attr[i].i]))
            out_attr[i].i = in_attr[i].i;
          break;
+
+
+       case Tag_CPU_arch_profile:
+         if (out_attr[i].i != in_attr[i].i)
+           {
+             /* 0 will merge with anything.
+                'A' and 'S' merge to 'A'.
+                'R' and 'S' merge to 'R'.
+                'M' and 'A|R|S' is an error.  */
+             if (out_attr[i].i == 0
+                 || (out_attr[i].i == 'S'
+                     && (in_attr[i].i == 'A' || in_attr[i].i == 'R')))
+               out_attr[i].i = in_attr[i].i;
+             else if (in_attr[i].i == 0
+                      || (in_attr[i].i == 'S'
+                          && (out_attr[i].i == 'A' || out_attr[i].i == 'R')))
+               ; /* Do nothing. */
+             else
+               {
+                 _bfd_error_handler
+                   (_("ERROR: %B: Conflicting architecture profiles %c/%c"),
+                    ibfd,
+                    in_attr[i].i ? in_attr[i].i : '0',
+                    out_attr[i].i ? out_attr[i].i : '0');
+                 result = FALSE;
+               }
+           }
+         break;
        case Tag_VFP_arch:
-         if (in_attr[i].i > 4 || out_attr[i].i > 4
-             || order_01243[in_attr[i].i] > order_01243[out_attr[i].i])
+         /* Use the "greatest" from the sequence 0, 1, 2, 4, 3, or the
+            largest value if greater than 4 (for future-proofing).  */
+         if ((in_attr[i].i > 4 && in_attr[i].i > out_attr[i].i)
+             || (in_attr[i].i <= 4 && out_attr[i].i <= 4
+                 && order_01243[in_attr[i].i] > order_01243[out_attr[i].i]))
            out_attr[i].i = in_attr[i].i;
          break;
        case Tag_PCS_config:
@@ -8293,7 +8576,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
            {
              _bfd_error_handler
                (_("ERROR: %B: Conflicting use of R9"), ibfd);
-             return FALSE;
+             result = FALSE;
            }
          if (out_attr[i].i == AEABI_R9_unused)
            out_attr[i].i = in_attr[i].i;
@@ -8306,22 +8589,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
              _bfd_error_handler
                (_("ERROR: %B: SB relative addressing conflicts with use of R9"),
                 ibfd);
-             return FALSE;
+             result = FALSE;
            }
          /* Use the smallest value specified.  */
          if (in_attr[i].i < out_attr[i].i)
            out_attr[i].i = in_attr[i].i;
          break;
-       case Tag_ABI_PCS_RO_data:
-         /* Use the smallest value specified.  */
-         if (in_attr[i].i < out_attr[i].i)
-           out_attr[i].i = in_attr[i].i;
-         break;
-       case Tag_ABI_PCS_GOT_use:
-         if (in_attr[i].i > 2 || out_attr[i].i > 2
-             || order_312[in_attr[i].i] < order_312[out_attr[i].i])
-           out_attr[i].i = in_attr[i].i;
-         break;
        case Tag_ABI_PCS_wchar_t:
          if (out_attr[i].i && in_attr[i].i && out_attr[i].i != in_attr[i].i
              && !elf_arm_tdata (obfd)->no_wchar_size_warning)
@@ -8333,12 +8606,6 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
          else if (in_attr[i].i && !out_attr[i].i)
            out_attr[i].i = in_attr[i].i;
          break;
-       case Tag_ABI_align8_needed:
-         /* ??? Check against Tag_ABI_align8_preserved.  */
-         if (in_attr[i].i > 2 || out_attr[i].i > 2
-             || order_312[in_attr[i].i] < order_312[out_attr[i].i])
-           out_attr[i].i = in_attr[i].i;
-         break;
        case Tag_ABI_enum_size:
          if (in_attr[i].i != AEABI_enum_unused)
            {
@@ -8353,12 +8620,19 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                       && out_attr[i].i != in_attr[i].i
                       && !elf_arm_tdata (obfd)->no_enum_size_warning)
                {
-                 const char *aeabi_enum_names[] =
+                 static const char *aeabi_enum_names[] =
                    { "", "variable-size", "32-bit", "" };
+                 const char *in_name =
+                   in_attr[i].i < ARRAY_SIZE(aeabi_enum_names)
+                   ? aeabi_enum_names[in_attr[i].i]
+                   : "<unknown>";
+                 const char *out_name =
+                   out_attr[i].i < ARRAY_SIZE(aeabi_enum_names)
+                   ? aeabi_enum_names[out_attr[i].i]
+                   : "<unknown>";
                  _bfd_error_handler
                    (_("warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail"),
-                    ibfd, aeabi_enum_names[in_attr[i].i],
-                    aeabi_enum_names[out_attr[i].i]);
+                    ibfd, in_name, out_name);
                }
            }
          break;
@@ -8371,34 +8645,98 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
              _bfd_error_handler
                (_("ERROR: %B uses iWMMXt register arguments, %B does not"),
                 ibfd, obfd);
-             return FALSE;
+             result = FALSE;
            }
          break;
-
        case Tag_compatibility:
          /* Merged in target-independent code.  */
          break;
+       case Tag_ABI_HardFP_use:
+         /* 1 (SP) and 2 (DP) conflict, so combine to 3 (SP & DP).  */
+         if ((in_attr[i].i == 1 && out_attr[i].i == 2)
+             || (in_attr[i].i == 2 && out_attr[i].i == 1))
+           out_attr[i].i = 3;
+         else if (in_attr[i].i > out_attr[i].i)
+           out_attr[i].i = in_attr[i].i;
+         break;
+       case Tag_ABI_FP_16bit_format:
+         if (in_attr[i].i != 0 && out_attr[i].i != 0)
+           {
+             if (in_attr[i].i != out_attr[i].i)
+               {
+                 _bfd_error_handler
+                   (_("ERROR: fp16 format mismatch between %B and %B"),
+                    ibfd, obfd);
+                 result = FALSE;
+               }
+           }
+         if (in_attr[i].i != 0)
+           out_attr[i].i = in_attr[i].i;
+         break;
 
-       default: /* All known attributes should be explicitly covered.   */
-         abort ();
-       }
+       case Tag_nodefaults:
+         /* This tag is set if it exists, but the value is unused.
+            Unfortunately, we don't record whether each attribute is zero
+            initialized, or read from the file, so the information has been
+            lost.  In any case, we don't write attributes with zero values.
+            Do nothing. */
+         break;
+       case Tag_also_compatible_with:
+         /* Already done in Tag_CPU_arch.  */
+         break;
+       case Tag_conformance:
+         /* Keep the attribute if it matches.  Throw it away otherwise.
+            No attribute means no claim to conform.  */
+         if (!in_attr[i].s || !out_attr[i].s
+             || strcmp (in_attr[i].s, out_attr[i].s) != 0)
+           out_attr[i].s = NULL;
+         break;
 
-      if (in_attr[i].type && !out_attr[i].type)
-       switch (in_attr[i].type)
+       default:
          {
-         case 1:
-           if (out_attr[i].i)
-             out_attr[i].type = 1;
-           break;
+           bfd *err_bfd = NULL;
 
-         case 2:
-           if (out_attr[i].s)
-             out_attr[i].type = 2;
-           break;
+           /* The "known_obj_attributes" table does contain some undefined
+              attributes.  Ensure that there are unused.  */
+           if (out_attr[i].i != 0 || out_attr[i].s != NULL)
+             err_bfd = obfd;
+           else if (in_attr[i].i != 0 || in_attr[i].s != NULL)
+             err_bfd = ibfd;
 
-         default:
-           abort ();
+           if (err_bfd != NULL)
+             {
+               /* Attribute numbers >=64 (mod 128) can be safely ignored.  */
+               if ((i & 127) < 64)
+                 {
+                   _bfd_error_handler
+                     (_("%B: Unknown mandatory EABI object attribute %d"),
+                      err_bfd, i);
+                   bfd_set_error (bfd_error_bad_value);
+                   result = FALSE;
+                 }
+               else
+                 {
+                   _bfd_error_handler
+                     (_("Warning: %B: Unknown EABI object attribute %d"),
+                      err_bfd, i);
+                 }
+             }
+
+           /* Only pass on attributes that match in both inputs.  */
+           if (in_attr[i].i != out_attr[i].i
+               || in_attr[i].s != out_attr[i].s
+               || (in_attr[i].s != NULL && out_attr[i].s != NULL
+                   && strcmp (in_attr[i].s, out_attr[i].s) != 0))
+             {
+               out_attr[i].i = 0;
+               out_attr[i].s = NULL;
+             }
          }
+       }
+
+      /* If out_attr was copied from in_attr then it won't have a type yet.  */
+      if (in_attr[i].type && !out_attr[i].type)
+       out_attr[i].type = in_attr[i].type;
     }
 
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
@@ -8406,67 +8744,78 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
 
   /* Check for any attributes not known on ARM.  */
   in_list = elf_other_obj_attributes_proc (ibfd);
-  out_list = elf_other_obj_attributes_proc (obfd);
+  out_listp = &elf_other_obj_attributes_proc (obfd);
+  out_list = *out_listp;
 
-  for (; in_list != NULL; )
+  for (; in_list || out_list; )
     {
-      if (out_list == NULL)
-       {
-         elf32_arm_copy_eabi_other_attribute_list (ibfd, obfd, in_list);
-         return TRUE;
-       }
+      bfd *err_bfd = NULL;
+      int err_tag = 0;
 
       /* The tags for each list are in numerical order.  */
       /* If the tags are equal, then merge.  */
-      if (in_list->tag == out_list->tag)
-        {
-         switch (in_list->tag)
-           {
-           case Tag_VFP_HP_extension:
-             if (out_list->attr.i == 0)
-               out_list->attr.i = in_list->attr.i;
-             break;
-
-           case Tag_ABI_FP_16bit_format:
-             if (in_list->attr.i != 0 && out_list->attr.i != 0)
-               {
-                 if (in_list->attr.i != out_list->attr.i)
-                   {
-                     _bfd_error_handler
-                       (_("ERROR: fp16 format mismatch between %B and %B"),
-                        ibfd, obfd);
-                     return FALSE;
-                   }
-               }
-             if (in_list->attr.i != 0)
-               out_list->attr.i = in_list->attr.i;
-             break;
-
-           default:
-             if ((in_list->tag & 127) < 64)
-               {
-                 _bfd_error_handler
-                   (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
-                 break;
-               }
-           }
-       }
-      else if (in_list->tag < out_list->tag)
+      if (out_list && (!in_list || in_list->tag > out_list->tag))
        {
-         /* This attribute is in ibfd, but not obfd.  Copy to obfd and advance to
-            next input attribute.  */
-         elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
+         /* This attribute only exists in obfd.  We can't merge, and we don't
+            know what the tag means, so delete it.  */
+         err_bfd = obfd;
+         err_tag = out_list->tag;
+         *out_listp = out_list->next;
+         out_list = *out_listp;
        }
-      if (in_list->tag <= out_list->tag)
+      else if (in_list && (!out_list || in_list->tag < out_list->tag))
        {
+         /* This attribute only exists in ibfd. We can't merge, and we don't
+            know what the tag means, so ignore it.  */
+         err_bfd = ibfd;
+         err_tag = in_list->tag;
          in_list = in_list->next;
-         if (in_list == NULL)
-           continue;
        }
-      while (out_list && out_list->tag < in_list->tag)
-        out_list = out_list->next;
+      else /* The tags are equal.  */
+       {
+         /* As present, all attributes in the list are unknown, and
+            therefore can't be merged meaningfully.  */
+         err_bfd = obfd;
+         err_tag = out_list->tag;
+
+         /*  Only pass on attributes that match in both inputs.  */
+         if (in_list->attr.i != out_list->attr.i
+             || in_list->attr.s != out_list->attr.s
+             || (in_list->attr.s && out_list->attr.s
+                 && strcmp (in_list->attr.s, out_list->attr.s) != 0))
+           {
+             /* No match.  Delete the attribute.  */
+             *out_listp = out_list->next;
+             out_list = *out_listp;
+           }
+         else
+           {
+             /* Matched.  Keep the attribute and move to the next.  */
+             out_list = out_list->next;
+             in_list = in_list->next;
+           }
+       }
+
+      if (err_bfd)
+       {
+         /* Attribute numbers >=64 (mod 128) can be safely ignored.  */
+         if ((err_tag & 127) < 64)
+           {
+             _bfd_error_handler
+               (_("%B: Unknown mandatory EABI object attribute %d"),
+                err_bfd, err_tag);
+             bfd_set_error (bfd_error_bad_value);
+             result = FALSE;
+           }
+         else
+           {
+             _bfd_error_handler
+               (_("Warning: %B: Unknown EABI object attribute %d"),
+                err_bfd, err_tag);
+           }
+       }
     }
-  return TRUE;
+  return result;
 }
 
 
index 7740294e9da82b0eb3fda6cf19edb31d067c4b51..db2c7724f1fc979d3ed34fd6258ff777268d5826 100644 (file)
@@ -1,3 +1,8 @@
+2009-01-15  Andrew Stubbs  <ams@codesourcery.com>
+           Julian Brown   <julian@codesourcery.com>
+
+       * config/tc-arm.c (cpu_arch): Change ARM_ARCH_V6M to 11.
+
 2009-01-15  Andrew Stubbs  <ams@codesourcery.com>
 
        * read.c (s_vendor_attribute): bfd_elf_add_obj_attr_compat ->
index 5998e5555ba548279ce5c51aad5ad74888afad30..a8aca804750781a18760dba5a9ab243b99738d7c 100644 (file)
@@ -20719,7 +20719,7 @@ static const cpu_arch_ver_table cpu_arch_ver[] =
     {6, ARM_ARCH_V6},
     {7, ARM_ARCH_V6Z},
     {9, ARM_ARCH_V6K},
-    {9, ARM_ARCH_V6M},
+    {11, ARM_ARCH_V6M},
     {8, ARM_ARCH_V6T2},
     {10, ARM_ARCH_V7A},
     {10, ARM_ARCH_V7R},
index 367702b4a83bc6eccf2fb667122453f0938db5db..3faff0d2e4ac2ea789b0fff06b9e11862aa675ef 100644 (file)
@@ -1,3 +1,15 @@
+2009-01-15  Andrew Stubbs  <ams@codesourcery.com>
+           Julian Brown   <julian@codesourcery.com>
+
+       * arm.h (TAG_CPU_ARCH_V6_M, TAG_CPU_ARCH_V6S_M): New defines.
+       (MAX_TAG_CPU_ARCH, TAG_CPU_ARCH_V4T_PLUS_V6_M): New defines.
+       (Tag_NEON_arch): Rename to Tag_Advanced_SIMD_arch to match ARM ABI
+       version 2.07.
+       (Tag_undefined39, Tag_nodefaults): New enum values.
+       (Tag_also_compatible_with, Tag_T2EE_use): Likewise.
+       (Tag_conformance, Tag_Virtualization_use): Likewise.
+       (Tag_undefined69, Tag_MPextension_use): Likewise.
+
 2009-01-15  Douglas B Rupp  <rupp@gnat.com>
 
        * ia64.h (SHT_IA_64_VMS_DISPLAY_NAME_INFO, EF_IA_64_ARCHVER_1):
index ade479c92f990e8c030925b4bff3caeb9dab50b0..ed8a26ee4b902fdf318ee6d37f04cb4ffaedd54f 100644 (file)
 #define PF_ARM_ABS         0x40000000   /* Segment must be loaded at its base address.  */
 
 /* Values for the Tag_CPU_arch EABI attribute.  */
-#define TAG_CPU_ARCH_PRE_V4    0
-#define TAG_CPU_ARCH_V4                1
-#define TAG_CPU_ARCH_V4T       2
-#define TAG_CPU_ARCH_V5T       3
-#define TAG_CPU_ARCH_V5TE      4
-#define TAG_CPU_ARCH_V5TEJ     5
-#define TAG_CPU_ARCH_V6                6
-#define TAG_CPU_ARCH_V6KZ      7
-#define TAG_CPU_ARCH_V6T2      8
-#define TAG_CPU_ARCH_V6K       9
-#define TAG_CPU_ARCH_V7                10
+#define TAG_CPU_ARCH_PRE_V4    0
+#define TAG_CPU_ARCH_V4                1
+#define TAG_CPU_ARCH_V4T       2
+#define TAG_CPU_ARCH_V5T       3
+#define TAG_CPU_ARCH_V5TE      4
+#define TAG_CPU_ARCH_V5TEJ     5
+#define TAG_CPU_ARCH_V6                6
+#define TAG_CPU_ARCH_V6KZ      7
+#define TAG_CPU_ARCH_V6T2      8
+#define TAG_CPU_ARCH_V6K       9
+#define TAG_CPU_ARCH_V7                10
+#define TAG_CPU_ARCH_V6_M      11
+#define TAG_CPU_ARCH_V6S_M     12
+#define MAX_TAG_CPU_ARCH       12
+/* Pseudo-architecture to allow objects to be compatible with the subset of
+   armv4t and armv6-m.  This value should never be stored in object files.  */
+#define TAG_CPU_ARCH_V4T_PLUS_V6_M (MAX_TAG_CPU_ARCH + 1)
 
 /* Relocation types.  */
 
@@ -251,7 +257,7 @@ enum
   Tag_THUMB_ISA_use,
   Tag_VFP_arch,
   Tag_WMMX_arch,
-  Tag_NEON_arch,
+  Tag_Advanced_SIMD_arch,
   Tag_PCS_config,
   Tag_ABI_PCS_R9_use,
   Tag_ABI_PCS_RW_data,
@@ -271,13 +277,21 @@ enum
   Tag_ABI_WMMX_args,
   Tag_ABI_optimization_goals,
   Tag_ABI_FP_optimization_goals,
-  /* 32 is generic.  */
+  /* 32 is generic (Tag_compatibility).  */
   Tag_undefined33 = 33,
   Tag_CPU_unaligned_access,
-  Tag_undefined35, 
+  Tag_undefined35,
   Tag_VFP_HP_extension,
   Tag_undefined37,
-  Tag_ABI_FP_16bit_format = 38,
+  Tag_ABI_FP_16bit_format,
+  Tag_undefined39,
+  Tag_nodefaults = 64,
+  Tag_also_compatible_with,
+  Tag_T2EE_use,
+  Tag_conformance,
+  Tag_Virtualization_use,
+  Tag_undefined69,
+  Tag_MPextension_use
 };
 
 #endif