* 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.
This commit is contained in:
Joseph Myers 2007-06-29 16:29:17 +00:00
parent 5ab7998193
commit 104d59d19c
35 changed files with 1236 additions and 687 deletions

View 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

View 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

View 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

2
bfd/configure vendored
View File

@ -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

View 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

628
bfd/elf-attrs.c Normal file
View File

@ -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;
}

View 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])
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;

View File

@ -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;

View 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 */

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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 */

View 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);
}

View 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:

View File

@ -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,

View File

@ -1,3 +1,9 @@
2007-06-29 Joseph Myers <joseph@codesourcery.com>
* readelf.c (display_gnu_attribute): New.
(process_arm_specific): Rearrange as process_attributes.
(process_arm_specific): Replace by wrapper of process_attributes.
2007-06-28 Roland McGrath <roland@frob.com>
* objcopy.c (setup_section): Don't reset ELF section type to

View File

@ -8297,8 +8297,61 @@ display_arm_attribute (unsigned char *p)
return p;
}
static unsigned char *
display_gnu_attribute (unsigned char *p,
unsigned char *(*display_proc_gnu_attribute)
(unsigned char *, int))
{
int tag;
unsigned int len;
int val;
int type;
tag = read_uleb128 (p, &len);
p += len;
/* Tag_compatibility is the only generic GNU attribute defined at
present. */
if (tag == 32)
{
val = read_uleb128 (p, &len);
p += len;
printf ("flag = %d, vendor = %s\n", val, p);
p += strlen((char *)p) + 1;
return p;
}
if ((tag & 2) == 0 && display_proc_gnu_attribute)
return display_proc_gnu_attribute (p, tag);
if (tag & 1)
type = 1; /* String. */
else
type = 2; /* uleb128. */
printf (" Tag_unknown_%d: ", tag);
if (type == 1)
{
printf ("\"%s\"\n", p);
p += strlen ((char *)p) + 1;
}
else
{
val = read_uleb128 (p, &len);
p += len;
printf ("%d (0x%x)\n", val, val);
}
return p;
}
static int
process_arm_specific (FILE *file)
process_attributes (FILE *file, const char *public_name,
unsigned int proc_type,
unsigned char *(*display_pub_attribute) (unsigned char *),
unsigned char *(*display_proc_gnu_attribute)
(unsigned char *, int))
{
Elf_Internal_Shdr *sect;
unsigned char *contents;
@ -8313,7 +8366,7 @@ process_arm_specific (FILE *file)
i < elf_header.e_shnum;
i++, sect++)
{
if (sect->sh_type != SHT_ARM_ATTRIBUTES)
if (sect->sh_type != proc_type && sect->sh_type != SHT_GNU_ATTRIBUTES)
continue;
contents = get_data (NULL, file, sect->sh_offset, 1, sect->sh_size,
@ -8330,6 +8383,7 @@ process_arm_specific (FILE *file)
{
int namelen;
bfd_boolean public_section;
bfd_boolean gnu_section;
section_len = byte_get (p, 4);
p += 4;
@ -8341,10 +8395,14 @@ process_arm_specific (FILE *file)
}
len -= section_len;
printf ("Attribute Section: %s\n", p);
if (strcmp ((char *)p, "aeabi") == 0)
if (public_name && strcmp ((char *)p, public_name) == 0)
public_section = TRUE;
else
public_section = FALSE;
if (strcmp ((char *)p, "gnu") == 0)
gnu_section = TRUE;
else
gnu_section = FALSE;
namelen = strlen ((char *)p) + 1;
p += namelen;
section_len -= namelen + 4;
@ -8393,7 +8451,13 @@ process_arm_specific (FILE *file)
if (public_section)
{
while (p < end)
p = display_arm_attribute(p);
p = display_pub_attribute (p);
}
else if (gnu_section)
{
while (p < end)
p = display_gnu_attribute (p,
display_proc_gnu_attribute);
}
else
{
@ -8414,6 +8478,13 @@ process_arm_specific (FILE *file)
return 1;
}
static int
process_arm_specific (FILE *file)
{
return process_attributes (file, "aeabi", SHT_ARM_ATTRIBUTES,
display_arm_attribute, NULL);
}
static int
process_mips_specific (FILE *file)
{

View File

@ -1,3 +1,18 @@
2007-06-29 Joseph Myers <joseph@codesourcery.com>
* 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.
2007-06-29 M R Swami Reddy <MR.Swami.Redd@nsc.com>
* Makefile.am: Add CR16 related entry.

View File

@ -1031,6 +1031,33 @@ perform_an_assembly_pass (int argc, char ** argv)
read_a_source_file ("");
}
#ifdef OBJ_ELF
static void
create_obj_attrs_section (void)
{
segT s;
char *p;
addressT addr;
offsetT size;
const char *name;
size = bfd_elf_obj_attr_size (stdoutput);
if (size)
{
name = get_elf_backend_data (stdoutput)->obj_attrs_section;
if (!name)
name = ".gnu.attributes";
s = subseg_new (name, 0);
elf_section_type (s)
= get_elf_backend_data (stdoutput)->obj_attrs_section_type;
bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
addr = frag_now_fix ();
p = frag_more (size);
bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
}
}
#endif
int
main (int argc, char ** argv)
@ -1146,6 +1173,10 @@ main (int argc, char ** argv)
md_end ();
#endif
#ifdef OBJ_ELF
create_obj_attrs_section ();
#endif
#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
if ((flag_execstack || flag_noexecstack)
&& OUTPUT_FLAVOR == bfd_target_elf_flavour)

View File

@ -3829,84 +3829,7 @@ s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
static void
s_arm_eabi_attribute (int ignored ATTRIBUTE_UNUSED)
{
expressionS exp;
bfd_boolean is_string;
int tag;
unsigned int i = 0;
char *s = NULL;
char saved_char;
expression (& exp);
if (exp.X_op != O_constant)
goto bad;
tag = exp.X_add_number;
if (tag == 4 || tag == 5 || tag == 32 || (tag > 32 && (tag & 1) != 0))
is_string = 1;
else
is_string = 0;
if (skip_past_comma (&input_line_pointer) == FAIL)
goto bad;
if (tag == 32 || !is_string)
{
expression (& exp);
if (exp.X_op != O_constant)
{
as_bad (_("expected numeric constant"));
ignore_rest_of_line ();
return;
}
i = exp.X_add_number;
}
if (tag == Tag_compatibility
&& skip_past_comma (&input_line_pointer) == FAIL)
{
as_bad (_("expected comma"));
ignore_rest_of_line ();
return;
}
if (is_string)
{
skip_whitespace(input_line_pointer);
if (*input_line_pointer != '"')
goto bad_string;
input_line_pointer++;
s = input_line_pointer;
while (*input_line_pointer && *input_line_pointer != '"')
input_line_pointer++;
if (*input_line_pointer != '"')
goto bad_string;
saved_char = *input_line_pointer;
*input_line_pointer = 0;
}
else
{
s = NULL;
saved_char = 0;
}
if (tag == Tag_compatibility)
elf32_arm_add_eabi_attr_compat (stdoutput, i, s);
else if (is_string)
elf32_arm_add_eabi_attr_string (stdoutput, tag, s);
else
elf32_arm_add_eabi_attr_int (stdoutput, tag, i);
if (s)
{
*input_line_pointer = saved_char;
input_line_pointer++;
}
demand_empty_rest_of_line ();
return;
bad_string:
as_bad (_("bad string constant"));
ignore_rest_of_line ();
return;
bad:
as_bad (_("expected <tag> , <value>"));
ignore_rest_of_line ();
s_vendor_attribute (OBJ_ATTR_PROC);
}
#endif /* OBJ_ELF */
@ -20609,65 +20532,54 @@ aeabi_set_public_attributes (void)
for (i = 0; p[i]; i++)
p[i] = TOUPPER (p[i]);
}
elf32_arm_add_eabi_attr_string (stdoutput, 5, p);
bfd_elf_add_proc_attr_string (stdoutput, 5, p);
}
/* Tag_CPU_arch. */
elf32_arm_add_eabi_attr_int (stdoutput, 6, arch);
bfd_elf_add_proc_attr_int (stdoutput, 6, arch);
/* Tag_CPU_arch_profile. */
if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a))
elf32_arm_add_eabi_attr_int (stdoutput, 7, 'A');
bfd_elf_add_proc_attr_int (stdoutput, 7, 'A');
else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7r))
elf32_arm_add_eabi_attr_int (stdoutput, 7, 'R');
bfd_elf_add_proc_attr_int (stdoutput, 7, 'R');
else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7m))
elf32_arm_add_eabi_attr_int (stdoutput, 7, 'M');
bfd_elf_add_proc_attr_int (stdoutput, 7, 'M');
/* Tag_ARM_ISA_use. */
if (ARM_CPU_HAS_FEATURE (arm_arch_used, arm_arch_full))
elf32_arm_add_eabi_attr_int (stdoutput, 8, 1);
bfd_elf_add_proc_attr_int (stdoutput, 8, 1);
/* Tag_THUMB_ISA_use. */
if (ARM_CPU_HAS_FEATURE (thumb_arch_used, arm_arch_full))
elf32_arm_add_eabi_attr_int (stdoutput, 9,
bfd_elf_add_proc_attr_int (stdoutput, 9,
ARM_CPU_HAS_FEATURE (thumb_arch_used, arm_arch_t2) ? 2 : 1);
/* Tag_VFP_arch. */
if (ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_vfp_ext_v3)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_vfp_ext_v3))
elf32_arm_add_eabi_attr_int (stdoutput, 10, 3);
bfd_elf_add_proc_attr_int (stdoutput, 10, 3);
else if (ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_vfp_ext_v2)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_vfp_ext_v2))
elf32_arm_add_eabi_attr_int (stdoutput, 10, 2);
bfd_elf_add_proc_attr_int (stdoutput, 10, 2);
else if (ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_vfp_ext_v1)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_vfp_ext_v1)
|| ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_vfp_ext_v1xd)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_vfp_ext_v1xd))
elf32_arm_add_eabi_attr_int (stdoutput, 10, 1);
bfd_elf_add_proc_attr_int (stdoutput, 10, 1);
/* Tag_WMMX_arch. */
if (ARM_CPU_HAS_FEATURE (thumb_arch_used, arm_cext_iwmmxt)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, arm_cext_iwmmxt))
elf32_arm_add_eabi_attr_int (stdoutput, 11, 1);
bfd_elf_add_proc_attr_int (stdoutput, 11, 1);
/* Tag_NEON_arch. */
if (ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_neon_ext_v1)
|| ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_neon_ext_v1))
elf32_arm_add_eabi_attr_int (stdoutput, 12, 1);
bfd_elf_add_proc_attr_int (stdoutput, 12, 1);
}
/* Add the .ARM.attributes section. */
/* Add the default contents for the .ARM.attributes section. */
void
arm_md_end (void)
{
segT s;
char *p;
addressT addr;
offsetT size;
if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4)
return;
aeabi_set_public_attributes ();
size = elf32_arm_eabi_attr_size (stdoutput);
s = subseg_new (".ARM.attributes", 0);
bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
addr = frag_now_fix ();
p = frag_more (size);
elf32_arm_set_eabi_attr_contents (stdoutput, (bfd_byte *)p, size);
}
#endif /* OBJ_ELF */

View File

@ -213,6 +213,9 @@ static void do_align (int, char *, int, int);
static void s_align (int, int);
static void s_altmacro (int);
static void s_bad_end (int);
#ifdef OBJ_ELF
static void s_gnu_attribute (int);
#endif
static void s_reloc (int);
static int hex_float (int, char *);
static segT get_known_segmented_expression (expressionS * expP);
@ -339,6 +342,9 @@ static const pseudo_typeS potable[] = {
{"func", s_func, 0},
{"global", s_globl, 0},
{"globl", s_globl, 0},
#ifdef OBJ_ELF
{"gnu_attribute", s_gnu_attribute, 0},
#endif
{"hword", cons, 2},
{"if", s_if, (int) O_ne},
{"ifb", s_ifb, 1},
@ -2033,6 +2039,120 @@ s_globl (int ignore ATTRIBUTE_UNUSED)
mri_comment_end (stop, stopc);
}
#ifdef OBJ_ELF
#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0)
static inline int
skip_past_char (char ** str, char c)
{
if (**str == c)
{
(*str)++;
return 0;
}
else
return -1;
}
#define skip_past_comma(str) skip_past_char (str, ',')
/* Parse an attribute directive for VENDOR. */
void
s_vendor_attribute (int vendor)
{
expressionS exp;
int type;
int tag;
unsigned int i = 0;
char *s = NULL;
char saved_char;
expression (& exp);
if (exp.X_op != O_constant)
goto bad;
tag = exp.X_add_number;
type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
if (skip_past_comma (&input_line_pointer) == -1)
goto bad;
if (type & 1)
{
expression (& exp);
if (exp.X_op != O_constant)
{
as_bad (_("expected numeric constant"));
ignore_rest_of_line ();
return;
}
i = exp.X_add_number;
}
if (type == 3
&& skip_past_comma (&input_line_pointer) == -1)
{
as_bad (_("expected comma"));
ignore_rest_of_line ();
return;
}
if (type & 2)
{
skip_whitespace(input_line_pointer);
if (*input_line_pointer != '"')
goto bad_string;
input_line_pointer++;
s = input_line_pointer;
while (*input_line_pointer && *input_line_pointer != '"')
input_line_pointer++;
if (*input_line_pointer != '"')
goto bad_string;
saved_char = *input_line_pointer;
*input_line_pointer = 0;
}
else
{
s = NULL;
saved_char = 0;
}
switch (type)
{
case 3:
bfd_elf_add_obj_attr_compat (stdoutput, vendor, i, s);
break;
case 2:
bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
break;
case 1:
bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
break;
default:
abort ();
}
if (s)
{
*input_line_pointer = saved_char;
input_line_pointer++;
}
demand_empty_rest_of_line ();
return;
bad_string:
as_bad (_("bad string constant"));
ignore_rest_of_line ();
return;
bad:
as_bad (_("expected <tag> , <value>"));
ignore_rest_of_line ();
}
/* Parse a .gnu_attribute directive. */
static void
s_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
{
s_vendor_attribute (OBJ_ATTR_GNU);
}
#endif /* OBJ_ELF */
/* Handle the MRI IRP and IRPC pseudo-ops. */
void

View File

@ -185,4 +185,5 @@ extern void stringer (int append_zero);
extern void s_xstab (int what);
extern void s_rva (int);
extern void s_incbin (int);
extern void s_vendor_attribute (int);
extern void s_weakref (int);

View 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.

View 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

View File

@ -343,6 +343,7 @@
#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 */

View File

@ -1,3 +1,11 @@
2007-06-29 Joseph Myers <joseph@codesourcery.com>
* 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.
2006-06-29 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
* scripttemp/elf32cr16.sc: Default linker script.

View File

@ -10,8 +10,8 @@ OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)'
OTHER_BSS_SYMBOLS='__bss_start__ = .;'
OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
OTHER_END_SYMBOLS='__end__ = . ;'
OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }'
OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
OTHER_READONLY_SECTIONS="
.ARM.extab ${RELOCATING-0} : { *(.ARM.extab${RELOCATING+* .gnu.linkonce.armextab.*}) }
${RELOCATING+ __exidx_start = .; }

View File

@ -15,6 +15,7 @@
# OTHER_RELRO_SECTIONS - other than .data.rel.ro ...
# (e.g. PPC32 .fixup, .got[12])
# OTHER_BSS_SECTIONS - other than .bss .sbss ...
# ATTRS_SECTIONS - at the end
# OTHER_SECTIONS - at the end
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
@ -96,6 +97,7 @@ test -z "${ETEXT_NAME}" && ETEXT_NAME=etext
test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT
test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_RELRO_END=""
DATA_SEGMENT_END=""
@ -513,6 +515,7 @@ cat <<EOF
${TINY_BSS_SECTION}
${STACK_ADDR+${STACK}}
${ATTRS_SECTIONS}
${OTHER_SECTIONS}
${RELOCATING+${OTHER_SYMBOLS}}
${RELOCATING+${STACKNOTE}}

View File

@ -8,6 +8,7 @@
# OTHER_TEXT_SECTIONS - these get put in .text when relocating
# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
# (e.g., .PARISC.global)
# ATTRS_SECTIONS - at the end
# OTHER_SECTIONS - at the end
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
@ -71,6 +72,7 @@ test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
test "$LD_FLAG" = "N" && DATA_ADDR=.
test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_END=""
if test -n "${COMMONPAGESIZE}"; then
@ -375,6 +377,7 @@ cat <<EOF
.debug_varnames 0 : { *(.debug_varnames) }
${STACK_ADDR+${STACK}}
${ATTRS_SECTIONS}
${OTHER_SECTIONS}
${RELOCATING+${OTHER_SYMBOLS}}
${RELOCATING+${STACKNOTE}}

View File

@ -10,6 +10,7 @@
# OTHER_TEXT_SECTIONS - these get put in .text when relocating
# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
# (e.g., .PARISC.global)
# ATTRS_SECTIONS - at the end
# OTHER_SECTIONS - at the end
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
@ -68,6 +69,7 @@ test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
test -z "${ELFSIZE}" && ELFSIZE=32
test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
test "$LD_FLAG" = "N" && DATA_ADDR=.
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
PLT=".plt ${RELOCATING-0} : { *(.plt) }"
@ -349,6 +351,7 @@ cat <<EOF
.debug_varnames 0 : { *(.debug_varnames) }
${STACK_ADDR+${STACK}}
${ATTRS_SECTIONS}
${OTHER_SECTIONS}
${RELOCATING+${OTHER_SYMBOLS}}
}

View File

@ -8,6 +8,7 @@
# (e.g., .PARISC.milli)
# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
# (e.g., .PARISC.global)
# ATTRS_SECTIONS - at the end
# OTHER_SECTIONS - at the end
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
@ -24,6 +25,7 @@
test -z "$ENTRY" && ENTRY=_start
test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
test "$LD_FLAG" = "N" && DATA_ADDR=.
SBSS2=".sbss2 ${RELOCATING-0} : { *(.sbss2) }"
SDATA2=".sdata2 ${RELOCATING-0} : { *(.sdata2) }"
@ -212,6 +214,7 @@ SECTIONS
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
${ATTRS_SECTIONS}
${OTHER_SECTIONS}
}
EOF

View File

@ -15,6 +15,7 @@
# OTHER_RELRO_SECTIONS - other than .data.rel.ro ...
# (e.g. PPC32 .fixup, .got[12])
# OTHER_BSS_SECTIONS - other than .bss .sbss ...
# ATTRS_SECTIONS - at the end
# OTHER_SECTIONS - at the end
# EXECUTABLE_SYMBOLS - symbols that must be defined for an
# executable (e.g., _DYNAMIC_LINK)
@ -109,6 +110,7 @@ test -z "${ETEXT_NAME}" && ETEXT_NAME=etext
test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT
test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_RELRO_END=""
DATA_SEGMENT_END=""
@ -533,6 +535,7 @@ cat <<EOF
${TINY_BSS_SECTION}
${STACK_ADDR+${STACK}}
${ATTRS_SECTIONS}
${OTHER_SECTIONS}
${RELOCATING+${OTHER_SYMBOLS}}
${RELOCATING+${STACKNOTE}}