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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [elfcomm.c] - Diff between revs 15 and 166

Only display areas with differences | Details | Blame | View Log

Rev 15 Rev 166
/* elfcomm.c -- common code for ELF format file.
/* elfcomm.c -- common code for ELF format file.
   Copyright 2010
   Copyright 2010
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   Originally developed by Eric Youngdale <eric@andante.jic.com>
   Originally developed by Eric Youngdale <eric@andante.jic.com>
   Modifications by Nick Clifton <nickc@redhat.com>
   Modifications by Nick Clifton <nickc@redhat.com>
 
 
   This file is part of GNU Binutils.
   This file is part of GNU Binutils.
 
 
   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, MA
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "libiberty.h"
#include "libiberty.h"
#include "filenames.h"
#include "filenames.h"
#include "bfd.h"
#include "bfd.h"
#include "aout/ar.h"
#include "aout/ar.h"
#include "bucomm.h"
#include "bucomm.h"
#include "elfcomm.h"
#include "elfcomm.h"
 
 
void
void
error (const char *message, ...)
error (const char *message, ...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, message);
  va_start (args, message);
  fprintf (stderr, _("%s: Error: "), program_name);
  fprintf (stderr, _("%s: Error: "), program_name);
  vfprintf (stderr, message, args);
  vfprintf (stderr, message, args);
  va_end (args);
  va_end (args);
}
}
 
 
void
void
warn (const char *message, ...)
warn (const char *message, ...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, message);
  va_start (args, message);
  fprintf (stderr, _("%s: Warning: "), program_name);
  fprintf (stderr, _("%s: Warning: "), program_name);
  vfprintf (stderr, message, args);
  vfprintf (stderr, message, args);
  va_end (args);
  va_end (args);
}
}
 
 
void (*byte_put) (unsigned char *, elf_vma, int);
void (*byte_put) (unsigned char *, elf_vma, int);
 
 
void
void
byte_put_little_endian (unsigned char * field, elf_vma value, int size)
byte_put_little_endian (unsigned char * field, elf_vma value, int size)
{
{
  switch (size)
  switch (size)
    {
    {
    case 8:
    case 8:
      field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
      field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
      field[6] = ((value >> 24) >> 24) & 0xff;
      field[6] = ((value >> 24) >> 24) & 0xff;
      field[5] = ((value >> 24) >> 16) & 0xff;
      field[5] = ((value >> 24) >> 16) & 0xff;
      field[4] = ((value >> 24) >> 8) & 0xff;
      field[4] = ((value >> 24) >> 8) & 0xff;
      /* Fall through.  */
      /* Fall through.  */
    case 4:
    case 4:
      field[3] = (value >> 24) & 0xff;
      field[3] = (value >> 24) & 0xff;
      /* Fall through.  */
      /* Fall through.  */
    case 3:
    case 3:
      field[2] = (value >> 16) & 0xff;
      field[2] = (value >> 16) & 0xff;
      /* Fall through.  */
      /* Fall through.  */
    case 2:
    case 2:
      field[1] = (value >> 8) & 0xff;
      field[1] = (value >> 8) & 0xff;
      /* Fall through.  */
      /* Fall through.  */
    case 1:
    case 1:
      field[0] = value & 0xff;
      field[0] = value & 0xff;
      break;
      break;
 
 
    default:
    default:
      error (_("Unhandled data length: %d\n"), size);
      error (_("Unhandled data length: %d\n"), size);
      abort ();
      abort ();
    }
    }
}
}
 
 
void
void
byte_put_big_endian (unsigned char * field, elf_vma value, int size)
byte_put_big_endian (unsigned char * field, elf_vma value, int size)
{
{
  switch (size)
  switch (size)
    {
    {
    case 8:
    case 8:
      field[7] = value & 0xff;
      field[7] = value & 0xff;
      field[6] = (value >> 8) & 0xff;
      field[6] = (value >> 8) & 0xff;
      field[5] = (value >> 16) & 0xff;
      field[5] = (value >> 16) & 0xff;
      field[4] = (value >> 24) & 0xff;
      field[4] = (value >> 24) & 0xff;
      value >>= 16;
      value >>= 16;
      value >>= 16;
      value >>= 16;
      /* Fall through.  */
      /* Fall through.  */
    case 4:
    case 4:
      field[3] = value & 0xff;
      field[3] = value & 0xff;
      value >>= 8;
      value >>= 8;
      /* Fall through.  */
      /* Fall through.  */
    case 3:
    case 3:
      field[2] = value & 0xff;
      field[2] = value & 0xff;
      value >>= 8;
      value >>= 8;
      /* Fall through.  */
      /* Fall through.  */
    case 2:
    case 2:
      field[1] = value & 0xff;
      field[1] = value & 0xff;
      value >>= 8;
      value >>= 8;
      /* Fall through.  */
      /* Fall through.  */
    case 1:
    case 1:
      field[0] = value & 0xff;
      field[0] = value & 0xff;
      break;
      break;
 
 
    default:
    default:
      error (_("Unhandled data length: %d\n"), size);
      error (_("Unhandled data length: %d\n"), size);
      abort ();
      abort ();
    }
    }
}
}
 
 
elf_vma (*byte_get) (unsigned char *, int);
elf_vma (*byte_get) (unsigned char *, int);
 
 
elf_vma
elf_vma
byte_get_little_endian (unsigned char *field, int size)
byte_get_little_endian (unsigned char *field, int size)
{
{
  switch (size)
  switch (size)
    {
    {
    case 1:
    case 1:
      return *field;
      return *field;
 
 
    case 2:
    case 2:
      return  ((unsigned int) (field[0]))
      return  ((unsigned int) (field[0]))
        |    (((unsigned int) (field[1])) << 8);
        |    (((unsigned int) (field[1])) << 8);
 
 
    case 3:
    case 3:
      return  ((unsigned long) (field[0]))
      return  ((unsigned long) (field[0]))
        |    (((unsigned long) (field[1])) << 8)
        |    (((unsigned long) (field[1])) << 8)
        |    (((unsigned long) (field[2])) << 16);
        |    (((unsigned long) (field[2])) << 16);
 
 
    case 4:
    case 4:
      return  ((unsigned long) (field[0]))
      return  ((unsigned long) (field[0]))
        |    (((unsigned long) (field[1])) << 8)
        |    (((unsigned long) (field[1])) << 8)
        |    (((unsigned long) (field[2])) << 16)
        |    (((unsigned long) (field[2])) << 16)
        |    (((unsigned long) (field[3])) << 24);
        |    (((unsigned long) (field[3])) << 24);
 
 
    case 8:
    case 8:
      if (sizeof (elf_vma) == 8)
      if (sizeof (elf_vma) == 8)
        return  ((elf_vma) (field[0]))
        return  ((elf_vma) (field[0]))
          |    (((elf_vma) (field[1])) << 8)
          |    (((elf_vma) (field[1])) << 8)
          |    (((elf_vma) (field[2])) << 16)
          |    (((elf_vma) (field[2])) << 16)
          |    (((elf_vma) (field[3])) << 24)
          |    (((elf_vma) (field[3])) << 24)
          |    (((elf_vma) (field[4])) << 32)
          |    (((elf_vma) (field[4])) << 32)
          |    (((elf_vma) (field[5])) << 40)
          |    (((elf_vma) (field[5])) << 40)
          |    (((elf_vma) (field[6])) << 48)
          |    (((elf_vma) (field[6])) << 48)
          |    (((elf_vma) (field[7])) << 56);
          |    (((elf_vma) (field[7])) << 56);
      else if (sizeof (elf_vma) == 4)
      else if (sizeof (elf_vma) == 4)
        /* We want to extract data from an 8 byte wide field and
        /* We want to extract data from an 8 byte wide field and
           place it into a 4 byte wide field.  Since this is a little
           place it into a 4 byte wide field.  Since this is a little
           endian source we can just use the 4 byte extraction code.  */
           endian source we can just use the 4 byte extraction code.  */
        return  ((unsigned long) (field[0]))
        return  ((unsigned long) (field[0]))
          |    (((unsigned long) (field[1])) << 8)
          |    (((unsigned long) (field[1])) << 8)
          |    (((unsigned long) (field[2])) << 16)
          |    (((unsigned long) (field[2])) << 16)
          |    (((unsigned long) (field[3])) << 24);
          |    (((unsigned long) (field[3])) << 24);
 
 
    default:
    default:
      error (_("Unhandled data length: %d\n"), size);
      error (_("Unhandled data length: %d\n"), size);
      abort ();
      abort ();
    }
    }
}
}
 
 
elf_vma
elf_vma
byte_get_big_endian (unsigned char *field, int size)
byte_get_big_endian (unsigned char *field, int size)
{
{
  switch (size)
  switch (size)
    {
    {
    case 1:
    case 1:
      return *field;
      return *field;
 
 
    case 2:
    case 2:
      return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
      return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
 
 
    case 3:
    case 3:
      return ((unsigned long) (field[2]))
      return ((unsigned long) (field[2]))
        |   (((unsigned long) (field[1])) << 8)
        |   (((unsigned long) (field[1])) << 8)
        |   (((unsigned long) (field[0])) << 16);
        |   (((unsigned long) (field[0])) << 16);
 
 
    case 4:
    case 4:
      return ((unsigned long) (field[3]))
      return ((unsigned long) (field[3]))
        |   (((unsigned long) (field[2])) << 8)
        |   (((unsigned long) (field[2])) << 8)
        |   (((unsigned long) (field[1])) << 16)
        |   (((unsigned long) (field[1])) << 16)
        |   (((unsigned long) (field[0])) << 24);
        |   (((unsigned long) (field[0])) << 24);
 
 
    case 8:
    case 8:
      if (sizeof (elf_vma) == 8)
      if (sizeof (elf_vma) == 8)
        return ((elf_vma) (field[7]))
        return ((elf_vma) (field[7]))
          |   (((elf_vma) (field[6])) << 8)
          |   (((elf_vma) (field[6])) << 8)
          |   (((elf_vma) (field[5])) << 16)
          |   (((elf_vma) (field[5])) << 16)
          |   (((elf_vma) (field[4])) << 24)
          |   (((elf_vma) (field[4])) << 24)
          |   (((elf_vma) (field[3])) << 32)
          |   (((elf_vma) (field[3])) << 32)
          |   (((elf_vma) (field[2])) << 40)
          |   (((elf_vma) (field[2])) << 40)
          |   (((elf_vma) (field[1])) << 48)
          |   (((elf_vma) (field[1])) << 48)
          |   (((elf_vma) (field[0])) << 56);
          |   (((elf_vma) (field[0])) << 56);
      else if (sizeof (elf_vma) == 4)
      else if (sizeof (elf_vma) == 4)
        {
        {
          /* Although we are extracing data from an 8 byte wide field,
          /* Although we are extracing data from an 8 byte wide field,
             we are returning only 4 bytes of data.  */
             we are returning only 4 bytes of data.  */
          field += 4;
          field += 4;
          return ((unsigned long) (field[3]))
          return ((unsigned long) (field[3]))
            |   (((unsigned long) (field[2])) << 8)
            |   (((unsigned long) (field[2])) << 8)
            |   (((unsigned long) (field[1])) << 16)
            |   (((unsigned long) (field[1])) << 16)
            |   (((unsigned long) (field[0])) << 24);
            |   (((unsigned long) (field[0])) << 24);
        }
        }
 
 
    default:
    default:
      error (_("Unhandled data length: %d\n"), size);
      error (_("Unhandled data length: %d\n"), size);
      abort ();
      abort ();
    }
    }
}
}
 
 
elf_vma
elf_vma
byte_get_signed (unsigned char *field, int size)
byte_get_signed (unsigned char *field, int size)
{
{
  elf_vma x = byte_get (field, size);
  elf_vma x = byte_get (field, size);
 
 
  switch (size)
  switch (size)
    {
    {
    case 1:
    case 1:
      return (x ^ 0x80) - 0x80;
      return (x ^ 0x80) - 0x80;
    case 2:
    case 2:
      return (x ^ 0x8000) - 0x8000;
      return (x ^ 0x8000) - 0x8000;
    case 4:
    case 4:
      return (x ^ 0x80000000) - 0x80000000;
      return (x ^ 0x80000000) - 0x80000000;
    case 8:
    case 8:
      return x;
      return x;
    default:
    default:
      abort ();
      abort ();
    }
    }
}
}
 
 
 
/* Return the high-order 32-bits and the low-order 32-bits
 
   of an 8-byte value separately.  */
 
 
 
void
 
byte_get_64 (unsigned char *field, elf_vma *high, elf_vma *low)
 
{
 
  if (byte_get == byte_get_big_endian)
 
    {
 
      *high = byte_get_big_endian (field, 4);
 
      *low = byte_get_big_endian (field + 4, 4);
 
    }
 
  else
 
    {
 
      *high = byte_get_little_endian (field + 4, 4);
 
      *low = byte_get_little_endian (field, 4);
 
    }
 
  return;
 
}
 
 
/* Return the path name for a proxy entry in a thin archive, adjusted
/* Return the path name for a proxy entry in a thin archive, adjusted
   relative to the path name of the thin archive itself if necessary.
   relative to the path name of the thin archive itself if necessary.
   Always returns a pointer to malloc'ed memory.  */
   Always returns a pointer to malloc'ed memory.  */
 
 
char *
char *
adjust_relative_path (const char *file_name, const char *name,
adjust_relative_path (const char *file_name, const char *name,
                      int name_len)
                      int name_len)
{
{
  char * member_file_name;
  char * member_file_name;
  const char * base_name = lbasename (file_name);
  const char * base_name = lbasename (file_name);
 
 
  /* This is a proxy entry for a thin archive member.
  /* This is a proxy entry for a thin archive member.
     If the extended name table contains an absolute path
     If the extended name table contains an absolute path
     name, or if the archive is in the current directory,
     name, or if the archive is in the current directory,
     use the path name as given.  Otherwise, we need to
     use the path name as given.  Otherwise, we need to
     find the member relative to the directory where the
     find the member relative to the directory where the
     archive is located.  */
     archive is located.  */
  if (IS_ABSOLUTE_PATH (name) || base_name == file_name)
  if (IS_ABSOLUTE_PATH (name) || base_name == file_name)
    {
    {
      member_file_name = (char *) malloc (name_len + 1);
      member_file_name = (char *) malloc (name_len + 1);
      if (member_file_name == NULL)
      if (member_file_name == NULL)
        {
        {
          error (_("Out of memory\n"));
          error (_("Out of memory\n"));
          return NULL;
          return NULL;
        }
        }
      memcpy (member_file_name, name, name_len);
      memcpy (member_file_name, name, name_len);
      member_file_name[name_len] = '\0';
      member_file_name[name_len] = '\0';
    }
    }
  else
  else
    {
    {
      /* Concatenate the path components of the archive file name
      /* Concatenate the path components of the archive file name
         to the relative path name from the extended name table.  */
         to the relative path name from the extended name table.  */
      size_t prefix_len = base_name - file_name;
      size_t prefix_len = base_name - file_name;
      member_file_name = (char *) malloc (prefix_len + name_len + 1);
      member_file_name = (char *) malloc (prefix_len + name_len + 1);
      if (member_file_name == NULL)
      if (member_file_name == NULL)
        {
        {
          error (_("Out of memory\n"));
          error (_("Out of memory\n"));
          return NULL;
          return NULL;
        }
        }
      memcpy (member_file_name, file_name, prefix_len);
      memcpy (member_file_name, file_name, prefix_len);
      memcpy (member_file_name + prefix_len, name, name_len);
      memcpy (member_file_name + prefix_len, name, name_len);
      member_file_name[prefix_len + name_len] = '\0';
      member_file_name[prefix_len + name_len] = '\0';
    }
    }
  return member_file_name;
  return member_file_name;
}
}
 
 
/* Read the symbol table and long-name table from an archive.  */
/* Read the symbol table and long-name table from an archive.  */
 
 
int
int
setup_archive (struct archive_info *arch, const char *file_name,
setup_archive (struct archive_info *arch, const char *file_name,
               FILE *file, bfd_boolean is_thin_archive,
               FILE *file, bfd_boolean is_thin_archive,
               bfd_boolean read_symbols)
               bfd_boolean read_symbols)
{
{
  size_t got;
  size_t got;
  unsigned long size;
  unsigned long size;
 
 
  arch->file_name = strdup (file_name);
  arch->file_name = strdup (file_name);
  arch->file = file;
  arch->file = file;
  arch->index_num = 0;
  arch->index_num = 0;
  arch->index_array = NULL;
  arch->index_array = NULL;
  arch->sym_table = NULL;
  arch->sym_table = NULL;
  arch->sym_size = 0;
  arch->sym_size = 0;
  arch->longnames = NULL;
  arch->longnames = NULL;
  arch->longnames_size = 0;
  arch->longnames_size = 0;
  arch->nested_member_origin = 0;
  arch->nested_member_origin = 0;
  arch->is_thin_archive = is_thin_archive;
  arch->is_thin_archive = is_thin_archive;
  arch->next_arhdr_offset = SARMAG;
  arch->next_arhdr_offset = SARMAG;
 
 
  /* Read the first archive member header.  */
  /* Read the first archive member header.  */
  if (fseek (file, SARMAG, SEEK_SET) != 0)
  if (fseek (file, SARMAG, SEEK_SET) != 0)
    {
    {
      error (_("%s: failed to seek to first archive header\n"), file_name);
      error (_("%s: failed to seek to first archive header\n"), file_name);
      return 1;
      return 1;
    }
    }
  got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
  got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
  if (got != sizeof arch->arhdr)
  if (got != sizeof arch->arhdr)
    {
    {
      if (got == 0)
      if (got == 0)
        return 0;
        return 0;
 
 
      error (_("%s: failed to read archive header\n"), file_name);
      error (_("%s: failed to read archive header\n"), file_name);
      return 1;
      return 1;
    }
    }
 
 
  /* See if this is the archive symbol table.  */
  /* See if this is the archive symbol table.  */
  if (const_strneq (arch->arhdr.ar_name, "/               ")
  if (const_strneq (arch->arhdr.ar_name, "/               ")
      || const_strneq (arch->arhdr.ar_name, "/SYM64/         "))
      || const_strneq (arch->arhdr.ar_name, "/SYM64/         "))
    {
    {
      size = strtoul (arch->arhdr.ar_size, NULL, 10);
      size = strtoul (arch->arhdr.ar_size, NULL, 10);
      size = size + (size & 1);
      size = size + (size & 1);
 
 
      arch->next_arhdr_offset += sizeof arch->arhdr + size;
      arch->next_arhdr_offset += sizeof arch->arhdr + size;
 
 
      if (read_symbols)
      if (read_symbols)
        {
        {
          unsigned long i;
          unsigned long i;
          /* A buffer used to hold numbers read in from an archive index.
          /* A buffer used to hold numbers read in from an archive index.
             These are always 4 bytes long and stored in big-endian
             These are always 4 bytes long and stored in big-endian
             format.  */
             format.  */
#define SIZEOF_AR_INDEX_NUMBERS 4
#define SIZEOF_AR_INDEX_NUMBERS 4
          unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS];
          unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS];
          unsigned char * index_buffer;
          unsigned char * index_buffer;
 
 
          /* Check the size of the archive index.  */
          /* Check the size of the archive index.  */
          if (size < SIZEOF_AR_INDEX_NUMBERS)
          if (size < SIZEOF_AR_INDEX_NUMBERS)
            {
            {
              error (_("%s: the archive index is empty\n"), file_name);
              error (_("%s: the archive index is empty\n"), file_name);
              return 1;
              return 1;
            }
            }
 
 
          /* Read the numer of entries in the archive index.  */
          /* Read the numer of entries in the archive index.  */
          got = fread (integer_buffer, 1, sizeof integer_buffer, file);
          got = fread (integer_buffer, 1, sizeof integer_buffer, file);
          if (got != sizeof (integer_buffer))
          if (got != sizeof (integer_buffer))
            {
            {
              error (_("%s: failed to read archive index\n"), file_name);
              error (_("%s: failed to read archive index\n"), file_name);
              return 1;
              return 1;
            }
            }
          arch->index_num = byte_get_big_endian (integer_buffer,
          arch->index_num = byte_get_big_endian (integer_buffer,
                                                 sizeof integer_buffer);
                                                 sizeof integer_buffer);
          size -= SIZEOF_AR_INDEX_NUMBERS;
          size -= SIZEOF_AR_INDEX_NUMBERS;
 
 
          /* Read in the archive index.  */
          /* Read in the archive index.  */
          if (size < arch->index_num * SIZEOF_AR_INDEX_NUMBERS)
          if (size < arch->index_num * SIZEOF_AR_INDEX_NUMBERS)
            {
            {
              error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"),
              error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"),
                     file_name, arch->index_num);
                     file_name, arch->index_num);
              return 1;
              return 1;
            }
            }
          index_buffer = (unsigned char *)
          index_buffer = (unsigned char *)
              malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS);
              malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS);
          if (index_buffer == NULL)
          if (index_buffer == NULL)
            {
            {
              error (_("Out of memory whilst trying to read archive symbol index\n"));
              error (_("Out of memory whilst trying to read archive symbol index\n"));
              return 1;
              return 1;
            }
            }
          got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS,
          got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS,
                       arch->index_num, file);
                       arch->index_num, file);
          if (got != arch->index_num)
          if (got != arch->index_num)
            {
            {
              free (index_buffer);
              free (index_buffer);
              error (_("%s: failed to read archive index\n"), file_name);
              error (_("%s: failed to read archive index\n"), file_name);
              return 1;
              return 1;
            }
            }
          size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS;
          size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS;
 
 
          /* Convert the index numbers into the host's numeric format.  */
          /* Convert the index numbers into the host's numeric format.  */
          arch->index_array = (long unsigned int *)
          arch->index_array = (long unsigned int *)
              malloc (arch->index_num * sizeof (* arch->index_array));
              malloc (arch->index_num * sizeof (* arch->index_array));
          if (arch->index_array == NULL)
          if (arch->index_array == NULL)
            {
            {
              free (index_buffer);
              free (index_buffer);
              error (_("Out of memory whilst trying to convert the archive symbol index\n"));
              error (_("Out of memory whilst trying to convert the archive symbol index\n"));
              return 1;
              return 1;
            }
            }
 
 
          for (i = 0; i < arch->index_num; i++)
          for (i = 0; i < arch->index_num; i++)
            arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
            arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
                                                        SIZEOF_AR_INDEX_NUMBERS);
                                                        SIZEOF_AR_INDEX_NUMBERS);
          free (index_buffer);
          free (index_buffer);
 
 
          /* The remaining space in the header is taken up by the symbol
          /* The remaining space in the header is taken up by the symbol
             table.  */
             table.  */
          if (size < 1)
          if (size < 1)
            {
            {
              error (_("%s: the archive has an index but no symbols\n"),
              error (_("%s: the archive has an index but no symbols\n"),
                     file_name);
                     file_name);
              return 1;
              return 1;
            }
            }
          arch->sym_table = (char *) malloc (size);
          arch->sym_table = (char *) malloc (size);
          arch->sym_size = size;
          arch->sym_size = size;
          if (arch->sym_table == NULL)
          if (arch->sym_table == NULL)
            {
            {
              error (_("Out of memory whilst trying to read archive index symbol table\n"));
              error (_("Out of memory whilst trying to read archive index symbol table\n"));
              return 1;
              return 1;
            }
            }
          got = fread (arch->sym_table, 1, size, file);
          got = fread (arch->sym_table, 1, size, file);
          if (got != size)
          if (got != size)
            {
            {
              error (_("%s: failed to read archive index symbol table\n"),
              error (_("%s: failed to read archive index symbol table\n"),
                     file_name);
                     file_name);
              return 1;
              return 1;
            }
            }
        }
        }
      else
      else
        {
        {
          if (fseek (file, size, SEEK_CUR) != 0)
          if (fseek (file, size, SEEK_CUR) != 0)
            {
            {
              error (_("%s: failed to skip archive symbol table\n"),
              error (_("%s: failed to skip archive symbol table\n"),
                     file_name);
                     file_name);
              return 1;
              return 1;
            }
            }
        }
        }
 
 
      /* Read the next archive header.  */
      /* Read the next archive header.  */
      got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
      got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
      if (got != sizeof arch->arhdr)
      if (got != sizeof arch->arhdr)
        {
        {
          if (got == 0)
          if (got == 0)
            return 0;
            return 0;
          error (_("%s: failed to read archive header following archive index\n"),
          error (_("%s: failed to read archive header following archive index\n"),
                 file_name);
                 file_name);
          return 1;
          return 1;
        }
        }
    }
    }
  else if (read_symbols)
  else if (read_symbols)
    printf (_("%s has no archive index\n"), file_name);
    printf (_("%s has no archive index\n"), file_name);
 
 
  if (const_strneq (arch->arhdr.ar_name, "//              "))
  if (const_strneq (arch->arhdr.ar_name, "//              "))
    {
    {
      /* This is the archive string table holding long member names.  */
      /* This is the archive string table holding long member names.  */
      arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10);
      arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10);
      arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size;
      arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size;
 
 
      arch->longnames = (char *) malloc (arch->longnames_size);
      arch->longnames = (char *) malloc (arch->longnames_size);
      if (arch->longnames == NULL)
      if (arch->longnames == NULL)
        {
        {
          error (_("Out of memory reading long symbol names in archive\n"));
          error (_("Out of memory reading long symbol names in archive\n"));
          return 1;
          return 1;
        }
        }
 
 
      if (fread (arch->longnames, arch->longnames_size, 1, file) != 1)
      if (fread (arch->longnames, arch->longnames_size, 1, file) != 1)
        {
        {
          free (arch->longnames);
          free (arch->longnames);
          arch->longnames = NULL;
          arch->longnames = NULL;
          error (_("%s: failed to read long symbol name string table\n"),
          error (_("%s: failed to read long symbol name string table\n"),
                 file_name);
                 file_name);
          return 1;
          return 1;
        }
        }
 
 
      if ((arch->longnames_size & 1) != 0)
      if ((arch->longnames_size & 1) != 0)
        getc (file);
        getc (file);
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* Open and setup a nested archive, if not already open.  */
/* Open and setup a nested archive, if not already open.  */
 
 
int
int
setup_nested_archive (struct archive_info *nested_arch,
setup_nested_archive (struct archive_info *nested_arch,
                      const char *member_file_name)
                      const char *member_file_name)
{
{
  FILE * member_file;
  FILE * member_file;
 
 
  /* Have we already setup this archive?  */
  /* Have we already setup this archive?  */
  if (nested_arch->file_name != NULL
  if (nested_arch->file_name != NULL
      && streq (nested_arch->file_name, member_file_name))
      && streq (nested_arch->file_name, member_file_name))
    return 0;
    return 0;
 
 
  /* Close previous file and discard cached information.  */
  /* Close previous file and discard cached information.  */
  if (nested_arch->file != NULL)
  if (nested_arch->file != NULL)
    fclose (nested_arch->file);
    fclose (nested_arch->file);
  release_archive (nested_arch);
  release_archive (nested_arch);
 
 
  member_file = fopen (member_file_name, "rb");
  member_file = fopen (member_file_name, "rb");
  if (member_file == NULL)
  if (member_file == NULL)
    return 1;
    return 1;
  return setup_archive (nested_arch, member_file_name, member_file,
  return setup_archive (nested_arch, member_file_name, member_file,
                        FALSE, FALSE);
                        FALSE, FALSE);
}
}
 
 
/* Release the memory used for the archive information.  */
/* Release the memory used for the archive information.  */
 
 
void
void
release_archive (struct archive_info * arch)
release_archive (struct archive_info * arch)
{
{
  if (arch->file_name != NULL)
  if (arch->file_name != NULL)
    free (arch->file_name);
    free (arch->file_name);
  if (arch->index_array != NULL)
  if (arch->index_array != NULL)
    free (arch->index_array);
    free (arch->index_array);
  if (arch->sym_table != NULL)
  if (arch->sym_table != NULL)
    free (arch->sym_table);
    free (arch->sym_table);
  if (arch->longnames != NULL)
  if (arch->longnames != NULL)
    free (arch->longnames);
    free (arch->longnames);
}
}
 
 
/* Get the name of an archive member from the current archive header.
/* Get the name of an archive member from the current archive header.
   For simple names, this will modify the ar_name field of the current
   For simple names, this will modify the ar_name field of the current
   archive header.  For long names, it will return a pointer to the
   archive header.  For long names, it will return a pointer to the
   longnames table.  For nested archives, it will open the nested archive
   longnames table.  For nested archives, it will open the nested archive
   and get the name recursively.  NESTED_ARCH is a single-entry cache so
   and get the name recursively.  NESTED_ARCH is a single-entry cache so
   we don't keep rereading the same information from a nested archive.  */
   we don't keep rereading the same information from a nested archive.  */
 
 
char *
char *
get_archive_member_name (struct archive_info *arch,
get_archive_member_name (struct archive_info *arch,
                         struct archive_info *nested_arch)
                         struct archive_info *nested_arch)
{
{
  unsigned long j, k;
  unsigned long j, k;
 
 
  if (arch->arhdr.ar_name[0] == '/')
  if (arch->arhdr.ar_name[0] == '/')
    {
    {
      /* We have a long name.  */
      /* We have a long name.  */
      char *endp;
      char *endp;
      char *member_file_name;
      char *member_file_name;
      char *member_name;
      char *member_name;
 
 
      arch->nested_member_origin = 0;
      arch->nested_member_origin = 0;
      k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10);
      k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10);
      if (arch->is_thin_archive && endp != NULL && * endp == ':')
      if (arch->is_thin_archive && endp != NULL && * endp == ':')
        arch->nested_member_origin = strtoul (endp + 1, NULL, 10);
        arch->nested_member_origin = strtoul (endp + 1, NULL, 10);
 
 
      while ((j < arch->longnames_size)
      while ((j < arch->longnames_size)
             && (arch->longnames[j] != '\n')
             && (arch->longnames[j] != '\n')
             && (arch->longnames[j] != '\0'))
             && (arch->longnames[j] != '\0'))
        j++;
        j++;
      if (arch->longnames[j-1] == '/')
      if (arch->longnames[j-1] == '/')
        j--;
        j--;
      arch->longnames[j] = '\0';
      arch->longnames[j] = '\0';
 
 
      if (!arch->is_thin_archive || arch->nested_member_origin == 0)
      if (!arch->is_thin_archive || arch->nested_member_origin == 0)
        return arch->longnames + k;
        return arch->longnames + k;
 
 
      /* This is a proxy for a member of a nested archive.
      /* This is a proxy for a member of a nested archive.
         Find the name of the member in that archive.  */
         Find the name of the member in that archive.  */
      member_file_name = adjust_relative_path (arch->file_name,
      member_file_name = adjust_relative_path (arch->file_name,
                                               arch->longnames + k, j - k);
                                               arch->longnames + k, j - k);
      if (member_file_name != NULL
      if (member_file_name != NULL
          && setup_nested_archive (nested_arch, member_file_name) == 0)
          && setup_nested_archive (nested_arch, member_file_name) == 0)
        {
        {
          member_name = get_archive_member_name_at (nested_arch,
          member_name = get_archive_member_name_at (nested_arch,
                                                    arch->nested_member_origin,
                                                    arch->nested_member_origin,
                                                    NULL);
                                                    NULL);
          if (member_name != NULL)
          if (member_name != NULL)
            {
            {
              free (member_file_name);
              free (member_file_name);
              return member_name;
              return member_name;
            }
            }
        }
        }
      free (member_file_name);
      free (member_file_name);
 
 
      /* Last resort: just return the name of the nested archive.  */
      /* Last resort: just return the name of the nested archive.  */
      return arch->longnames + k;
      return arch->longnames + k;
    }
    }
 
 
  /* We have a normal (short) name.  */
  /* We have a normal (short) name.  */
  for (j = 0; j < sizeof (arch->arhdr.ar_name); j++)
  for (j = 0; j < sizeof (arch->arhdr.ar_name); j++)
    if (arch->arhdr.ar_name[j] == '/')
    if (arch->arhdr.ar_name[j] == '/')
      {
      {
        arch->arhdr.ar_name[j] = '\0';
        arch->arhdr.ar_name[j] = '\0';
        return arch->arhdr.ar_name;
        return arch->arhdr.ar_name;
      }
      }
 
 
  /* The full ar_name field is used.  Don't rely on ar_date starting
  /* The full ar_name field is used.  Don't rely on ar_date starting
     with a zero byte.  */
     with a zero byte.  */
  {
  {
    char *name = xmalloc (sizeof (arch->arhdr.ar_name) + 1);
    char *name = xmalloc (sizeof (arch->arhdr.ar_name) + 1);
    memcpy (name, arch->arhdr.ar_name, sizeof (arch->arhdr.ar_name));
    memcpy (name, arch->arhdr.ar_name, sizeof (arch->arhdr.ar_name));
    name[sizeof (arch->arhdr.ar_name)] = '\0';
    name[sizeof (arch->arhdr.ar_name)] = '\0';
    return name;
    return name;
  }
  }
}
}
 
 
/* Get the name of an archive member at a given OFFSET within an archive
/* Get the name of an archive member at a given OFFSET within an archive
   ARCH.  */
   ARCH.  */
 
 
char *
char *
get_archive_member_name_at (struct archive_info *arch,
get_archive_member_name_at (struct archive_info *arch,
                            unsigned long offset,
                            unsigned long offset,
                            struct archive_info *nested_arch)
                            struct archive_info *nested_arch)
{
{
  size_t got;
  size_t got;
 
 
  if (fseek (arch->file, offset, SEEK_SET) != 0)
  if (fseek (arch->file, offset, SEEK_SET) != 0)
    {
    {
      error (_("%s: failed to seek to next file name\n"), arch->file_name);
      error (_("%s: failed to seek to next file name\n"), arch->file_name);
      return NULL;
      return NULL;
    }
    }
  got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file);
  got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file);
  if (got != sizeof arch->arhdr)
  if (got != sizeof arch->arhdr)
    {
    {
      error (_("%s: failed to read archive header\n"), arch->file_name);
      error (_("%s: failed to read archive header\n"), arch->file_name);
      return NULL;
      return NULL;
    }
    }
  if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0)
  if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0)
    {
    {
      error (_("%s: did not find a valid archive header\n"),
      error (_("%s: did not find a valid archive header\n"),
             arch->file_name);
             arch->file_name);
      return NULL;
      return NULL;
    }
    }
 
 
  return get_archive_member_name (arch, nested_arch);
  return get_archive_member_name (arch, nested_arch);
}
}
 
 
/* Construct a string showing the name of the archive member, qualified
/* Construct a string showing the name of the archive member, qualified
   with the name of the containing archive file.  For thin archives, we
   with the name of the containing archive file.  For thin archives, we
   use square brackets to denote the indirection.  For nested archives,
   use square brackets to denote the indirection.  For nested archives,
   we show the qualified name of the external member inside the square
   we show the qualified name of the external member inside the square
   brackets (e.g., "thin.a[normal.a(foo.o)]").  */
   brackets (e.g., "thin.a[normal.a(foo.o)]").  */
 
 
char *
char *
make_qualified_name (struct archive_info * arch,
make_qualified_name (struct archive_info * arch,
                     struct archive_info * nested_arch,
                     struct archive_info * nested_arch,
                     const char *member_name)
                     const char *member_name)
{
{
  size_t len;
  size_t len;
  char * name;
  char * name;
 
 
  len = strlen (arch->file_name) + strlen (member_name) + 3;
  len = strlen (arch->file_name) + strlen (member_name) + 3;
  if (arch->is_thin_archive && arch->nested_member_origin != 0)
  if (arch->is_thin_archive && arch->nested_member_origin != 0)
    len += strlen (nested_arch->file_name) + 2;
    len += strlen (nested_arch->file_name) + 2;
 
 
  name = (char *) malloc (len);
  name = (char *) malloc (len);
  if (name == NULL)
  if (name == NULL)
    {
    {
      error (_("Out of memory\n"));
      error (_("Out of memory\n"));
      return NULL;
      return NULL;
    }
    }
 
 
  if (arch->is_thin_archive && arch->nested_member_origin != 0)
  if (arch->is_thin_archive && arch->nested_member_origin != 0)
    snprintf (name, len, "%s[%s(%s)]", arch->file_name,
    snprintf (name, len, "%s[%s(%s)]", arch->file_name,
              nested_arch->file_name, member_name);
              nested_arch->file_name, member_name);
  else if (arch->is_thin_archive)
  else if (arch->is_thin_archive)
    snprintf (name, len, "%s[%s]", arch->file_name, member_name);
    snprintf (name, len, "%s[%s]", arch->file_name, member_name);
  else
  else
    snprintf (name, len, "%s(%s)", arch->file_name, member_name);
    snprintf (name, len, "%s(%s)", arch->file_name, member_name);
 
 
  return name;
  return name;
}
}
 
 

powered by: WebSVN 2.1.0

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