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]

Re: [patch] Arm EABI object attributes


Attached is an updated patch to implement Arm EABI object attributes. The 
original patch can be found here:
http://sourceware.org/ml/binutils/2005-09/msg00339.html

This patch should address all the concerns raised.

Notable changes are:

arm_cpus has grown an extra field for the canonical name. Most of the time 
this is NULL, so the uppercase version of the normal name is used.

The first 32 tags are always defined (implicitly or explicitly), so these are 
held in an array rather than a linked list. This is more efficient, and 
simplifies the checks done when merging attributes from different sources.

Tested with cross to arm-none-eabi.
Ok?

Paul

2005-10-01  Paul Brook  <paul@codesourcery.com>

bfd/
	* elf32-arm.c: Move #include "elf/arm.h" after libbfd.h.
	(NUM_KNOWN_ATTRIBUTES): Define.
	(aeabi_attribute, aeabi_attribute_list): Define.
	(elf32_arm_obj_tdata): Add known_eabi_attributes and
	other_eabi_attributes.
	(uleb128_size, is_default_attr, eabi_attr_size,
	elf32_arm_eabi_attr_size, write_uleb128, write_eabi_attribute,
	elf32_arm_set_eabi_attr_contents, elf32_arm_bfd_final_link,
	elf32_arm_new_eabi_attr, attr_strdup, elf32_arm_add_eabi_attr_int,
	elf32_arm_add_eabi_attr_compat, copy_eabi_attributes,
	elf32_arm_merge_eabi_attributes): New functions.
	(elf32_arm_copy_private_bfd_data): Copy EABI object attributes.
	(elf32_arm_fake_sections): Handle .ARM.attributes.
	(elf32_arm_parse_attributes): New function.
	(elf32_arm_section_from_shdr): Use it.
	(bfd_elf32_bfd_final_link): Define.
gas/
	* config/tc-arm.c: Don't provide fallback default for CPU_DEFAULT.
	(arm_arch_used, thumb_arch_used, selected_cpu, selected_cpu_name):
	New variables.
	(arm_cpu_option_table): Add canonical_name.
	(arm_cpus): Populate canonical_name field.
	(s_arm_eabi_attribute, s_arm_arch, s_arm_cpu, s_arm_fpu,
	aeabi_set_public_attributes, arm_md_end): New functions.
	(md_pseudo_table): Add "cpu", "arch", "fpu" and "eabi_attribute".
	(md_assemble): Set thumb_arch_used and arm_arch_used.
	(md_begin): Set defaut cpu if CPU_DEFAULT not defined.
	* config/tc-arm.h (md_end): Define.
	* doc/c-arm.texi: Document .cpu, .arch, .fpu and .eabi_attribute.
gas/testsuite/
	* gas/arm/eabi_attr_1.s: New test.
	* gas/arm/eabi_attr_1.d: New test.
	* gas/arm/eabi_attr_2.s: New test.
	* gas/arm/eabi_attr_2.d: New test.
	* gas/arm/arm7t.d: Only disassemble code sections.
	* gas/arm/bignum1.d: Ignore Arm object attribute sections.
	* gas/arm/mapping.d: Ditto.
	* gas/arm/unwind.d: Ditto.
	* gas/elf/section0.d: Ditto.
	* gas/elf/section1.d: Ditto.
	* gas/elf/elf.exp: Set target_machine for Arm EABI based targets.
	* gas/elf/section2.e-armeabi: New file.
include/elf/
	* arm.h: Add prototypes for BFD object attribute routines.
ld/testsuite/
	* ld-arm/arm-rel31.d: Ignore Arm object attribute sections.
	* ld-arm/arm-target1-abs.d: Ditto.
	* ld-arm/arm-target1-rel.d: Ditto.
	* ld-arm/arm-target2-abs.d: Ditto.
	* ld-arm/arm-target2-got-rel.d: Ditto.
	* ld-arm/arm-target2-rel.d: Ditto.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.55
diff -u -p -r1.55 elf32-arm.c
--- bfd/elf32-arm.c	9 Sep 2005 13:10:01 -0000	1.55
+++ bfd/elf32-arm.c	1 Oct 2005 02:04:40 -0000
@@ -18,11 +18,11 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-#include "elf/arm.h"
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
+#include "elf/arm.h"
 
 #ifndef NUM_ELEM
 #define NUM_ELEM(a)  (sizeof (a) / (sizeof (a)[0]))
@@ -1529,12 +1529,31 @@ _arm_elf_section_data;
 /* The size of the thread control block.  */
 #define TCB_SIZE	8
 
+#define NUM_KNOWN_ATTRIBUTES 32
+
+typedef struct aeabi_attribute
+{
+  int type;
+  unsigned int i;
+  char *s;
+} aeabi_attribute;
+
+typedef struct aeabi_attribute_list
+{
+  struct aeabi_attribute_list *next;
+  int tag;
+  aeabi_attribute attr;
+} aeabi_attribute_list;
+
 struct elf32_arm_obj_tdata
 {
   struct elf_obj_tdata root;
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  aeabi_attribute known_eabi_attributes[NUM_KNOWN_ATTRIBUTES];
+  aeabi_attribute_list *other_eabi_attributes;
 };
 
 #define elf32_arm_tdata(abfd) \
@@ -3909,6 +3928,194 @@ elf32_arm_final_link_relocate (reloc_how
     }
 }
 
+
+static int
+uleb128_size (unsigned int i)
+{
+  int size;
+  size = 1;
+  while (i >= 0x80)
+    {
+      i >>= 7;
+      size++;
+    }
+  return size;
+}
+
+/* Return TRUE if the attribute has the default value (0/"").  */
+static bfd_boolean
+is_default_attr (aeabi_attribute *attr)
+{
+  if ((attr->type & 1) && attr->i != 0)
+    return FALSE;
+  if ((attr->type & 2) && attr->s && *attr->s)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Return the size of a single attribute.  */
+static bfd_vma
+eabi_attr_size(int tag, aeabi_attribute *attr)
+{
+  bfd_vma size;
+
+  if (is_default_attr (attr))
+    return 0;
+
+  size = uleb128_size (tag);
+  if (attr->type & 1)
+    size += uleb128_size (attr->i);
+  if (attr->type & 2)
+    size += strlen ((char *)attr->s) + 1;
+  return size;
+}
+  
+/* Returns the size of the eabi object attributess section.  */
+bfd_vma
+elf32_arm_eabi_attr_size (bfd *abfd)
+{
+  bfd_vma size;
+  aeabi_attribute *attr;
+  aeabi_attribute_list *list;
+  int i;
+
+  attr = elf32_arm_tdata (abfd)->known_eabi_attributes;
+  size = 16; /* 'A' <size> "aeabi" 0x1 <size>.  */
+  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
+    size += eabi_attr_size (i, &attr[i]);
+
+  for (list = elf32_arm_tdata (abfd)->other_eabi_attributes;
+       list;
+       list = list->next)
+    size += eabi_attr_size (list->tag, &list->attr);
+
+  return size;
+}
+
+static bfd_byte *
+write_uleb128 (bfd_byte *p, unsigned int val)
+{
+  bfd_byte c;
+  do
+    {
+      c = val & 0x7f;
+      val >>= 7;
+      if (val)
+	c |= 0x80;
+      *(p++) = c;
+    }
+  while (val);
+  return p;
+}
+
+/* Write attribute ATTR to butter P, and return a pointer to the following
+   byte.  */
+static bfd_byte *
+write_eabi_attribute (bfd_byte *p, int tag, aeabi_attribute *attr)
+{
+  /* Suppress default entries.  */
+  if (is_default_attr(attr))
+    return p;
+
+  p = write_uleb128 (p, tag);
+  if (attr->type & 1)
+    p = write_uleb128 (p, attr->i);
+  if (attr->type & 2)
+    {
+      int len;
+
+      len = strlen (attr->s) + 1;
+      memcpy (p, attr->s, len);
+      p += len;
+    }
+
+  return p;
+}
+
+/* Write the contents of the eabi attributes section to p.  */
+void
+elf32_arm_set_eabi_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
+{
+  bfd_byte *p;
+  aeabi_attribute *attr;
+  aeabi_attribute_list *list;
+  int i;
+
+  p = contents;
+  *(p++) = 'A';
+  bfd_put_32 (abfd, size - 1, p);
+  p += 4;
+  memcpy (p, "aeabi", 6);
+  p += 6;
+  *(p++) = Tag_File;
+  bfd_put_32 (abfd, size - 11, p);
+  p += 4;
+
+  attr = elf32_arm_tdata (abfd)->known_eabi_attributes;
+  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
+    p = write_eabi_attribute (p, i, &attr[i]);
+
+  for (list = elf32_arm_tdata (abfd)->other_eabi_attributes;
+       list;
+       list = list->next)
+    p = write_eabi_attribute (p, list->tag, &list->attr);
+}
+
+/* Override final_link to handle EABI object attribute sections.  */
+
+static bfd_boolean
+elf32_arm_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
+{
+  asection *o;
+  struct bfd_link_order *p;
+  asection *attr_section = NULL;
+  bfd_byte *contents;
+  bfd_vma size = 0;
+
+  /* elf32_arm_merge_private_bfd_data will already have merged the
+     object attributes.  Remove the input sections from the link, and set
+     the contents of the output secton.  */
+  for (o = abfd->sections; o != NULL; o = o->next)
+    {
+      if (strcmp (o->name, ".ARM.attributes") == 0)
+	{
+	  for (p = o->map_head.link_order; p != NULL; p = p->next)
+	    {
+	      asection *input_section;
+
+	      if (p->type != bfd_indirect_link_order)
+		continue;
+	      input_section = p->u.indirect.section;
+	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
+		 elf_link_input_bfd ignores this section.  */
+	      input_section->flags &= ~SEC_HAS_CONTENTS;
+	    }
+	    
+	  size = elf32_arm_eabi_attr_size (abfd);
+	  bfd_set_section_size (abfd, o, size);
+	  attr_section = o;
+	  /* Skip this section later on.  */
+	  o->map_head.link_order = NULL;
+	}
+    }
+  /* Invoke the ELF linker to do all the work.  */
+  if (!bfd_elf_final_link (abfd, info))
+    return FALSE;
+
+  if (attr_section)
+    {
+      contents = bfd_malloc(size);
+      if (contents == NULL)
+	return FALSE;
+      elf32_arm_set_eabi_attr_contents (abfd, contents, size);
+      bfd_set_section_contents (abfd, attr_section, contents, 0, size);
+      free (contents);
+    }
+  return TRUE;
+}
+
+
 /* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS.  */
 static void
 arm_add_to_rel (bfd *              abfd,
@@ -4239,6 +4446,105 @@ elf32_arm_relocate_section (bfd *       
   return TRUE;
 }
 
+/* Allocate/find an object attribute.  */
+static aeabi_attribute *
+elf32_arm_new_eabi_attr (bfd *abfd, int tag)
+{
+  aeabi_attribute *attr;
+  aeabi_attribute_list *list;
+  aeabi_attribute_list *p;
+  aeabi_attribute_list **lastp;
+
+
+  if (tag < NUM_KNOWN_ATTRIBUTES)
+    {
+      /* Knwon tags are preallocated.  */
+      attr = &elf32_arm_tdata (abfd)->known_eabi_attributes[tag];
+    }
+  else
+    {
+      /* Create a new tag.  */
+      list = (aeabi_attribute_list *)
+	bfd_alloc (abfd, sizeof (aeabi_attribute_list));
+      memset (list, 0, sizeof (aeabi_attribute_list));
+      list->tag = tag;
+      /* Keep the tag list in order.  */
+      lastp = &elf32_arm_tdata (abfd)->other_eabi_attributes;
+      for (p = *lastp; p; p = p->next)
+	{
+	  if (tag < p->tag)
+	    break;
+	  lastp = &p->next;
+	}
+      list->next = *lastp;
+      *lastp = list;
+      attr = &list->attr;
+    }
+
+  return attr;
+}
+
+void
+elf32_arm_add_eabi_attr_int (bfd *abfd, int tag, unsigned int i)
+{
+  aeabi_attribute *attr;
+
+  attr = elf32_arm_new_eabi_attr (abfd, tag);
+  attr->type = 1;
+  attr->i = i;
+}
+
+static char *
+attr_strdup (bfd *abfd, const char * s)
+{
+  char * p;
+  int len;
+  
+  len = strlen (s) + 1;
+  p = (char *)bfd_alloc(abfd, len);
+  return memcpy (p, s, len);
+}
+
+void
+elf32_arm_add_eabi_attr_string (bfd *abfd, int tag, const char *s)
+{
+  aeabi_attribute *attr;
+
+  attr = elf32_arm_new_eabi_attr (abfd, tag);
+  attr->type = 2;
+  attr->s = attr_strdup (abfd, s);
+}
+
+void
+elf32_arm_add_eabi_attr_compat (bfd *abfd, unsigned int i, const char *s)
+{
+  aeabi_attribute_list *list;
+  aeabi_attribute_list *p;
+  aeabi_attribute_list **lastp;
+
+  list = (aeabi_attribute_list *)
+    bfd_alloc (abfd, sizeof (aeabi_attribute_list));
+  memset (list, 0, sizeof (aeabi_attribute_list));
+  list->tag = Tag_compatibility;
+  list->attr.type = 3;
+  list->attr.i = i;
+  list->attr.s = attr_strdup (abfd, s);
+
+  lastp = &elf32_arm_tdata (abfd)->other_eabi_attributes;
+  for (p = *lastp; p; p = p->next)
+    {
+      int cmp;
+      if (p->tag != Tag_compatibility)
+	break;
+      cmp = strcmp(s, p->attr.s);
+      if (cmp < 0 || (cmp == 0 && i < p->attr.i))
+	break;
+      lastp = &p->next;
+    }
+  list->next = *lastp;
+  *lastp = list;
+}
+
 /* Set the right machine number.  */
 
 static bfd_boolean
@@ -4289,6 +4595,49 @@ elf32_arm_set_private_flags (bfd *abfd, 
   return TRUE;
 }
 
+/* Copy the eabi object attribute from IBFD to OBFD.  */
+static void
+copy_eabi_attributes (bfd *ibfd, bfd *obfd)
+{
+  aeabi_attribute *in_attr;
+  aeabi_attribute *out_attr;
+  aeabi_attribute_list *list;
+  int i;
+
+  in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
+  out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
+  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
+    {
+      out_attr->i = in_attr->i;
+      if (in_attr->s && *in_attr->s)
+	out_attr->s = attr_strdup (obfd, in_attr->s);
+      in_attr++;
+      out_attr++;
+    }
+
+  for (list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
+       list;
+       list = list->next)
+    {
+      in_attr = &list->attr;
+      switch (in_attr->type)
+	{
+	case 1:
+	  elf32_arm_add_eabi_attr_int (obfd, list->tag, in_attr->i);
+	  break;
+	case 2:
+	  elf32_arm_add_eabi_attr_string (obfd, list->tag, in_attr->s);
+	  break;
+	case 3:
+	  elf32_arm_add_eabi_attr_compat (obfd, in_attr->i, in_attr->s);
+	  break;
+	default:
+	  abort();
+	}
+    }
+}
+
+
 /* Copy backend specific data from one object module to another.  */
 
 static bfd_boolean
@@ -4340,6 +4689,289 @@ elf32_arm_copy_private_bfd_data (bfd *ib
   elf_elfheader (obfd)->e_ident[EI_OSABI] =
     elf_elfheader (ibfd)->e_ident[EI_OSABI];
 
+  /* Copy EABI object attributes.  */
+  copy_eabi_attributes (ibfd, obfd);
+
+  return TRUE;
+}
+
+/* Values for Tag_ABI_PCS_R9_use.  */
+enum
+{
+  AEABI_R9_V6,
+  AEABI_R9_SB,
+  AEABI_R9_TLS,
+  AEABI_R9_unused
+};
+
+/* Values for Tag_ABI_PCS_RW_data.  */
+enum
+{
+  AEABI_PCS_RW_data_absolute,
+  AEABI_PCS_RW_data_PCrel,
+  AEABI_PCS_RW_data_SBrel,
+  AEABI_PCS_RW_data_unused
+};
+
+/* Values for Tag_ABI_enum_size.  */
+enum
+{
+  AEABI_enum_unused,
+  AEABI_enum_short,
+  AEABI_enum_wide,
+  AEABI_enum_forced_wide
+};
+
+/* Merge EABI object attributes from IBFD into OBFD.  Raise an error if there
+   are conflicting attributes.  */
+static bfd_boolean
+elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
+{
+  aeabi_attribute *in_attr;
+  aeabi_attribute *out_attr;
+  aeabi_attribute_list *in_list;
+  aeabi_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};
+  int i;
+
+  if (!elf32_arm_tdata (ibfd)->known_eabi_attributes[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      copy_eabi_attributes (ibfd, obfd);
+      return TRUE;
+    }
+
+  /* Use the Tag_null value to indicate the attributes have been
+     initialized.  */
+  elf32_arm_tdata (ibfd)->known_eabi_attributes[0].i = 1;
+
+  in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
+  out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
+  /* This needs to happen before Tag_ABI_FP_number_model is merged.  */
+  if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i)
+    {
+      /* Ignore mismatches if teh object doesn't use floating point.  */
+      if (out_attr[Tag_ABI_FP_number_model].i == 0)
+	out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i;
+      else if (in_attr[Tag_ABI_FP_number_model].i != 0)
+	{
+	  _bfd_error_handler
+	    (_("ERROR: %B uses VFP register arguments, %B does not"),
+	     ibfd, obfd);
+	  return FALSE;
+	}
+    }
+
+  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
+    {
+      /* Merge this attribute with existing attributes.  */
+      switch (i)
+	{
+	case Tag_CPU_raw_name:
+	case Tag_CPU_name:
+	  /* Use whichever has the greatest architecture requirements.  */
+	  if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i)
+	    out_attr[i].s = attr_strdup(obfd, in_attr[i].s);
+	  break;
+
+	case Tag_ABI_optimization_goals:
+	case Tag_ABI_FP_optimization_goals:
+	  /* Use the first value seen.  */
+	  break;
+
+	case Tag_CPU_arch:
+	case Tag_ARM_ISA_use:
+	case Tag_THUMB_ISA_use:
+	case Tag_VFP_arch:
+	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_PCS_config:
+	  if (out_attr[i].i == 0)
+	    out_attr[i].i = in_attr[i].i;
+	  else if (in_attr[i].i != 0 && out_attr[i].i != 0)
+	    {
+	      /* It's sometimes ok to mix different configs, so this is only
+	         a warning.  */
+	      _bfd_error_handler
+		(_("Warning: %B: Conflicting platform configuration"), ibfd);
+	    }
+	  break;
+	case Tag_ABI_PCS_R9_use:
+	  if (out_attr[i].i != AEABI_R9_unused
+	      && in_attr[i].i != AEABI_R9_unused)
+	    {
+	      _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;
+	  break;
+	case Tag_ABI_PCS_RW_data:
+	  if (in_attr[i].i == AEABI_PCS_RW_data_SBrel
+	      && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_SB
+	      && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_unused)
+	    {
+	      _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)
+	    {
+	      _bfd_error_handler
+		(_("ERROR: %B: Conflicting definitions of wchar_t"), ibfd);
+	      return FALSE;
+	    }
+	  if (in_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)
+	    {
+	      if (out_attr[i].i == AEABI_enum_unused
+		  || out_attr[i].i == AEABI_enum_forced_wide)
+		{
+		  /* The existing object is compatible with anything.
+		     Use whatever requirements the new object has.  */
+		  out_attr[i].i = in_attr[i].i;
+		}
+	      else if (in_attr[i].i != AEABI_enum_forced_wide
+		       && out_attr[i].i != in_attr[i].i)
+		{
+		  _bfd_error_handler
+		    (_("ERROR: %B: Conflicting enum sizes"), ibfd);
+		}
+	    }
+	  break;
+	case Tag_ABI_VFP_args:
+	  /* Aready done.  */
+	  break;
+	case Tag_ABI_WMMX_args:
+	  if (in_attr[i].i != out_attr[i].i)
+	    {
+	      _bfd_error_handler
+		(_("ERROR: %B uses iWMMXt register arguments, %B does not"),
+		 ibfd, obfd);
+	      return FALSE;
+	    }
+	  break;
+	default: /* All known attributes should be explicitly covered.   */
+	  abort ();
+	}
+    }
+
+  in_list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
+  out_list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
+  while (in_list && in_list->tag == Tag_compatibility)
+    {
+      in_attr = &in_list->attr;
+      if (in_attr->i == 0)
+	continue;
+      if (in_attr->i == 1)
+	{
+	  _bfd_error_handler
+	    (_("ERROR: %B: Must be processed by '%s' toolchain"),
+	     ibfd, in_attr->s);
+	  return FALSE;
+	}
+      if (!out_list || out_list->tag != Tag_compatibility
+	  || strcmp (in_attr->s, out_list->attr.s) != 0)
+	{
+	  /* Add this compatibility tag to the output.  */
+	  elf32_arm_add_eabi_attr_compat (obfd, in_attr->i, in_attr->s);
+	  continue;
+	}
+      out_attr = &out_list->attr;
+      /* Check all the input tags with the same identifier.  */
+      for (;;)
+	{
+	  if (out_list->tag != Tag_compatibility
+	      || in_attr->i != out_attr->i
+	      || strcmp (in_attr->s, out_attr->s) != 0)
+	    {
+	      _bfd_error_handler
+		(_("ERROR: %B: Incompatible object tag '%s':%d"),
+		 ibfd, in_attr->s, in_attr->i);
+	      return FALSE;
+	    }
+	  in_list = in_list->next;
+	  if (in_list->tag != Tag_compatibility
+	      || strcmp (in_attr->s, in_list->attr.s) != 0)
+	    break;
+	  in_attr = &in_list->attr;
+	  out_list = out_list->next;
+	  if (out_list)
+	    out_attr = &out_list->attr;
+	}
+
+      /* Check the output doesn't have extra tags with this identifier.  */
+      if (out_list && out_list->tag == Tag_compatibility
+	  && strcmp (in_attr->s, out_list->attr.s) == 0)
+	{
+	  _bfd_error_handler
+	    (_("ERROR: %B: Incompatible object tag '%s':%d"),
+	     ibfd, in_attr->s, out_list->attr.i);
+	  return FALSE;
+	}
+    }
+
+  for (; in_list; in_list = in_list->next)
+    {
+      if ((in_list->tag & 128) < 64)
+	_bfd_error_handler
+	  (_("Warning: %B: Unknown EABI object attribute %d"),
+	   ibfd, in_list->tag);
+      break;
+    }
   return TRUE;
 }
 
@@ -4362,6 +4994,9 @@ elf32_arm_merge_private_bfd_data (bfd * 
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
+  if (!elf32_arm_merge_eabi_attributes (ibfd, obfd))
+    return FALSE;
+
   /* The input BFD must have had its flags initialised.  */
   /* The following seems bogus to me -- The flags are initialized in
      the assembler but I don't think an elf_flags_init field is
@@ -6489,9 +7124,125 @@ elf32_arm_fake_sections (bfd * abfd, Elf
       hdr->sh_type = SHT_ARM_EXIDX;
       hdr->sh_flags |= SHF_LINK_ORDER;
     }
+  else if (strcmp(name, ".ARM.attributes") == 0)
+    {
+      hdr->sh_type = SHT_ARM_ATTRIBUTES;
+    }
   return TRUE;
 }
 
+/* Parse an Arm EABI attributes section.  */
+static void
+elf32_arm_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
+{
+  bfd_byte *contents;
+  bfd_byte *p;
+  bfd_vma len;
+
+  contents = bfd_malloc (hdr->sh_size);
+  if (!contents)
+    return;
+  if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
+				 hdr->sh_size))
+    {
+      free (contents);
+      return;
+    }
+  p = contents;
+  if (*(p++) == 'A')
+    {
+      len = hdr->sh_size - 1;
+      while (len > 0)
+	{
+	  int namelen;
+	  bfd_vma section_len;
+
+	  section_len = bfd_get_32 (abfd, p);
+	  p += 4;
+	  if (section_len > len)
+	    section_len = len;
+	  len -= section_len;
+	  namelen = strlen ((char *)p) + 1;
+	  section_len -= namelen + 4;
+	  if (strcmp((char *)p, "aeabi") != 0)
+	    {
+	      /* Vendor section.  Ignore it.  */
+	      p += namelen + section_len;
+	    }
+	  else
+	    {
+	      p += namelen;
+	      while (section_len > 0)
+		{
+		  int tag;
+		  unsigned int n;
+		  unsigned int val;
+		  bfd_vma subsection_len;
+		  bfd_byte *end;
+
+		  tag = read_unsigned_leb128 (abfd, p, &n);
+		  p += n;
+		  subsection_len = bfd_get_32 (abfd, p);
+		  p += 4;
+		  if (subsection_len > section_len)
+		    subsection_len = section_len;
+		  section_len -= subsection_len;
+		  subsection_len -= n + 4;
+		  end = p + subsection_len;
+		  switch (tag)
+		    {
+		    case Tag_File:
+		      while (p < end)
+			{
+			  bfd_boolean is_string;
+
+			  tag = read_unsigned_leb128 (abfd, p, &n);
+			  p += n;
+			  if (tag == 4 || tag == 5)
+			    is_string = 1;
+			  else if (tag < 32)
+			    is_string = 0;
+			  else
+			    is_string = (tag & 1) != 0;
+			  if (tag == Tag_compatibility)
+			    {
+			      val = read_unsigned_leb128 (abfd, p, &n);
+			      p += n;
+			      elf32_arm_add_eabi_attr_compat (abfd, val,
+							      (char *)p);
+			      p += strlen ((char *)p) + 1;
+			    }
+			  else if (is_string)
+			    {
+			      elf32_arm_add_eabi_attr_string (abfd, tag,
+							      (char *)p);
+			      p += strlen ((char *)p) + 1;
+			    }
+			  else
+			    {
+			      val = read_unsigned_leb128 (abfd, p, &n);
+			      p += n;
+			      elf32_arm_add_eabi_attr_int (abfd, tag, val);
+			    }
+			}
+		      break;
+		    case Tag_Section:
+		    case Tag_Symbol:
+		      /* Don't have anywhere convenient to attach these.
+		         Fall through for now.  */
+		    default:
+		      /* Ignore things we don't kow about.  */
+		      p += subsection_len;
+		      subsection_len = 0;
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+  free (contents);
+}
+
 /* Handle an ARM specific section when reading an object file.  This is
    called when bfd_section_from_shdr finds a section with an unknown
    type.  */
@@ -6521,6 +7272,8 @@ elf32_arm_section_from_shdr (bfd *abfd,
   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
     return FALSE;
 
+  if (hdr->sh_type == SHT_ARM_ATTRIBUTES)
+    elf32_arm_parse_attributes(abfd, hdr);
   return TRUE;
 }
 
@@ -6926,6 +7679,7 @@ const struct elf_size_info elf32_arm_siz
 #define bfd_elf32_new_section_hook		elf32_arm_new_section_hook
 #define bfd_elf32_bfd_is_target_special_symbol	elf32_arm_is_target_special_symbol
 #define bfd_elf32_close_and_cleanup             elf32_arm_close_and_cleanup
+#define bfd_elf32_bfd_final_link		elf32_arm_bfd_final_link
 
 #define elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
Index: binutils/testsuite/binutils-all/readelf.ss
===================================================================
RCS file: /var/cvsroot/src-cvs/src/binutils/testsuite/binutils-all/readelf.ss,v
retrieving revision 1.6
diff -u -p -r1.6 readelf.ss
--- binutils/testsuite/binutils-all/readelf.ss	30 Dec 2004 22:37:31 -0000	1.6
+++ binutils/testsuite/binutils-all/readelf.ss	1 Oct 2005 02:04:40 -0000
@@ -13,6 +13,6 @@ Symbol table '.symtab' contains .* entri
 # and .call_table_text sections.
 #...
 .*   .: 00000000     0 NOTYPE  GLOBAL DEFAULT    1 text_symbol
-     .: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND external_symbol
+    ..: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND external_symbol
     ..: 00000000     0 NOTYPE  GLOBAL DEFAULT    [34] data_symbol
     ..: 00000004     4 OBJECT  GLOBAL DEFAULT ( COM|ANSI_COM) common_symbol
Index: gas/config/tc-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
retrieving revision 1.229
diff -u -p -r1.229 tc-arm.c
--- gas/config/tc-arm.c	30 Sep 2005 13:34:10 -0000	1.229
+++ gas/config/tc-arm.c	1 Oct 2005 03:14:15 -0000
@@ -115,8 +115,6 @@ enum arm_float_abi
 #else
 #if defined __thumb__
 #define CPU_DEFAULT	(ARM_ARCH_V5T)
-#else
-#define CPU_DEFAULT	ARM_ANY
 #endif
 #endif
 #endif
@@ -142,6 +140,8 @@ enum arm_float_abi
 #define streq(a, b)	      (strcmp (a, b) == 0)
 
 static unsigned long cpu_variant;
+static unsigned long arm_arch_used;
+static unsigned long thumb_arch_used;
 
 /* Flags stored in private area of BFD structure.  */
 static int uses_apcs_26	     = FALSE;
@@ -162,6 +162,11 @@ static int march_cpu_opt = -1;
 static int march_fpu_opt = -1;
 static int mfpu_opt = -1;
 static int mfloat_abi_opt = -1;
+/* Record user cpu selection for object attributes.
+   Zero if no default or user specified CPU.  */
+static int selected_cpu = -1;
+/* Must be long enough to hold any of the names in arm_cpus.  */
+static char selected_cpu_name[16];
 #ifdef OBJ_ELF
 # ifdef EABI_DEFAULT
 static int meabi_flags = EABI_DEFAULT;
@@ -2790,6 +2795,96 @@ s_arm_unwind_raw (int ignored ATTRIBUTE_
 
   demand_empty_rest_of_line ();
 }
+
+
+/* Parse a .eabi_attribute directive.  */
+
+static void
+s_arm_eabi_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+  bfd_boolean is_string;
+  int tag;
+  unsigned int i = 0;
+  char *s = NULL;
+  char saved_char;
+
+  expression (& exp);
+  if (exp.X_op != O_constant)
+    goto bad;
+
+  tag = exp.X_add_number;
+  if (tag == 4 || tag == 5 || tag == 32 || (tag > 32 && (tag & 1) != 0))
+    is_string = 1;
+  else
+    is_string = 0;
+
+  if (skip_past_comma (&input_line_pointer) == FAIL)
+    goto bad;
+  if (tag == 32 || !is_string)
+    {
+      expression (& exp);
+      if (exp.X_op != O_constant)
+	{
+	  as_bad (_("expected numeric constant"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+      i = exp.X_add_number;
+    }
+  if (tag == Tag_compatibility
+      && skip_past_comma (&input_line_pointer) == FAIL)
+    {
+      as_bad (_("expected comma"));
+      ignore_rest_of_line ();
+      return;
+    }
+  if (is_string)
+    {
+      skip_whitespace(input_line_pointer);
+      if (*input_line_pointer != '"')
+	goto bad_string;
+      input_line_pointer++;
+      s = input_line_pointer;
+      while (*input_line_pointer && *input_line_pointer != '"')
+	input_line_pointer++;
+      if (*input_line_pointer != '"')
+	goto bad_string;
+      saved_char = *input_line_pointer;
+      *input_line_pointer = 0;
+    }
+  else
+    {
+      s = NULL;
+      saved_char = 0;
+    }
+  
+  if (tag == Tag_compatibility)
+    elf32_arm_add_eabi_attr_compat (stdoutput, i, s);
+  else if (is_string)
+    elf32_arm_add_eabi_attr_string (stdoutput, tag, s);
+  else
+    elf32_arm_add_eabi_attr_int (stdoutput, tag, i);
+
+  if (s)
+    {
+      *input_line_pointer = saved_char;
+      input_line_pointer++;
+    }
+  demand_empty_rest_of_line ();
+  return;
+bad_string:
+  as_bad (_("bad string constant"));
+  ignore_rest_of_line ();
+  return;
+bad:
+  as_bad (_("expected <tag> , <value>"));
+  ignore_rest_of_line ();
+}
+
+static void s_arm_arch (int);
+static void s_arm_cpu (int);
+static void s_arm_fpu (int);
 #endif /* OBJ_ELF */
 
 /* This table describes all the machine specific pseudo-ops the assembler
@@ -2830,6 +2925,10 @@ const pseudo_typeS md_pseudo_table[] =
   { "pad",		s_arm_unwind_pad,	0 },
   { "setfp",		s_arm_unwind_setfp,	0 },
   { "unwind_raw",	s_arm_unwind_raw,	0 },
+  { "cpu",		s_arm_cpu,		0 },
+  { "arch",		s_arm_arch,		0 },
+  { "fpu",		s_arm_fpu,		0 },
+  { "eabi_attribute",	s_arm_eabi_attribute,	0 },
 #else
   { "word",	   cons, 4},
 #endif
@@ -8010,6 +8109,14 @@ md_assemble (char *str)
 	      return;
 	    }
 	}
+      thumb_arch_used |= opcode->tvariant;
+      /* Many Thumb-2 instructions also have Thumb-1 variants, so explicitly
+         set those bits when Thumb-2 32-bit instuctions are seen.  ie.
+	 anything other than bl/blx.
+	 This is overly pessimistic for relaxable instructions.  */
+      if ((inst.size == 4 && (inst.instruction & 0xf800e800) != 0xf000e800)
+	  || inst.relax)
+	thumb_arch_used |= ARM_EXT_V6T2;
     }
   else
     {
@@ -8034,6 +8141,12 @@ md_assemble (char *str)
       inst.size = INSN_SIZE;
       if (!parse_operands (p, opcode->operands))
 	opcode->aencode ();
+      /* Arm mode bx is marked as both v4T and v5 because it's still required
+         on a hypothetical non-thumb v5 core.  */
+      if (opcode->avariant == (ARM_EXT_V4T | ARM_EXT_V5))
+	arm_arch_used |= ARM_EXT_V4T;
+      else
+	arm_arch_used |= opcode->avariant;
     }
   output_inst (str);
 }
@@ -12279,11 +12392,23 @@ md_begin (void)
 	mfpu_opt = FPU_ARCH_FPA;
     }
 
+#ifdef CPU_DEFAULT
+  if (mcpu_cpu_opt == -1)
+    selected_cpu = mcpu_cpu_opt = CPU_DEFAULT;
+#else
   if (mcpu_cpu_opt == -1)
-    mcpu_cpu_opt = CPU_DEFAULT;
+    {
+      mcpu_cpu_opt = ARM_ANY;
+      selected_cpu = 0;
+    }
+  else
+    selected_cpu = mcpu_cpu_opt;
+#endif
 
   cpu_variant = mcpu_cpu_opt | mfpu_opt;
 
+  arm_arch_used = thumb_arch_used = 0;
+
 #if defined OBJ_COFF || defined OBJ_ELF
   {
     unsigned int flags = 0;
@@ -12641,97 +12766,100 @@ struct arm_cpu_option_table
   /* For some CPUs we assume an FPU unless the user explicitly sets
      -mfpu=...	*/
   int	default_fpu;
+  /* The canonical name of the CPU, or NULL to use NAME converted to upper
+     case.  */
+  const char *canonical_name;
 };
 
 /* This list should, at a minimum, contain all the cpu names
    recognized by GCC.  */
 static struct arm_cpu_option_table arm_cpus[] =
 {
-  {"all",		ARM_ANY,	 FPU_ARCH_FPA},
-  {"arm1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
-  {"arm2",		ARM_ARCH_V2,	 FPU_ARCH_FPA},
-  {"arm250",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
-  {"arm3",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
-  {"arm6",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm60",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm600",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm610",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm620",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7m",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
-  {"arm7d",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7dm",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
-  {"arm7di",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7dmi",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
-  {"arm70",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm700",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm700i",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm710",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm710t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm720",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm720t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm740t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm710c",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7100",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7500",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7500fe",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
-  {"arm7t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm7tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm7tdmi-s",	ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm8",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"arm810",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"strongarm",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"strongarm1",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"strongarm110",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"strongarm1100",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"strongarm1110",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
-  {"arm9",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm920",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm920t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm922t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm940t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
-  {"arm9tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
+  {"all",		ARM_ANY,	 FPU_ARCH_FPA,    NULL},
+  {"arm1",		ARM_ARCH_V1,	 FPU_ARCH_FPA,    NULL},
+  {"arm2",		ARM_ARCH_V2,	 FPU_ARCH_FPA,    NULL},
+  {"arm250",		ARM_ARCH_V2S,	 FPU_ARCH_FPA,    NULL},
+  {"arm3",		ARM_ARCH_V2S,	 FPU_ARCH_FPA,    NULL},
+  {"arm6",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm60",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm600",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm610",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm620",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7m",		ARM_ARCH_V3M,	 FPU_ARCH_FPA,    NULL},
+  {"arm7d",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7dm",		ARM_ARCH_V3M,	 FPU_ARCH_FPA,    NULL},
+  {"arm7di",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7dmi",		ARM_ARCH_V3M,	 FPU_ARCH_FPA,    NULL},
+  {"arm70",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm700",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm700i",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm710",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm710t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm720",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm720t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm740t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm710c",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7100",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7500",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7500fe",		ARM_ARCH_V3,	 FPU_ARCH_FPA,    NULL},
+  {"arm7t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm7tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm7tdmi-s",	ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm8",		ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"arm810",		ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"strongarm",		ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"strongarm1",	ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"strongarm110",	ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"strongarm1100",	ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"strongarm1110",	ARM_ARCH_V4,	 FPU_ARCH_FPA,    NULL},
+  {"arm9",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm920",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    "ARM920T"},
+  {"arm920t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm922t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm940t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,    NULL},
+  {"arm9tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA,	  NULL},
   /* For V5 or later processors we default to using VFP; but the user
      should really set the FPU type explicitly.	 */
-  {"arm9e-r0",		ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
-  {"arm9e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm926ej",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
-  {"arm926ejs",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
-  {"arm926ej-s",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
-  {"arm946e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
-  {"arm946e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm946e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm966e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
-  {"arm966e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm966e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm968e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm10t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
-  {"arm10tdmi",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
-  {"arm10e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm1020",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm1020t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
-  {"arm1020e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm1022e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
-  {"arm1026ejs",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
-  {"arm1026ej-s",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
-  {"arm1136js",		ARM_ARCH_V6,	 FPU_NONE},
-  {"arm1136j-s",	ARM_ARCH_V6,	 FPU_NONE},
-  {"arm1136jfs",	ARM_ARCH_V6,	 FPU_ARCH_VFP_V2},
-  {"arm1136jf-s",	ARM_ARCH_V6,	 FPU_ARCH_VFP_V2},
-  {"mpcore",		ARM_ARCH_V6K,	 FPU_ARCH_VFP_V2},
-  {"mpcorenovfp",	ARM_ARCH_V6K,	 FPU_NONE},
-  {"arm1156t2-s",	ARM_ARCH_V6T2,	 FPU_NONE},
-  {"arm1156t2f-s",	ARM_ARCH_V6T2,	 FPU_ARCH_VFP_V2},
-  {"arm1176jz-s",	ARM_ARCH_V6ZK,	 FPU_NONE},
-  {"arm1176jzf-s",	ARM_ARCH_V6ZK,	 FPU_ARCH_VFP_V2},
+  {"arm9e-r0",		ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2, NULL},
+  {"arm9e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm926ej",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2, "ARM926EJ-S"},
+  {"arm926ejs",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2, "ARM926EJ-S"},
+  {"arm926ej-s",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm946e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2, NULL},
+  {"arm946e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, "ARM946E-S"},
+  {"arm946e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm966e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2, NULL},
+  {"arm966e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, "ARM966E-S"},
+  {"arm966e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm968e-s",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm10t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1, NULL},
+  {"arm10tdmi",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1, NULL},
+  {"arm10e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm1020",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, "ARM1020E"},
+  {"arm1020t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1, NULL},
+  {"arm1020e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm1022e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm1026ejs",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2, "ARM1026EJ-S"},
+  {"arm1026ej-s",	ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm1136js",		ARM_ARCH_V6,	 FPU_NONE,	  "ARM1136J-S"},
+  {"arm1136j-s",	ARM_ARCH_V6,	 FPU_NONE,	  NULL},
+  {"arm1136jfs",	ARM_ARCH_V6,	 FPU_ARCH_VFP_V2, "ARM1136JF-S"},
+  {"arm1136jf-s",	ARM_ARCH_V6,	 FPU_ARCH_VFP_V2, NULL},
+  {"mpcore",		ARM_ARCH_V6K,	 FPU_ARCH_VFP_V2, NULL},
+  {"mpcorenovfp",	ARM_ARCH_V6K,	 FPU_NONE,	  NULL},
+  {"arm1156t2-s",	ARM_ARCH_V6T2,	 FPU_NONE,	  NULL},
+  {"arm1156t2f-s",	ARM_ARCH_V6T2,	 FPU_ARCH_VFP_V2, NULL},
+  {"arm1176jz-s",	ARM_ARCH_V6ZK,	 FPU_NONE,	  NULL},
+  {"arm1176jzf-s",	ARM_ARCH_V6ZK,	 FPU_ARCH_VFP_V2, NULL},
   /* ??? XSCALE is really an architecture.  */
-  {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
+  {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL},
   /* ??? iwmmxt is not a processor.  */
-  {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
-  {"i80200",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
+  {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2, NULL},
+  {"i80200",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL},
   /* Maverick */
-  {"ep9312",		ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
-  {NULL, 0, 0}
+  {"ep9312",	ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK, NULL},
+  {NULL, 0, 0, NULL}
 };
 
 struct arm_arch_option_table
@@ -12915,6 +13043,15 @@ arm_parse_cpu (char * str)
       {
 	mcpu_cpu_opt = opt->value;
 	mcpu_fpu_opt = opt->default_fpu;
+	if (opt->canonical_name)
+	  strcpy(selected_cpu_name, opt->canonical_name);
+	else
+	  {
+	    int i;
+	    for (i = 0; i < optlen; i++)
+	      selected_cpu_name[i] = TOUPPER (opt->name[i]);
+	    selected_cpu_name[i] = 0;
+	  }
 
 	if (ext != NULL)
 	  return arm_parse_extension (ext, &mcpu_cpu_opt);
@@ -12944,12 +13081,12 @@ arm_parse_arch (char * str)
       return 0;
     }
 
-
   for (opt = arm_archs; opt->name != NULL; opt++)
     if (streq (opt->name, str))
       {
 	march_cpu_opt = opt->value;
 	march_fpu_opt = opt->default_fpu;
+	strcpy(selected_cpu_name, opt->name);
 
 	if (ext != NULL)
 	  return arm_parse_extension (ext, &march_cpu_opt);
@@ -13125,3 +13262,198 @@ md_show_usage (FILE * fp)
   -EL                     assemble code for a little-endian cpu\n"));
 #endif
 }
+
+
+#ifdef OBJ_ELF
+/* Set the public EABI object attributes.  */
+static void
+aeabi_set_public_attributes (void)
+{
+  int arch;
+  int flags;
+
+  /* Choose the architecture based on the capabilities of the requested cpu
+     (if any) and/or the instructions actually used.  */
+  flags = mcpu_cpu_opt | arm_arch_used | thumb_arch_used;
+  if (flags & ARM_EXT_V6T2)
+    arch = 8;
+  else if (flags & ARM_EXT_V6Z)
+    arch = 7;
+  else if (flags & ARM_EXT_V6K)
+    arch = 9;
+  else if (flags & ARM_EXT_V6)
+    arch = 6;
+  else if (flags & ARM_EXT_V5E)
+    arch = 4;
+  else if (flags & (ARM_EXT_V5 | ARM_EXT_V5T))
+    arch = 3;
+  else if (flags & ARM_EXT_V4T)
+    arch = 2;
+  else if (flags & ARM_EXT_V4)
+    arch = 1;
+  else
+    arch = 0;
+
+  /* Tag_CPU_name.  */
+  if (selected_cpu_name[0])
+    {
+      char *p;
+
+      p = selected_cpu_name;
+      if (strncmp(p, "armv", 4) == 0)
+	{
+	  int i;
+	  
+	  p += 4;
+	  for (i = 0; p[i]; i++)
+	    p[i] = TOUPPER (p[i]);
+	}
+      elf32_arm_add_eabi_attr_string (stdoutput, 5, p);
+    }
+  /* Tag_CPU_arch.  */
+  elf32_arm_add_eabi_attr_int (stdoutput, 6, arch);
+  /* Tag_ARM_ISA_use.  */
+  if (arm_arch_used)
+    elf32_arm_add_eabi_attr_int (stdoutput, 8, 1);
+  /* Tag_THUMB_ISA_use.  */
+  if (thumb_arch_used)
+    elf32_arm_add_eabi_attr_int (stdoutput, 9,
+				 (thumb_arch_used & ARM_EXT_V6T2) ? 2 : 1);
+  /* Tag_VFP_arch.  */
+  if ((arm_arch_used | thumb_arch_used) & FPU_ARCH_VFP_V2)
+    elf32_arm_add_eabi_attr_int (stdoutput, 10, 2);
+  else if ((arm_arch_used | thumb_arch_used) & FPU_ARCH_VFP_V1)
+    elf32_arm_add_eabi_attr_int (stdoutput, 10, 1);
+  /* Tag_WMMX_arch.  */
+  if ((arm_arch_used | thumb_arch_used) & ARM_CEXT_IWMMXT)
+    elf32_arm_add_eabi_attr_int (stdoutput, 11, 1);
+}
+
+/* Add the .ARM.attributes section.  */
+void
+arm_md_end (void)
+{
+  segT s;
+  char *p;
+  addressT addr;
+  offsetT size;
+  
+  if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4)
+    return;
+
+  aeabi_set_public_attributes ();
+  size = elf32_arm_eabi_attr_size (stdoutput);
+  s = subseg_new (".ARM.attributes", 0);
+  bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
+  addr = frag_now_fix ();
+  p = frag_more (size);
+  elf32_arm_set_eabi_attr_contents (stdoutput, (bfd_byte *)p, size);
+}
+
+
+/* Parse a .cpu directive.  */
+
+static void
+s_arm_cpu (int ignored ATTRIBUTE_UNUSED)
+{
+  struct arm_cpu_option_table *opt;
+  char *name;
+  char saved_char;
+
+  name = input_line_pointer;
+  while (*input_line_pointer && !ISSPACE(*input_line_pointer))
+    input_line_pointer++;
+  saved_char = *input_line_pointer;
+  *input_line_pointer = 0;
+
+  /* Skip the first "all" entry.  */
+  for (opt = arm_cpus + 1; opt->name != NULL; opt++)
+    if (streq (opt->name, name))
+      {
+	mcpu_cpu_opt = opt->value;
+	selected_cpu = mcpu_cpu_opt;
+	if (opt->canonical_name)
+	  strcpy(selected_cpu_name, opt->canonical_name);
+	else
+	  {
+	    int i;
+	    for (i = 0; opt->name[i]; i++)
+	      selected_cpu_name[i] = TOUPPER (opt->name[i]);
+	    selected_cpu_name[i] = 0;
+	  }
+	cpu_variant = mcpu_cpu_opt | mfpu_opt;
+	*input_line_pointer = saved_char;
+	demand_empty_rest_of_line ();
+	return;
+      }
+  as_bad (_("unknown cpu `%s'"), name);
+  *input_line_pointer = saved_char;
+  ignore_rest_of_line ();
+}
+
+
+/* Parse a .arch directive.  */
+
+static void
+s_arm_arch (int ignored ATTRIBUTE_UNUSED)
+{
+  struct arm_arch_option_table *opt;
+  char saved_char;
+  char *name;
+
+  name = input_line_pointer;
+  while (*input_line_pointer && !ISSPACE(*input_line_pointer))
+    input_line_pointer++;
+  saved_char = *input_line_pointer;
+  *input_line_pointer = 0;
+
+  /* Skip the first "all" entry.  */
+  for (opt = arm_archs + 1; opt->name != NULL; opt++)
+    if (streq (opt->name, name))
+      {
+	mcpu_cpu_opt = opt->value;
+	selected_cpu = mcpu_cpu_opt;
+	strcpy(selected_cpu_name, opt->name);
+	cpu_variant = mcpu_cpu_opt | mfpu_opt;
+	*input_line_pointer = saved_char;
+	demand_empty_rest_of_line ();
+	return;
+      }
+
+  as_bad (_("unknown architecture `%s'\n"), name);
+  *input_line_pointer = saved_char;
+  ignore_rest_of_line ();
+}
+
+
+/* Parse a .fpu directive.  */
+
+static void
+s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
+{
+  struct arm_option_value_table *opt;
+  char saved_char;
+  char *name;
+
+  name = input_line_pointer;
+  while (*input_line_pointer && !ISSPACE(*input_line_pointer))
+    input_line_pointer++;
+  saved_char = *input_line_pointer;
+  *input_line_pointer = 0;
+  
+  for (opt = arm_fpus; opt->name != NULL; opt++)
+    if (streq (opt->name, name))
+      {
+	mfpu_opt = opt->value;
+	cpu_variant = mcpu_cpu_opt | mfpu_opt;
+	*input_line_pointer = saved_char;
+	demand_empty_rest_of_line ();
+	return;
+      }
+
+  as_bad (_("unknown floating point format `%s'\n"), name);
+  *input_line_pointer = saved_char;
+  ignore_rest_of_line ();
+}
+#endif /* OBJ_ELF */
+
Index: gas/config/tc-arm.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.h,v
retrieving revision 1.35
diff -u -p -r1.35 tc-arm.h
--- gas/config/tc-arm.h	6 Sep 2005 16:59:23 -0000	1.35
+++ gas/config/tc-arm.h	1 Oct 2005 02:04:40 -0000
@@ -92,6 +92,11 @@ extern int arm_relax_frag (asection *, s
 /* We also need to mark assembler created symbols:  */
 #define tc_frob_fake_label(S) arm_frob_label (S)
 
+#ifdef OBJ_ELF
+#define md_end arm_md_end
+extern void arm_md_end (void);
+#endif
+
 /* NOTE: The fake label creation in stabs.c:s_stab_generic() has
    deliberately not been updated to mark assembler created stabs
    symbols as Thumb.  */
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/doc/c-arm.texi,v
retrieving revision 1.34
diff -u -p -r1.34 c-arm.texi
--- gas/doc/c-arm.texi	27 Sep 2005 13:23:38 -0000	1.34
+++ gas/doc/c-arm.texi	1 Oct 2005 02:04:40 -0000
@@ -505,6 +505,27 @@ the stack pointer by @var{offset} bytes.
 For example @code{.unwind_raw 4, 0xb1, 0x01} is equivalent to
 @code{.save @{r0@}}
 
+@cindex @code{.cpu} directive, ARM
+@item .cpu @var{name}
+Select the target processor.  Valid values for @var{name} are the same as
+for the @option{-mcpu} commandline option.
+
+@cindex @code{.arch} directive, ARM
+@item .arch @var{name}
+Select the target architecture.  Valid values for @var{name} are the same as
+for the @option{-march} commandline option.
+
+@cindex @code{.fpu} directive, ARM
+@item .fpu @var{name}
+Select the floating point unit to assemble for.  Valid values for @var{name}
+are the same as for the @option{-mfpu} commandline option.
+
+@cindex @code{.eabi_attribute} directive, ARM
+@item .eabi_attribute @var{tag}, @var{value}
+Set the EABI object attribute number @var{tag} to @var{value}.  The value
+is either a @code{number}, @code{"string"}, or @code{number, "string"}
+depending on the tag.
+
 @end table
 
 @node ARM Opcodes
Index: gas/testsuite/gas/arm/arm7t.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/arm7t.d,v
retrieving revision 1.11
diff -u -p -r1.11 arm7t.d
--- gas/testsuite/gas/arm/arm7t.d	14 Nov 2003 15:12:43 -0000	1.11
+++ gas/testsuite/gas/arm/arm7t.d	1 Oct 2005 02:04:40 -0000
@@ -1,4 +1,4 @@
-#objdump: -Dr --prefix-addresses --show-raw-insn
+#objdump: -dr --prefix-addresses --show-raw-insn
 #name: ARM arm7t
 #as: -mcpu=arm7t -EL
 
Index: gas/testsuite/gas/arm/bignum1.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/bignum1.d,v
retrieving revision 1.3
diff -u -p -r1.3 bignum1.d
--- gas/testsuite/gas/arm/bignum1.d	4 Jul 2005 14:55:52 -0000	1.3
+++ gas/testsuite/gas/arm/bignum1.d	1 Oct 2005 02:04:40 -0000
@@ -8,3 +8,5 @@
 
 Contents of section .data:
  0000 [08]0000000 000000[08]0 11111111 11111111  \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.
+# Ignore .ARM.attributes section
+#...
Index: gas/testsuite/gas/arm/eabi_attr_1.d
===================================================================
RCS file: gas/testsuite/gas/arm/eabi_attr_1.d
diff -N gas/testsuite/gas/arm/eabi_attr_1.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/eabi_attr_1.d	1 Oct 2005 02:53:37 -0000
@@ -0,0 +1,13 @@
+# as: -meabi=4
+# readelf: -A
+# This test is only valid on ELF based ports.
+#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+Attribute Section: aeabi
+File Attributes
+  Tag_CPU_name: "ARM1136JF-S"
+  Tag_CPU_arch: v6
+  Tag_ARM_ISA_use: Yes
+  Tag_ABI_VFP_args: VFP registers
+  Tag_compatibility: flag = 3, vendor = GNU
+  Tag_unknown_128: 1234 \(0x4d2\)
+  Tag_unknown_129: "bar"
Index: gas/testsuite/gas/arm/eabi_attr_1.s
===================================================================
RCS file: gas/testsuite/gas/arm/eabi_attr_1.s
diff -N gas/testsuite/gas/arm/eabi_attr_1.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/eabi_attr_1.s	1 Oct 2005 02:04:40 -0000
@@ -0,0 +1,9 @@
+.text
+.cpu arm1136jf-s
+foo:
+bx lr
+.eabi_attribute 32, 3, "GNU"
+.eabi_attribute 28, 1
+.eabi_attribute 128, 1234
+.eabi_attribute 129, "bar"
+
Index: gas/testsuite/gas/arm/mapping.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/mapping.d,v
retrieving revision 1.6
diff -u -p -r1.6 mapping.d
--- gas/testsuite/gas/arm/mapping.d	4 Jul 2005 14:55:52 -0000	1.6
+++ gas/testsuite/gas/arm/mapping.d	1 Oct 2005 02:04:40 -0000
@@ -16,5 +16,7 @@ SYMBOL TABLE:
 0+00 l       .data	0+0 \$d
 0+00 l    d  foo	0+0 (|foo)
 0+00 l       foo	0+0 \$t
+#Maybe section symbol for .ARM.attributes
+#...
 0+00 g       .text	0+0 mapping
 0+08 g     F .text	0+0 thumb_mapping
Index: gas/testsuite/gas/arm/unwind.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/unwind.d,v
retrieving revision 1.7
diff -u -p -r1.7 unwind.d
--- gas/testsuite/gas/arm/unwind.d	4 Jul 2005 14:55:52 -0000	1.7
+++ gas/testsuite/gas/arm/unwind.d	1 Oct 2005 02:04:40 -0000
@@ -37,3 +37,5 @@ Contents of section .ARM.exidx:
  0000 00000000 (b0b0a880 04000000|80a8b0b0 00000004) 00000000  .*
  0010 (08000000 0c000000 0c000000 1c000000|00000008 0000000c 0000000c 0000001c)  .*
  0020 (10000000 08849780|00000010 80978408)                    .*
+# Ignore .ARM.attributes section
+#...
Index: gas/testsuite/gas/elf/elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/elf/elf.exp,v
retrieving revision 1.29
diff -u -p -r1.29 elf.exp
--- gas/testsuite/gas/elf/elf.exp	15 Apr 2005 11:38:59 -0000	1.29
+++ gas/testsuite/gas/elf/elf.exp	1 Oct 2005 02:04:40 -0000
@@ -50,6 +50,12 @@ if { ([istarget "*-*-*elf*"]		
     if {[istarget m32r*-*-*]} then {
 	set target_machine -m32r
     }
+    if { ([istarget "*arm*-*-*"]
+	  || [istarget "xscale*-*-*"])
+	&& ([istarget "*-*-*eabi"]
+	    || [istarget "*-*-symbianelf"])} then {
+	set target_machine -armeabi
+    }
     run_dump_test "ehopt0"
     run_dump_test "group0a" 
     run_dump_test "group0b" 
Index: gas/testsuite/gas/elf/section0.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/elf/section0.d,v
retrieving revision 1.4
diff -u -p -r1.4 section0.d
--- gas/testsuite/gas/elf/section0.d	3 Sep 2003 08:26:50 -0000	1.4
+++ gas/testsuite/gas/elf/section0.d	1 Oct 2005 02:04:40 -0000
@@ -13,3 +13,5 @@ Contents of section B:
  0+000 02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02.*
 Contents of section C:
  0+000 03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03.*
+# Arm includes a .ARM.attributes section here
+#...
Index: gas/testsuite/gas/elf/section1.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/elf/section1.d,v
retrieving revision 1.4
diff -u -p -r1.4 section1.d
--- gas/testsuite/gas/elf/section1.d	3 Sep 2003 08:26:50 -0000	1.4
+++ gas/testsuite/gas/elf/section1.d	1 Oct 2005 02:04:40 -0000
@@ -13,3 +13,5 @@ Contents of section B:
  0+000 02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02 ?02.*
 Contents of section C:
  0+000 03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03 ?03.*
+# Arm includes a .ARM.attributes section here
+#...
Index: include/elf/arm.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/include/elf/arm.h,v
retrieving revision 1.26
diff -u -p -r1.26 arm.h
--- include/elf/arm.h	9 Sep 2005 13:06:21 -0000	1.26
+++ include/elf/arm.h	1 Oct 2005 02:04:40 -0000
@@ -223,6 +223,54 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
   FAKE_RELOC (R_ARM_PC13,               R_ARM_LDR_PC_G0)  /* Unclear whether meaning is different.  */
 END_RELOC_NUMBERS (R_ARM_max)
 
+#ifdef BFD_ARCH_SIZE
+/* Routines for manipulating EABI object attributes.  */
+void elf32_arm_add_eabi_attr_int (bfd *, int, unsigned int);
+void elf32_arm_add_eabi_attr_string (bfd *, int, const char *);
+void elf32_arm_add_eabi_attr_compat (bfd *, unsigned int, const char *);
+
+void elf32_arm_set_eabi_attr_contents (bfd *, bfd_byte *, bfd_vma);
+bfd_vma elf32_arm_eabi_attr_size (bfd *);
+
+enum
+{
+  Tag_NULL,
+  Tag_File,
+  Tag_Section,
+  Tag_Symbol,
+  Tag_CPU_raw_name,
+  Tag_CPU_name,
+  Tag_CPU_arch,
+  Tag_CPU_arch_profile,
+  Tag_ARM_ISA_use,
+  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,
+  Tag_ABI_PCS_RO_data,
+  Tag_ABI_PCS_GOT_use,
+  Tag_ABI_PCS_wchar_t,
+  Tag_ABI_FP_rounding,
+  Tag_ABI_FP_denormal,
+  Tag_ABI_FP_exceptions,
+  Tag_ABI_FP_user_exceptions,
+  Tag_ABI_FP_number_model,
+  Tag_ABI_align8_needed,
+  Tag_ABI_align8_preserved,
+  Tag_ABI_enum_size,
+  Tag_ABI_HardFP_use,
+  Tag_ABI_VFP_args,
+  Tag_ABI_WMMX_args,
+  Tag_ABI_optimization_goals,
+  Tag_ABI_FP_optimization_goals,
+  Tag_compatibility,
+};
+
+#endif
+
 /* The name of the note section used to identify arm variants.  */
 #define ARM_NOTE_SECTION ".note.gnu.arm.ident"
 
Index: ld/testsuite/ld-arm/arm-rel31.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-rel31.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-rel31.d
--- ld/testsuite/ld-arm/arm-rel31.d	17 Sep 2004 12:18:18 -0000	1.1
+++ ld/testsuite/ld-arm/arm-rel31.d	1 Oct 2005 02:04:40 -0000
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (10000000 fcffff7f 08000080 f4ffffff|00000010 7ffffffc 80000008 fffffff4) .*
+# Ignore .ARM.attributes section
+#...
Index: ld/testsuite/ld-arm/arm-target1-abs.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-target1-abs.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-target1-abs.d
--- ld/testsuite/ld-arm/arm-target1-abs.d	17 Sep 2004 12:18:18 -0000	1.1
+++ ld/testsuite/ld-arm/arm-target1-abs.d	1 Oct 2005 02:04:40 -0000
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
Index: ld/testsuite/ld-arm/arm-target1-rel.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-target1-rel.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-target1-rel.d
--- ld/testsuite/ld-arm/arm-target1-rel.d	17 Sep 2004 12:18:18 -0000	1.1
+++ ld/testsuite/ld-arm/arm-target1-rel.d	1 Oct 2005 02:04:40 -0000
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04000000|00000004) .*
+# Ignore .ARM.attributes section
+#...
Index: ld/testsuite/ld-arm/arm-target2-abs.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-target2-abs.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-target2-abs.d
--- ld/testsuite/ld-arm/arm-target2-abs.d	30 Sep 2004 17:03:53 -0000	1.1
+++ ld/testsuite/ld-arm/arm-target2-abs.d	1 Oct 2005 02:04:40 -0000
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
Index: ld/testsuite/ld-arm/arm-target2-got-rel.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-target2-got-rel.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-target2-got-rel.d
--- ld/testsuite/ld-arm/arm-target2-got-rel.d	17 Sep 2004 12:18:18 -0000	1.1
+++ ld/testsuite/ld-arm/arm-target2-got-rel.d	1 Oct 2005 02:04:40 -0000
@@ -5,3 +5,5 @@ Contents of section .text:
  8000 (00100000|00001000) .*
 Contents of section .got:
  9000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
Index: ld/testsuite/ld-arm/arm-target2-rel.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-target2-rel.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-target2-rel.d
--- ld/testsuite/ld-arm/arm-target2-rel.d	17 Sep 2004 12:18:18 -0000	1.1
+++ ld/testsuite/ld-arm/arm-target2-rel.d	1 Oct 2005 02:04:40 -0000
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04000000|00000004) .*
+# Ignore .ARM.attributes section
+#...

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