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