2005-10-08 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Sat, 8 Oct 2005 17:07:19 +0000 (17:07 +0000)
committerPaul Brook <paul@codesourcery.com>
Sat, 8 Oct 2005 17:07:19 +0000 (17:07 +0000)
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/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.

26 files changed:
bfd/ChangeLog
bfd/elf32-arm.c
binutils/testsuite/binutils-all/readelf.ss
gas/ChangeLog
gas/config/tc-arm.c
gas/config/tc-arm.h
gas/doc/c-arm.texi
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/arm7t.d
gas/testsuite/gas/arm/bignum1.d
gas/testsuite/gas/arm/eabi_attr_1.d [new file with mode: 0644]
gas/testsuite/gas/arm/eabi_attr_1.s [new file with mode: 0644]
gas/testsuite/gas/arm/mapping.d
gas/testsuite/gas/arm/unwind.d
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/section0.d
gas/testsuite/gas/elf/section1.d
include/elf/ChangeLog
include/elf/arm.h
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-rel31.d
ld/testsuite/ld-arm/arm-target1-abs.d
ld/testsuite/ld-arm/arm-target1-rel.d
ld/testsuite/ld-arm/arm-target2-abs.d
ld/testsuite/ld-arm/arm-target2-got-rel.d
ld/testsuite/ld-arm/arm-target2-rel.d

index a0a02c9..fdf2809 100644 (file)
@@ -1,3 +1,22 @@
+2005-10-08  Paul Brook  <paul@codesourcery.com>
+
+       * 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.
+
 2005-10-06  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * elf32-arm.c (elf32_arm_check_relocs): Avoid aliasing warnings from
index b9024e9..0961c7a 100644 (file)
    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_howto_type *           howto,
     }
 }
 
+
+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 *                  output_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, flagword flags)
   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 *ibfd, bfd *obfd)
   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 * ibfd, bfd * obfd)
       || 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
@@ -6488,9 +7123,125 @@ elf32_arm_fake_sections (bfd * abfd, Elf_Internal_Shdr * hdr, asection * sec)
       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.  */
@@ -6520,6 +7271,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;
 }
 
@@ -6947,6 +7700,7 @@ const struct elf_size_info elf32_arm_size_info = {
 #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 ceefb9f..7daee1b 100644 (file)
@@ -13,6 +13,6 @@ Symbol table '.symtab' contains .* entries:
 # 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 446cf70..173ff23 100644 (file)
@@ -1,3 +1,18 @@
+2005-10-08  Paul Brook  <paul@codesourcery.com>
+
+       * 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.
+
 2005-10-06  Khem Raj  <kraj@mvista.com>
             NIIBE Yutaka  <gniibe@m17n.org>
 
index 926f5d8..ed9632c 100644 (file)
@@ -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_UNUSED)
 
   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, "ARM920T"},
+  {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 c2ae6d6..3b33324 100644 (file)
@@ -92,6 +92,11 @@ extern int arm_relax_frag (asection *, struct frag *, long);
 /* 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 97ab9be..6a6ceb6 100644 (file)
@@ -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 fa3cd2a..6896141 100644 (file)
@@ -1,3 +1,16 @@
+2005-10-08  Paul Brook  <paul@codesourcery.com>
+
+       * gas/arm/eabi_attr_1.s: New test.
+       * gas/arm/eabi_attr_1.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.
+
 2005-10-06  Khem Raj  <kraj@mvista.com>
             NIIBE Yutaka  <gniibe@m17n.org>
 
index 768ce13..17e4e9d 100644 (file)
@@ -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 e75c1fb..cef2036 100644 (file)
@@ -8,3 +8,5 @@
 
 Contents of section .data:
  0000 [08]0000000 000000[08]0 11111111 11111111  \.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.
+# Ignore .ARM.attributes section
+#...
diff --git a/gas/testsuite/gas/arm/eabi_attr_1.d b/gas/testsuite/gas/arm/eabi_attr_1.d
new file mode 100644 (file)
index 0000000..0e97add
--- /dev/null
@@ -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"
diff --git a/gas/testsuite/gas/arm/eabi_attr_1.s b/gas/testsuite/gas/arm/eabi_attr_1.s
new file mode 100644 (file)
index 0000000..3375acd
--- /dev/null
@@ -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 7d05107..e6db1a9 100644 (file)
@@ -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 2a04d44..b42bf73 100644 (file)
@@ -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 89dffe8..4068253 100644 (file)
@@ -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 286327c..6978d0a 100644 (file)
@@ -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 4084752..c6b7fd4 100644 (file)
@@ -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 310e997..cf4b578 100644 (file)
@@ -1,3 +1,7 @@
+2005-10-08  Paul Brook  <paul@codesourcery.com>
+
+       * arm.h: Add prototypes for BFD object attribute routines.
+
 2005-09-09  Richard Earnshaw  <richard.earnshaw@arm.com>
 
        * arm.h (SHT_ARM_PREEMPTMAP, SHT_ARM_ATTRIBUTES): New defines.
index c4bfaf2..2d76ab6 100644 (file)
@@ -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 684b7d3..c80b5db 100644 (file)
@@ -1,3 +1,12 @@
+2005-10-08  Paul Brook  <paul@codesourcery.com>
+
+       * 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.
+
 2005-10-04  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/1396
index 1ab6839..ac99e92 100644 (file)
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (10000000 fcffff7f 08000080 f4ffffff|00000010 7ffffffc 80000008 fffffff4) .*
+# Ignore .ARM.attributes section
+#...
index 81cc9cc..af64e60 100644 (file)
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
index 2d10dee..fcd6c1a 100644 (file)
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04000000|00000004) .*
+# Ignore .ARM.attributes section
+#...
index 81cc9cc..af64e60 100644 (file)
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
index 089c061..1a996f0 100644 (file)
@@ -5,3 +5,5 @@ Contents of section .text:
  8000 (00100000|00001000) .*
 Contents of section .got:
  9000 (04800000|00008004) .*
+# Ignore .ARM.attributes section
+#...
index 4913e07..569d6b5 100644 (file)
@@ -3,3 +3,5 @@
 
 Contents of section .text:
  8000 (04000000|00000004) .*
+# Ignore .ARM.attributes section
+#...