aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2007-06-29 16:29:17 +0000
committerJoseph Myers <joseph@codesourcery.com>2007-06-29 16:29:17 +0000
commit104d59d19c416dcbf54fb387970b27178feb17d5 (patch)
tree90921bc1aa5b7bca865fdf8645f7b47502946c2f /bfd
parent5ab79981933708d465b91676baf6994996979da8 (diff)
downloadbinutils-104d59d19c416dcbf54fb387970b27178feb17d5.zip
binutils-104d59d19c416dcbf54fb387970b27178feb17d5.tar.gz
binutils-104d59d19c416dcbf54fb387970b27178feb17d5.tar.bz2
bfd:
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog63
-rw-r--r--bfd/Makefile.am5
-rw-r--r--bfd/Makefile.in5
-rwxr-xr-xbfd/configure2
-rw-r--r--bfd/configure.in2
-rw-r--r--bfd/elf-attrs.c628
-rw-r--r--bfd/elf-bfd.h82
-rw-r--r--bfd/elf.c14
-rw-r--r--bfd/elf32-arm.c610
-rw-r--r--bfd/elf32-bfin.c4
-rw-r--r--bfd/elf32-frv.c4
-rw-r--r--bfd/elf32-iq2000.c4
-rw-r--r--bfd/elf32-mep.c4
-rw-r--r--bfd/elf32-mt.c4
-rw-r--r--bfd/elf32-sh.c3
-rw-r--r--bfd/elf64-sh64.c3
-rw-r--r--bfd/elflink.c47
-rw-r--r--bfd/elfxx-target.h16
18 files changed, 935 insertions, 565 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1f7f5c4..051b530 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 59c8367..2dd906f 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -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
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index fa347a2..7777144 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -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
diff --git a/bfd/configure b/bfd/configure
index cbab0d3..3cff895 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -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
diff --git a/bfd/configure.in b/bfd/configure.in
index 7fb45ae..1ea98ae 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -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
index 0000000..d1a64f4
--- /dev/null
+++ b/bfd/elf-attrs.c
@@ -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;
+}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 3ead565..f4c3a0a 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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])
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;
diff --git a/bfd/elf.c b/bfd/elf.c
index baa9512..68b226a 100644
--- 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;
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index a213bab..85ed8d7 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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 */
diff --git a/bfd/elf32-bfin.c b/bfd/elf32-bfin.c
index e0ef0c9..bf8ed86 100644
--- a/bfd/elf32-bfin.c
+++ b/bfd/elf32-bfin.c
@@ -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;
}
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index 0981522..97cce0b 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -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;
}
diff --git a/bfd/elf32-iq2000.c b/bfd/elf32-iq2000.c
index 536826b..160c996 100644
--- a/bfd/elf32-iq2000.c
+++ b/bfd/elf32-iq2000.c
@@ -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;
}
diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c
index 1db8346..169da44 100644
--- a/bfd/elf32-mep.c
+++ b/bfd/elf32-mep.c
@@ -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;
}
diff --git a/bfd/elf32-mt.c b/bfd/elf32-mt.c
index 2b539d0..a1d8652 100644
--- a/bfd/elf32-mt.c
+++ b/bfd/elf32-mt.c
@@ -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;
}
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index c982860..739d2d7 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -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 */
diff --git a/bfd/elf64-sh64.c b/bfd/elf64-sh64.c
index 969e312..6d343b7 100644
--- a/bfd/elf64-sh64.c
+++ b/bfd/elf64-sh64.c
@@ -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);
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f27db39..9f0efa5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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:
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 7b14781..be0cfec 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -431,6 +431,18 @@
#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,