OSDN Git Service

bfd:
authorJoseph Myers <jsm@polyomino.org.uk>
Fri, 29 Jun 2007 16:29:16 +0000 (16:29 +0000)
committerJoseph Myers <jsm@polyomino.org.uk>
Fri, 29 Jun 2007 16:29:16 +0000 (16:29 +0000)
* elf-attrs.c: New.
* Makefile.am (BFD32_BACKENDS): Add elf-attrs.lo.
(BFD32_BACKENDS_CFILES): Add elf-attrs.c.
(elf-attrs.lo): Generate dependencies.
* Makefile.in: Regenerate.
* configure.in (elf): Add elf-attrs.lo.
* configure: Regenerate.
* elf-bfd.h (struct elf_backend_data): Add entries for object
attributes.
(NUM_KNOWN_OBJ_ATTRIBUTES, obj_attribute, obj_attribute_list,
OBJ_ATTR_PROC, OBJ_ATTR_GNU, OBJ_ATTR_FIRST, OBJ_ATTR_LAST,
Tag_NULL, Tag_File, Tag_Section, Tag_Symbol, Tag_compatibility):
New.
(struct elf_obj_tdata): Add entries for object attributes.
(elf_known_obj_attributes, elf_other_obj_attributes,
elf_known_obj_attributes_proc, elf_other_obj_attributes_proc):
New.
(bfd_elf_obj_attr_size, bfd_elf_set_obj_attr_contents,
bfd_elf_get_obj_attr_int, bfd_elf_add_obj_attr_int,
bfd_elf_add_proc_attr_int, bfd_elf_add_obj_attr_string,
bfd_elf_add_proc_attr_string, bfd_elf_add_obj_attr_compat,
bfd_elf_add_proc_attr_compat, _bfd_elf_attr_strdup,
_bfd_elf_copy_obj_attributes, _bfd_elf_obj_attrs_arg_type,
_bfd_elf_parse_attributes, _bfd_elf_merge_object_attributes): New.
* elf.c (_bfd_elf_copy_private_bfd_data): Copy object attributes.
(bfd_section_from_shdr): Handle attributes sections.
* elflink.c (bfd_elf_final_link): Handle attributes sections.
* elfxx-target.h (elf_backend_obj_attrs_vendor,
elf_backend_obj_attrs_section, elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type): New.
(elfNN_bed): Update.
* elf32-arm.c (NUM_KNOWN_ATTRIBUTES, aeabi_attribute,
aeabi_attribute_list): Remove.
(struct elf32_arm_obj_tdata): Remove object attributes fields.
(check_use_blx, bfd_elf32_arm_set_vfp11_fix, using_thumb2,
elf32_arm_copy_private_bfd_data, elf32_arm_merge_eabi_attributes):
Update for new object attributes interfaces.
(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, elf32_arm_get_eabi_attr_int,
elf32_arm_add_eabi_attr_int, attr_strdup,
elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat,
copy_eabi_attributes, elf32_arm_parse_attributes): Remove.  Moved
to generic code in elf-attrs.c.
(elf32_arm_obj_attrs_arg_type): New.
(elf32_arm_fake_sections): Do not handle .ARM.attributes.
(elf32_arm_section_from_shdr): Do not handle SHT_ARM_ATTRIBUTES.
(bfd_elf32_bfd_final_link): Remove.
(elf_backend_obj_attrs_vendor, elf_backend_obj_attrs_section,
elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type): New.
* elf32-bfin.c (bfin_elf_copy_private_bfd_data): Copy object
attributes.
* elf32-frv.c (frv_elf_copy_private_bfd_data): Likewise.
* elf32-iq2000.c (iq2000_elf_copy_private_bfd_data): Likewise.
* elf32-mep.c (mep_elf_copy_private_bfd_data): Likewise.
* elf32-mt.c (mt_elf_copy_private_bfd_data): Likewise.
* elf32-sh.c (sh_elf_copy_private_data): Likewise.
* elf64-sh64.c (sh_elf64_copy_private_data_internal): Likewise.

binutils:
* readelf.c (display_gnu_attribute): New.
(process_arm_specific): Rearrange as process_attributes.
(process_arm_specific): Replace by wrapper of process_attributes.

gas:
* as.c (create_obj_attrs_section): New.
(main): Call create_obj_attrs_section for ELF.
* read.c (s_gnu_attribute, skip_whitespace, skip_past_char,
skip_past_comma, s_vendor_attribute): New.
(potable): Add gnu_attribute for ELF.
* read.h (s_vendor_attribute): Declare.
* config/tc-arm.c (s_arm_eabi_attribute): Replace by wrapper
round s_vendor_attribute.
(aeabi_set_public_attributes): Update for new attributes
interfaces.
(arm_md_end): Remove attributes contents setting now done
generically.

include/elf:
* arm.h (elf32_arm_add_eabi_attr_int,
elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat,
elf32_arm_get_eabi_attr_int, elf32_arm_set_eabi_attr_contents,
elf32_arm_eabi_attr_size, Tag_NULL, Tag_File, Tag_Section,
Tag_Symbol, Tag_compatibility): Remove.
* common.h (SHT_GNU_ATTRIBUTES): Define.

ld:
* emulparams/armelf.sh (OTHER_SECTIONS): Remove .ARM.attributes.
(ATTRS_SECTIONS): Define.
* scripttempl/elf.sc, scripttempl/elf32sh-symbian.sc,
scripttempl/elf_chaos.sc, scripttempl/elfi370.sc,
scripttempl/elfxtensa.sc: Handle ATTRS_SECTIONS.

21 files changed:
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/configure
bfd/configure.in
bfd/elf-attrs.c [new file with mode: 0644]
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-arm.c
bfd/elf32-bfin.c
bfd/elf32-frv.c
bfd/elf32-iq2000.c
bfd/elf32-mep.c
bfd/elf32-mt.c
bfd/elf32-sh.c
bfd/elf64-sh64.c
bfd/elflink.c
bfd/elfxx-target.h
include/elf/ChangeLog
include/elf/arm.h
include/elf/common.h

index 1f7f5c4..051b530 100644 (file)
@@ -1,3 +1,66 @@
+2007-06-29  Joseph Myers  <joseph@codesourcery.com>
+
+       * elf-attrs.c: New.
+       * Makefile.am (BFD32_BACKENDS): Add elf-attrs.lo.
+       (BFD32_BACKENDS_CFILES): Add elf-attrs.c.
+       (elf-attrs.lo): Generate dependencies.
+       * Makefile.in: Regenerate.
+       * configure.in (elf): Add elf-attrs.lo.
+       * configure: Regenerate.
+       * elf-bfd.h (struct elf_backend_data): Add entries for object
+       attributes.
+       (NUM_KNOWN_OBJ_ATTRIBUTES, obj_attribute, obj_attribute_list,
+       OBJ_ATTR_PROC, OBJ_ATTR_GNU, OBJ_ATTR_FIRST, OBJ_ATTR_LAST,
+       Tag_NULL, Tag_File, Tag_Section, Tag_Symbol, Tag_compatibility):
+       New.
+       (struct elf_obj_tdata): Add entries for object attributes.
+       (elf_known_obj_attributes, elf_other_obj_attributes,
+       elf_known_obj_attributes_proc, elf_other_obj_attributes_proc):
+       New.
+       (bfd_elf_obj_attr_size, bfd_elf_set_obj_attr_contents,
+       bfd_elf_get_obj_attr_int, bfd_elf_add_obj_attr_int,
+       bfd_elf_add_proc_attr_int, bfd_elf_add_obj_attr_string,
+       bfd_elf_add_proc_attr_string, bfd_elf_add_obj_attr_compat,
+       bfd_elf_add_proc_attr_compat, _bfd_elf_attr_strdup,
+       _bfd_elf_copy_obj_attributes, _bfd_elf_obj_attrs_arg_type,
+       _bfd_elf_parse_attributes, _bfd_elf_merge_object_attributes): New.
+       * elf.c (_bfd_elf_copy_private_bfd_data): Copy object attributes.
+       (bfd_section_from_shdr): Handle attributes sections.
+       * elflink.c (bfd_elf_final_link): Handle attributes sections.
+       * elfxx-target.h (elf_backend_obj_attrs_vendor,
+       elf_backend_obj_attrs_section, elf_backend_obj_attrs_arg_type,
+       elf_backend_obj_attrs_section_type): New.
+       (elfNN_bed): Update.
+       * elf32-arm.c (NUM_KNOWN_ATTRIBUTES, aeabi_attribute,
+       aeabi_attribute_list): Remove.
+       (struct elf32_arm_obj_tdata): Remove object attributes fields.
+       (check_use_blx, bfd_elf32_arm_set_vfp11_fix, using_thumb2,
+       elf32_arm_copy_private_bfd_data, elf32_arm_merge_eabi_attributes):
+       Update for new object attributes interfaces.
+       (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, elf32_arm_get_eabi_attr_int,
+       elf32_arm_add_eabi_attr_int, attr_strdup,
+       elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat,
+       copy_eabi_attributes, elf32_arm_parse_attributes): Remove.  Moved
+       to generic code in elf-attrs.c.
+       (elf32_arm_obj_attrs_arg_type): New.
+       (elf32_arm_fake_sections): Do not handle .ARM.attributes.
+       (elf32_arm_section_from_shdr): Do not handle SHT_ARM_ATTRIBUTES.
+       (bfd_elf32_bfd_final_link): Remove.
+       (elf_backend_obj_attrs_vendor, elf_backend_obj_attrs_section,
+       elf_backend_obj_attrs_arg_type,
+       elf_backend_obj_attrs_section_type): New.
+       * elf32-bfin.c (bfin_elf_copy_private_bfd_data): Copy object
+       attributes.
+       * elf32-frv.c (frv_elf_copy_private_bfd_data): Likewise.
+       * elf32-iq2000.c (iq2000_elf_copy_private_bfd_data): Likewise.
+       * elf32-mep.c (mep_elf_copy_private_bfd_data): Likewise.
+       * elf32-mt.c (mt_elf_copy_private_bfd_data): Likewise.
+       * elf32-sh.c (sh_elf_copy_private_data): Likewise.
+       * elf64-sh64.c (sh_elf64_copy_private_data_internal): Likewise.
+
 2007-06-29  Paul Brook  <paul@codesourcery.com>
 
        * elf32-arm.c (bfd_elf32_arm_process_before_allocation): Suppress
index 59c8367..2dd906f 100644 (file)
@@ -297,6 +297,7 @@ BFD32_BACKENDS = \
        elf32-xc16x.lo \
        elf32.lo \
        elflink.lo \
+       elf-attrs.lo \
        elf-strtab.lo \
        elf-eh-frame.lo \
        elf-vxworks.lo \
@@ -475,6 +476,7 @@ BFD32_BACKENDS_CFILES = \
        elf32-xc16x.c \
        elf32.c \
        elflink.c \
+       elf-attrs.c \
        elf-strtab.c \
        elf-eh-frame.c \
        elf-vxworks.c \
@@ -1562,6 +1564,9 @@ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
   $(INCDIR)/libiberty.h $(INCDIR)/objalloc.h
+elf-attrs.lo: elf-attrs.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h
 elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h
index fa347a2..7777144 100644 (file)
@@ -546,6 +546,7 @@ BFD32_BACKENDS = \
        elf32-xc16x.lo \
        elf32.lo \
        elflink.lo \
+       elf-attrs.lo \
        elf-strtab.lo \
        elf-eh-frame.lo \
        elf-vxworks.lo \
@@ -724,6 +725,7 @@ BFD32_BACKENDS_CFILES = \
        elf32-xc16x.c \
        elf32.c \
        elflink.c \
+       elf-attrs.c \
        elf-strtab.c \
        elf-eh-frame.c \
        elf-vxworks.c \
@@ -2141,6 +2143,9 @@ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
   $(INCDIR)/libiberty.h $(INCDIR)/objalloc.h
+elf-attrs.lo: elf-attrs.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h
 elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h
index cbab0d3..3cff895 100755 (executable)
@@ -18578,7 +18578,7 @@ selarchs="$f"
 # Target backend .o files.
 tb=
 
-elf="elf.lo elflink.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
+elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
 
 for vec in $selvecs
 do
index 7fb45ae..1ea98ae 100644 (file)
@@ -569,7 +569,7 @@ selarchs="$f"
 # Target backend .o files.
 tb=
 
-elf="elf.lo elflink.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
+elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
 
 for vec in $selvecs
 do
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
new file mode 100644 (file)
index 0000000..d1a64f4
--- /dev/null
@@ -0,0 +1,628 @@
+/* ELF attributes support (based on ARM EABI attributes).
+   Copyright 2005, 2006, 2007
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* Return the number of bytes needed by I in uleb128 format.  */
+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 (obj_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
+obj_attr_size (int tag, obj_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;
+}
+
+/* Return the vendor name for a given object attributes section.  */
+static const char *
+vendor_obj_attr_name (bfd *abfd, int vendor)
+{
+  return (vendor == OBJ_ATTR_PROC
+         ? get_elf_backend_data (abfd)->obj_attrs_vendor
+         : "gnu");
+}
+
+/* Return the size of the object attributes section for VENDOR
+   (OBJ_ATTR_PROC or OBJ_ATTR_GNU), or 0 if there are no attributes
+   for that vendor to record and the vendor is OBJ_ATTR_GNU.  */
+static bfd_vma
+vendor_obj_attr_size (bfd *abfd, int vendor)
+{
+  bfd_vma size;
+  obj_attribute *attr;
+  obj_attribute_list *list;
+  int i;
+  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
+
+  if (!vendor_name)
+    return 0;
+
+  attr = elf_known_obj_attributes (abfd)[vendor];
+  size = 0;
+  for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
+    size += obj_attr_size (i, &attr[i]);
+
+  for (list = elf_other_obj_attributes (abfd)[vendor];
+       list;
+       list = list->next)
+    size += obj_attr_size (list->tag, &list->attr);
+
+  /* <size> <vendor_name> NUL 0x1 <size> */
+  return ((size || vendor == OBJ_ATTR_PROC)
+         ? size + 10 + strlen (vendor_name)
+         : 0);
+}
+
+/* Return the size of the object attributes section.  */
+bfd_vma
+bfd_elf_obj_attr_size (bfd *abfd)
+{
+  bfd_vma size;
+
+  size = vendor_obj_attr_size (abfd, OBJ_ATTR_PROC);
+  size += vendor_obj_attr_size (abfd, OBJ_ATTR_GNU);
+
+  /* 'A' <sections for each vendor> */
+  return (size ? size + 1 : 0);
+}
+
+/* Write VAL in uleb128 format to P, returning a pointer to the
+   following byte.  */
+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_obj_attribute (bfd_byte *p, int tag, obj_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 object attributes section (length SIZE)
+   for VENDOR to CONTENTS.  */
+static void
+vendor_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size,
+                             int vendor)
+{
+  bfd_byte *p;
+  obj_attribute *attr;
+  obj_attribute_list *list;
+  int i;
+  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
+  size_t vendor_length = strlen (vendor_name) + 1;
+
+  p = contents;
+  bfd_put_32 (abfd, size, p);
+  p += 4;
+  memcpy (p, vendor_name, vendor_length);
+  p += vendor_length;
+  *(p++) = Tag_File;
+  bfd_put_32 (abfd, size - 4 - vendor_length, p);
+  p += 4;
+
+  attr = elf_known_obj_attributes (abfd)[vendor];
+  for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
+    p = write_obj_attribute (p, i, &attr[i]);
+
+  for (list = elf_other_obj_attributes (abfd)[vendor];
+       list;
+       list = list->next)
+    p = write_obj_attribute (p, list->tag, &list->attr);
+}
+
+/* Write the contents of the object attributes section to CONTENTS.  */
+void
+bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
+{
+  bfd_byte *p;
+  int vendor;
+  bfd_vma my_size;
+
+  p = contents;
+  *(p++) = 'A';
+  my_size = 1;
+  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
+    {
+      bfd_vma vendor_size = vendor_obj_attr_size (abfd, vendor);
+      if (vendor_size)
+       vendor_set_obj_attr_contents (abfd, p, vendor_size, vendor);
+      p += vendor_size;
+      my_size += vendor_size;
+    }
+
+  if (size != my_size)
+    abort ();
+}
+
+/* Allocate/find an object attribute.  */
+static obj_attribute *
+elf_new_obj_attr (bfd *abfd, int vendor, int tag)
+{
+  obj_attribute *attr;
+  obj_attribute_list *list;
+  obj_attribute_list *p;
+  obj_attribute_list **lastp;
+
+
+  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
+    {
+      /* Knwon tags are preallocated.  */
+      attr = &elf_known_obj_attributes (abfd)[vendor][tag];
+    }
+  else
+    {
+      /* Create a new tag.  */
+      list = (obj_attribute_list *)
+       bfd_alloc (abfd, sizeof (obj_attribute_list));
+      memset (list, 0, sizeof (obj_attribute_list));
+      list->tag = tag;
+      /* Keep the tag list in order.  */
+      lastp = &elf_other_obj_attributes (abfd)[vendor];
+      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;
+}
+
+/* Return the value of an integer object attribute.  */
+int
+bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag)
+{
+  obj_attribute_list *p;
+
+  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
+    {
+      /* Knwon tags are preallocated.  */
+      return elf_known_obj_attributes (abfd)[vendor][tag].i;
+    }
+  else
+    {
+      for (p = elf_other_obj_attributes (abfd)[vendor];
+          p;
+          p = p->next)
+       {
+         if (tag == p->tag)
+           return p->attr.i;
+         if (tag < p->tag)
+           break;
+       }
+      return 0;
+    }
+}
+
+/* Add an integer object attribute.  */
+void
+bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i)
+{
+  obj_attribute *attr;
+
+  attr = elf_new_obj_attr (abfd, vendor, tag);
+  attr->type = 1;
+  attr->i = i;
+}
+
+/* Duplicate an object attribute string value.  */
+char *
+_bfd_elf_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);
+}
+
+/* Add a string object attribute.  */
+void
+bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s)
+{
+  obj_attribute *attr;
+
+  attr = elf_new_obj_attr (abfd, vendor, tag);
+  attr->type = 2;
+  attr->s = _bfd_elf_attr_strdup (abfd, s);
+}
+
+/* Add a Tag_compatibility object attribute.  */
+void
+bfd_elf_add_obj_attr_compat (bfd *abfd, int vendor, unsigned int i,
+                            const char *s)
+{
+  obj_attribute_list *list;
+  obj_attribute_list *p;
+  obj_attribute_list **lastp;
+
+  list = (obj_attribute_list *)
+    bfd_alloc (abfd, sizeof (obj_attribute_list));
+  memset (list, 0, sizeof (obj_attribute_list));
+  list->tag = Tag_compatibility;
+  list->attr.type = 3;
+  list->attr.i = i;
+  list->attr.s = _bfd_elf_attr_strdup (abfd, s);
+
+  lastp = &elf_other_obj_attributes (abfd)[vendor];
+  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;
+}
+
+/* Copy the object attributes from IBFD to OBFD.  */
+void
+_bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+  obj_attribute_list *list;
+  int i;
+  int vendor;
+
+  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
+    {
+      in_attr = &elf_known_obj_attributes (ibfd)[vendor][4];
+      out_attr = &elf_known_obj_attributes (obfd)[vendor][4];
+      for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
+       {
+         out_attr->type = in_attr->type;
+         out_attr->i = in_attr->i;
+         if (in_attr->s && *in_attr->s)
+           out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
+         in_attr++;
+         out_attr++;
+       }
+
+      for (list = elf_other_obj_attributes (ibfd)[vendor];
+          list;
+          list = list->next)
+       {
+         in_attr = &list->attr;
+         switch (in_attr->type)
+           {
+           case 1:
+             bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
+             break;
+           case 2:
+             bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
+                                          in_attr->s);
+             break;
+           case 3:
+             bfd_elf_add_obj_attr_compat (obfd, vendor, in_attr->i,
+                                          in_attr->s);
+             break;
+           default:
+             abort ();
+           }
+       }
+    }
+}
+
+/* Determine whether a GNU object attribute tag takes an integer, a
+   string or both.  */
+static int
+gnu_obj_attrs_arg_type (int tag)
+{
+  /* Except for Tag_compatibility, for GNU attributes we follow the
+     same rule ARM ones > 32 follow: odd-numbered tags take strings
+     and even-numbered tags take integers.  In addition, tag & 2 is
+     nonzero for architecture-independent tags and zero for
+     architecture-dependent ones.  */
+  if (tag == Tag_compatibility)
+    return 3;
+  else
+    return (tag & 1) != 0 ? 2 : 1;
+}
+
+/* Determine what arguments an attribute tag takes.  */
+int
+_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
+{
+  switch (vendor)
+    {
+    case OBJ_ATTR_PROC:
+      return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
+      break;
+    case OBJ_ATTR_GNU:
+      return gnu_obj_attrs_arg_type (tag);
+      break;
+    default:
+      abort ();
+    }
+}
+
+/* Parse an object attributes section.  */
+void
+_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
+{
+  bfd_byte *contents;
+  bfd_byte *p;
+  bfd_vma len;
+  const char *std_section;
+
+  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;
+  std_section = get_elf_backend_data (abfd)->obj_attrs_vendor;
+  if (*(p++) == 'A')
+    {
+      len = hdr->sh_size - 1;
+      while (len > 0)
+       {
+         int namelen;
+         bfd_vma section_len;
+         int vendor;
+
+         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 (std_section && strcmp ((char *)p, std_section) == 0)
+           vendor = OBJ_ATTR_PROC;
+         else if (strcmp ((char *)p, "gnu") == 0)
+           vendor = OBJ_ATTR_GNU;
+         else
+           {
+             /* Other vendor section.  Ignore it.  */
+             p += namelen + section_len;
+             continue;
+           }
+
+         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)
+                   {
+                     int type;
+
+                     tag = read_unsigned_leb128 (abfd, p, &n);
+                     p += n;
+                     type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
+                     switch (type)
+                       {
+                       case 3:
+                         val = read_unsigned_leb128 (abfd, p, &n);
+                         p += n;
+                         bfd_elf_add_obj_attr_compat (abfd, vendor, val,
+                                                      (char *)p);
+                         p += strlen ((char *)p) + 1;
+                         break;
+                       case 2:
+                         bfd_elf_add_obj_attr_string (abfd, vendor, tag,
+                                                      (char *)p);
+                         p += strlen ((char *)p) + 1;
+                         break;
+                       case 1:
+                         val = read_unsigned_leb128 (abfd, p, &n);
+                         p += n;
+                         bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
+                         break;
+                       default:
+                         abort ();
+                       }
+                   }
+                 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);
+}
+
+/* Merge common object attributes from IBFD into OBFD.  Raise an error
+   if there are conflicting attributes.  Any processor-specific
+   attributes have already been merged.  This must be called from the
+   bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
+   target, along with any target-specific merging.  Because there are
+   no common attributes other than Tag_compatibility at present, and
+   non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
+   is not presently called for targets without their own
+   attributes.  */
+
+bfd_boolean
+_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+  obj_attribute_list *in_list;
+  obj_attribute_list *out_list;
+  int vendor;
+
+  /* The only common attribute is currently Tag_compatibility,
+     accepted in both processor and "gnu" sections.  */
+  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
+    {
+      in_list = elf_other_obj_attributes (ibfd)[vendor];
+      out_list = elf_other_obj_attributes (ibfd)[vendor];
+      while (in_list && in_list->tag == Tag_compatibility)
+       {
+         in_attr = &in_list->attr;
+         if (in_attr->i == 0)
+           continue;
+         if (in_attr->i == 1 && strcmp (in_attr->s, "gnu") != 0)
+           {
+             _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.  */
+             bfd_elf_add_proc_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;
+           }
+       }
+    }
+
+  return TRUE;
+}
index 3ead565..f4c3a0a 100644 (file)
@@ -1075,6 +1075,19 @@ struct elf_backend_data
      so-called reserved entries on some systems.  */
   bfd_vma got_header_size;
 
+  /* The vendor name to use for a processor-standard attributes section.  */
+  const char *obj_attrs_vendor;
+
+  /* The section name to use for a processor-standard attributes section.  */
+  const char *obj_attrs_section;
+
+  /* Return 1, 2 or 3 to indicate what type of arguments a
+     processor-specific tag takes.  */
+  int (*obj_attrs_arg_type) (int);
+
+  /* The section type to use for an attributes section.  */
+  unsigned int obj_attrs_section_type;
+
   /* This is TRUE if the linker should act like collect and gather
      global constructors and destructors by name.  This is TRUE for
      MIPS ELF because the Irix 5 tools can not handle the .init
@@ -1268,6 +1281,46 @@ struct elf_find_verdep_info
   bfd_boolean failed;
 };
 
+/* The maximum number of known object attributes for any target.  */
+#define NUM_KNOWN_OBJ_ATTRIBUTES 32
+
+/* The value of an object attribute.  type & 1 indicates whether there
+   is an integer value; type & 2 indicates whether there is a string
+   value.  */
+
+typedef struct obj_attribute
+{
+  int type;
+  unsigned int i;
+  char *s;
+} obj_attribute;
+
+typedef struct obj_attribute_list
+{
+  struct obj_attribute_list *next;
+  int tag;
+  obj_attribute attr;
+} obj_attribute_list;
+
+/* Object attributes may either be defined by the processor ABI, index
+   OBJ_ATTR_PROC in the *_obj_attributes arrays, or be GNU-specific
+   (and possibly also processor-specific), index OBJ_ATTR_GNU.  */
+#define OBJ_ATTR_PROC 0
+#define OBJ_ATTR_GNU 1
+#define OBJ_ATTR_FIRST OBJ_ATTR_PROC
+#define OBJ_ATTR_LAST OBJ_ATTR_GNU
+
+/* The following object attribute tags are taken as generic, for all
+   targets and for "gnu" where there is no target standard.  */
+enum
+{
+  Tag_NULL = 0,
+  Tag_File = 1,
+  Tag_Section = 2,
+  Tag_Symbol = 3,
+  Tag_compatibility = 32
+};
+
 /* Some private data is stashed away for future use using the tdata pointer
    in the bfd structure.  */
 
@@ -1409,6 +1462,9 @@ struct elf_obj_tdata
 
   /* Symbol buffer.  */
   void *symbuf;
+
+  obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
+  obj_attribute_list *other_obj_attributes[2];
 };
 
 #define elf_tdata(bfd)         ((bfd) -> tdata.elf_obj_data)
@@ -1438,6 +1494,12 @@ struct elf_obj_tdata
 #define elf_dyn_lib_class(bfd) (elf_tdata(bfd) -> dyn_lib_class)
 #define elf_bad_symtab(bfd)    (elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)    (elf_tdata(bfd) -> flags_init)
+#define elf_known_obj_attributes(bfd) (elf_tdata (bfd) -> known_obj_attributes)
+#define elf_other_obj_attributes(bfd) (elf_tdata (bfd) -> other_obj_attributes)
+#define elf_known_obj_attributes_proc(bfd) \
+  (elf_known_obj_attributes (bfd) [OBJ_ATTR_PROC])
+#define elf_other_obj_attributes_proc(bfd) \
+  (elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC])
 \f
 extern void _bfd_elf_swap_verdef_in
   (bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *);
@@ -1953,6 +2015,26 @@ extern bfd *_bfd_elf64_bfd_from_remote_memory
   (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,
    int (*target_read_memory) (bfd_vma, bfd_byte *, int));
 
+extern bfd_vma bfd_elf_obj_attr_size (bfd *);
+extern void bfd_elf_set_obj_attr_contents (bfd *, bfd_byte *, bfd_vma);
+extern int bfd_elf_get_obj_attr_int (bfd *, int, int);
+extern void bfd_elf_add_obj_attr_int (bfd *, int, int, unsigned int);
+#define bfd_elf_add_proc_attr_int(BFD, TAG, VALUE) \
+  bfd_elf_add_obj_attr_int ((BFD), OBJ_ATTR_PROC, (TAG), (VALUE))
+extern void bfd_elf_add_obj_attr_string (bfd *, int, int, const char *);
+#define bfd_elf_add_proc_attr_string(BFD, TAG, VALUE) \
+  bfd_elf_add_obj_attr_string ((BFD), OBJ_ATTR_PROC, (TAG), (VALUE))
+extern void bfd_elf_add_obj_attr_compat (bfd *, int, unsigned int,
+                                        const char *);
+#define bfd_elf_add_proc_attr_compat(BFD, INTVAL, STRVAL) \
+  bfd_elf_add_obj_attr_compat ((BFD), OBJ_ATTR_PROC, (INTVAL), (STRVAL))
+
+extern char *_bfd_elf_attr_strdup (bfd *, const char *);
+extern void _bfd_elf_copy_obj_attributes (bfd *, bfd *);
+extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int);
+extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
+extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
+
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
 
index baa9512..68b226a 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1113,6 +1113,10 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
   elf_gp (obfd) = elf_gp (ibfd);
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
@@ -2195,6 +2199,16 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       break;
 
     default:
+      /* Possibly an attributes section.  */
+      if (hdr->sh_type == SHT_GNU_ATTRIBUTES
+         || hdr->sh_type == bed->obj_attrs_section_type)
+       {
+         if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+           return FALSE;
+         _bfd_elf_parse_attributes (abfd, hdr);
+         return TRUE;
+       }
+
       /* Check for any processor-specific section types.  */
       if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex))
        return TRUE;
index a213bab..85ed8d7 100644 (file)
@@ -2064,22 +2064,6 @@ _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;
@@ -2087,9 +2071,6 @@ struct elf32_arm_obj_tdata
   /* 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;
-
   /* Zero to warn when linking objects with incompatible enum sizes.  */
   int no_enum_size_warning;
 };
@@ -3103,7 +3084,8 @@ bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info)
 
 static void check_use_blx(struct elf32_arm_link_hash_table *globals)
 {
-  if (elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch) > 2)
+  if (bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+                               Tag_CPU_arch) > 2)
     globals->use_blx = 1;
 }
 
@@ -3321,7 +3303,7 @@ void
 bfd_elf32_arm_set_vfp11_fix (bfd *obfd, struct bfd_link_info *link_info)
 {
   struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info);
-  aeabi_attribute *out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
+  obj_attribute *out_attr = elf_known_obj_attributes_proc (obfd);
   
   /* We assume that ARMv7+ does not need the VFP11 denorm erratum fix.  */
   if (out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V7)
@@ -4488,7 +4470,8 @@ identify_add_or_sub(bfd_vma insn)
 
 static int using_thumb2 (struct elf32_arm_link_hash_table *globals)
 {
-  int arch = elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch);
+  int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+                                      Tag_CPU_arch);
   return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7;
 }
 
@@ -6273,194 +6256,6 @@ 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,
@@ -6795,130 +6590,6 @@ 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;
-}
-
-int
-elf32_arm_get_eabi_attr_int (bfd *abfd, int tag)
-{
-  aeabi_attribute_list *p;
-
-  if (tag < NUM_KNOWN_ATTRIBUTES)
-    {
-      /* Knwon tags are preallocated.  */
-      return elf32_arm_tdata (abfd)->known_eabi_attributes[tag].i;
-    }
-  else
-    {
-      for (p = elf32_arm_tdata (abfd)->other_eabi_attributes;
-          p;
-          p = p->next)
-       {
-         if (tag == p->tag)
-           return p->attr.i;
-         if (tag < p->tag)
-           break;
-       }
-      return 0;
-    }
-}
-
-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
@@ -6969,50 +6640,6 @@ 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[4];
-  out_attr = &elf32_arm_tdata (obfd)->known_eabi_attributes[4];
-  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
-    {
-      out_attr->type = in_attr->type;
-      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
@@ -7064,8 +6691,8 @@ 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);
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
   return TRUE;
 }
@@ -7097,34 +6724,48 @@ enum
   AEABI_enum_forced_wide
 };
 
+/* Determine whether an object attribute tag takes an integer, a
+   string or both.  */
+static int
+elf32_arm_obj_attrs_arg_type (int tag)
+{
+  if (tag == Tag_compatibility)
+    return 3;
+  else if (tag == 4 || tag == 5)
+    return 2;
+  else if (tag < 32)
+    return 1;
+  else
+    return (tag & 1) != 0 ? 2 : 1;
+}
+
 /* 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;
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+  obj_attribute_list *in_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 (obfd)->known_eabi_attributes[0].i)
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
     {
       /* This is the first object.  Copy the attributes.  */
-      copy_eabi_attributes (ibfd, obfd);
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
       /* Use the Tag_null value to indicate the attributes have been
         initialized.  */
-      elf32_arm_tdata (obfd)->known_eabi_attributes[0].i = 1;
+      elf_known_obj_attributes_proc (obfd)[0].i = 1;
 
       return TRUE;
     }
 
-  in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
-  out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
+  in_attr = elf_known_obj_attributes_proc (ibfd);
+  out_attr = elf_known_obj_attributes_proc (obfd);
   /* 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)
     {
@@ -7140,7 +6781,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
        }
     }
 
-  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
+  for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
     {
       /* Merge this attribute with existing attributes.  */
       switch (i)
@@ -7152,7 +6793,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
             name is non-NULL.  */
          if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i
              && in_attr[i].s)
-           out_attr[i].s = attr_strdup(obfd, in_attr[i].s);
+           out_attr[i].s = _bfd_elf_attr_strdup (obfd, in_attr[i].s);
          break;
 
        case Tag_ABI_optimization_goals:
@@ -7294,60 +6935,13 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
        }
     }
 
-  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;
-       }
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, obfd);
 
-      /* 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;
-       }
-    }
+  /* Check for any attributes not known on ARM.  */
+  in_list = elf_other_obj_attributes_proc (ibfd);
+  while (in_list && in_list->tag == Tag_compatibility)
+    in_list = in_list->next;
 
   for (; in_list; in_list = in_list->next)
     {
@@ -9800,125 +9394,9 @@ 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.  */
@@ -9948,8 +9426,6 @@ 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;
 }
 
@@ -10677,7 +10153,6 @@ const struct elf_size_info elf32_arm_size_info = {
 #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_free_cached_info          elf32_arm_bfd_free_cached_info
-#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
@@ -10722,6 +10197,15 @@ const struct elf_size_info elf32_arm_size_info = {
 
 #define elf_backend_got_header_size    12
 
+#undef elf_backend_obj_attrs_vendor
+#define elf_backend_obj_attrs_vendor   "aeabi"
+#undef elf_backend_obj_attrs_section
+#define elf_backend_obj_attrs_section  ".ARM.attributes"
+#undef elf_backend_obj_attrs_arg_type
+#define elf_backend_obj_attrs_arg_type elf32_arm_obj_attrs_arg_type
+#undef elf_backend_obj_attrs_section_type
+#define elf_backend_obj_attrs_section_type     SHT_ARM_ATTRIBUTES
+
 #include "elf32-target.h"
 
 /* VxWorks Targets */
index e0ef0c9..bf8ed86 100644 (file)
@@ -4725,6 +4725,10 @@ bfin_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
index 0981522..97cce0b 100644 (file)
@@ -6490,6 +6490,10 @@ frv_elf_copy_private_bfd_data (ibfd, obfd)
 
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
index 536826b..160c996 100644 (file)
@@ -736,6 +736,10 @@ iq2000_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
index 1db8346..169da44 100644 (file)
@@ -750,6 +750,10 @@ mep_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
 
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
index 2b539d0..a1d8652 100644 (file)
@@ -515,6 +515,10 @@ mt_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
 
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
   elf_flags_init (obfd) = TRUE;
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return TRUE;
 }
 
index c982860..739d2d7 100644 (file)
@@ -5356,6 +5356,9 @@ sh_elf_copy_private_data (bfd * ibfd, bfd * obfd)
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
 }
 #endif /* not sh_elf_copy_private_data */
index 969e312..6d343b7 100644 (file)
@@ -2316,6 +2316,9 @@ sh_elf64_copy_private_data_internal (bfd *ibfd, bfd *obfd)
        }
     }
 
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
   return sh_elf64_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
 }
 
index f27db39..9f0efa5 100644 (file)
@@ -9266,6 +9266,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   size_t relativecount = 0;
   asection *reldyn = 0;
   bfd_size_type amt;
+  asection *attr_section = NULL;
+  bfd_vma attr_size = 0;
+  const char *std_attrs_section;
 
   if (! is_elf_hash_table (info->hash))
     return FALSE;
@@ -9313,6 +9316,40 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   finfo.symbuf_count = 0;
   finfo.shndxbuf_size = 0;
 
+  /* The object attributes have been merged.  Remove the input
+     sections from the link, and set the contents of the output
+     secton.  */
+  std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
+  for (o = abfd->sections; o != NULL; o = o->next)
+    {
+      if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
+         || strcmp (o->name, ".gnu.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;
+           }
+           
+         attr_size = bfd_elf_obj_attr_size (abfd);
+         if (attr_size)
+           {
+             bfd_set_section_size (abfd, o, attr_size);
+             attr_section = o;
+             /* Skip this section later on.  */
+             o->map_head.link_order = NULL;
+           }
+         else
+           o->flags |= SEC_EXCLUDE;
+       }
+    }
+
   /* Count up the number of relocations we will output for each output
      section, so that we know the sizes of the reloc sections.  We
      also figure out some maximum sizes.  */
@@ -10257,6 +10294,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   elf_tdata (abfd)->linker = TRUE;
 
+  if (attr_section)
+    {
+      bfd_byte *contents = bfd_malloc (attr_size);
+      if (contents == NULL)
+       goto error_return;
+      bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
+      bfd_set_section_contents (abfd, attr_section, contents, 0, attr_size);
+      free (contents);
+    }
+
   return TRUE;
 
  error_return:
index 7b14781..be0cfec 100644 (file)
 #ifndef elf_backend_got_header_size
 #define elf_backend_got_header_size    0
 #endif
+#ifndef elf_backend_obj_attrs_vendor
+#define elf_backend_obj_attrs_vendor           NULL
+#endif
+#ifndef elf_backend_obj_attrs_section
+#define elf_backend_obj_attrs_section          NULL
+#endif
+#ifndef elf_backend_obj_attrs_arg_type
+#define elf_backend_obj_attrs_arg_type         NULL
+#endif
+#ifndef elf_backend_obj_attrs_section_type
+#define elf_backend_obj_attrs_section_type             SHT_GNU_ATTRIBUTES
+#endif
 #ifndef elf_backend_post_process_headers
 #define elf_backend_post_process_headers       NULL
 #endif
@@ -684,6 +696,10 @@ static struct elf_backend_data elfNN_bed =
   &elf_backend_size_info,
   elf_backend_special_sections,
   elf_backend_got_header_size,
+  elf_backend_obj_attrs_vendor,
+  elf_backend_obj_attrs_section,
+  elf_backend_obj_attrs_arg_type,
+  elf_backend_obj_attrs_section_type,
   elf_backend_collect,
   elf_backend_type_change_ok,
   elf_backend_may_use_rel_p,
index 60ae510..d6fe54a 100644 (file)
@@ -1,3 +1,12 @@
+2007-06-29  Joseph Myers  <joseph@codesourcery.com>
+
+       * arm.h (elf32_arm_add_eabi_attr_int,
+       elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat,
+       elf32_arm_get_eabi_attr_int, elf32_arm_set_eabi_attr_contents,
+       elf32_arm_eabi_attr_size, Tag_NULL, Tag_File, Tag_Section,
+       Tag_Symbol, Tag_compatibility): Remove.
+       * common.h (SHT_GNU_ATTRIBUTES): Define.
+
 2007-06-29  M R Swami Reddy  <MR.Swami.Reddy@nsc.com>
 
        * common.h (EM_CR16): New entry for CR16 cpu.
index 890ef8d..e701883 100644 (file)
@@ -237,22 +237,12 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
 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 *);
-int elf32_arm_get_eabi_attr_int (bfd *, int);
-
-void elf32_arm_set_eabi_attr_contents (bfd *, bfd_byte *, bfd_vma);
-bfd_vma elf32_arm_eabi_attr_size (bfd *);
+/* EABI object attributes.  */
 
 enum
 {
-  Tag_NULL,
-  Tag_File,
-  Tag_Section,
-  Tag_Symbol,
-  Tag_CPU_raw_name,
+  /* 0-3 are generic.  */
+  Tag_CPU_raw_name = 4,
   Tag_CPU_name,
   Tag_CPU_arch,
   Tag_CPU_arch_profile,
@@ -280,7 +270,7 @@ enum
   Tag_ABI_WMMX_args,
   Tag_ABI_optimization_goals,
   Tag_ABI_FP_optimization_goals,
-  Tag_compatibility,
+  /* 32 is generic.  */
 };
 
 #endif
index ae90491..2eb6853 100644 (file)
 #define SHT_LOOS       0x60000000      /* First of OS specific semantics */
 #define SHT_HIOS       0x6fffffff      /* Last of OS specific semantics */
 
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5  /* Object attributes */
 #define SHT_GNU_HASH   0x6ffffff6      /* GNU style symbol hash table */
 #define SHT_GNU_LIBLIST        0x6ffffff7      /* List of prelink dependencies */