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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [elfedit.c] - Diff between revs 161 and 166

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

Rev 161 Rev 166
/* elfedit.c -- Update the ELF header of an ELF format file
/* elfedit.c -- Update the ELF header of an ELF format file
   Copyright 2010
   Copyright 2010, 2011, 2012
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   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 "config.h"
 
#include "sysdep.h"
#include "sysdep.h"
#include <assert.h>
#include <assert.h>
#include <sys/stat.h>
 
 
 
#if __GNUC__ >= 2
#if __GNUC__ >= 2
/* Define BFD64 here, even if our default architecture is 32 bit ELF
/* Define BFD64 here, even if our default architecture is 32 bit ELF
   as this will allow us to read in and parse 64bit and 32bit ELF files.
   as this will allow us to read in and parse 64bit and 32bit ELF files.
   Only do this if we believe that the compiler can support a 64 bit
   Only do this if we believe that the compiler can support a 64 bit
   data type.  For now we only rely on GCC being able to do this.  */
   data type.  For now we only rely on GCC being able to do this.  */
#define BFD64
#define BFD64
#endif
#endif
 
 
#include "bfd.h"
#include "bfd.h"
#include "elfcomm.h"
#include "elfcomm.h"
#include "bucomm.h"
#include "bucomm.h"
 
 
#include "elf/common.h"
#include "elf/common.h"
#include "elf/external.h"
#include "elf/external.h"
#include "elf/internal.h"
#include "elf/internal.h"
 
 
#include "getopt.h"
#include "getopt.h"
#include "libiberty.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "filenames.h"
#include "filenames.h"
 
 
char * program_name = "elfedit";
char * program_name = "elfedit";
static long archive_file_offset;
static long archive_file_offset;
static unsigned long archive_file_size;
static unsigned long archive_file_size;
static Elf_Internal_Ehdr elf_header;
static Elf_Internal_Ehdr elf_header;
static Elf32_External_Ehdr ehdr32;
static Elf32_External_Ehdr ehdr32;
static Elf64_External_Ehdr ehdr64;
static Elf64_External_Ehdr ehdr64;
static int input_elf_machine = -1;
static int input_elf_machine = -1;
static int output_elf_machine = -1;
static int output_elf_machine = -1;
static int input_elf_type = -1;
static int input_elf_type = -1;
static int output_elf_type = -1;
static int output_elf_type = -1;
static int input_elf_osabi = -1;
static int input_elf_osabi = -1;
static int output_elf_osabi = -1;
static int output_elf_osabi = -1;
static int input_elf_class = -1;
static int input_elf_class = -1;
 
 
static int
static int
update_elf_header (const char *file_name, FILE *file)
update_elf_header (const char *file_name, FILE *file)
{
{
  int class, machine, type, status, osabi;
  int class, machine, type, status, osabi;
 
 
  if (elf_header.e_ident[EI_MAG0] != ELFMAG0
  if (elf_header.e_ident[EI_MAG0] != ELFMAG0
      || elf_header.e_ident[EI_MAG1] != ELFMAG1
      || elf_header.e_ident[EI_MAG1] != ELFMAG1
      || elf_header.e_ident[EI_MAG2] != ELFMAG2
      || elf_header.e_ident[EI_MAG2] != ELFMAG2
      || elf_header.e_ident[EI_MAG3] != ELFMAG3)
      || elf_header.e_ident[EI_MAG3] != ELFMAG3)
    {
    {
      error
      error
        (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
        (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
         file_name);
         file_name);
      return 0;
      return 0;
    }
    }
 
 
  if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
  if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
    {
    {
      error
      error
        (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
        (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
         file_name, elf_header.e_ident[EI_VERSION],
         file_name, elf_header.e_ident[EI_VERSION],
         EV_CURRENT);
         EV_CURRENT);
      return 0;
      return 0;
    }
    }
 
 
  /* Return if e_machine is the same as output_elf_machine.  */
  /* Return if e_machine is the same as output_elf_machine.  */
  if (output_elf_machine == elf_header.e_machine)
  if (output_elf_machine == elf_header.e_machine)
    return 1;
    return 1;
 
 
  class = elf_header.e_ident[EI_CLASS];
  class = elf_header.e_ident[EI_CLASS];
 
 
  /* Skip if class doesn't match. */
  /* Skip if class doesn't match. */
  if (input_elf_class != -1 && class != input_elf_class)
  if (input_elf_class != -1 && class != input_elf_class)
    {
    {
      error
      error
        (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
        (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
         file_name, class, input_elf_class);
         file_name, class, input_elf_class);
      return 0;
      return 0;
    }
    }
 
 
  machine = elf_header.e_machine;
  machine = elf_header.e_machine;
 
 
  /* Skip if e_machine doesn't match. */
  /* Skip if e_machine doesn't match. */
  if (input_elf_machine != -1 && machine != input_elf_machine)
  if (input_elf_machine != -1 && machine != input_elf_machine)
    {
    {
      error
      error
        (_("%s: Unmatched e_machine: %d is not %d\n"),
        (_("%s: Unmatched e_machine: %d is not %d\n"),
         file_name, machine, input_elf_machine);
         file_name, machine, input_elf_machine);
      return 0;
      return 0;
    }
    }
 
 
  type = elf_header.e_type;
  type = elf_header.e_type;
 
 
  /* Skip if e_type doesn't match. */
  /* Skip if e_type doesn't match. */
  if (input_elf_type != -1 && type != input_elf_type)
  if (input_elf_type != -1 && type != input_elf_type)
    {
    {
      error
      error
        (_("%s: Unmatched e_type: %d is not %d\n"),
        (_("%s: Unmatched e_type: %d is not %d\n"),
         file_name, type, input_elf_type);
         file_name, type, input_elf_type);
      return 0;
      return 0;
    }
    }
 
 
  osabi = elf_header.e_ident[EI_OSABI];
  osabi = elf_header.e_ident[EI_OSABI];
 
 
  /* Skip if OSABI doesn't match. */
  /* Skip if OSABI doesn't match. */
  if (input_elf_osabi != -1 && osabi != input_elf_osabi)
  if (input_elf_osabi != -1 && osabi != input_elf_osabi)
    {
    {
      error
      error
        (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
        (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
         file_name, osabi, input_elf_osabi);
         file_name, osabi, input_elf_osabi);
      return 0;
      return 0;
    }
    }
 
 
  /* Update e_machine, e_type and EI_OSABI.  */
  /* Update e_machine, e_type and EI_OSABI.  */
  switch (class)
  switch (class)
    {
    {
    default:
    default:
      /* We should never get here.  */
      /* We should never get here.  */
      abort ();
      abort ();
      break;
      break;
    case ELFCLASS32:
    case ELFCLASS32:
      if (output_elf_machine != -1)
      if (output_elf_machine != -1)
        BYTE_PUT (ehdr32.e_machine, output_elf_machine);
        BYTE_PUT (ehdr32.e_machine, output_elf_machine);
      if (output_elf_type != -1)
      if (output_elf_type != -1)
        BYTE_PUT (ehdr32.e_type, output_elf_type);
        BYTE_PUT (ehdr32.e_type, output_elf_type);
      if (output_elf_osabi != -1)
      if (output_elf_osabi != -1)
        ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
        ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
      status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
      status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
      break;
      break;
    case ELFCLASS64:
    case ELFCLASS64:
      if (output_elf_machine != -1)
      if (output_elf_machine != -1)
        BYTE_PUT (ehdr64.e_machine, output_elf_machine);
        BYTE_PUT (ehdr64.e_machine, output_elf_machine);
      if (output_elf_type != -1)
      if (output_elf_type != -1)
        BYTE_PUT (ehdr64.e_type, output_elf_type);
        BYTE_PUT (ehdr64.e_type, output_elf_type);
      if (output_elf_osabi != -1)
      if (output_elf_osabi != -1)
        ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
        ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
      status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
      status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
      break;
      break;
    }
    }
 
 
  if (status != 1)
  if (status != 1)
    error (_("%s: Failed to update ELF header: %s\n"),
    error (_("%s: Failed to update ELF header: %s\n"),
               file_name, strerror (errno));
               file_name, strerror (errno));
 
 
  return status;
  return status;
}
}
 
 
static int
static int
get_file_header (FILE * file)
get_file_header (FILE * file)
{
{
  /* Read in the identity array.  */
  /* Read in the identity array.  */
  if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
  if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
    return 0;
    return 0;
 
 
  /* Determine how to read the rest of the header.  */
  /* Determine how to read the rest of the header.  */
  switch (elf_header.e_ident[EI_DATA])
  switch (elf_header.e_ident[EI_DATA])
    {
    {
    default: /* fall through */
    default: /* fall through */
    case ELFDATANONE: /* fall through */
    case ELFDATANONE: /* fall through */
    case ELFDATA2LSB:
    case ELFDATA2LSB:
      byte_get = byte_get_little_endian;
      byte_get = byte_get_little_endian;
      byte_put = byte_put_little_endian;
      byte_put = byte_put_little_endian;
      break;
      break;
    case ELFDATA2MSB:
    case ELFDATA2MSB:
      byte_get = byte_get_big_endian;
      byte_get = byte_get_big_endian;
      byte_put = byte_put_big_endian;
      byte_put = byte_put_big_endian;
      break;
      break;
    }
    }
 
 
  /* Read in the rest of the header.  For now we only support 32 bit
  /* Read in the rest of the header.  For now we only support 32 bit
     and 64 bit ELF files.  */
     and 64 bit ELF files.  */
  switch (elf_header.e_ident[EI_CLASS])
  switch (elf_header.e_ident[EI_CLASS])
    {
    {
    default:
    default:
      error (_("Unsupported EI_CLASS: %d\n"),
      error (_("Unsupported EI_CLASS: %d\n"),
                 elf_header.e_ident[EI_CLASS]);
                 elf_header.e_ident[EI_CLASS]);
      return 0;
      return 0;
 
 
    case ELFCLASS32:
    case ELFCLASS32:
      if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
      if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
                 1, file) != 1)
                 1, file) != 1)
        return 0;
        return 0;
 
 
      elf_header.e_type      = BYTE_GET (ehdr32.e_type);
      elf_header.e_type      = BYTE_GET (ehdr32.e_type);
      elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
      elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
      elf_header.e_version   = BYTE_GET (ehdr32.e_version);
      elf_header.e_version   = BYTE_GET (ehdr32.e_version);
      elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
      elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
      elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
      elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
      elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
      elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
      elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
      elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
      elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
      elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
      elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
      elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
      elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
      elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
      elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
      elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
      elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
      elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
      elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
      elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
 
 
      memcpy (&ehdr32, &elf_header, EI_NIDENT);
      memcpy (&ehdr32, &elf_header, EI_NIDENT);
      break;
      break;
 
 
    case ELFCLASS64:
    case ELFCLASS64:
      /* If we have been compiled with sizeof (bfd_vma) == 4, then
      /* If we have been compiled with sizeof (bfd_vma) == 4, then
         we will not be able to cope with the 64bit data found in
         we will not be able to cope with the 64bit data found in
         64 ELF files.  Detect this now and abort before we start
         64 ELF files.  Detect this now and abort before we start
         overwriting things.  */
         overwriting things.  */
      if (sizeof (bfd_vma) < 8)
      if (sizeof (bfd_vma) < 8)
        {
        {
          error (_("This executable has been built without support for a\n\
          error (_("This executable has been built without support for a\n\
64 bit data type and so it cannot process 64 bit ELF files.\n"));
64 bit data type and so it cannot process 64 bit ELF files.\n"));
          return 0;
          return 0;
        }
        }
 
 
      if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
      if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
                 1, file) != 1)
                 1, file) != 1)
        return 0;
        return 0;
 
 
      elf_header.e_type      = BYTE_GET (ehdr64.e_type);
      elf_header.e_type      = BYTE_GET (ehdr64.e_type);
      elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
      elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
      elf_header.e_version   = BYTE_GET (ehdr64.e_version);
      elf_header.e_version   = BYTE_GET (ehdr64.e_version);
      elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
      elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
      elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
      elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
      elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
      elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
      elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
      elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
      elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
      elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
      elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
      elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
      elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
      elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
      elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
      elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
      elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
      elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
      elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
      elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
 
 
      memcpy (&ehdr64, &elf_header, EI_NIDENT);
      memcpy (&ehdr64, &elf_header, EI_NIDENT);
      break;
      break;
    }
    }
  return 1;
  return 1;
}
}
 
 
/* Process one ELF object file according to the command line options.
/* Process one ELF object file according to the command line options.
   This file may actually be stored in an archive.  The file is
   This file may actually be stored in an archive.  The file is
   positioned at the start of the ELF object.  */
   positioned at the start of the ELF object.  */
 
 
static int
static int
process_object (const char *file_name, FILE *file)
process_object (const char *file_name, FILE *file)
{
{
  /* Rememeber where we are.  */
  /* Rememeber where we are.  */
  long offset = ftell (file);
  long offset = ftell (file);
 
 
  if (! get_file_header (file))
  if (! get_file_header (file))
    {
    {
      error (_("%s: Failed to read ELF header\n"), file_name);
      error (_("%s: Failed to read ELF header\n"), file_name);
      return 1;
      return 1;
    }
    }
 
 
  /* Go to the position of the ELF header.  */
  /* Go to the position of the ELF header.  */
  if (fseek (file, offset, SEEK_SET) != 0)
  if (fseek (file, offset, SEEK_SET) != 0)
    {
    {
      error (_("%s: Failed to seek to ELF header\n"), file_name);
      error (_("%s: Failed to seek to ELF header\n"), file_name);
    }
    }
 
 
  if (! update_elf_header (file_name, file))
  if (! update_elf_header (file_name, file))
    return 1;
    return 1;
 
 
  return 0;
  return 0;
}
}
 
 
/* Process an ELF archive.
/* Process an ELF archive.
   On entry the file is positioned just after the ARMAG string.  */
   On entry the file is positioned just after the ARMAG string.  */
 
 
static int
static int
process_archive (const char * file_name, FILE * file,
process_archive (const char * file_name, FILE * file,
                 bfd_boolean is_thin_archive)
                 bfd_boolean is_thin_archive)
{
{
  struct archive_info arch;
  struct archive_info arch;
  struct archive_info nested_arch;
  struct archive_info nested_arch;
  size_t got;
  size_t got;
  int ret;
  int ret;
 
 
  /* The ARCH structure is used to hold information about this archive.  */
  /* The ARCH structure is used to hold information about this archive.  */
  arch.file_name = NULL;
  arch.file_name = NULL;
  arch.file = NULL;
  arch.file = NULL;
  arch.index_array = NULL;
  arch.index_array = NULL;
  arch.sym_table = NULL;
  arch.sym_table = NULL;
  arch.longnames = NULL;
  arch.longnames = NULL;
 
 
  /* The NESTED_ARCH structure is used as a single-item cache of information
  /* The NESTED_ARCH structure is used as a single-item cache of information
     about a nested archive (when members of a thin archive reside within
     about a nested archive (when members of a thin archive reside within
     another regular archive file).  */
     another regular archive file).  */
  nested_arch.file_name = NULL;
  nested_arch.file_name = NULL;
  nested_arch.file = NULL;
  nested_arch.file = NULL;
  nested_arch.index_array = NULL;
  nested_arch.index_array = NULL;
  nested_arch.sym_table = NULL;
  nested_arch.sym_table = NULL;
  nested_arch.longnames = NULL;
  nested_arch.longnames = NULL;
 
 
  if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
  if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
    {
    {
      ret = 1;
      ret = 1;
      goto out;
      goto out;
    }
    }
 
 
  ret = 0;
  ret = 0;
 
 
  while (1)
  while (1)
    {
    {
      char * name;
      char * name;
      size_t namelen;
      size_t namelen;
      char * qualified_name;
      char * qualified_name;
 
 
      /* Read the next archive header.  */
      /* Read the next archive header.  */
      if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
      if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
        {
        {
          error (_("%s: failed to seek to next archive header\n"),
          error (_("%s: failed to seek to next archive header\n"),
                     file_name);
                     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)
            break;
            break;
          error (_("%s: failed to read archive header\n"),
          error (_("%s: failed to read archive header\n"),
                     file_name);
                     file_name);
          ret = 1;
          ret = 1;
          break;
          break;
        }
        }
      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);
          ret = 1;
          ret = 1;
          break;
          break;
        }
        }
 
 
      arch.next_arhdr_offset += sizeof arch.arhdr;
      arch.next_arhdr_offset += sizeof arch.arhdr;
 
 
      archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
      archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
      if (archive_file_size & 01)
      if (archive_file_size & 01)
        ++archive_file_size;
        ++archive_file_size;
 
 
      name = get_archive_member_name (&arch, &nested_arch);
      name = get_archive_member_name (&arch, &nested_arch);
      if (name == NULL)
      if (name == NULL)
        {
        {
          error (_("%s: bad archive file name\n"), file_name);
          error (_("%s: bad archive file name\n"), file_name);
          ret = 1;
          ret = 1;
          break;
          break;
        }
        }
      namelen = strlen (name);
      namelen = strlen (name);
 
 
      qualified_name = make_qualified_name (&arch, &nested_arch, name);
      qualified_name = make_qualified_name (&arch, &nested_arch, name);
      if (qualified_name == NULL)
      if (qualified_name == NULL)
        {
        {
          error (_("%s: bad archive file name\n"), file_name);
          error (_("%s: bad archive file name\n"), file_name);
          ret = 1;
          ret = 1;
          break;
          break;
        }
        }
 
 
      if (is_thin_archive && arch.nested_member_origin == 0)
      if (is_thin_archive && arch.nested_member_origin == 0)
        {
        {
          /* This is a proxy for an external member of a thin archive.  */
          /* This is a proxy for an external member of a thin archive.  */
          FILE *member_file;
          FILE *member_file;
          char *member_file_name = adjust_relative_path (file_name,
          char *member_file_name = adjust_relative_path (file_name,
                                                         name, namelen);
                                                         name, namelen);
          if (member_file_name == NULL)
          if (member_file_name == NULL)
            {
            {
              ret = 1;
              ret = 1;
              break;
              break;
            }
            }
 
 
          member_file = fopen (member_file_name, "r+b");
          member_file = fopen (member_file_name, "r+b");
          if (member_file == NULL)
          if (member_file == NULL)
            {
            {
              error (_("Input file '%s' is not readable\n"),
              error (_("Input file '%s' is not readable\n"),
                         member_file_name);
                         member_file_name);
              free (member_file_name);
              free (member_file_name);
              ret = 1;
              ret = 1;
              break;
              break;
            }
            }
 
 
          archive_file_offset = arch.nested_member_origin;
          archive_file_offset = arch.nested_member_origin;
 
 
          ret |= process_object (qualified_name, member_file);
          ret |= process_object (qualified_name, member_file);
 
 
          fclose (member_file);
          fclose (member_file);
          free (member_file_name);
          free (member_file_name);
        }
        }
      else if (is_thin_archive)
      else if (is_thin_archive)
        {
        {
          /* This is a proxy for a member of a nested archive.  */
          /* This is a proxy for a member of a nested archive.  */
          archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
          archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
 
 
          /* The nested archive file will have been opened and setup by
          /* The nested archive file will have been opened and setup by
             get_archive_member_name.  */
             get_archive_member_name.  */
          if (fseek (nested_arch.file, archive_file_offset,
          if (fseek (nested_arch.file, archive_file_offset,
                     SEEK_SET) != 0)
                     SEEK_SET) != 0)
            {
            {
              error (_("%s: failed to seek to archive member\n"),
              error (_("%s: failed to seek to archive member\n"),
                         nested_arch.file_name);
                         nested_arch.file_name);
              ret = 1;
              ret = 1;
              break;
              break;
            }
            }
 
 
          ret |= process_object (qualified_name, nested_arch.file);
          ret |= process_object (qualified_name, nested_arch.file);
        }
        }
      else
      else
        {
        {
          archive_file_offset = arch.next_arhdr_offset;
          archive_file_offset = arch.next_arhdr_offset;
          arch.next_arhdr_offset += archive_file_size;
          arch.next_arhdr_offset += archive_file_size;
 
 
          ret |= process_object (qualified_name, file);
          ret |= process_object (qualified_name, file);
        }
        }
 
 
      free (qualified_name);
      free (qualified_name);
    }
    }
 
 
 out:
 out:
  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);
  release_archive (&arch);
  release_archive (&arch);
 
 
  return ret;
  return ret;
}
}
 
 
static int
static int
check_file (const char *file_name, struct stat *statbuf_p)
check_file (const char *file_name, struct stat *statbuf_p)
{
{
  struct stat statbuf;
  struct stat statbuf;
 
 
  if (statbuf_p == NULL)
  if (statbuf_p == NULL)
    statbuf_p = &statbuf;
    statbuf_p = &statbuf;
 
 
  if (stat (file_name, statbuf_p) < 0)
  if (stat (file_name, statbuf_p) < 0)
    {
    {
      if (errno == ENOENT)
      if (errno == ENOENT)
        error (_("'%s': No such file\n"), file_name);
        error (_("'%s': No such file\n"), file_name);
      else
      else
        error (_("Could not locate '%s'.  System error message: %s\n"),
        error (_("Could not locate '%s'.  System error message: %s\n"),
                   file_name, strerror (errno));
                   file_name, strerror (errno));
      return 1;
      return 1;
    }
    }
 
 
  if (! S_ISREG (statbuf_p->st_mode))
  if (! S_ISREG (statbuf_p->st_mode))
    {
    {
      error (_("'%s' is not an ordinary file\n"), file_name);
      error (_("'%s' is not an ordinary file\n"), file_name);
      return 1;
      return 1;
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
static int
static int
process_file (const char *file_name)
process_file (const char *file_name)
{
{
  FILE * file;
  FILE * file;
  char armag[SARMAG];
  char armag[SARMAG];
  int ret;
  int ret;
 
 
  if (check_file (file_name, NULL))
  if (check_file (file_name, NULL))
    return 1;
    return 1;
 
 
  file = fopen (file_name, "r+b");
  file = fopen (file_name, "r+b");
  if (file == NULL)
  if (file == NULL)
    {
    {
      error (_("Input file '%s' is not readable\n"), file_name);
      error (_("Input file '%s' is not readable\n"), file_name);
      return 1;
      return 1;
    }
    }
 
 
  if (fread (armag, SARMAG, 1, file) != 1)
  if (fread (armag, SARMAG, 1, file) != 1)
    {
    {
      error (_("%s: Failed to read file's magic number\n"),
      error (_("%s: Failed to read file's magic number\n"),
                 file_name);
                 file_name);
      fclose (file);
      fclose (file);
      return 1;
      return 1;
    }
    }
 
 
  if (memcmp (armag, ARMAG, SARMAG) == 0)
  if (memcmp (armag, ARMAG, SARMAG) == 0)
    ret = process_archive (file_name, file, FALSE);
    ret = process_archive (file_name, file, FALSE);
  else if (memcmp (armag, ARMAGT, SARMAG) == 0)
  else if (memcmp (armag, ARMAGT, SARMAG) == 0)
    ret = process_archive (file_name, file, TRUE);
    ret = process_archive (file_name, file, TRUE);
  else
  else
    {
    {
      rewind (file);
      rewind (file);
      archive_file_size = archive_file_offset = 0;
      archive_file_size = archive_file_offset = 0;
      ret = process_object (file_name, file);
      ret = process_object (file_name, file);
    }
    }
 
 
  fclose (file);
  fclose (file);
 
 
  return ret;
  return ret;
}
}
 
 
static const struct
static const struct
{
{
  int osabi;
  int osabi;
  const char *name;
  const char *name;
}
}
osabis[] =
osabis[] =
{
{
  { ELFOSABI_NONE, "none" },
  { ELFOSABI_NONE, "none" },
  { ELFOSABI_HPUX, "HPUX" },
  { ELFOSABI_HPUX, "HPUX" },
  { ELFOSABI_NETBSD, "NetBSD" },
  { ELFOSABI_NETBSD, "NetBSD" },
  { ELFOSABI_GNU, "GNU" },
  { ELFOSABI_GNU, "GNU" },
  { ELFOSABI_GNU, "Linux" },
  { ELFOSABI_GNU, "Linux" },
  { ELFOSABI_SOLARIS, "Solaris" },
  { ELFOSABI_SOLARIS, "Solaris" },
  { ELFOSABI_AIX, "AIX" },
  { ELFOSABI_AIX, "AIX" },
  { ELFOSABI_IRIX, "Irix" },
  { ELFOSABI_IRIX, "Irix" },
  { ELFOSABI_FREEBSD, "FreeBSD" },
  { ELFOSABI_FREEBSD, "FreeBSD" },
  { ELFOSABI_TRU64, "TRU64" },
  { ELFOSABI_TRU64, "TRU64" },
  { ELFOSABI_MODESTO, "Modesto" },
  { ELFOSABI_MODESTO, "Modesto" },
  { ELFOSABI_OPENBSD, "OpenBSD" },
  { ELFOSABI_OPENBSD, "OpenBSD" },
  { ELFOSABI_OPENVMS, "OpenVMS" },
  { ELFOSABI_OPENVMS, "OpenVMS" },
  { ELFOSABI_NSK, "NSK" },
  { ELFOSABI_NSK, "NSK" },
  { ELFOSABI_AROS, "AROS" },
  { ELFOSABI_AROS, "AROS" },
  { ELFOSABI_FENIXOS, "FenixOS" }
  { ELFOSABI_FENIXOS, "FenixOS" }
};
};
 
 
/* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
/* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
 
 
static int
static int
elf_osabi (const char *osabi)
elf_osabi (const char *osabi)
{
{
  unsigned int i;
  unsigned int i;
 
 
  for (i = 0; i < ARRAY_SIZE (osabis); i++)
  for (i = 0; i < ARRAY_SIZE (osabis); i++)
    if (strcasecmp (osabi, osabis[i].name) == 0)
    if (strcasecmp (osabi, osabis[i].name) == 0)
      return osabis[i].osabi;
      return osabis[i].osabi;
 
 
  error (_("Unknown OSABI: %s\n"), osabi);
  error (_("Unknown OSABI: %s\n"), osabi);
 
 
  return -1;
  return -1;
}
}
 
 
/* Return EM_XXX for a machine string, MACH.  */
/* Return EM_XXX for a machine string, MACH.  */
 
 
static int
static int
elf_machine (const char *mach)
elf_machine (const char *mach)
{
{
  if (strcasecmp (mach, "l1om") == 0)
  if (strcasecmp (mach, "l1om") == 0)
    return EM_L1OM;
    return EM_L1OM;
  if (strcasecmp (mach, "k1om") == 0)
  if (strcasecmp (mach, "k1om") == 0)
    return EM_K1OM;
    return EM_K1OM;
  if (strcasecmp (mach, "x86_64") == 0)
  if (strcasecmp (mach, "x86_64") == 0)
    return EM_X86_64;
    return EM_X86_64;
  if (strcasecmp (mach, "x86-64") == 0)
  if (strcasecmp (mach, "x86-64") == 0)
    return EM_X86_64;
    return EM_X86_64;
  if (strcasecmp (mach, "none") == 0)
  if (strcasecmp (mach, "none") == 0)
    return EM_NONE;
    return EM_NONE;
 
 
  error (_("Unknown machine type: %s\n"), mach);
  error (_("Unknown machine type: %s\n"), mach);
 
 
  return -1;
  return -1;
}
}
 
 
/* Return ELF class for a machine type, MACH.  */
/* Return ELF class for a machine type, MACH.  */
 
 
static int
static int
elf_class (int mach)
elf_class (int mach)
{
{
  switch (mach)
  switch (mach)
    {
    {
    case EM_L1OM:
    case EM_L1OM:
    case EM_K1OM:
    case EM_K1OM:
    case EM_X86_64:
    case EM_X86_64:
      return ELFCLASS64;
      return ELFCLASS64;
    case EM_NONE:
    case EM_NONE:
      return ELFCLASSNONE;
      return ELFCLASSNONE;
    default:
    default:
      error (_("Unknown machine type: %d\n"), mach);
      error (_("Unknown machine type: %d\n"), mach);
      return -1;
      return -1;
    }
    }
}
}
 
 
/* Return ET_XXX for a type string, TYPE.  */
/* Return ET_XXX for a type string, TYPE.  */
 
 
static int
static int
elf_type (const char *type)
elf_type (const char *type)
{
{
  if (strcasecmp (type, "rel") == 0)
  if (strcasecmp (type, "rel") == 0)
    return ET_REL;
    return ET_REL;
  if (strcasecmp (type, "exec") == 0)
  if (strcasecmp (type, "exec") == 0)
    return ET_EXEC;
    return ET_EXEC;
  if (strcasecmp (type, "dyn") == 0)
  if (strcasecmp (type, "dyn") == 0)
    return ET_DYN;
    return ET_DYN;
  if (strcasecmp (type, "none") == 0)
  if (strcasecmp (type, "none") == 0)
    return ET_NONE;
    return ET_NONE;
 
 
  error (_("Unknown type: %s\n"), type);
  error (_("Unknown type: %s\n"), type);
 
 
  return -1;
  return -1;
}
}
 
 
enum command_line_switch
enum command_line_switch
  {
  {
    OPTION_INPUT_MACH = 150,
    OPTION_INPUT_MACH = 150,
    OPTION_OUTPUT_MACH,
    OPTION_OUTPUT_MACH,
    OPTION_INPUT_TYPE,
    OPTION_INPUT_TYPE,
    OPTION_OUTPUT_TYPE,
    OPTION_OUTPUT_TYPE,
    OPTION_INPUT_OSABI,
    OPTION_INPUT_OSABI,
    OPTION_OUTPUT_OSABI
    OPTION_OUTPUT_OSABI
  };
  };
 
 
static struct option options[] =
static struct option options[] =
{
{
  {"input-mach",        required_argument, 0, OPTION_INPUT_MACH},
  {"input-mach",        required_argument, 0, OPTION_INPUT_MACH},
  {"output-mach",       required_argument, 0, OPTION_OUTPUT_MACH},
  {"output-mach",       required_argument, 0, OPTION_OUTPUT_MACH},
  {"input-type",        required_argument, 0, OPTION_INPUT_TYPE},
  {"input-type",        required_argument, 0, OPTION_INPUT_TYPE},
  {"output-type",       required_argument, 0, OPTION_OUTPUT_TYPE},
  {"output-type",       required_argument, 0, OPTION_OUTPUT_TYPE},
  {"input-osabi",       required_argument, 0, OPTION_INPUT_OSABI},
  {"input-osabi",       required_argument, 0, OPTION_INPUT_OSABI},
  {"output-osabi",      required_argument, 0, OPTION_OUTPUT_OSABI},
  {"output-osabi",      required_argument, 0, OPTION_OUTPUT_OSABI},
  {"version",           no_argument, 0, 'v'},
  {"version",           no_argument, 0, 'v'},
  {"help",              no_argument, 0, 'h'},
  {"help",              no_argument, 0, 'h'},
  {0,                    no_argument, 0, 0}
  {0,                    no_argument, 0, 0}
};
};
 
 
static void
static void
usage (FILE *stream, int exit_status)
usage (FILE *stream, int exit_status)
{
{
  fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
  fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
           program_name);
           program_name);
  fprintf (stream, _(" Update the ELF header of ELF files\n"));
  fprintf (stream, _(" Update the ELF header of ELF files\n"));
  fprintf (stream, _(" The options are:\n"));
  fprintf (stream, _(" The options are:\n"));
  fprintf (stream, _("\
  fprintf (stream, _("\
  --input-mach <machine>      Set input machine type to <machine>\n\
  --input-mach <machine>      Set input machine type to <machine>\n\
  --output-mach <machine>     Set output machine type to <machine>\n\
  --output-mach <machine>     Set output machine type to <machine>\n\
  --input-type <type>         Set input file type to <type>\n\
  --input-type <type>         Set input file type to <type>\n\
  --output-type <type>        Set output file type to <type>\n\
  --output-type <type>        Set output file type to <type>\n\
  --input-osabi <osabi>       Set input OSABI to <osabi>\n\
  --input-osabi <osabi>       Set input OSABI to <osabi>\n\
  --output-osabi <osabi>      Set output OSABI to <osabi>\n\
  --output-osabi <osabi>      Set output OSABI to <osabi>\n\
  -h --help                   Display this information\n\
  -h --help                   Display this information\n\
  -v --version                Display the version number of %s\n\
  -v --version                Display the version number of %s\n\
"),
"),
           program_name);
           program_name);
  if (REPORT_BUGS_TO[0] && exit_status == 0)
  if (REPORT_BUGS_TO[0] && exit_status == 0)
    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
  exit (exit_status);
  exit (exit_status);
}
}
 
 
int
int
main (int argc, char ** argv)
main (int argc, char ** argv)
{
{
  int c, status;
  int c, status;
 
 
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
  setlocale (LC_MESSAGES, "");
  setlocale (LC_MESSAGES, "");
#endif
#endif
#if defined (HAVE_SETLOCALE)
#if defined (HAVE_SETLOCALE)
  setlocale (LC_CTYPE, "");
  setlocale (LC_CTYPE, "");
#endif
#endif
  bindtextdomain (PACKAGE, LOCALEDIR);
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
  textdomain (PACKAGE);
 
 
  expandargv (&argc, &argv);
  expandargv (&argc, &argv);
 
 
  while ((c = getopt_long (argc, argv, "hv",
  while ((c = getopt_long (argc, argv, "hv",
                           options, (int *) 0)) != EOF)
                           options, (int *) 0)) != EOF)
    {
    {
      switch (c)
      switch (c)
        {
        {
        case OPTION_INPUT_MACH:
        case OPTION_INPUT_MACH:
          input_elf_machine = elf_machine (optarg);
          input_elf_machine = elf_machine (optarg);
          if (input_elf_machine < 0)
          if (input_elf_machine < 0)
            return 1;
            return 1;
          input_elf_class = elf_class (input_elf_machine);
          input_elf_class = elf_class (input_elf_machine);
          if (input_elf_class < 0)
          if (input_elf_class < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case OPTION_OUTPUT_MACH:
        case OPTION_OUTPUT_MACH:
          output_elf_machine = elf_machine (optarg);
          output_elf_machine = elf_machine (optarg);
          if (output_elf_machine < 0)
          if (output_elf_machine < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case OPTION_INPUT_TYPE:
        case OPTION_INPUT_TYPE:
          input_elf_type = elf_type (optarg);
          input_elf_type = elf_type (optarg);
          if (input_elf_type < 0)
          if (input_elf_type < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case OPTION_OUTPUT_TYPE:
        case OPTION_OUTPUT_TYPE:
          output_elf_type = elf_type (optarg);
          output_elf_type = elf_type (optarg);
          if (output_elf_type < 0)
          if (output_elf_type < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case OPTION_INPUT_OSABI:
        case OPTION_INPUT_OSABI:
          input_elf_osabi = elf_osabi (optarg);
          input_elf_osabi = elf_osabi (optarg);
          if (input_elf_osabi < 0)
          if (input_elf_osabi < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case OPTION_OUTPUT_OSABI:
        case OPTION_OUTPUT_OSABI:
          output_elf_osabi = elf_osabi (optarg);
          output_elf_osabi = elf_osabi (optarg);
          if (output_elf_osabi < 0)
          if (output_elf_osabi < 0)
            return 1;
            return 1;
          break;
          break;
 
 
        case 'h':
        case 'h':
          usage (stdout, 0);
          usage (stdout, 0);
 
 
        case 'v':
        case 'v':
          print_version (program_name);
          print_version (program_name);
          break;
          break;
 
 
        default:
        default:
          usage (stderr, 1);
          usage (stderr, 1);
        }
        }
    }
    }
 
 
  if (optind == argc
  if (optind == argc
      || (output_elf_machine == -1
      || (output_elf_machine == -1
          && output_elf_type == -1
          && output_elf_type == -1
          && output_elf_osabi == -1))
          && output_elf_osabi == -1))
    usage (stderr, 1);
    usage (stderr, 1);
 
 
  status = 0;
  status = 0;
  while (optind < argc)
  while (optind < argc)
    status |= process_file (argv[optind++]);
    status |= process_file (argv[optind++]);
 
 
  return status;
  return status;
}
}
 
 

powered by: WebSVN 2.1.0

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