OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [elf-attrs.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* ELF attributes support (based on ARM EABI attributes).
/* ELF attributes support (based on ARM EABI attributes).
   Copyright 2005, 2006, 2007
   Copyright 2005, 2006, 2007
   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
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "libiberty.h"
#include "libiberty.h"
#include "libbfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
 
 
/* Return the number of bytes needed by I in uleb128 format.  */
/* Return the number of bytes needed by I in uleb128 format.  */
static int
static int
uleb128_size (unsigned int i)
uleb128_size (unsigned int i)
{
{
  int size;
  int size;
  size = 1;
  size = 1;
  while (i >= 0x80)
  while (i >= 0x80)
    {
    {
      i >>= 7;
      i >>= 7;
      size++;
      size++;
    }
    }
  return size;
  return size;
}
}
 
 
/* 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 & 1) && attr->i != 0)
    return FALSE;
    return FALSE;
  if ((attr->type & 2) && attr->s && *attr->s)
  if ((attr->type & 2) && attr->s && *attr->s)
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Return the size of a single attribute.  */
/* Return the size of a single attribute.  */
static bfd_vma
static bfd_vma
obj_attr_size (int tag, obj_attribute *attr)
obj_attr_size (int tag, obj_attribute *attr)
{
{
  bfd_vma size;
  bfd_vma size;
 
 
  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 & 1)
    size += uleb128_size (attr->i);
    size += uleb128_size (attr->i);
  if (attr->type & 2)
  if (attr->type & 2)
    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.  */
static const char *
static const char *
vendor_obj_attr_name (bfd *abfd, int vendor)
vendor_obj_attr_name (bfd *abfd, int vendor)
{
{
  return (vendor == OBJ_ATTR_PROC
  return (vendor == OBJ_ATTR_PROC
          ? get_elf_backend_data (abfd)->obj_attrs_vendor
          ? get_elf_backend_data (abfd)->obj_attrs_vendor
          : "gnu");
          : "gnu");
}
}
 
 
/* Return the size of the object attributes section for VENDOR
/* Return the size of the object attributes section for VENDOR
   (OBJ_ATTR_PROC or OBJ_ATTR_GNU), or 0 if there are no attributes
   (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.  */
   for that vendor to record and the vendor is OBJ_ATTR_GNU.  */
static bfd_vma
static bfd_vma
vendor_obj_attr_size (bfd *abfd, int vendor)
vendor_obj_attr_size (bfd *abfd, int vendor)
{
{
  bfd_vma size;
  bfd_vma size;
  obj_attribute *attr;
  obj_attribute *attr;
  obj_attribute_list *list;
  obj_attribute_list *list;
  int i;
  int i;
  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
 
 
  if (!vendor_name)
  if (!vendor_name)
    return 0;
    return 0;
 
 
  attr = elf_known_obj_attributes (abfd)[vendor];
  attr = elf_known_obj_attributes (abfd)[vendor];
  size = 0;
  size = 0;
  for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
  for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
    size += obj_attr_size (i, &attr[i]);
    size += obj_attr_size (i, &attr[i]);
 
 
  for (list = elf_other_obj_attributes (abfd)[vendor];
  for (list = elf_other_obj_attributes (abfd)[vendor];
       list;
       list;
       list = list->next)
       list = list->next)
    size += obj_attr_size (list->tag, &list->attr);
    size += obj_attr_size (list->tag, &list->attr);
 
 
  /* <size> <vendor_name> NUL 0x1 <size> */
  /* <size> <vendor_name> NUL 0x1 <size> */
  return ((size || vendor == OBJ_ATTR_PROC)
  return ((size || vendor == OBJ_ATTR_PROC)
          ? size + 10 + strlen (vendor_name)
          ? size + 10 + strlen (vendor_name)
          : 0);
          : 0);
}
}
 
 
/* Return the size of the object attributes section.  */
/* Return the size of the object attributes section.  */
bfd_vma
bfd_vma
bfd_elf_obj_attr_size (bfd *abfd)
bfd_elf_obj_attr_size (bfd *abfd)
{
{
  bfd_vma size;
  bfd_vma size;
 
 
  size = vendor_obj_attr_size (abfd, OBJ_ATTR_PROC);
  size = vendor_obj_attr_size (abfd, OBJ_ATTR_PROC);
  size += vendor_obj_attr_size (abfd, OBJ_ATTR_GNU);
  size += vendor_obj_attr_size (abfd, OBJ_ATTR_GNU);
 
 
  /* 'A' <sections for each vendor> */
  /* 'A' <sections for each vendor> */
  return (size ? size + 1 : 0);
  return (size ? size + 1 : 0);
}
}
 
 
/* Write VAL in uleb128 format to P, returning a pointer to the
/* Write VAL in uleb128 format to P, returning a pointer to the
   following byte.  */
   following byte.  */
static bfd_byte *
static bfd_byte *
write_uleb128 (bfd_byte *p, unsigned int val)
write_uleb128 (bfd_byte *p, unsigned int val)
{
{
  bfd_byte c;
  bfd_byte c;
  do
  do
    {
    {
      c = val & 0x7f;
      c = val & 0x7f;
      val >>= 7;
      val >>= 7;
      if (val)
      if (val)
        c |= 0x80;
        c |= 0x80;
      *(p++) = c;
      *(p++) = c;
    }
    }
  while (val);
  while (val);
  return p;
  return p;
}
}
 
 
/* Write attribute ATTR to butter P, and return a pointer to the following
/* Write attribute ATTR to butter P, and return a pointer to the following
   byte.  */
   byte.  */
static bfd_byte *
static bfd_byte *
write_obj_attribute (bfd_byte *p, int tag, obj_attribute *attr)
write_obj_attribute (bfd_byte *p, int tag, obj_attribute *attr)
{
{
  /* 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 & 1)
    p = write_uleb128 (p, attr->i);
    p = write_uleb128 (p, attr->i);
  if (attr->type & 2)
  if (attr->type & 2)
    {
    {
      int len;
      int len;
 
 
      len = strlen (attr->s) + 1;
      len = strlen (attr->s) + 1;
      memcpy (p, attr->s, len);
      memcpy (p, attr->s, len);
      p += len;
      p += len;
    }
    }
 
 
  return p;
  return p;
}
}
 
 
/* Write the contents of the object attributes section (length SIZE)
/* Write the contents of the object attributes section (length SIZE)
   for VENDOR to CONTENTS.  */
   for VENDOR to CONTENTS.  */
static void
static void
vendor_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size,
vendor_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size,
                              int vendor)
                              int vendor)
{
{
  bfd_byte *p;
  bfd_byte *p;
  obj_attribute *attr;
  obj_attribute *attr;
  obj_attribute_list *list;
  obj_attribute_list *list;
  int i;
  int i;
  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
  const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
  size_t vendor_length = strlen (vendor_name) + 1;
  size_t vendor_length = strlen (vendor_name) + 1;
 
 
  p = contents;
  p = contents;
  bfd_put_32 (abfd, size, p);
  bfd_put_32 (abfd, size, p);
  p += 4;
  p += 4;
  memcpy (p, vendor_name, vendor_length);
  memcpy (p, vendor_name, vendor_length);
  p += vendor_length;
  p += vendor_length;
  *(p++) = Tag_File;
  *(p++) = Tag_File;
  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]);
    p = write_obj_attribute (p, i, &attr[i]);
 
 
  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);
}
}
 
 
/* Write the contents of the object attributes section to CONTENTS.  */
/* Write the contents of the object attributes section to CONTENTS.  */
void
void
bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
{
{
  bfd_byte *p;
  bfd_byte *p;
  int vendor;
  int vendor;
  bfd_vma my_size;
  bfd_vma my_size;
 
 
  p = contents;
  p = contents;
  *(p++) = 'A';
  *(p++) = 'A';
  my_size = 1;
  my_size = 1;
  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
    {
    {
      bfd_vma vendor_size = vendor_obj_attr_size (abfd, vendor);
      bfd_vma vendor_size = vendor_obj_attr_size (abfd, vendor);
      if (vendor_size)
      if (vendor_size)
        vendor_set_obj_attr_contents (abfd, p, vendor_size, vendor);
        vendor_set_obj_attr_contents (abfd, p, vendor_size, vendor);
      p += vendor_size;
      p += vendor_size;
      my_size += vendor_size;
      my_size += vendor_size;
    }
    }
 
 
  if (size != my_size)
  if (size != my_size)
    abort ();
    abort ();
}
}
 
 
/* Allocate/find an object attribute.  */
/* Allocate/find an object attribute.  */
static obj_attribute *
static obj_attribute *
elf_new_obj_attr (bfd *abfd, int vendor, int tag)
elf_new_obj_attr (bfd *abfd, int vendor, int tag)
{
{
  obj_attribute *attr;
  obj_attribute *attr;
  obj_attribute_list *list;
  obj_attribute_list *list;
  obj_attribute_list *p;
  obj_attribute_list *p;
  obj_attribute_list **lastp;
  obj_attribute_list **lastp;
 
 
 
 
  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
    {
    {
      /* Knwon tags are preallocated.  */
      /* Knwon 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.  */
      list = (obj_attribute_list *)
      list = (obj_attribute_list *)
        bfd_alloc (abfd, sizeof (obj_attribute_list));
        bfd_alloc (abfd, sizeof (obj_attribute_list));
      memset (list, 0, sizeof (obj_attribute_list));
      memset (list, 0, sizeof (obj_attribute_list));
      list->tag = tag;
      list->tag = tag;
      /* Keep the tag list in order.  */
      /* Keep the tag list in order.  */
      lastp = &elf_other_obj_attributes (abfd)[vendor];
      lastp = &elf_other_obj_attributes (abfd)[vendor];
      for (p = *lastp; p; p = p->next)
      for (p = *lastp; p; p = p->next)
        {
        {
          if (tag < p->tag)
          if (tag < p->tag)
            break;
            break;
          lastp = &p->next;
          lastp = &p->next;
        }
        }
      list->next = *lastp;
      list->next = *lastp;
      *lastp = list;
      *lastp = list;
      attr = &list->attr;
      attr = &list->attr;
    }
    }
 
 
  return attr;
  return attr;
}
}
 
 
/* Return the value of an integer object attribute.  */
/* Return the value of an integer object attribute.  */
int
int
bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag)
bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag)
{
{
  obj_attribute_list *p;
  obj_attribute_list *p;
 
 
  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
    {
    {
      /* Knwon tags are preallocated.  */
      /* Knwon 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];
           p;
           p;
           p = p->next)
           p = p->next)
        {
        {
          if (tag == p->tag)
          if (tag == p->tag)
            return p->attr.i;
            return p->attr.i;
          if (tag < p->tag)
          if (tag < p->tag)
            break;
            break;
        }
        }
      return 0;
      return 0;
    }
    }
}
}
 
 
/* Add an integer object attribute.  */
/* Add an integer object attribute.  */
void
void
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 = 1;
  attr->i = i;
  attr->i = i;
}
}
 
 
/* Duplicate an object attribute string value.  */
/* Duplicate an object attribute string value.  */
char *
char *
_bfd_elf_attr_strdup (bfd *abfd, const char * s)
_bfd_elf_attr_strdup (bfd *abfd, const char * s)
{
{
  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 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 = 2;
  attr->s = _bfd_elf_attr_strdup (abfd, s);
  attr->s = _bfd_elf_attr_strdup (abfd, s);
}
}
 
 
/* Add a Tag_compatibility object attribute.  */
/* Add a Tag_compatibility object attribute.  */
void
void
bfd_elf_add_obj_attr_compat (bfd *abfd, int vendor, unsigned int i,
bfd_elf_add_obj_attr_compat (bfd *abfd, int vendor, unsigned int i,
                             const char *s)
                             const char *s)
{
{
  obj_attribute_list *list;
  obj_attribute_list *list;
  obj_attribute_list *p;
  obj_attribute_list *p;
  obj_attribute_list **lastp;
  obj_attribute_list **lastp;
 
 
  list = (obj_attribute_list *)
  list = (obj_attribute_list *)
    bfd_alloc (abfd, sizeof (obj_attribute_list));
    bfd_alloc (abfd, sizeof (obj_attribute_list));
  memset (list, 0, sizeof (obj_attribute_list));
  memset (list, 0, sizeof (obj_attribute_list));
  list->tag = Tag_compatibility;
  list->tag = Tag_compatibility;
  list->attr.type = 3;
  list->attr.type = 3;
  list->attr.i = i;
  list->attr.i = i;
  list->attr.s = _bfd_elf_attr_strdup (abfd, s);
  list->attr.s = _bfd_elf_attr_strdup (abfd, s);
 
 
  lastp = &elf_other_obj_attributes (abfd)[vendor];
  lastp = &elf_other_obj_attributes (abfd)[vendor];
  for (p = *lastp; p; p = p->next)
  for (p = *lastp; p; p = p->next)
    {
    {
      int cmp;
      int cmp;
      if (p->tag != Tag_compatibility)
      if (p->tag != Tag_compatibility)
        break;
        break;
      cmp = strcmp(s, p->attr.s);
      cmp = strcmp(s, p->attr.s);
      if (cmp < 0 || (cmp == 0 && i < p->attr.i))
      if (cmp < 0 || (cmp == 0 && i < p->attr.i))
        break;
        break;
      lastp = &p->next;
      lastp = &p->next;
    }
    }
  list->next = *lastp;
  list->next = *lastp;
  *lastp = list;
  *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)
{
{
  obj_attribute *in_attr;
  obj_attribute *in_attr;
  obj_attribute *out_attr;
  obj_attribute *out_attr;
  obj_attribute_list *list;
  obj_attribute_list *list;
  int i;
  int i;
  int vendor;
  int vendor;
 
 
  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
  for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
    {
    {
      in_attr = &elf_known_obj_attributes (ibfd)[vendor][4];
      in_attr = &elf_known_obj_attributes (ibfd)[vendor][4];
      out_attr = &elf_known_obj_attributes (obfd)[vendor][4];
      out_attr = &elf_known_obj_attributes (obfd)[vendor][4];
      for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
      for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
        {
        {
          out_attr->type = in_attr->type;
          out_attr->type = in_attr->type;
          out_attr->i = in_attr->i;
          out_attr->i = in_attr->i;
          if (in_attr->s && *in_attr->s)
          if (in_attr->s && *in_attr->s)
            out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
            out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
          in_attr++;
          in_attr++;
          out_attr++;
          out_attr++;
        }
        }
 
 
      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)
            {
            {
            case 1:
            case 1:
              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 2:
              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 3:
              bfd_elf_add_obj_attr_compat (obfd, vendor, in_attr->i,
              bfd_elf_add_obj_attr_compat (obfd, vendor, in_attr->i,
                                           in_attr->s);
                                           in_attr->s);
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
        }
        }
    }
    }
}
}
 
 
/* Determine whether a GNU object attribute tag takes an integer, a
/* Determine whether a GNU object attribute tag takes an integer, a
   string or both.  */
   string or both.  */
static int
static int
gnu_obj_attrs_arg_type (int tag)
gnu_obj_attrs_arg_type (int tag)
{
{
  /* Except for Tag_compatibility, for GNU attributes we follow the
  /* Except for Tag_compatibility, for GNU attributes we follow the
     same rule ARM ones > 32 follow: odd-numbered tags take strings
     same rule ARM ones > 32 follow: odd-numbered tags take strings
     and even-numbered tags take integers.  In addition, tag & 2 is
     and even-numbered tags take integers.  In addition, tag & 2 is
     nonzero for architecture-independent tags and zero for
     nonzero for architecture-independent tags and zero for
     architecture-dependent ones.  */
     architecture-dependent ones.  */
  if (tag == Tag_compatibility)
  if (tag == Tag_compatibility)
    return 3;
    return 3;
  else
  else
    return (tag & 1) != 0 ? 2 : 1;
    return (tag & 1) != 0 ? 2 : 1;
}
}
 
 
/* Determine what arguments an attribute tag takes.  */
/* Determine what arguments an attribute tag takes.  */
int
int
_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
{
{
  switch (vendor)
  switch (vendor)
    {
    {
    case OBJ_ATTR_PROC:
    case OBJ_ATTR_PROC:
      return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
      return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
      break;
      break;
    case OBJ_ATTR_GNU:
    case OBJ_ATTR_GNU:
      return gnu_obj_attrs_arg_type (tag);
      return gnu_obj_attrs_arg_type (tag);
      break;
      break;
    default:
    default:
      abort ();
      abort ();
    }
    }
}
}
 
 
/* Parse an object attributes section.  */
/* Parse an object attributes section.  */
void
void
_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
{
{
  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_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))
    {
    {
      free (contents);
      free (contents);
      return;
      return;
    }
    }
  p = contents;
  p = contents;
  std_section = get_elf_backend_data (abfd)->obj_attrs_vendor;
  std_section = get_elf_backend_data (abfd)->obj_attrs_vendor;
  if (*(p++) == 'A')
  if (*(p++) == 'A')
    {
    {
      len = hdr->sh_size - 1;
      len = hdr->sh_size - 1;
      while (len > 0)
      while (len > 0)
        {
        {
          int namelen;
          int namelen;
          bfd_vma section_len;
          bfd_vma section_len;
          int vendor;
          int vendor;
 
 
          section_len = bfd_get_32 (abfd, p);
          section_len = bfd_get_32 (abfd, p);
          p += 4;
          p += 4;
          if (section_len > len)
          if (section_len > len)
            section_len = len;
            section_len = len;
          len -= section_len;
          len -= section_len;
          namelen = strlen ((char *)p) + 1;
          namelen = strlen ((char *)p) + 1;
          section_len -= namelen + 4;
          section_len -= namelen + 4;
          if (std_section && strcmp ((char *)p, std_section) == 0)
          if (std_section && strcmp ((char *)p, std_section) == 0)
            vendor = OBJ_ATTR_PROC;
            vendor = OBJ_ATTR_PROC;
          else if (strcmp ((char *)p, "gnu") == 0)
          else if (strcmp ((char *)p, "gnu") == 0)
            vendor = OBJ_ATTR_GNU;
            vendor = OBJ_ATTR_GNU;
          else
          else
            {
            {
              /* Other vendor section.  Ignore it.  */
              /* Other vendor section.  Ignore it.  */
              p += namelen + section_len;
              p += namelen + section_len;
              continue;
              continue;
            }
            }
 
 
          p += namelen;
          p += namelen;
          while (section_len > 0)
          while (section_len > 0)
            {
            {
              int tag;
              int tag;
              unsigned int n;
              unsigned int n;
              unsigned int val;
              unsigned int val;
              bfd_vma subsection_len;
              bfd_vma subsection_len;
              bfd_byte *end;
              bfd_byte *end;
 
 
              tag = read_unsigned_leb128 (abfd, p, &n);
              tag = read_unsigned_leb128 (abfd, p, &n);
              p += n;
              p += n;
              subsection_len = bfd_get_32 (abfd, p);
              subsection_len = bfd_get_32 (abfd, p);
              p += 4;
              p += 4;
              if (subsection_len > section_len)
              if (subsection_len > section_len)
                subsection_len = section_len;
                subsection_len = section_len;
              section_len -= subsection_len;
              section_len -= subsection_len;
              subsection_len -= n + 4;
              subsection_len -= n + 4;
              end = p + subsection_len;
              end = p + subsection_len;
              switch (tag)
              switch (tag)
                {
                {
                case Tag_File:
                case Tag_File:
                  while (p < end)
                  while (p < end)
                    {
                    {
                      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)
                        {
                        {
                        case 3:
                        case 3:
                          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_compat (abfd, vendor, val,
                                                       (char *)p);
                                                       (char *)p);
                          p += strlen ((char *)p) + 1;
                          p += strlen ((char *)p) + 1;
                          break;
                          break;
                        case 2:
                        case 2:
                          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 1:
                          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:
                          abort ();
                          abort ();
                        }
                        }
                    }
                    }
                  break;
                  break;
                case Tag_Section:
                case Tag_Section:
                case Tag_Symbol:
                case Tag_Symbol:
                  /* Don't have anywhere convenient to attach these.
                  /* Don't have anywhere convenient to attach these.
                     Fall through for now.  */
                     Fall through for now.  */
                default:
                default:
                  /* Ignore things we don't kow about.  */
                  /* Ignore things we don't kow about.  */
                  p += subsection_len;
                  p += subsection_len;
                  subsection_len = 0;
                  subsection_len = 0;
                  break;
                  break;
                }
                }
            }
            }
        }
        }
    }
    }
  free (contents);
  free (contents);
}
}
 
 
/* Merge common object attributes from IBFD into OBFD.  Raise an error
/* Merge common object attributes from IBFD into OBFD.  Raise an error
   if there are conflicting attributes.  Any processor-specific
   if there are conflicting attributes.  Any processor-specific
   attributes have already been merged.  This must be called from the
   attributes have already been merged.  This must be called from the
   bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
   bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
   target, along with any target-specific merging.  Because there are
   target, along with any target-specific merging.  Because there are
   no common attributes other than Tag_compatibility at present, and
   no common attributes other than Tag_compatibility at present, and
   non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
   non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
   is not presently called for targets without their own
   is not presently called for targets without their own
   attributes.  */
   attributes.  */
 
 
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 *in_list;
  obj_attribute_list *out_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];
      in_list = elf_other_obj_attributes (ibfd)[vendor];
      out_list = elf_other_obj_attributes (ibfd)[vendor];
      out_list = elf_other_obj_attributes (ibfd)[vendor];
      while (in_list && in_list->tag == Tag_compatibility)
      while (in_list && in_list->tag == Tag_compatibility)
        {
        {
          in_attr = &in_list->attr;
          in_attr = &in_list->attr;
          if (in_attr->i == 0)
          if (in_attr->i == 0)
            continue;
            continue;
          if (in_attr->i == 1 && 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
          if (!out_list || out_list->tag != Tag_compatibility
              || strcmp (in_attr->s, out_list->attr.s) != 0)
              || strcmp (in_attr->s, out_list->attr.s) != 0)
            {
            {
              /* Add this compatibility tag to the output.  */
              /* Add this compatibility tag to the output.  */
              bfd_elf_add_proc_attr_compat (obfd, in_attr->i, in_attr->s);
              bfd_elf_add_proc_attr_compat (obfd, in_attr->i, in_attr->s);
              continue;
              continue;
            }
            }
          out_attr = &out_list->attr;
          out_attr = &out_list->attr;
          /* Check all the input tags with the same identifier.  */
          /* Check all the input tags with the same identifier.  */
          for (;;)
          for (;;)
            {
            {
              if (out_list->tag != Tag_compatibility
              if (out_list->tag != Tag_compatibility
                  || in_attr->i != out_attr->i
                  || in_attr->i != out_attr->i
                  || strcmp (in_attr->s, out_attr->s) != 0)
                  || strcmp (in_attr->s, out_attr->s) != 0)
                {
                {
                  _bfd_error_handler
                  _bfd_error_handler
                    (_("ERROR: %B: Incompatible object tag '%s':%d"),
                    (_("ERROR: %B: Incompatible object tag '%s':%d"),
                     ibfd, in_attr->s, in_attr->i);
                     ibfd, in_attr->s, in_attr->i);
                  return FALSE;
                  return FALSE;
                }
                }
              in_list = in_list->next;
              in_list = in_list->next;
              if (in_list->tag != Tag_compatibility
              if (in_list->tag != Tag_compatibility
                  || strcmp (in_attr->s, in_list->attr.s) != 0)
                  || strcmp (in_attr->s, in_list->attr.s) != 0)
                break;
                break;
              in_attr = &in_list->attr;
              in_attr = &in_list->attr;
              out_list = out_list->next;
              out_list = out_list->next;
              if (out_list)
              if (out_list)
                out_attr = &out_list->attr;
                out_attr = &out_list->attr;
            }
            }
 
 
          /* Check the output doesn't have extra tags with this identifier.  */
          /* Check the output doesn't have extra tags with this identifier.  */
          if (out_list && out_list->tag == Tag_compatibility
          if (out_list && out_list->tag == Tag_compatibility
              && strcmp (in_attr->s, out_list->attr.s) == 0)
              && strcmp (in_attr->s, out_list->attr.s) == 0)
            {
            {
              _bfd_error_handler
              _bfd_error_handler
                (_("ERROR: %B: Incompatible object tag '%s':%d"),
                (_("ERROR: %B: Incompatible object tag '%s':%d"),
                 ibfd, in_attr->s, out_list->attr.i);
                 ibfd, in_attr->s, out_list->attr.i);
              return FALSE;
              return FALSE;
            }
            }
        }
        }
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.