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" 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; 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 } 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]; 119 machine = elf_header.e_machine; 120 121 /* Skip if class doesn't match. */ 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) 127 { 128 error 129 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"), 130 file_name, class, input_elf_class); 131 return 0; 132 } 133 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 } 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 { 596 if (strcasecmp (mach, "i386") == 0) 597 return EM_386; 598 if (strcasecmp (mach, "iamcu") == 0) 599 return EM_IAMCU; 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); 707 if (input_elf_class == ELF_CLASS_UNKNOWN) 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; 715 output_elf_class = elf_class (output_elf_machine); 716 if (output_elf_class == ELF_CLASS_UNKNOWN) 717 return 1; 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 } 768