Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
cpu-arm.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "libiberty.h"

Go to the source code of this file.

Classes

struct  arm_Note

Defines

#define N(number, print, default, next)   { 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
#define NOTE_ARCH_STRING   "arch: "

Functions

static const bfd_arch_info_typecompatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
static bfd_boolean scan (const struct bfd_arch_info *info, const char *string)
bfd_boolean bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
static bfd_boolean arm_check_note (bfd *abfd, bfd_byte *buffer, bfd_size_type buffer_size, const char *expected_name, char **description_return)
bfd_boolean bfd_arm_update_notes (bfd *abfd, const char *note_section)
unsigned int bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
bfd_boolean bfd_is_arm_special_symbol_name (const char *name, int type)

Variables

struct {
unsigned int mach
char * name
processors []
static const bfd_arch_info_type arch_info_struct []
const bfd_arch_info_type bfd_arm_arch
struct {
const char * string
unsigned int mach
architectures []

Class Documentation

struct arm_Note

Definition at line 213 of file cpu-arm.c.

Class Members
unsigned char descsz
char name
unsigned char namesz
unsigned char type

Define Documentation

#define N (   number,
  print,
  default,
  next 
)    { 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }

Definition at line 125 of file cpu-arm.c.

#define NOTE_ARCH_STRING   "arch: "

Definition at line 271 of file cpu-arm.c.


Function Documentation

static bfd_boolean arm_check_note ( bfd abfd,
bfd_byte buffer,
bfd_size_type  buffer_size,
const char *  expected_name,
char **  description_return 
) [static]

Definition at line 222 of file cpu-arm.c.

{
  unsigned long namesz;
  unsigned long descsz;
  unsigned long type;
  char *        descr;

  if (buffer_size < offsetof (arm_Note, name))
    return FALSE;

  /* We have to extract the values this way to allow for a
     host whose endian-ness is different from the target.  */
  namesz = bfd_get_32 (abfd, buffer);
  descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
  type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
  descr  = (char *) buffer + offsetof (arm_Note, name);

  /* Check for buffer overflow.  */
  if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
    return FALSE;

  if (expected_name == NULL)
    {
      if (namesz != 0)
       return FALSE;
    }
  else
    { 
      if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
       return FALSE;
      
      if (strcmp (descr, expected_name) != 0)
       return FALSE;

      descr += (namesz + 3) & ~3;
    }

  /* FIXME: We should probably check the type as well.  */

  if (description_return != NULL)
    * description_return = descr;

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned int bfd_arm_get_mach_from_notes ( bfd abfd,
const char *  note_section 
)

Definition at line 371 of file cpu-arm.c.

{
  asection *     arm_arch_section;
  bfd_size_type  buffer_size;
  bfd_byte *     buffer;
  char *         arch_string;
  int            i;

  /* Look for a note section.  If one is present check the architecture
     string encoded in it, and set it to the current architecture if it is
     different.  */
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);

  if (arm_arch_section == NULL)
    return bfd_mach_arm_unknown;

  buffer_size = arm_arch_section->size;
  if (buffer_size == 0)
    return bfd_mach_arm_unknown;

  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
    goto FAIL;

  /* Parse the note.  */
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
    goto FAIL;

  /* Interpret the architecture string.  */
  for (i = ARRAY_SIZE (architectures); i--;)
    if (strcmp (arch_string, architectures[i].string) == 0)
      {
       free (buffer);
       return architectures[i].mach;
      }

 FAIL:
  if (buffer != NULL)
    free (buffer);
  return bfd_mach_arm_unknown;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean bfd_arm_merge_machines ( bfd ibfd,
bfd obfd 
)

Definition at line 156 of file cpu-arm.c.

{
  unsigned int in  = bfd_get_mach (ibfd);
  unsigned int out = bfd_get_mach (obfd);

  /* If the output architecture is unknown, we now have a value to set.  */
  if (out == bfd_mach_arm_unknown)
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);

  /* If the input architecture is unknown,
     then so must be the output architecture.  */
  else if (in == bfd_mach_arm_unknown)
    /* FIXME: We ought to have some way to
       override this on the command line.  */
    bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);

  /* If they are the same then nothing needs to be done.  */
  else if (out == in)
    ;

  /* Otherwise the general principle that a earlier architecture can be
     linked with a later architecture to produce a binary that will execute
     on the later architecture.

     We fail however if we attempt to link a Cirrus EP9312 binary with an
     Intel XScale binary, since these architecture have co-processors which
     will not both be present on the same physical hardware.  */
  else if (in == bfd_mach_arm_ep9312
          && (out == bfd_mach_arm_XScale
              || out == bfd_mach_arm_iWMMXt
              || out == bfd_mach_arm_iWMMXt2))
    {
      _bfd_error_handler (_("\
ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
                       ibfd, obfd);
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
    }
  else if (out == bfd_mach_arm_ep9312
          && (in == bfd_mach_arm_XScale
              || in == bfd_mach_arm_iWMMXt
              || in == bfd_mach_arm_iWMMXt2))
    {
      _bfd_error_handler (_("\
ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
                       obfd, ibfd);
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
    }
  else if (in > out)
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
  /* else
     Nothing to do.  */

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean bfd_arm_update_notes ( bfd abfd,
const char *  note_section 
)

Definition at line 274 of file cpu-arm.c.

{
  asection *     arm_arch_section;
  bfd_size_type  buffer_size;
  bfd_byte *     buffer;
  char *         arch_string;
  char *         expected;

  /* Look for a note section.  If one is present check the architecture
     string encoded in it, and set it to the current architecture if it is
     different.  */
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);

  if (arm_arch_section == NULL)
    return TRUE;

  buffer_size = arm_arch_section->size;
  if (buffer_size == 0)
    return FALSE;

  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
    goto FAIL;

  /* Parse the note.  */
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
    goto FAIL;

  /* Check the architecture in the note against the architecture of the bfd.  */
  switch (bfd_get_mach (abfd))
    {
    default:
    case bfd_mach_arm_unknown: expected = "unknown"; break;
    case bfd_mach_arm_2:       expected = "armv2"; break;
    case bfd_mach_arm_2a:      expected = "armv2a"; break;
    case bfd_mach_arm_3:       expected = "armv3"; break;
    case bfd_mach_arm_3M:      expected = "armv3M"; break;
    case bfd_mach_arm_4:       expected = "armv4"; break;
    case bfd_mach_arm_4T:      expected = "armv4t"; break;
    case bfd_mach_arm_5:       expected = "armv5"; break;
    case bfd_mach_arm_5T:      expected = "armv5t"; break;
    case bfd_mach_arm_5TE:     expected = "armv5te"; break;
    case bfd_mach_arm_XScale:  expected = "XScale"; break;
    case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
    case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
    case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
    }

  if (strcmp (arch_string, expected) != 0)
    {
      strcpy ((char *) buffer + (offsetof (arm_Note, name)
                             + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
             expected);

      if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
                                  (file_ptr) 0, buffer_size))
       {
         (*_bfd_error_handler)
           (_("warning: unable to update contents of %s section in %s"),
            note_section, bfd_get_filename (abfd));
         goto FAIL;
       }
    }

  free (buffer);
  return TRUE;

 FAIL:
  if (buffer != NULL)
    free (buffer);
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean bfd_is_arm_special_symbol_name ( const char *  name,
int  type 
)

Definition at line 413 of file cpu-arm.c.

{
  /* The ARM compiler outputs several obsolete forms.  Recognize them
     in addition to the standard $a, $t and $d.  We are somewhat loose
     in what we accept here, since the full set is not documented.  */
  if (!name || name[0] != '$')
    return FALSE;
  if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
    type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
  else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
    type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
  else if (name[1] >= 'a' && name[1] <= 'z')
    type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
  else
    return FALSE;

  return (type != 0 && (name[2] == 0 || name[2] == '.'));
}

Here is the caller graph for this function:

Definition at line 32 of file cpu-arm.c.

{
  /* If a & b are for different architecture we can do nothing.  */
  if (a->arch != b->arch)
      return NULL;

  /* If a & b are for the same machine then all is well.  */
  if (a->mach == b->mach)
    return a;

  /* Otherwise if either a or b is the 'default' machine
     then it can be polymorphed into the other.  */
  if (a->the_default)
    return b;

  if (b->the_default)
    return a;

  /* So far all newer ARM architecture cores are
     supersets of previous cores.  */
  if (a->mach < b->mach)
    return b;
  else if (a->mach > b->mach)
    return a;

  /* Never reached!  */
  return NULL;
}

Here is the caller graph for this function:

static bfd_boolean scan ( const struct bfd_arch_info info,
const char *  string 
) [static]

Definition at line 100 of file cpu-arm.c.

{
  int  i;

  /* First test for an exact match.  */
  if (strcasecmp (string, info->printable_name) == 0)
    return TRUE;

  /* Next check for a processor name instead of an Architecture name.  */
  for (i = sizeof (processors) / sizeof (processors[0]); i--;)
    {
      if (strcasecmp (string, processors [i].name) == 0)
       break;
    }

  if (i != -1 && info->mach == processors [i].mach)
    return TRUE;

  /* Finally check for the default architecture.  */
  if (strcasecmp (string, "arm") == 0)
    return info->the_default;

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:

Definition at line 128 of file cpu-arm.c.

struct { ... } architectures[] [static]
Initial value:
  N (0, "arm", TRUE, & arch_info_struct[0])

Definition at line 145 of file cpu-arm.c.

struct { ... } processors[] [static]