1 /* elfedit.c -- Update the ELF header of an ELF format file 2 Copyright (C) 2010-2020 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 "config.h" 22 #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 #ifdef HAVE_MMAP 70 #include <sys/mman.h> 71 72 static unsigned int enable_x86_features; 73 static unsigned int disable_x86_features; 74 75 static int 76 update_gnu_property (const char *file_name, FILE *file) 77 { 78 char *map; 79 Elf_Internal_Phdr *phdrs; 80 struct stat st_buf; 81 unsigned int i; 82 int ret; 83 84 if (!enable_x86_features && !disable_x86_features) 85 return 0; 86 87 if (elf_header.e_machine != EM_386 88 && elf_header.e_machine != EM_X86_64) 89 { 90 error (_("%s: Not an i386 nor x86-64 ELF file\n"), file_name); 91 return 0; 92 } 93 94 if (fstat (fileno (file), &st_buf) < 0) 95 { 96 error (_("%s: stat () failed\n"), file_name); 97 return 1; 98 } 99 100 map = mmap (NULL, st_buf.st_size, PROT_READ | PROT_WRITE, 101 MAP_SHARED, fileno (file), 0); 102 if (map == MAP_FAILED) 103 { 104 error (_("%s: mmap () failed\n"), file_name); 105 return 0; 106 } 107 108 phdrs = xmalloc (elf_header.e_phnum * sizeof (*phdrs)); 109 110 if (elf_header.e_ident[EI_CLASS] == ELFCLASS32) 111 { 112 Elf32_External_Phdr *phdrs32 113 = (Elf32_External_Phdr *) (map + elf_header.e_phoff); 114 for (i = 0; i < elf_header.e_phnum; i++) 115 { 116 phdrs[i].p_type = BYTE_GET (phdrs32[i].p_type); 117 phdrs[i].p_offset = BYTE_GET (phdrs32[i].p_offset); 118 phdrs[i].p_vaddr = BYTE_GET (phdrs32[i].p_vaddr); 119 phdrs[i].p_paddr = BYTE_GET (phdrs32[i].p_paddr); 120 phdrs[i].p_filesz = BYTE_GET (phdrs32[i].p_filesz); 121 phdrs[i].p_memsz = BYTE_GET (phdrs32[i].p_memsz); 122 phdrs[i].p_flags = BYTE_GET (phdrs32[i].p_flags); 123 phdrs[i].p_align = BYTE_GET (phdrs32[i].p_align); 124 } 125 } 126 else 127 { 128 Elf64_External_Phdr *phdrs64 129 = (Elf64_External_Phdr *) (map + elf_header.e_phoff); 130 for (i = 0; i < elf_header.e_phnum; i++) 131 { 132 phdrs[i].p_type = BYTE_GET (phdrs64[i].p_type); 133 phdrs[i].p_offset = BYTE_GET (phdrs64[i].p_offset); 134 phdrs[i].p_vaddr = BYTE_GET (phdrs64[i].p_vaddr); 135 phdrs[i].p_paddr = BYTE_GET (phdrs64[i].p_paddr); 136 phdrs[i].p_filesz = BYTE_GET (phdrs64[i].p_filesz); 137 phdrs[i].p_memsz = BYTE_GET (phdrs64[i].p_memsz); 138 phdrs[i].p_flags = BYTE_GET (phdrs64[i].p_flags); 139 phdrs[i].p_align = BYTE_GET (phdrs64[i].p_align); 140 } 141 } 142 143 ret = 0; 144 for (i = 0; i < elf_header.e_phnum; i++) 145 if (phdrs[i].p_type == PT_NOTE) 146 { 147 size_t offset = phdrs[i].p_offset; 148 size_t size = phdrs[i].p_filesz; 149 size_t align = phdrs[i].p_align; 150 char *buf = map + offset; 151 char *p = buf; 152 153 while (p < buf + size) 154 { 155 Elf_External_Note *xnp = (Elf_External_Note *) p; 156 Elf_Internal_Note in; 157 158 if (offsetof (Elf_External_Note, name) > buf - p + size) 159 { 160 ret = 1; 161 goto out; 162 } 163 164 in.type = BYTE_GET (xnp->type); 165 in.namesz = BYTE_GET (xnp->namesz); 166 in.namedata = xnp->name; 167 if (in.namesz > buf - in.namedata + size) 168 { 169 ret = 1; 170 goto out; 171 } 172 173 in.descsz = BYTE_GET (xnp->descsz); 174 in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align); 175 in.descpos = offset + (in.descdata - buf); 176 if (in.descsz != 0 177 && (in.descdata >= buf + size 178 || in.descsz > buf - in.descdata + size)) 179 { 180 ret = 1; 181 goto out; 182 } 183 184 if (in.namesz == sizeof "GNU" 185 && strcmp (in.namedata, "GNU") == 0 186 && in.type == NT_GNU_PROPERTY_TYPE_0) 187 { 188 unsigned char *ptr; 189 unsigned char *ptr_end; 190 191 if (in.descsz < 8 || (in.descsz % align) != 0) 192 { 193 ret = 1; 194 goto out; 195 } 196 197 ptr = (unsigned char *) in.descdata; 198 ptr_end = ptr + in.descsz; 199 200 do 201 { 202 unsigned int type = byte_get (ptr, 4); 203 unsigned int datasz = byte_get (ptr + 4, 4); 204 unsigned int bitmask, old_bitmask; 205 206 ptr += 8; 207 if ((ptr + datasz) > ptr_end) 208 { 209 ret = 1; 210 goto out; 211 } 212 213 if (type == GNU_PROPERTY_X86_FEATURE_1_AND) 214 { 215 if (datasz != 4) 216 { 217 ret = 1; 218 goto out; 219 } 220 221 old_bitmask = byte_get (ptr, 4); 222 bitmask = old_bitmask; 223 if (enable_x86_features) 224 bitmask |= enable_x86_features; 225 if (disable_x86_features) 226 bitmask &= ~disable_x86_features; 227 if (old_bitmask != bitmask) 228 byte_put (ptr, bitmask, 4); 229 goto out; 230 } 231 232 ptr += ELF_ALIGN_UP (datasz, align); 233 } 234 while ((ptr_end - ptr) >= 8); 235 } 236 237 p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align); 238 } 239 } 240 241 out: 242 if (ret != 0) 243 error (_("%s: Invalid PT_NOTE segment\n"), file_name); 244 245 free (phdrs); 246 munmap (map, st_buf.st_size); 247 248 return ret; 249 } 250 251 /* Set enable_x86_features and disable_x86_features for a feature 252 string, FEATURE. */ 253 254 static int 255 elf_x86_feature (const char *feature, int enable) 256 { 257 unsigned int x86_feature; 258 if (strcasecmp (feature, "ibt") == 0) 259 x86_feature = GNU_PROPERTY_X86_FEATURE_1_IBT; 260 else if (strcasecmp (feature, "shstk") == 0) 261 x86_feature = GNU_PROPERTY_X86_FEATURE_1_SHSTK; 262 else 263 { 264 error (_("Unknown x86 feature: %s\n"), feature); 265 return -1; 266 } 267 268 if (enable) 269 { 270 enable_x86_features |= x86_feature; 271 disable_x86_features &= ~x86_feature; 272 } 273 else 274 { 275 disable_x86_features |= x86_feature; 276 enable_x86_features &= ~x86_feature; 277 } 278 279 return 0; 280 } 281 #endif 282 283 /* Return ELF class for a machine type, MACH. */ 284 285 static enum elfclass 286 elf_class (int mach) 287 { 288 switch (mach) 289 { 290 case EM_386: 291 case EM_IAMCU: 292 return ELF_CLASS_32; 293 case EM_L1OM: 294 case EM_K1OM: 295 return ELF_CLASS_64; 296 case EM_X86_64: 297 case EM_NONE: 298 return ELF_CLASS_BOTH; 299 default: 300 return ELF_CLASS_BOTH; 301 } 302 } 303 304 static int 305 update_elf_header (const char *file_name, FILE *file) 306 { 307 int class, machine, type, status, osabi; 308 309 if (elf_header.e_ident[EI_VERSION] != EV_CURRENT) 310 { 311 error 312 (_("%s: Unsupported EI_VERSION: %d is not %d\n"), 313 file_name, elf_header.e_ident[EI_VERSION], 314 EV_CURRENT); 315 return 0; 316 } 317 318 /* Return if e_machine is the same as output_elf_machine. */ 319 if (output_elf_machine == elf_header.e_machine) 320 return 1; 321 322 class = elf_header.e_ident[EI_CLASS]; 323 machine = elf_header.e_machine; 324 325 /* Skip if class doesn't match. */ 326 if (input_elf_class == ELF_CLASS_UNKNOWN) 327 input_elf_class = elf_class (machine); 328 329 if (input_elf_class != ELF_CLASS_BOTH 330 && (int) input_elf_class != class) 331 { 332 error 333 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"), 334 file_name, class, input_elf_class); 335 return 0; 336 } 337 338 if (output_elf_class != ELF_CLASS_BOTH 339 && (int) output_elf_class != class) 340 { 341 error 342 (_("%s: Unmatched output EI_CLASS: %d is not %d\n"), 343 file_name, class, output_elf_class); 344 return 0; 345 } 346 347 /* Skip if e_machine doesn't match. */ 348 if (input_elf_machine != -1 && machine != input_elf_machine) 349 { 350 error 351 (_("%s: Unmatched e_machine: %d is not %d\n"), 352 file_name, machine, input_elf_machine); 353 return 0; 354 } 355 356 type = elf_header.e_type; 357 358 /* Skip if e_type doesn't match. */ 359 if (input_elf_type != -1 && type != input_elf_type) 360 { 361 error 362 (_("%s: Unmatched e_type: %d is not %d\n"), 363 file_name, type, input_elf_type); 364 return 0; 365 } 366 367 osabi = elf_header.e_ident[EI_OSABI]; 368 369 /* Skip if OSABI doesn't match. */ 370 if (input_elf_osabi != -1 && osabi != input_elf_osabi) 371 { 372 error 373 (_("%s: Unmatched EI_OSABI: %d is not %d\n"), 374 file_name, osabi, input_elf_osabi); 375 return 0; 376 } 377 378 /* Update e_machine, e_type and EI_OSABI. */ 379 switch (class) 380 { 381 default: 382 /* We should never get here. */ 383 abort (); 384 break; 385 case ELFCLASS32: 386 if (output_elf_machine != -1) 387 BYTE_PUT (ehdr32.e_machine, output_elf_machine); 388 if (output_elf_type != -1) 389 BYTE_PUT (ehdr32.e_type, output_elf_type); 390 if (output_elf_osabi != -1) 391 ehdr32.e_ident[EI_OSABI] = output_elf_osabi; 392 status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1; 393 break; 394 case ELFCLASS64: 395 if (output_elf_machine != -1) 396 BYTE_PUT (ehdr64.e_machine, output_elf_machine); 397 if (output_elf_type != -1) 398 BYTE_PUT (ehdr64.e_type, output_elf_type); 399 if (output_elf_osabi != -1) 400 ehdr64.e_ident[EI_OSABI] = output_elf_osabi; 401 status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1; 402 break; 403 } 404 405 if (status != 1) 406 error (_("%s: Failed to update ELF header: %s\n"), 407 file_name, strerror (errno)); 408 409 return status; 410 } 411 412 static int 413 get_file_header (FILE * file) 414 { 415 /* Read in the identity array. */ 416 if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1) 417 return 0; 418 419 if (elf_header.e_ident[EI_MAG0] != ELFMAG0 420 || elf_header.e_ident[EI_MAG1] != ELFMAG1 421 || elf_header.e_ident[EI_MAG2] != ELFMAG2 422 || elf_header.e_ident[EI_MAG3] != ELFMAG3) 423 return 0; 424 425 /* Determine how to read the rest of the header. */ 426 switch (elf_header.e_ident[EI_DATA]) 427 { 428 default: /* fall through */ 429 case ELFDATANONE: /* fall through */ 430 case ELFDATA2LSB: 431 byte_get = byte_get_little_endian; 432 byte_put = byte_put_little_endian; 433 break; 434 case ELFDATA2MSB: 435 byte_get = byte_get_big_endian; 436 byte_put = byte_put_big_endian; 437 break; 438 } 439 440 /* Read in the rest of the header. For now we only support 32 bit 441 and 64 bit ELF files. */ 442 switch (elf_header.e_ident[EI_CLASS]) 443 { 444 default: 445 return 0; 446 447 case ELFCLASS32: 448 if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 449 1, file) != 1) 450 return 0; 451 452 elf_header.e_type = BYTE_GET (ehdr32.e_type); 453 elf_header.e_machine = BYTE_GET (ehdr32.e_machine); 454 elf_header.e_version = BYTE_GET (ehdr32.e_version); 455 elf_header.e_entry = BYTE_GET (ehdr32.e_entry); 456 elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff); 457 elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff); 458 elf_header.e_flags = BYTE_GET (ehdr32.e_flags); 459 elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize); 460 elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize); 461 elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum); 462 elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize); 463 elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum); 464 elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx); 465 466 memcpy (&ehdr32, &elf_header, EI_NIDENT); 467 break; 468 469 case ELFCLASS64: 470 /* If we have been compiled with sizeof (bfd_vma) == 4, then 471 we will not be able to cope with the 64bit data found in 472 64 ELF files. Detect this now and abort before we start 473 overwriting things. */ 474 if (sizeof (bfd_vma) < 8) 475 { 476 error (_("This executable has been built without support for a\n\ 477 64 bit data type and so it cannot process 64 bit ELF files.\n")); 478 return 0; 479 } 480 481 if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 482 1, file) != 1) 483 return 0; 484 485 elf_header.e_type = BYTE_GET (ehdr64.e_type); 486 elf_header.e_machine = BYTE_GET (ehdr64.e_machine); 487 elf_header.e_version = BYTE_GET (ehdr64.e_version); 488 elf_header.e_entry = BYTE_GET (ehdr64.e_entry); 489 elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff); 490 elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff); 491 elf_header.e_flags = BYTE_GET (ehdr64.e_flags); 492 elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize); 493 elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize); 494 elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum); 495 elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize); 496 elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum); 497 elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx); 498 499 memcpy (&ehdr64, &elf_header, EI_NIDENT); 500 break; 501 } 502 return 1; 503 } 504 505 /* Process one ELF object file according to the command line options. 506 This file may actually be stored in an archive. The file is 507 positioned at the start of the ELF object. */ 508 509 static int 510 process_object (const char *file_name, FILE *file) 511 { 512 /* Rememeber where we are. */ 513 long offset = ftell (file); 514 515 if (! get_file_header (file)) 516 { 517 error (_("%s: Failed to read ELF header\n"), file_name); 518 return 1; 519 } 520 521 /* Go to the position of the ELF header. */ 522 if (fseek (file, offset, SEEK_SET) != 0) 523 { 524 error (_("%s: Failed to seek to ELF header\n"), file_name); 525 } 526 527 if (! update_elf_header (file_name, file)) 528 return 1; 529 530 return 0; 531 } 532 533 /* Process an ELF archive. 534 On entry the file is positioned just after the ARMAG string. */ 535 536 static int 537 process_archive (const char * file_name, FILE * file, 538 bfd_boolean is_thin_archive) 539 { 540 struct archive_info arch; 541 struct archive_info nested_arch; 542 size_t got; 543 int ret; 544 545 /* The ARCH structure is used to hold information about this archive. */ 546 arch.file_name = NULL; 547 arch.file = NULL; 548 arch.index_array = NULL; 549 arch.sym_table = NULL; 550 arch.longnames = NULL; 551 552 /* The NESTED_ARCH structure is used as a single-item cache of information 553 about a nested archive (when members of a thin archive reside within 554 another regular archive file). */ 555 nested_arch.file_name = NULL; 556 nested_arch.file = NULL; 557 nested_arch.index_array = NULL; 558 nested_arch.sym_table = NULL; 559 nested_arch.longnames = NULL; 560 561 if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0) 562 { 563 ret = 1; 564 goto out; 565 } 566 567 ret = 0; 568 569 while (1) 570 { 571 char * name; 572 size_t namelen; 573 char * qualified_name; 574 575 /* Read the next archive header. */ 576 if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0) 577 { 578 error (_("%s: failed to seek to next archive header\n"), 579 file_name); 580 return 1; 581 } 582 got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file); 583 if (got != sizeof arch.arhdr) 584 { 585 if (got == 0) 586 break; 587 error (_("%s: failed to read archive header\n"), 588 file_name); 589 ret = 1; 590 break; 591 } 592 if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0) 593 { 594 error (_("%s: did not find a valid archive header\n"), 595 arch.file_name); 596 ret = 1; 597 break; 598 } 599 600 arch.next_arhdr_offset += sizeof arch.arhdr; 601 602 archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10); 603 if (archive_file_size & 01) 604 ++archive_file_size; 605 606 name = get_archive_member_name (&arch, &nested_arch); 607 if (name == NULL) 608 { 609 error (_("%s: bad archive file name\n"), file_name); 610 ret = 1; 611 break; 612 } 613 namelen = strlen (name); 614 615 qualified_name = make_qualified_name (&arch, &nested_arch, name); 616 if (qualified_name == NULL) 617 { 618 error (_("%s: bad archive file name\n"), file_name); 619 ret = 1; 620 break; 621 } 622 623 if (is_thin_archive && arch.nested_member_origin == 0) 624 { 625 /* This is a proxy for an external member of a thin archive. */ 626 FILE *member_file; 627 char *member_file_name = adjust_relative_path (file_name, 628 name, namelen); 629 if (member_file_name == NULL) 630 { 631 ret = 1; 632 break; 633 } 634 635 member_file = fopen (member_file_name, "r+b"); 636 if (member_file == NULL) 637 { 638 error (_("Input file '%s' is not readable\n"), 639 member_file_name); 640 free (member_file_name); 641 ret = 1; 642 break; 643 } 644 645 archive_file_offset = arch.nested_member_origin; 646 647 ret |= process_object (qualified_name, member_file); 648 649 fclose (member_file); 650 free (member_file_name); 651 } 652 else if (is_thin_archive) 653 { 654 /* This is a proxy for a member of a nested archive. */ 655 archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; 656 657 /* The nested archive file will have been opened and setup by 658 get_archive_member_name. */ 659 if (fseek (nested_arch.file, archive_file_offset, 660 SEEK_SET) != 0) 661 { 662 error (_("%s: failed to seek to archive member\n"), 663 nested_arch.file_name); 664 ret = 1; 665 break; 666 } 667 668 ret |= process_object (qualified_name, nested_arch.file); 669 } 670 else 671 { 672 archive_file_offset = arch.next_arhdr_offset; 673 arch.next_arhdr_offset += archive_file_size; 674 675 ret |= process_object (qualified_name, file); 676 } 677 678 free (qualified_name); 679 } 680 681 out: 682 if (nested_arch.file != NULL) 683 fclose (nested_arch.file); 684 release_archive (&nested_arch); 685 release_archive (&arch); 686 687 return ret; 688 } 689 690 static int 691 check_file (const char *file_name, struct stat *statbuf_p) 692 { 693 struct stat statbuf; 694 695 if (statbuf_p == NULL) 696 statbuf_p = &statbuf; 697 698 if (stat (file_name, statbuf_p) < 0) 699 { 700 if (errno == ENOENT) 701 error (_("'%s': No such file\n"), file_name); 702 else 703 error (_("Could not locate '%s'. System error message: %s\n"), 704 file_name, strerror (errno)); 705 return 1; 706 } 707 708 if (! S_ISREG (statbuf_p->st_mode)) 709 { 710 error (_("'%s' is not an ordinary file\n"), file_name); 711 return 1; 712 } 713 714 return 0; 715 } 716 717 static int 718 process_file (const char *file_name) 719 { 720 FILE * file; 721 char armag[SARMAG]; 722 int ret; 723 724 if (check_file (file_name, NULL)) 725 return 1; 726 727 file = fopen (file_name, "r+b"); 728 if (file == NULL) 729 { 730 error (_("Input file '%s' is not readable\n"), file_name); 731 return 1; 732 } 733 734 if (fread (armag, SARMAG, 1, file) != 1) 735 { 736 error (_("%s: Failed to read file's magic number\n"), 737 file_name); 738 fclose (file); 739 return 1; 740 } 741 742 if (memcmp (armag, ARMAG, SARMAG) == 0) 743 ret = process_archive (file_name, file, FALSE); 744 else if (memcmp (armag, ARMAGT, SARMAG) == 0) 745 ret = process_archive (file_name, file, TRUE); 746 else 747 { 748 rewind (file); 749 archive_file_size = archive_file_offset = 0; 750 ret = process_object (file_name, file); 751 #ifdef HAVE_MMAP 752 if (!ret 753 && (elf_header.e_type == ET_EXEC 754 || elf_header.e_type == ET_DYN)) 755 ret = update_gnu_property (file_name, file); 756 #endif 757 } 758 759 fclose (file); 760 761 return ret; 762 } 763 764 static const struct 765 { 766 int osabi; 767 const char *name; 768 } 769 osabis[] = 770 { 771 { ELFOSABI_NONE, "none" }, 772 { ELFOSABI_HPUX, "HPUX" }, 773 { ELFOSABI_NETBSD, "NetBSD" }, 774 { ELFOSABI_GNU, "GNU" }, 775 { ELFOSABI_GNU, "Linux" }, 776 { ELFOSABI_SOLARIS, "Solaris" }, 777 { ELFOSABI_AIX, "AIX" }, 778 { ELFOSABI_IRIX, "Irix" }, 779 { ELFOSABI_FREEBSD, "FreeBSD" }, 780 { ELFOSABI_TRU64, "TRU64" }, 781 { ELFOSABI_MODESTO, "Modesto" }, 782 { ELFOSABI_OPENBSD, "OpenBSD" }, 783 { ELFOSABI_OPENVMS, "OpenVMS" }, 784 { ELFOSABI_NSK, "NSK" }, 785 { ELFOSABI_AROS, "AROS" }, 786 { ELFOSABI_FENIXOS, "FenixOS" } 787 }; 788 789 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */ 790 791 static int 792 elf_osabi (const char *osabi) 793 { 794 unsigned int i; 795 796 for (i = 0; i < ARRAY_SIZE (osabis); i++) 797 if (strcasecmp (osabi, osabis[i].name) == 0) 798 return osabis[i].osabi; 799 800 error (_("Unknown OSABI: %s\n"), osabi); 801 802 return -1; 803 } 804 805 /* Return EM_XXX for a machine string, MACH. */ 806 807 static int 808 elf_machine (const char *mach) 809 { 810 if (strcasecmp (mach, "i386") == 0) 811 return EM_386; 812 if (strcasecmp (mach, "iamcu") == 0) 813 return EM_IAMCU; 814 if (strcasecmp (mach, "l1om") == 0) 815 return EM_L1OM; 816 if (strcasecmp (mach, "k1om") == 0) 817 return EM_K1OM; 818 if (strcasecmp (mach, "x86_64") == 0) 819 return EM_X86_64; 820 if (strcasecmp (mach, "x86-64") == 0) 821 return EM_X86_64; 822 if (strcasecmp (mach, "none") == 0) 823 return EM_NONE; 824 825 error (_("Unknown machine type: %s\n"), mach); 826 827 return -1; 828 } 829 830 /* Return ET_XXX for a type string, TYPE. */ 831 832 static int 833 elf_type (const char *type) 834 { 835 if (strcasecmp (type, "rel") == 0) 836 return ET_REL; 837 if (strcasecmp (type, "exec") == 0) 838 return ET_EXEC; 839 if (strcasecmp (type, "dyn") == 0) 840 return ET_DYN; 841 if (strcasecmp (type, "none") == 0) 842 return ET_NONE; 843 844 error (_("Unknown type: %s\n"), type); 845 846 return -1; 847 } 848 849 enum command_line_switch 850 { 851 OPTION_INPUT_MACH = 150, 852 OPTION_OUTPUT_MACH, 853 OPTION_INPUT_TYPE, 854 OPTION_OUTPUT_TYPE, 855 OPTION_INPUT_OSABI, 856 OPTION_OUTPUT_OSABI, 857 #ifdef HAVE_MMAP 858 OPTION_ENABLE_X86_FEATURE, 859 OPTION_DISABLE_X86_FEATURE, 860 #endif 861 }; 862 863 static struct option options[] = 864 { 865 {"input-mach", required_argument, 0, OPTION_INPUT_MACH}, 866 {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH}, 867 {"input-type", required_argument, 0, OPTION_INPUT_TYPE}, 868 {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE}, 869 {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI}, 870 {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI}, 871 #ifdef HAVE_MMAP 872 {"enable-x86-feature", 873 required_argument, 0, OPTION_ENABLE_X86_FEATURE}, 874 {"disable-x86-feature", 875 required_argument, 0, OPTION_DISABLE_X86_FEATURE}, 876 #endif 877 {"version", no_argument, 0, 'v'}, 878 {"help", no_argument, 0, 'h'}, 879 {0, no_argument, 0, 0} 880 }; 881 882 ATTRIBUTE_NORETURN static void 883 usage (FILE *stream, int exit_status) 884 { 885 fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"), 886 program_name); 887 fprintf (stream, _(" Update the ELF header of ELF files\n")); 888 fprintf (stream, _(" The options are:\n")); 889 fprintf (stream, _("\ 890 --input-mach <machine> Set input machine type to <machine>\n\ 891 --output-mach <machine> Set output machine type to <machine>\n\ 892 --input-type <type> Set input file type to <type>\n\ 893 --output-type <type> Set output file type to <type>\n\ 894 --input-osabi <osabi> Set input OSABI to <osabi>\n\ 895 --output-osabi <osabi> Set output OSABI to <osabi>\n")); 896 #ifdef HAVE_MMAP 897 fprintf (stream, _("\ 898 --enable-x86-feature <feature>\n\ 899 Enable x86 feature <feature>\n\ 900 --disable-x86-feature <feature>\n\ 901 Disable x86 feature <feature>\n")); 902 #endif 903 fprintf (stream, _("\ 904 -h --help Display this information\n\ 905 -v --version Display the version number of %s\n\ 906 "), 907 program_name); 908 if (REPORT_BUGS_TO[0] && exit_status == 0) 909 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 910 exit (exit_status); 911 } 912 913 int 914 main (int argc, char ** argv) 915 { 916 int c, status; 917 918 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 919 setlocale (LC_MESSAGES, ""); 920 #endif 921 #if defined (HAVE_SETLOCALE) 922 setlocale (LC_CTYPE, ""); 923 #endif 924 bindtextdomain (PACKAGE, LOCALEDIR); 925 textdomain (PACKAGE); 926 927 expandargv (&argc, &argv); 928 929 while ((c = getopt_long (argc, argv, "hv", 930 options, (int *) 0)) != EOF) 931 { 932 switch (c) 933 { 934 case OPTION_INPUT_MACH: 935 input_elf_machine = elf_machine (optarg); 936 if (input_elf_machine < 0) 937 return 1; 938 input_elf_class = elf_class (input_elf_machine); 939 if (input_elf_class == ELF_CLASS_UNKNOWN) 940 return 1; 941 break; 942 943 case OPTION_OUTPUT_MACH: 944 output_elf_machine = elf_machine (optarg); 945 if (output_elf_machine < 0) 946 return 1; 947 output_elf_class = elf_class (output_elf_machine); 948 if (output_elf_class == ELF_CLASS_UNKNOWN) 949 return 1; 950 break; 951 952 case OPTION_INPUT_TYPE: 953 input_elf_type = elf_type (optarg); 954 if (input_elf_type < 0) 955 return 1; 956 break; 957 958 case OPTION_OUTPUT_TYPE: 959 output_elf_type = elf_type (optarg); 960 if (output_elf_type < 0) 961 return 1; 962 break; 963 964 case OPTION_INPUT_OSABI: 965 input_elf_osabi = elf_osabi (optarg); 966 if (input_elf_osabi < 0) 967 return 1; 968 break; 969 970 case OPTION_OUTPUT_OSABI: 971 output_elf_osabi = elf_osabi (optarg); 972 if (output_elf_osabi < 0) 973 return 1; 974 break; 975 976 #ifdef HAVE_MMAP 977 case OPTION_ENABLE_X86_FEATURE: 978 if (elf_x86_feature (optarg, 1) < 0) 979 return 1; 980 break; 981 982 case OPTION_DISABLE_X86_FEATURE: 983 if (elf_x86_feature (optarg, 0) < 0) 984 return 1; 985 break; 986 #endif 987 988 case 'h': 989 usage (stdout, 0); 990 991 case 'v': 992 print_version (program_name); 993 break; 994 995 default: 996 usage (stderr, 1); 997 } 998 } 999 1000 if (optind == argc 1001 || (output_elf_machine == -1 1002 #ifdef HAVE_MMAP 1003 && ! enable_x86_features 1004 && ! disable_x86_features 1005 #endif 1006 && output_elf_type == -1 1007 && output_elf_osabi == -1)) 1008 usage (stderr, 1); 1009 1010 status = 0; 1011 while (optind < argc) 1012 status |= process_file (argv[optind++]); 1013 1014 return status; 1015 } 1016