This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch 2/6] ARM attributes: merging files


When files with attributes are linked, the attributes must be checked
for compatibility, and the attributes on the output file should be set
according to the inputs - i.e. merged.

This patch should bring the ARM attribute support up to ABI 2.07. It is
intended to be applied on top of my previous Tag_compatibility patch.

I've added support for all the new attributes, and changed the way old
attributes are merged, where they were broken or out-of-date.

The test cases are included in part 6 of the patch series.

OK?

Andrew


2009-01-12  Andrew Stubbs  <ams@codesourcery.com>
	    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/elf-bfd.h       |    2 
 bfd/elf32-arm.c     |  607 +++++++++++++--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 gas/config/tc-arm.c |    2 
 include/elf/arm.h   |   44 !!!
 4 files changed, 156 insertions(+), 20 deletions(-), 479 modifications(!)

Index: bfd/elf-bfd.h
===================================================================
*** bfd/elf-bfd.h.orig
--- bfd/elf-bfd.h
*************** struct elf_find_verdep_info
*** 1371,1377 ****
  };
  
  /* The maximum number of known object attributes for any target.  */
! #define NUM_KNOWN_OBJ_ATTRIBUTES 33
  
  /* The value of an object attribute.  type & 1 indicates whether there
     is an integer value; type & 2 indicates whether there is a string
--- 1371,1377 ----
  };
  
  /* The maximum number of known object attributes for any target.  */
! #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: bfd/elf32-arm.c
===================================================================
*** bfd/elf32-arm.c.orig
--- bfd/elf32-arm.c
*************** elf32_arm_obj_attrs_arg_type (int tag)
*** 8143,8173 ****
      return (tag & 1) != 0 ? 2 : 1;
  }
  
  static void
! elf32_arm_copy_one_eabi_other_attribute (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
  {
!   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;
  
!     default:
!       if ((in_list->tag & 127) < 64)
! 	{
! 	  _bfd_error_handler
! 	      (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
! 	  break;
! 	}
      }
  }
  
! 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);
  }
  
  /* Merge EABI object attributes from IBFD into OBFD.  Raise an error if there
--- 8143,8349 ----
      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
! set_secondary_compatible_arch (bfd *abfd, int arch)
  {
!   obj_attribute *attr =
!     &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with];
  
!   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';
  }
  
! /* 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
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8180,8191 ****
    obj_attribute *out_attr;
    obj_attribute_list *in_list;
    obj_attribute_list *out_list;
    /* Some tags have 0 = don't care, 1 = strong requirement,
       2 = weak requirement.  */
!   static const int order_312[3] = {3, 1, 2};
    /* For use with Tag_VFP_arch.  */
    static const int order_01243[5] = {0, 1, 2, 4, 3};
    int i;
  
    if (!elf_known_obj_attributes_proc (obfd)[0].i)
      {
--- 8356,8369 ----
    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_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)
      {
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8212,8218 ****
  	  _bfd_error_handler
  	    (_("ERROR: %B uses VFP register arguments, %B does not"),
  	     ibfd, obfd);
! 	  return FALSE;
  	}
      }
  
--- 8390,8396 ----
  	  _bfd_error_handler
  	    (_("ERROR: %B uses VFP register arguments, %B does not"),
  	     ibfd, obfd);
! 	  result = FALSE;
  	}
      }
  
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8223,8234 ****
  	{
  	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);
  	  break;
  
  	case Tag_ABI_optimization_goals:
--- 8401,8407 ----
  	{
  	case Tag_CPU_raw_name:
  	case Tag_CPU_name:
! 	  /* These are merged after Tag_CPU_arch. */
  	  break;
  
  	case Tag_ABI_optimization_goals:
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8237,8274 ****
  	  break;
  
  	case Tag_CPU_arch:
  	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_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:
  	  /* 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)
! 	    {
  	      _bfd_error_handler
! 		(_("ERROR: %B: Conflicting architecture profiles %c/%c"),
! 		 ibfd, in_attr[i].i, out_attr[i].i);
! 	      return FALSE;
  	    }
! 	  if (in_attr[i].i)
  	    out_attr[i].i = in_attr[i].i;
  	  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])
  	    out_attr[i].i = in_attr[i].i;
  	  break;
  	case Tag_PCS_config:
--- 8410,8557 ----
  	  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_Advanced_SIMD_arch:
! 	  /* ??? Do Advanced_SIMD (NEON) and WMMX conflict?  */
  	case Tag_ABI_FP_rounding:
  	case Tag_ABI_FP_exceptions:
  	case Tag_ABI_FP_user_exceptions:
  	case Tag_ABI_FP_number_model:
! 	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_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: 8-byte data alignment conflicts with %B"),
! 		 obfd, ibfd);
! 	      result = FALSE; */
  	    }
! 	  /* 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:
! 	  /* 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:
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8289,8295 ****
  	    {
  	      _bfd_error_handler
  		(_("ERROR: %B: Conflicting use of R9"), ibfd);
! 	      return FALSE;
  	    }
  	  if (out_attr[i].i == AEABI_R9_unused)
  	    out_attr[i].i = in_attr[i].i;
--- 8572,8578 ----
  	    {
  	      _bfd_error_handler
  		(_("ERROR: %B: Conflicting use of R9"), ibfd);
! 	      result = FALSE;
  	    }
  	  if (out_attr[i].i == AEABI_R9_unused)
  	    out_attr[i].i = in_attr[i].i;
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8302,8323 ****
  	      _bfd_error_handler
  		(_("ERROR: %B: SB relative addressing conflicts with use of R9"),
  		 ibfd);
! 	      return 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)
--- 8585,8596 ----
  	      _bfd_error_handler
  		(_("ERROR: %B: SB relative addressing conflicts with use of R9"),
  		 ibfd);
! 	      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_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)
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8329,8340 ****
  	  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)
  	    {
--- 8602,8607 ----
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8349,8360 ****
  		       && out_attr[i].i != in_attr[i].i
  		       && !elf_arm_tdata (obfd)->no_enum_size_warning)
  		{
! 		  const char *aeabi_enum_names[] =
  		    { "", "variable-size", "32-bit", "" };
  		  _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]);
  		}
  	    }
  	  break;
--- 8616,8634 ----
  		       && out_attr[i].i != in_attr[i].i
  		       && !elf_arm_tdata (obfd)->no_enum_size_warning)
  		{
! 		  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, in_name, out_name);
  		}
  	    }
  	  break;
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8367,8400 ****
  	      _bfd_error_handler
  		(_("ERROR: %B uses iWMMXt register arguments, %B does not"),
  		 ibfd, obfd);
! 	      return FALSE;
  	    }
  	  break;
- 
  	case Tag_compatibility:
  	  /* Merged in target-independent code.  */
  	  break;
  
! 	default: /* All known attributes should be explicitly covered.   */
! 	  abort ();
! 	}
  
!       if (in_attr[i].type && !out_attr[i].type)
! 	switch (in_attr[i].type)
  	  {
! 	  case 1:
! 	    if (out_attr[i].i)
! 	      out_attr[i].type = 1;
! 	    break;
  
! 	  case 2:
! 	    if (out_attr[i].s)
! 	      out_attr[i].type = 2;
! 	    break;
  
! 	  default:
! 	    abort ();
  	  }
      }
  
    /* Merge Tag_compatibility attributes and any common GNU ones.  */
--- 8641,8738 ----
  	      _bfd_error_handler
  		(_("ERROR: %B uses iWMMXt register arguments, %B does not"),
  		 ibfd, obfd);
! 	      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;
  
! 	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;
  
! 	default:
  	  {
! 	    bfd *err_bfd = NULL;
  
! 	    /* 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;
  
! 	    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.  */
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8402,8468 ****
  
    /* Check for any attributes not known on ARM.  */
    in_list = elf_other_obj_attributes_proc (ibfd);
!   out_list = elf_other_obj_attributes_proc (obfd);
  
!   for (; in_list != NULL; )
      {
!       if (out_list == NULL)
! 	{
! 	  elf32_arm_copy_eabi_other_attribute_list (ibfd, obfd, in_list);
! 	  return TRUE;
! 	}
  
        /* 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)
  	{
! 	  /* 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);
  	}
!       if (in_list->tag <= out_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;
      }
!   return TRUE;
  }
  
  
--- 8740,8817 ----
  
    /* Check for any attributes not known on ARM.  */
    in_list = elf_other_obj_attributes_proc (ibfd);
!   out_listp = &elf_other_obj_attributes_proc (obfd);
!   out_list = *out_listp;
  
!   for (; in_list || out_list; )
      {
!       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 (out_list && (!in_list || in_list->tag > out_list->tag))
! 	{
! 	  /* 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;
! 	}
!       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;
  	}
!       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 result;
  }
  
  
Index: gas/config/tc-arm.c
===================================================================
*** gas/config/tc-arm.c.orig
--- gas/config/tc-arm.c
*************** static const cpu_arch_ver_table cpu_arch
*** 20712,20718 ****
      {6, ARM_ARCH_V6},
      {7, ARM_ARCH_V6Z},
      {9, ARM_ARCH_V6K},
!     {9, ARM_ARCH_V6M},
      {8, ARM_ARCH_V6T2},
      {10, ARM_ARCH_V7A},
      {10, ARM_ARCH_V7R},
--- 20712,20718 ----
      {6, ARM_ARCH_V6},
      {7, ARM_ARCH_V6Z},
      {9, ARM_ARCH_V6K},
!     {11, ARM_ARCH_V6M},
      {8, ARM_ARCH_V6T2},
      {10, ARM_ARCH_V7A},
      {10, ARM_ARCH_V7R},
Index: include/elf/arm.h
===================================================================
*** include/elf/arm.h.orig
--- include/elf/arm.h
***************
*** 85,101 ****
  #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
  
  /* Relocation types.  */
  
--- 85,107 ----
  #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_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.  */
  
*************** enum
*** 251,257 ****
    Tag_THUMB_ISA_use,
    Tag_VFP_arch,
    Tag_WMMX_arch,
!   Tag_NEON_arch,
    Tag_PCS_config,
    Tag_ABI_PCS_R9_use,
    Tag_ABI_PCS_RW_data,
--- 257,263 ----
    Tag_THUMB_ISA_use,
    Tag_VFP_arch,
    Tag_WMMX_arch,
!   Tag_Advanced_SIMD_arch,
    Tag_PCS_config,
    Tag_ABI_PCS_R9_use,
    Tag_ABI_PCS_RW_data,
*************** enum
*** 271,283 ****
    Tag_ABI_WMMX_args,
    Tag_ABI_optimization_goals,
    Tag_ABI_FP_optimization_goals,
!   /* 32 is generic.  */
    Tag_undefined33 = 33,
    Tag_CPU_unaligned_access,
!   Tag_undefined35, 
    Tag_VFP_HP_extension,
    Tag_undefined37,
!   Tag_ABI_FP_16bit_format = 38,
  };
  
  #endif
--- 277,297 ----
    Tag_ABI_WMMX_args,
    Tag_ABI_optimization_goals,
    Tag_ABI_FP_optimization_goals,
!   /* 32 is generic (Tag_compatibility).  */
    Tag_undefined33 = 33,
    Tag_CPU_unaligned_access,
!   Tag_undefined35,
    Tag_VFP_HP_extension,
    Tag_undefined37,
!   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




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]