Line 1... |
Line 1... |
/* ELF attributes support (based on ARM EABI attributes).
|
/* ELF attributes support (based on ARM EABI attributes).
|
Copyright 2005, 2006, 2007
|
Copyright 2005, 2006, 2007, 2009
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
Line 41... |
Line 41... |
|
|
/* Return TRUE if the attribute has the default value (0/""). */
|
/* Return TRUE if the attribute has the default value (0/""). */
|
static bfd_boolean
|
static bfd_boolean
|
is_default_attr (obj_attribute *attr)
|
is_default_attr (obj_attribute *attr)
|
{
|
{
|
if ((attr->type & 1) && attr->i != 0)
|
if (ATTR_TYPE_HAS_INT_VAL (attr->type) && attr->i != 0)
|
return FALSE;
|
return FALSE;
|
if ((attr->type & 2) && attr->s && *attr->s)
|
if (ATTR_TYPE_HAS_STR_VAL (attr->type) && attr->s && *attr->s)
|
|
return FALSE;
|
|
if (ATTR_TYPE_HAS_NO_DEFAULT (attr->type))
|
return FALSE;
|
return FALSE;
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
Line 59... |
Line 61... |
|
|
if (is_default_attr (attr))
|
if (is_default_attr (attr))
|
return 0;
|
return 0;
|
|
|
size = uleb128_size (tag);
|
size = uleb128_size (tag);
|
if (attr->type & 1)
|
if (ATTR_TYPE_HAS_INT_VAL (attr->type))
|
size += uleb128_size (attr->i);
|
size += uleb128_size (attr->i);
|
if (attr->type & 2)
|
if (ATTR_TYPE_HAS_STR_VAL (attr->type))
|
size += strlen ((char *)attr->s) + 1;
|
size += strlen ((char *)attr->s) + 1;
|
return size;
|
return size;
|
}
|
}
|
|
|
/* Return the vendor name for a given object attributes section. */
|
/* Return the vendor name for a given object attributes section. */
|
Line 147... |
Line 149... |
/* Suppress default entries. */
|
/* Suppress default entries. */
|
if (is_default_attr (attr))
|
if (is_default_attr (attr))
|
return p;
|
return p;
|
|
|
p = write_uleb128 (p, tag);
|
p = write_uleb128 (p, tag);
|
if (attr->type & 1)
|
if (ATTR_TYPE_HAS_INT_VAL (attr->type))
|
p = write_uleb128 (p, attr->i);
|
p = write_uleb128 (p, attr->i);
|
if (attr->type & 2)
|
if (ATTR_TYPE_HAS_STR_VAL (attr->type))
|
{
|
{
|
int len;
|
int len;
|
|
|
len = strlen (attr->s) + 1;
|
len = strlen (attr->s) + 1;
|
memcpy (p, attr->s, len);
|
memcpy (p, attr->s, len);
|
Line 185... |
Line 187... |
bfd_put_32 (abfd, size - 4 - vendor_length, p);
|
bfd_put_32 (abfd, size - 4 - vendor_length, p);
|
p += 4;
|
p += 4;
|
|
|
attr = elf_known_obj_attributes (abfd)[vendor];
|
attr = elf_known_obj_attributes (abfd)[vendor];
|
for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
|
for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
|
p = write_obj_attribute (p, i, &attr[i]);
|
{
|
|
int tag = i;
|
|
if (get_elf_backend_data (abfd)->obj_attrs_order)
|
|
tag = get_elf_backend_data (abfd)->obj_attrs_order (i);
|
|
p = write_obj_attribute (p, tag, &attr[tag]);
|
|
}
|
|
|
for (list = elf_other_obj_attributes (abfd)[vendor];
|
for (list = elf_other_obj_attributes (abfd)[vendor];
|
list;
|
list;
|
list = list->next)
|
list = list->next)
|
p = write_obj_attribute (p, list->tag, &list->attr);
|
p = write_obj_attribute (p, list->tag, &list->attr);
|
Line 229... |
Line 236... |
obj_attribute_list **lastp;
|
obj_attribute_list **lastp;
|
|
|
|
|
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
|
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
|
{
|
{
|
/* Knwon tags are preallocated. */
|
/* Known tags are preallocated. */
|
attr = &elf_known_obj_attributes (abfd)[vendor][tag];
|
attr = &elf_known_obj_attributes (abfd)[vendor][tag];
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Create a new tag. */
|
/* Create a new tag. */
|
Line 263... |
Line 270... |
{
|
{
|
obj_attribute_list *p;
|
obj_attribute_list *p;
|
|
|
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
|
if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
|
{
|
{
|
/* Knwon tags are preallocated. */
|
/* Known tags are preallocated. */
|
return elf_known_obj_attributes (abfd)[vendor][tag].i;
|
return elf_known_obj_attributes (abfd)[vendor][tag].i;
|
}
|
}
|
else
|
else
|
{
|
{
|
for (p = elf_other_obj_attributes (abfd)[vendor];
|
for (p = elf_other_obj_attributes (abfd)[vendor];
|
Line 288... |
Line 295... |
bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i)
|
bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i)
|
{
|
{
|
obj_attribute *attr;
|
obj_attribute *attr;
|
|
|
attr = elf_new_obj_attr (abfd, vendor, tag);
|
attr = elf_new_obj_attr (abfd, vendor, tag);
|
attr->type = 1;
|
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
|
attr->i = i;
|
attr->i = i;
|
}
|
}
|
|
|
/* Duplicate an object attribute string value. */
|
/* Duplicate an object attribute string value. */
|
char *
|
char *
|
Line 301... |
Line 308... |
char * p;
|
char * p;
|
int len;
|
int len;
|
|
|
len = strlen (s) + 1;
|
len = strlen (s) + 1;
|
p = (char *) bfd_alloc (abfd, len);
|
p = (char *) bfd_alloc (abfd, len);
|
return memcpy (p, s, len);
|
return (char *) memcpy (p, s, len);
|
}
|
}
|
|
|
/* Add a string object attribute. */
|
/* Add a string object attribute. */
|
void
|
void
|
bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s)
|
bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s)
|
{
|
{
|
obj_attribute *attr;
|
obj_attribute *attr;
|
|
|
attr = elf_new_obj_attr (abfd, vendor, tag);
|
attr = elf_new_obj_attr (abfd, vendor, tag);
|
attr->type = 2;
|
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
|
attr->s = _bfd_elf_attr_strdup (abfd, s);
|
attr->s = _bfd_elf_attr_strdup (abfd, s);
|
}
|
}
|
|
|
/* Add a Tag_compatibility object attribute. */
|
/* Add a int+string object attribute. */
|
void
|
void
|
bfd_elf_add_obj_attr_compat (bfd *abfd, int vendor, unsigned int i,
|
bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, int tag,
|
const char *s)
|
unsigned int i, const char *s)
|
{
|
{
|
obj_attribute_list *list;
|
obj_attribute *attr;
|
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];
|
attr = elf_new_obj_attr (abfd, vendor, tag);
|
for (p = *lastp; p; p = p->next)
|
attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
|
{
|
attr->i = i;
|
int cmp;
|
attr->s = _bfd_elf_attr_strdup (abfd, s);
|
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. */
|
/* Copy the object attributes from IBFD to OBFD. */
|
void
|
void
|
_bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
|
_bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
|
Line 376... |
Line 364... |
for (list = elf_other_obj_attributes (ibfd)[vendor];
|
for (list = elf_other_obj_attributes (ibfd)[vendor];
|
list;
|
list;
|
list = list->next)
|
list = list->next)
|
{
|
{
|
in_attr = &list->attr;
|
in_attr = &list->attr;
|
switch (in_attr->type)
|
switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
|
{
|
{
|
case 1:
|
case ATTR_TYPE_FLAG_INT_VAL:
|
bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
|
bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
|
break;
|
break;
|
case 2:
|
case ATTR_TYPE_FLAG_STR_VAL:
|
bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
|
bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
|
in_attr->s);
|
in_attr->s);
|
break;
|
break;
|
case 3:
|
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
|
bfd_elf_add_obj_attr_compat (obfd, vendor, in_attr->i,
|
bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag,
|
in_attr->s);
|
in_attr->i, in_attr->s);
|
break;
|
break;
|
default:
|
default:
|
abort ();
|
abort ();
|
}
|
}
|
}
|
}
|
Line 438... |
Line 426... |
bfd_byte *contents;
|
bfd_byte *contents;
|
bfd_byte *p;
|
bfd_byte *p;
|
bfd_vma len;
|
bfd_vma len;
|
const char *std_section;
|
const char *std_section;
|
|
|
contents = bfd_malloc (hdr->sh_size);
|
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
|
if (!contents)
|
if (!contents)
|
return;
|
return;
|
if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
|
if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
|
hdr->sh_size))
|
hdr->sh_size))
|
{
|
{
|
Line 504... |
Line 492... |
int type;
|
int type;
|
|
|
tag = read_unsigned_leb128 (abfd, p, &n);
|
tag = read_unsigned_leb128 (abfd, p, &n);
|
p += n;
|
p += n;
|
type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
|
type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
|
switch (type)
|
switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
|
{
|
{
|
case 3:
|
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
|
val = read_unsigned_leb128 (abfd, p, &n);
|
val = read_unsigned_leb128 (abfd, p, &n);
|
p += n;
|
p += n;
|
bfd_elf_add_obj_attr_compat (abfd, vendor, val,
|
bfd_elf_add_obj_attr_int_string (abfd, vendor, tag,
|
(char *)p);
|
val, (char *)p);
|
p += strlen ((char *)p) + 1;
|
p += strlen ((char *)p) + 1;
|
break;
|
break;
|
case 2:
|
case ATTR_TYPE_FLAG_STR_VAL:
|
bfd_elf_add_obj_attr_string (abfd, vendor, tag,
|
bfd_elf_add_obj_attr_string (abfd, vendor, tag,
|
(char *)p);
|
(char *)p);
|
p += strlen ((char *)p) + 1;
|
p += strlen ((char *)p) + 1;
|
break;
|
break;
|
case 1:
|
case ATTR_TYPE_FLAG_INT_VAL:
|
val = read_unsigned_leb128 (abfd, p, &n);
|
val = read_unsigned_leb128 (abfd, p, &n);
|
p += n;
|
p += n;
|
bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
|
bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
|
break;
|
break;
|
default:
|
default:
|
Line 559... |
Line 547... |
bfd_boolean
|
bfd_boolean
|
_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
|
_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
|
{
|
{
|
obj_attribute *in_attr;
|
obj_attribute *in_attr;
|
obj_attribute *out_attr;
|
obj_attribute *out_attr;
|
obj_attribute_list *in_list;
|
|
obj_attribute_list *out_list;
|
|
int vendor;
|
int vendor;
|
|
|
/* The only common attribute is currently Tag_compatibility,
|
/* The only common attribute is currently Tag_compatibility,
|
accepted in both processor and "gnu" sections. */
|
accepted in both processor and "gnu" sections. */
|
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
|
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
|
{
|
{
|
in_list = elf_other_obj_attributes (ibfd)[vendor];
|
/* Handle Tag_compatibility. The tags are only compatible if the flags
|
out_list = elf_other_obj_attributes (ibfd)[vendor];
|
are identical and, if the flags are '1', the strings are identical.
|
while (in_list && in_list->tag == Tag_compatibility)
|
If the flags are non-zero, then we can only use the string "gnu". */
|
{
|
in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility];
|
in_attr = &in_list->attr;
|
out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility];
|
if (in_attr->i == 0)
|
|
continue;
|
if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0)
|
if (in_attr->i == 1 && strcmp (in_attr->s, "gnu") != 0)
|
|
{
|
{
|
_bfd_error_handler
|
_bfd_error_handler
|
(_("ERROR: %B: Must be processed by '%s' toolchain"),
|
(_("error: %B: Must be processed by '%s' toolchain"),
|
ibfd, in_attr->s);
|
ibfd, in_attr->s);
|
return FALSE;
|
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 (in_attr->i != out_attr->i
|
if (out_list && out_list->tag == Tag_compatibility
|
|| (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0))
|
&& strcmp (in_attr->s, out_list->attr.s) == 0)
|
|
{
|
{
|
_bfd_error_handler
|
_bfd_error_handler (_("error: %B: Object tag '%d, %s' is "
|
(_("ERROR: %B: Incompatible object tag '%s':%d"),
|
"incompatible with tag '%d, %s'"),
|
ibfd, in_attr->s, out_list->attr.i);
|
ibfd,
|
|
in_attr->i, in_attr->s ? in_attr->s : "",
|
|
out_attr->i, out_attr->s ? out_attr->s : "");
|
return FALSE;
|
return FALSE;
|
}
|
}
|
}
|
}
|
}
|
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|