Home | History | Annotate | Download | only in binutils
      1 /* elfedit.c -- Update the ELF header of an ELF format file
      2    Copyright (C) 2010-2016 Free Software Foundation, Inc.
      3 
      4    This file is part of GNU Binutils.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
     19    02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     23 #include <assert.h>
     24 
     25 #if __GNUC__ >= 2
     26 /* Define BFD64 here, even if our default architecture is 32 bit ELF
     27    as this will allow us to read in and parse 64bit and 32bit ELF files.
     28    Only do this if we believe that the compiler can support a 64 bit
     29    data type.  For now we only rely on GCC being able to do this.  */
     30 #define BFD64
     31 #endif
     32 
     33 #include "bfd.h"
     34 #include "elfcomm.h"
     35 #include "bucomm.h"
     36 
     37 #include "elf/common.h"
     38 #include "elf/external.h"
     39 #include "elf/internal.h"
     40 
     41 #include "getopt.h"
     42 #include "libiberty.h"
     43 #include "safe-ctype.h"
     44 #include "filenames.h"
     45 
     46 char * program_name = "elfedit";
     47 static long archive_file_offset;
     48 static unsigned long archive_file_size;
     49 static Elf_Internal_Ehdr elf_header;
     50 static Elf32_External_Ehdr ehdr32;
     51 static Elf64_External_Ehdr ehdr64;
     52 static int input_elf_machine = -1;
     53 static int output_elf_machine = -1;
     54 static int input_elf_type = -1;
     55 static int output_elf_type = -1;
     56 static int input_elf_osabi = -1;
     57 static int output_elf_osabi = -1;
     58 enum elfclass
     59   {
     60     ELF_CLASS_UNKNOWN = -1,
     61     ELF_CLASS_NONE = ELFCLASSNONE,
     62     ELF_CLASS_32 = ELFCLASS32,
     63     ELF_CLASS_64 = ELFCLASS64,
     64     ELF_CLASS_BOTH
     65   };
     66 static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
     67 static enum elfclass output_elf_class = ELF_CLASS_BOTH;
     68 
     69 /* Return ELF class for a machine type, MACH.  */
     70 
     71 static enum elfclass
     72 elf_class (int mach)
     73 {
     74   switch (mach)
     75     {
     76     case EM_386:
     77     case EM_IAMCU:
     78       return ELF_CLASS_32;
     79     case EM_L1OM:
     80     case EM_K1OM:
     81       return ELF_CLASS_64;
     82     case EM_X86_64:
     83     case EM_NONE:
     84       return ELF_CLASS_BOTH;
     85     default:
     86       return ELF_CLASS_BOTH;
     87     }
     88 }
     89 
     90 static int
     91 update_elf_header (const char *file_name, FILE *file)
     92 {
     93   int class, machine, type, status, osabi;
     94 
     95   if (elf_header.e_ident[EI_MAG0] != ELFMAG0
     96       || elf_header.e_ident[EI_MAG1] != ELFMAG1
     97       || elf_header.e_ident[EI_MAG2] != ELFMAG2
     98       || elf_header.e_ident[EI_MAG3] != ELFMAG3)
     99     {
    100       error
    101 	(_("%s: Not an ELF file - wrong magic bytes at the start\n"),
    102 	 file_name);
    103       return 0;
    104     }
    105 
    106   if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
    107     {
    108       error
    109 	(_("%s: Unsupported EI_VERSION: %d is not %d\n"),
    110 	 file_name, elf_header.e_ident[EI_VERSION],
    111 	 EV_CURRENT);
    112       return 0;
    113     }
    114 
    115   /* Return if e_machine is the same as output_elf_machine.  */
    116   if (output_elf_machine == elf_header.e_machine)
    117     return 1;
    118 
    119   class = elf_header.e_ident[EI_CLASS];
    120   machine = elf_header.e_machine;
    121 
    122   /* Skip if class doesn't match. */
    123   if (input_elf_class == ELF_CLASS_UNKNOWN)
    124     input_elf_class = elf_class (machine);
    125 
    126   if (input_elf_class != ELF_CLASS_BOTH
    127       && (int) input_elf_class != class)
    128     {
    129       error
    130 	(_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
    131 	 file_name, class, input_elf_class);
    132       return 0;
    133     }
    134 
    135   if (output_elf_class != ELF_CLASS_BOTH
    136       && (int) output_elf_class != class)
    137     {
    138       error
    139 	(_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
    140 	 file_name, class, output_elf_class);
    141       return 0;
    142     }
    143 
    144   /* Skip if e_machine doesn't match. */
    145   if (input_elf_machine != -1 && machine != input_elf_machine)
    146     {
    147       error
    148 	(_("%s: Unmatched e_machine: %d is not %d\n"),
    149 	 file_name, machine, input_elf_machine);
    150       return 0;
    151     }
    152 
    153   type = elf_header.e_type;
    154 
    155   /* Skip if e_type doesn't match. */
    156   if (input_elf_type != -1 && type != input_elf_type)
    157     {
    158       error
    159 	(_("%s: Unmatched e_type: %d is not %d\n"),
    160 	 file_name, type, input_elf_type);
    161       return 0;
    162     }
    163 
    164   osabi = elf_header.e_ident[EI_OSABI];
    165 
    166   /* Skip if OSABI doesn't match. */
    167   if (input_elf_osabi != -1 && osabi != input_elf_osabi)
    168     {
    169       error
    170 	(_("%s: Unmatched EI_OSABI: %d is not %d\n"),
    171 	 file_name, osabi, input_elf_osabi);
    172       return 0;
    173     }
    174 
    175   /* Update e_machine, e_type and EI_OSABI.  */
    176   switch (class)
    177     {
    178     default:
    179       /* We should never get here.  */
    180       abort ();
    181       break;
    182     case ELFCLASS32:
    183       if (output_elf_machine != -1)
    184 	BYTE_PUT (ehdr32.e_machine, output_elf_machine);
    185       if (output_elf_type != -1)
    186 	BYTE_PUT (ehdr32.e_type, output_elf_type);
    187       if (output_elf_osabi != -1)
    188 	ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
    189       status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
    190       break;
    191     case ELFCLASS64:
    192       if (output_elf_machine != -1)
    193 	BYTE_PUT (ehdr64.e_machine, output_elf_machine);
    194       if (output_elf_type != -1)
    195 	BYTE_PUT (ehdr64.e_type, output_elf_type);
    196       if (output_elf_osabi != -1)
    197 	ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
    198       status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
    199       break;
    200     }
    201 
    202   if (status != 1)
    203     error (_("%s: Failed to update ELF header: %s\n"),
    204 	       file_name, strerror (errno));
    205 
    206   return status;
    207 }
    208 
    209 static int
    210 get_file_header (FILE * file)
    211 {
    212   /* Read in the identity array.  */
    213   if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
    214     return 0;
    215 
    216   /* Determine how to read the rest of the header.  */
    217   switch (elf_header.e_ident[EI_DATA])
    218     {
    219     default: /* fall through */
    220     case ELFDATANONE: /* fall through */
    221     case ELFDATA2LSB:
    222       byte_get = byte_get_little_endian;
    223       byte_put = byte_put_little_endian;
    224       break;
    225     case ELFDATA2MSB:
    226       byte_get = byte_get_big_endian;
    227       byte_put = byte_put_big_endian;
    228       break;
    229     }
    230 
    231   /* Read in the rest of the header.  For now we only support 32 bit
    232      and 64 bit ELF files.  */
    233   switch (elf_header.e_ident[EI_CLASS])
    234     {
    235     default:
    236       error (_("Unsupported EI_CLASS: %d\n"),
    237 		 elf_header.e_ident[EI_CLASS]);
    238       return 0;
    239 
    240     case ELFCLASS32:
    241       if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
    242 		 1, file) != 1)
    243 	return 0;
    244 
    245       elf_header.e_type      = BYTE_GET (ehdr32.e_type);
    246       elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
    247       elf_header.e_version   = BYTE_GET (ehdr32.e_version);
    248       elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
    249       elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
    250       elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
    251       elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
    252       elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
    253       elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
    254       elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
    255       elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
    256       elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
    257       elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
    258 
    259       memcpy (&ehdr32, &elf_header, EI_NIDENT);
    260       break;
    261 
    262     case ELFCLASS64:
    263       /* If we have been compiled with sizeof (bfd_vma) == 4, then
    264 	 we will not be able to cope with the 64bit data found in
    265 	 64 ELF files.  Detect this now and abort before we start
    266 	 overwriting things.  */
    267       if (sizeof (bfd_vma) < 8)
    268 	{
    269 	  error (_("This executable has been built without support for a\n\
    270 64 bit data type and so it cannot process 64 bit ELF files.\n"));
    271 	  return 0;
    272 	}
    273 
    274       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
    275 		 1, file) != 1)
    276 	return 0;
    277 
    278       elf_header.e_type      = BYTE_GET (ehdr64.e_type);
    279       elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
    280       elf_header.e_version   = BYTE_GET (ehdr64.e_version);
    281       elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
    282       elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
    283       elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
    284       elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
    285       elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
    286       elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
    287       elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
    288       elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
    289       elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
    290       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
    291 
    292       memcpy (&ehdr64, &elf_header, EI_NIDENT);
    293       break;
    294     }
    295   return 1;
    296 }
    297 
    298 /* Process one ELF object file according to the command line options.
    299    This file may actually be stored in an archive.  The file is
    300    positioned at the start of the ELF object.  */
    301 
    302 static int
    303 process_object (const char *file_name, FILE *file)
    304 {
    305   /* Rememeber where we are.  */
    306   long offset = ftell (file);
    307 
    308   if (! get_file_header (file))
    309     {
    310       error (_("%s: Failed to read ELF header\n"), file_name);
    311       return 1;
    312     }
    313 
    314   /* Go to the position of the ELF header.  */
    315   if (fseek (file, offset, SEEK_SET) != 0)
    316     {
    317       error (_("%s: Failed to seek to ELF header\n"), file_name);
    318     }
    319 
    320   if (! update_elf_header (file_name, file))
    321     return 1;
    322 
    323   return 0;
    324 }
    325 
    326 /* Process an ELF archive.
    327    On entry the file is positioned just after the ARMAG string.  */
    328 
    329 static int
    330 process_archive (const char * file_name, FILE * file,
    331 		 bfd_boolean is_thin_archive)
    332 {
    333   struct archive_info arch;
    334   struct archive_info nested_arch;
    335   size_t got;
    336   int ret;
    337 
    338   /* The ARCH structure is used to hold information about this archive.  */
    339   arch.file_name = NULL;
    340   arch.file = NULL;
    341   arch.index_array = NULL;
    342   arch.sym_table = NULL;
    343   arch.longnames = NULL;
    344 
    345   /* The NESTED_ARCH structure is used as a single-item cache of information
    346      about a nested archive (when members of a thin archive reside within
    347      another regular archive file).  */
    348   nested_arch.file_name = NULL;
    349   nested_arch.file = NULL;
    350   nested_arch.index_array = NULL;
    351   nested_arch.sym_table = NULL;
    352   nested_arch.longnames = NULL;
    353 
    354   if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
    355     {
    356       ret = 1;
    357       goto out;
    358     }
    359 
    360   ret = 0;
    361 
    362   while (1)
    363     {
    364       char * name;
    365       size_t namelen;
    366       char * qualified_name;
    367 
    368       /* Read the next archive header.  */
    369       if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
    370         {
    371           error (_("%s: failed to seek to next archive header\n"),
    372 		     file_name);
    373           return 1;
    374         }
    375       got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
    376       if (got != sizeof arch.arhdr)
    377         {
    378           if (got == 0)
    379 	    break;
    380           error (_("%s: failed to read archive header\n"),
    381 		     file_name);
    382           ret = 1;
    383           break;
    384         }
    385       if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
    386         {
    387           error (_("%s: did not find a valid archive header\n"),
    388 		     arch.file_name);
    389           ret = 1;
    390           break;
    391         }
    392 
    393       arch.next_arhdr_offset += sizeof arch.arhdr;
    394 
    395       archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
    396       if (archive_file_size & 01)
    397         ++archive_file_size;
    398 
    399       name = get_archive_member_name (&arch, &nested_arch);
    400       if (name == NULL)
    401 	{
    402 	  error (_("%s: bad archive file name\n"), file_name);
    403 	  ret = 1;
    404 	  break;
    405 	}
    406       namelen = strlen (name);
    407 
    408       qualified_name = make_qualified_name (&arch, &nested_arch, name);
    409       if (qualified_name == NULL)
    410 	{
    411 	  error (_("%s: bad archive file name\n"), file_name);
    412 	  ret = 1;
    413 	  break;
    414 	}
    415 
    416       if (is_thin_archive && arch.nested_member_origin == 0)
    417         {
    418           /* This is a proxy for an external member of a thin archive.  */
    419           FILE *member_file;
    420           char *member_file_name = adjust_relative_path (file_name,
    421 							 name, namelen);
    422           if (member_file_name == NULL)
    423             {
    424               ret = 1;
    425               break;
    426             }
    427 
    428           member_file = fopen (member_file_name, "r+b");
    429           if (member_file == NULL)
    430             {
    431               error (_("Input file '%s' is not readable\n"),
    432 			 member_file_name);
    433               free (member_file_name);
    434               ret = 1;
    435               break;
    436             }
    437 
    438           archive_file_offset = arch.nested_member_origin;
    439 
    440           ret |= process_object (qualified_name, member_file);
    441 
    442           fclose (member_file);
    443           free (member_file_name);
    444         }
    445       else if (is_thin_archive)
    446         {
    447           /* This is a proxy for a member of a nested archive.  */
    448           archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
    449 
    450           /* The nested archive file will have been opened and setup by
    451              get_archive_member_name.  */
    452           if (fseek (nested_arch.file, archive_file_offset,
    453 		     SEEK_SET) != 0)
    454             {
    455               error (_("%s: failed to seek to archive member\n"),
    456 			 nested_arch.file_name);
    457               ret = 1;
    458               break;
    459             }
    460 
    461           ret |= process_object (qualified_name, nested_arch.file);
    462         }
    463       else
    464         {
    465           archive_file_offset = arch.next_arhdr_offset;
    466           arch.next_arhdr_offset += archive_file_size;
    467 
    468           ret |= process_object (qualified_name, file);
    469         }
    470 
    471       free (qualified_name);
    472     }
    473 
    474  out:
    475   if (nested_arch.file != NULL)
    476     fclose (nested_arch.file);
    477   release_archive (&nested_arch);
    478   release_archive (&arch);
    479 
    480   return ret;
    481 }
    482 
    483 static int
    484 check_file (const char *file_name, struct stat *statbuf_p)
    485 {
    486   struct stat statbuf;
    487 
    488   if (statbuf_p == NULL)
    489     statbuf_p = &statbuf;
    490 
    491   if (stat (file_name, statbuf_p) < 0)
    492     {
    493       if (errno == ENOENT)
    494 	error (_("'%s': No such file\n"), file_name);
    495       else
    496 	error (_("Could not locate '%s'.  System error message: %s\n"),
    497 		   file_name, strerror (errno));
    498       return 1;
    499     }
    500 
    501   if (! S_ISREG (statbuf_p->st_mode))
    502     {
    503       error (_("'%s' is not an ordinary file\n"), file_name);
    504       return 1;
    505     }
    506 
    507   return 0;
    508 }
    509 
    510 static int
    511 process_file (const char *file_name)
    512 {
    513   FILE * file;
    514   char armag[SARMAG];
    515   int ret;
    516 
    517   if (check_file (file_name, NULL))
    518     return 1;
    519 
    520   file = fopen (file_name, "r+b");
    521   if (file == NULL)
    522     {
    523       error (_("Input file '%s' is not readable\n"), file_name);
    524       return 1;
    525     }
    526 
    527   if (fread (armag, SARMAG, 1, file) != 1)
    528     {
    529       error (_("%s: Failed to read file's magic number\n"),
    530 		 file_name);
    531       fclose (file);
    532       return 1;
    533     }
    534 
    535   if (memcmp (armag, ARMAG, SARMAG) == 0)
    536     ret = process_archive (file_name, file, FALSE);
    537   else if (memcmp (armag, ARMAGT, SARMAG) == 0)
    538     ret = process_archive (file_name, file, TRUE);
    539   else
    540     {
    541       rewind (file);
    542       archive_file_size = archive_file_offset = 0;
    543       ret = process_object (file_name, file);
    544     }
    545 
    546   fclose (file);
    547 
    548   return ret;
    549 }
    550 
    551 static const struct
    552 {
    553   int osabi;
    554   const char *name;
    555 }
    556 osabis[] =
    557 {
    558   { ELFOSABI_NONE, "none" },
    559   { ELFOSABI_HPUX, "HPUX" },
    560   { ELFOSABI_NETBSD, "NetBSD" },
    561   { ELFOSABI_GNU, "GNU" },
    562   { ELFOSABI_GNU, "Linux" },
    563   { ELFOSABI_SOLARIS, "Solaris" },
    564   { ELFOSABI_AIX, "AIX" },
    565   { ELFOSABI_IRIX, "Irix" },
    566   { ELFOSABI_FREEBSD, "FreeBSD" },
    567   { ELFOSABI_TRU64, "TRU64" },
    568   { ELFOSABI_MODESTO, "Modesto" },
    569   { ELFOSABI_OPENBSD, "OpenBSD" },
    570   { ELFOSABI_OPENVMS, "OpenVMS" },
    571   { ELFOSABI_NSK, "NSK" },
    572   { ELFOSABI_AROS, "AROS" },
    573   { ELFOSABI_FENIXOS, "FenixOS" }
    574 };
    575 
    576 /* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
    577 
    578 static int
    579 elf_osabi (const char *osabi)
    580 {
    581   unsigned int i;
    582 
    583   for (i = 0; i < ARRAY_SIZE (osabis); i++)
    584     if (strcasecmp (osabi, osabis[i].name) == 0)
    585       return osabis[i].osabi;
    586 
    587   error (_("Unknown OSABI: %s\n"), osabi);
    588 
    589   return -1;
    590 }
    591 
    592 /* Return EM_XXX for a machine string, MACH.  */
    593 
    594 static int
    595 elf_machine (const char *mach)
    596 {
    597   if (strcasecmp (mach, "i386") == 0)
    598     return EM_386;
    599   if (strcasecmp (mach, "iamcu") == 0)
    600     return EM_IAMCU;
    601   if (strcasecmp (mach, "l1om") == 0)
    602     return EM_L1OM;
    603   if (strcasecmp (mach, "k1om") == 0)
    604     return EM_K1OM;
    605   if (strcasecmp (mach, "x86_64") == 0)
    606     return EM_X86_64;
    607   if (strcasecmp (mach, "x86-64") == 0)
    608     return EM_X86_64;
    609   if (strcasecmp (mach, "none") == 0)
    610     return EM_NONE;
    611 
    612   error (_("Unknown machine type: %s\n"), mach);
    613 
    614   return -1;
    615 }
    616 
    617 /* Return ET_XXX for a type string, TYPE.  */
    618 
    619 static int
    620 elf_type (const char *type)
    621 {
    622   if (strcasecmp (type, "rel") == 0)
    623     return ET_REL;
    624   if (strcasecmp (type, "exec") == 0)
    625     return ET_EXEC;
    626   if (strcasecmp (type, "dyn") == 0)
    627     return ET_DYN;
    628   if (strcasecmp (type, "none") == 0)
    629     return ET_NONE;
    630 
    631   error (_("Unknown type: %s\n"), type);
    632 
    633   return -1;
    634 }
    635 
    636 enum command_line_switch
    637   {
    638     OPTION_INPUT_MACH = 150,
    639     OPTION_OUTPUT_MACH,
    640     OPTION_INPUT_TYPE,
    641     OPTION_OUTPUT_TYPE,
    642     OPTION_INPUT_OSABI,
    643     OPTION_OUTPUT_OSABI
    644   };
    645 
    646 static struct option options[] =
    647 {
    648   {"input-mach",	required_argument, 0, OPTION_INPUT_MACH},
    649   {"output-mach",	required_argument, 0, OPTION_OUTPUT_MACH},
    650   {"input-type",	required_argument, 0, OPTION_INPUT_TYPE},
    651   {"output-type",	required_argument, 0, OPTION_OUTPUT_TYPE},
    652   {"input-osabi",	required_argument, 0, OPTION_INPUT_OSABI},
    653   {"output-osabi",	required_argument, 0, OPTION_OUTPUT_OSABI},
    654   {"version",		no_argument, 0, 'v'},
    655   {"help",		no_argument, 0, 'h'},
    656   {0,			no_argument, 0, 0}
    657 };
    658 
    659 static void
    660 usage (FILE *stream, int exit_status)
    661 {
    662   fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
    663 	   program_name);
    664   fprintf (stream, _(" Update the ELF header of ELF files\n"));
    665   fprintf (stream, _(" The options are:\n"));
    666   fprintf (stream, _("\
    667   --input-mach <machine>      Set input machine type to <machine>\n\
    668   --output-mach <machine>     Set output machine type to <machine>\n\
    669   --input-type <type>         Set input file type to <type>\n\
    670   --output-type <type>        Set output file type to <type>\n\
    671   --input-osabi <osabi>       Set input OSABI to <osabi>\n\
    672   --output-osabi <osabi>      Set output OSABI to <osabi>\n\
    673   -h --help                   Display this information\n\
    674   -v --version                Display the version number of %s\n\
    675 "),
    676 	   program_name);
    677   if (REPORT_BUGS_TO[0] && exit_status == 0)
    678     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
    679   exit (exit_status);
    680 }
    681 
    682 int
    683 main (int argc, char ** argv)
    684 {
    685   int c, status;
    686 
    687 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
    688   setlocale (LC_MESSAGES, "");
    689 #endif
    690 #if defined (HAVE_SETLOCALE)
    691   setlocale (LC_CTYPE, "");
    692 #endif
    693   bindtextdomain (PACKAGE, LOCALEDIR);
    694   textdomain (PACKAGE);
    695 
    696   expandargv (&argc, &argv);
    697 
    698   while ((c = getopt_long (argc, argv, "hv",
    699 			   options, (int *) 0)) != EOF)
    700     {
    701       switch (c)
    702 	{
    703 	case OPTION_INPUT_MACH:
    704 	  input_elf_machine = elf_machine (optarg);
    705 	  if (input_elf_machine < 0)
    706 	    return 1;
    707 	  input_elf_class = elf_class (input_elf_machine);
    708 	  if (input_elf_class == ELF_CLASS_UNKNOWN)
    709 	    return 1;
    710 	  break;
    711 
    712 	case OPTION_OUTPUT_MACH:
    713 	  output_elf_machine = elf_machine (optarg);
    714 	  if (output_elf_machine < 0)
    715 	    return 1;
    716 	  output_elf_class = elf_class (output_elf_machine);
    717 	  if (output_elf_class == ELF_CLASS_UNKNOWN)
    718 	    return 1;
    719 	  break;
    720 
    721 	case OPTION_INPUT_TYPE:
    722 	  input_elf_type = elf_type (optarg);
    723 	  if (input_elf_type < 0)
    724 	    return 1;
    725 	  break;
    726 
    727 	case OPTION_OUTPUT_TYPE:
    728 	  output_elf_type = elf_type (optarg);
    729 	  if (output_elf_type < 0)
    730 	    return 1;
    731 	  break;
    732 
    733 	case OPTION_INPUT_OSABI:
    734 	  input_elf_osabi = elf_osabi (optarg);
    735 	  if (input_elf_osabi < 0)
    736 	    return 1;
    737 	  break;
    738 
    739 	case OPTION_OUTPUT_OSABI:
    740 	  output_elf_osabi = elf_osabi (optarg);
    741 	  if (output_elf_osabi < 0)
    742 	    return 1;
    743 	  break;
    744 
    745 	case 'h':
    746 	  usage (stdout, 0);
    747 
    748 	case 'v':
    749 	  print_version (program_name);
    750 	  break;
    751 
    752 	default:
    753 	  usage (stderr, 1);
    754 	}
    755     }
    756 
    757   if (optind == argc
    758       || (output_elf_machine == -1
    759 	  && output_elf_type == -1
    760 	  && output_elf_osabi == -1))
    761     usage (stderr, 1);
    762 
    763   status = 0;
    764   while (optind < argc)
    765     status |= process_file (argv[optind++]);
    766 
    767   return status;
    768 }
    769