[BACK]Return to elfedit.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / binutils

Annotation of src/external/gpl3/binutils.old/dist/binutils/elfedit.c, Revision 1.5

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

CVSweb <webmaster@jp.NetBSD.org>