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