avoid unwarranted assumption in gdb.ada/fixed_points/fixed_points.adb
[binutils-gdb.git] / binutils / elfedit.c
blob91cba1d7470986f039c1e6f06cfca3134ac43850
1 /* elfedit.c -- Update the ELF header of an ELF format file
2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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.
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.
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. */
21 #include "config.h"
22 #include "sysdep.h"
23 #include <assert.h>
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
33 #include "bfd.h"
34 #include "elfcomm.h"
35 #include "bucomm.h"
37 #include "elf/common.h"
38 #include "elf/external.h"
39 #include "elf/internal.h"
41 #include "getopt.h"
42 #include "libiberty.h"
43 #include "safe-ctype.h"
44 #include "filenames.h"
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
60 ELF_CLASS_UNKNOWN = -1,
61 ELF_CLASS_NONE = ELFCLASSNONE,
62 ELF_CLASS_32 = ELFCLASS32,
63 ELF_CLASS_64 = ELFCLASS64,
64 ELF_CLASS_BOTH
66 static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
67 static enum elfclass output_elf_class = ELF_CLASS_BOTH;
69 #ifdef HAVE_MMAP
70 #include <sys/mman.h>
72 static unsigned int enable_x86_features;
73 static unsigned int disable_x86_features;
75 static int
76 update_gnu_property (const char *file_name, FILE *file)
78 char *map;
79 Elf_Internal_Phdr *phdrs;
80 struct stat st_buf;
81 unsigned int i;
82 int ret;
84 if (!enable_x86_features && !disable_x86_features)
85 return 0;
87 if (elf_header.e_machine != EM_386
88 && elf_header.e_machine != EM_X86_64)
90 error (_("%s: Not an i386 nor x86-64 ELF file\n"), file_name);
91 return 0;
94 if (fstat (fileno (file), &st_buf) < 0)
96 error (_("%s: stat () failed\n"), file_name);
97 return 1;
100 map = mmap (NULL, st_buf.st_size, PROT_READ | PROT_WRITE,
101 MAP_SHARED, fileno (file), 0);
102 if (map == MAP_FAILED)
104 error (_("%s: mmap () failed\n"), file_name);
105 return 0;
108 phdrs = xmalloc (elf_header.e_phnum * sizeof (*phdrs));
110 if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
112 Elf32_External_Phdr *phdrs32
113 = (Elf32_External_Phdr *) (map + elf_header.e_phoff);
114 for (i = 0; i < elf_header.e_phnum; i++)
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);
126 else
128 Elf64_External_Phdr *phdrs64
129 = (Elf64_External_Phdr *) (map + elf_header.e_phoff);
130 for (i = 0; i < elf_header.e_phnum; i++)
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);
143 ret = 0;
144 for (i = 0; i < elf_header.e_phnum; i++)
145 if (phdrs[i].p_type == PT_NOTE)
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;
153 while (p < buf + size)
155 Elf_External_Note *xnp = (Elf_External_Note *) p;
156 Elf_Internal_Note in;
158 if (offsetof (Elf_External_Note, name) > buf - p + size)
160 ret = 1;
161 goto out;
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)
169 ret = 1;
170 goto out;
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))
180 ret = 1;
181 goto out;
184 if (in.namesz == sizeof "GNU"
185 && strcmp (in.namedata, "GNU") == 0
186 && in.type == NT_GNU_PROPERTY_TYPE_0)
188 unsigned char *ptr;
189 unsigned char *ptr_end;
191 if (in.descsz < 8 || (in.descsz % align) != 0)
193 ret = 1;
194 goto out;
197 ptr = (unsigned char *) in.descdata;
198 ptr_end = ptr + in.descsz;
202 unsigned int type = byte_get (ptr, 4);
203 unsigned int datasz = byte_get (ptr + 4, 4);
204 unsigned int bitmask, old_bitmask;
206 ptr += 8;
207 if ((ptr + datasz) > ptr_end)
209 ret = 1;
210 goto out;
213 if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
215 if (datasz != 4)
217 ret = 1;
218 goto out;
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;
232 ptr += ELF_ALIGN_UP (datasz, align);
234 while ((ptr_end - ptr) >= 8);
237 p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
241 out:
242 if (ret != 0)
243 error (_("%s: Invalid PT_NOTE segment\n"), file_name);
245 free (phdrs);
246 munmap (map, st_buf.st_size);
248 return ret;
251 /* Set enable_x86_features and disable_x86_features for a feature
252 string, FEATURE. */
254 static int
255 elf_x86_feature (const char *feature, int enable)
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
264 error (_("Unknown x86 feature: %s\n"), feature);
265 return -1;
268 if (enable)
270 enable_x86_features |= x86_feature;
271 disable_x86_features &= ~x86_feature;
273 else
275 disable_x86_features |= x86_feature;
276 enable_x86_features &= ~x86_feature;
279 return 0;
281 #endif
283 /* Return ELF class for a machine type, MACH. */
285 static enum elfclass
286 elf_class (int mach)
288 switch (mach)
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;
304 static int
305 update_elf_header (const char *file_name, FILE *file)
307 int class, machine, type, status, osabi;
309 if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
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;
318 /* Return if e_machine is the same as output_elf_machine. */
319 if (output_elf_machine == elf_header.e_machine)
320 return 1;
322 class = elf_header.e_ident[EI_CLASS];
323 machine = elf_header.e_machine;
325 /* Skip if class doesn't match. */
326 if (input_elf_class == ELF_CLASS_UNKNOWN)
327 input_elf_class = elf_class (machine);
329 if (input_elf_class != ELF_CLASS_BOTH
330 && (int) input_elf_class != class)
332 error
333 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
334 file_name, class, input_elf_class);
335 return 0;
338 if (output_elf_class != ELF_CLASS_BOTH
339 && (int) output_elf_class != class)
341 error
342 (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
343 file_name, class, output_elf_class);
344 return 0;
347 /* Skip if e_machine doesn't match. */
348 if (input_elf_machine != -1 && machine != input_elf_machine)
350 error
351 (_("%s: Unmatched e_machine: %d is not %d\n"),
352 file_name, machine, input_elf_machine);
353 return 0;
356 type = elf_header.e_type;
358 /* Skip if e_type doesn't match. */
359 if (input_elf_type != -1 && type != input_elf_type)
361 error
362 (_("%s: Unmatched e_type: %d is not %d\n"),
363 file_name, type, input_elf_type);
364 return 0;
367 osabi = elf_header.e_ident[EI_OSABI];
369 /* Skip if OSABI doesn't match. */
370 if (input_elf_osabi != -1 && osabi != input_elf_osabi)
372 error
373 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
374 file_name, osabi, input_elf_osabi);
375 return 0;
378 /* Update e_machine, e_type and EI_OSABI. */
379 switch (class)
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;
405 if (status != 1)
406 error (_("%s: Failed to update ELF header: %s\n"),
407 file_name, strerror (errno));
409 return status;
412 static int
413 get_file_header (FILE * file)
415 /* Read in the identity array. */
416 if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
417 return 0;
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;
425 /* Determine how to read the rest of the header. */
426 switch (elf_header.e_ident[EI_DATA])
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;
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])
444 default:
445 return 0;
447 case ELFCLASS32:
448 if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
449 1, file) != 1)
450 return 0;
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);
466 memcpy (&ehdr32, &elf_header, EI_NIDENT);
467 break;
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)
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;
481 if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
482 1, file) != 1)
483 return 0;
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);
499 memcpy (&ehdr64, &elf_header, EI_NIDENT);
500 break;
502 return 1;
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. */
509 static int
510 process_object (const char *file_name, FILE *file)
512 /* Rememeber where we are. */
513 long offset = ftell (file);
515 if (! get_file_header (file))
517 error (_("%s: Failed to read ELF header\n"), file_name);
518 return 1;
521 /* Go to the position of the ELF header. */
522 if (fseek (file, offset, SEEK_SET) != 0)
524 error (_("%s: Failed to seek to ELF header\n"), file_name);
527 if (! update_elf_header (file_name, file))
528 return 1;
530 return 0;
533 /* Process an ELF archive.
534 On entry the file is positioned just after the ARMAG string. */
536 static int
537 process_archive (const char * file_name, FILE * file,
538 bfd_boolean is_thin_archive)
540 struct archive_info arch;
541 struct archive_info nested_arch;
542 size_t got;
543 int ret;
544 struct stat statbuf;
546 /* The ARCH structure is used to hold information about this archive. */
547 arch.file_name = NULL;
548 arch.file = NULL;
549 arch.index_array = NULL;
550 arch.sym_table = NULL;
551 arch.longnames = NULL;
553 /* The NESTED_ARCH structure is used as a single-item cache of information
554 about a nested archive (when members of a thin archive reside within
555 another regular archive file). */
556 nested_arch.file_name = NULL;
557 nested_arch.file = NULL;
558 nested_arch.index_array = NULL;
559 nested_arch.sym_table = NULL;
560 nested_arch.longnames = NULL;
562 if (fstat (fileno (file), &statbuf) < 0
563 || setup_archive (&arch, file_name, file, statbuf.st_size,
564 is_thin_archive, FALSE) != 0)
566 ret = 1;
567 goto out;
570 ret = 0;
572 while (1)
574 char * name;
575 size_t namelen;
576 char * qualified_name;
578 /* Read the next archive header. */
579 if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
581 error (_("%s: failed to seek to next archive header\n"),
582 file_name);
583 return 1;
585 got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
586 if (got != sizeof arch.arhdr)
588 if (got == 0)
589 break;
590 error (_("%s: failed to read archive header\n"),
591 file_name);
592 ret = 1;
593 break;
595 if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
597 error (_("%s: did not find a valid archive header\n"),
598 arch.file_name);
599 ret = 1;
600 break;
603 arch.next_arhdr_offset += sizeof arch.arhdr;
605 archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
606 if (archive_file_size & 01)
607 ++archive_file_size;
609 name = get_archive_member_name (&arch, &nested_arch);
610 if (name == NULL)
612 error (_("%s: bad archive file name\n"), file_name);
613 ret = 1;
614 break;
616 namelen = strlen (name);
618 qualified_name = make_qualified_name (&arch, &nested_arch, name);
619 if (qualified_name == NULL)
621 error (_("%s: bad archive file name\n"), file_name);
622 free (name);
623 ret = 1;
624 break;
627 if (is_thin_archive && arch.nested_member_origin == 0)
629 /* This is a proxy for an external member of a thin archive. */
630 FILE *member_file;
631 char *member_file_name = adjust_relative_path (file_name,
632 name, namelen);
633 free (name);
634 if (member_file_name == NULL)
636 free (qualified_name);
637 ret = 1;
638 break;
641 member_file = fopen (member_file_name, "r+b");
642 if (member_file == NULL)
644 error (_("Input file '%s' is not readable\n"),
645 member_file_name);
646 free (member_file_name);
647 free (qualified_name);
648 ret = 1;
649 break;
652 archive_file_offset = arch.nested_member_origin;
654 ret |= process_object (qualified_name, member_file);
656 fclose (member_file);
657 free (member_file_name);
659 else if (is_thin_archive)
661 free (name);
663 /* This is a proxy for a member of a nested archive. */
664 archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
666 /* The nested archive file will have been opened and setup by
667 get_archive_member_name. */
668 if (fseek (nested_arch.file, archive_file_offset,
669 SEEK_SET) != 0)
671 error (_("%s: failed to seek to archive member\n"),
672 nested_arch.file_name);
673 free (qualified_name);
674 ret = 1;
675 break;
678 ret |= process_object (qualified_name, nested_arch.file);
680 else
682 free (name);
683 archive_file_offset = arch.next_arhdr_offset;
684 arch.next_arhdr_offset += archive_file_size;
686 ret |= process_object (qualified_name, file);
689 free (qualified_name);
692 out:
693 if (nested_arch.file != NULL)
694 fclose (nested_arch.file);
695 release_archive (&nested_arch);
696 release_archive (&arch);
698 return ret;
701 static int
702 check_file (const char *file_name, struct stat *statbuf_p)
704 struct stat statbuf;
706 if (statbuf_p == NULL)
707 statbuf_p = &statbuf;
709 if (stat (file_name, statbuf_p) < 0)
711 if (errno == ENOENT)
712 error (_("'%s': No such file\n"), file_name);
713 else
714 error (_("Could not locate '%s'. System error message: %s\n"),
715 file_name, strerror (errno));
716 return 1;
719 if (! S_ISREG (statbuf_p->st_mode))
721 error (_("'%s' is not an ordinary file\n"), file_name);
722 return 1;
725 return 0;
728 static int
729 process_file (const char *file_name)
731 FILE * file;
732 char armag[SARMAG];
733 int ret;
735 if (check_file (file_name, NULL))
736 return 1;
738 file = fopen (file_name, "r+b");
739 if (file == NULL)
741 error (_("Input file '%s' is not readable\n"), file_name);
742 return 1;
745 if (fread (armag, SARMAG, 1, file) != 1)
747 error (_("%s: Failed to read file's magic number\n"),
748 file_name);
749 fclose (file);
750 return 1;
753 if (memcmp (armag, ARMAG, SARMAG) == 0)
754 ret = process_archive (file_name, file, FALSE);
755 else if (memcmp (armag, ARMAGT, SARMAG) == 0)
756 ret = process_archive (file_name, file, TRUE);
757 else
759 rewind (file);
760 archive_file_size = archive_file_offset = 0;
761 ret = process_object (file_name, file);
762 #ifdef HAVE_MMAP
763 if (!ret
764 && (elf_header.e_type == ET_EXEC
765 || elf_header.e_type == ET_DYN))
766 ret = update_gnu_property (file_name, file);
767 #endif
770 fclose (file);
772 return ret;
775 static const struct
777 int osabi;
778 const char *name;
780 osabis[] =
782 { ELFOSABI_NONE, "none" },
783 { ELFOSABI_HPUX, "HPUX" },
784 { ELFOSABI_NETBSD, "NetBSD" },
785 { ELFOSABI_GNU, "GNU" },
786 { ELFOSABI_GNU, "Linux" },
787 { ELFOSABI_SOLARIS, "Solaris" },
788 { ELFOSABI_AIX, "AIX" },
789 { ELFOSABI_IRIX, "Irix" },
790 { ELFOSABI_FREEBSD, "FreeBSD" },
791 { ELFOSABI_TRU64, "TRU64" },
792 { ELFOSABI_MODESTO, "Modesto" },
793 { ELFOSABI_OPENBSD, "OpenBSD" },
794 { ELFOSABI_OPENVMS, "OpenVMS" },
795 { ELFOSABI_NSK, "NSK" },
796 { ELFOSABI_AROS, "AROS" },
797 { ELFOSABI_FENIXOS, "FenixOS" }
800 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
802 static int
803 elf_osabi (const char *osabi)
805 unsigned int i;
807 for (i = 0; i < ARRAY_SIZE (osabis); i++)
808 if (strcasecmp (osabi, osabis[i].name) == 0)
809 return osabis[i].osabi;
811 error (_("Unknown OSABI: %s\n"), osabi);
813 return -1;
816 /* Return EM_XXX for a machine string, MACH. */
818 static int
819 elf_machine (const char *mach)
821 if (strcasecmp (mach, "i386") == 0)
822 return EM_386;
823 if (strcasecmp (mach, "iamcu") == 0)
824 return EM_IAMCU;
825 if (strcasecmp (mach, "l1om") == 0)
826 return EM_L1OM;
827 if (strcasecmp (mach, "k1om") == 0)
828 return EM_K1OM;
829 if (strcasecmp (mach, "x86_64") == 0)
830 return EM_X86_64;
831 if (strcasecmp (mach, "x86-64") == 0)
832 return EM_X86_64;
833 if (strcasecmp (mach, "none") == 0)
834 return EM_NONE;
836 error (_("Unknown machine type: %s\n"), mach);
838 return -1;
841 /* Return ET_XXX for a type string, TYPE. */
843 static int
844 elf_type (const char *type)
846 if (strcasecmp (type, "rel") == 0)
847 return ET_REL;
848 if (strcasecmp (type, "exec") == 0)
849 return ET_EXEC;
850 if (strcasecmp (type, "dyn") == 0)
851 return ET_DYN;
852 if (strcasecmp (type, "none") == 0)
853 return ET_NONE;
855 error (_("Unknown type: %s\n"), type);
857 return -1;
860 enum command_line_switch
862 OPTION_INPUT_MACH = 150,
863 OPTION_OUTPUT_MACH,
864 OPTION_INPUT_TYPE,
865 OPTION_OUTPUT_TYPE,
866 OPTION_INPUT_OSABI,
867 OPTION_OUTPUT_OSABI,
868 #ifdef HAVE_MMAP
869 OPTION_ENABLE_X86_FEATURE,
870 OPTION_DISABLE_X86_FEATURE,
871 #endif
874 static struct option options[] =
876 {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
877 {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
878 {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
879 {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
880 {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
881 {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
882 #ifdef HAVE_MMAP
883 {"enable-x86-feature",
884 required_argument, 0, OPTION_ENABLE_X86_FEATURE},
885 {"disable-x86-feature",
886 required_argument, 0, OPTION_DISABLE_X86_FEATURE},
887 #endif
888 {"version", no_argument, 0, 'v'},
889 {"help", no_argument, 0, 'h'},
890 {0, no_argument, 0, 0}
893 ATTRIBUTE_NORETURN static void
894 usage (FILE *stream, int exit_status)
896 fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
897 program_name);
898 fprintf (stream, _(" Update the ELF header of ELF files\n"));
899 fprintf (stream, _(" The options are:\n"));
900 fprintf (stream, _("\
901 --input-mach <machine> Set input machine type to <machine>\n\
902 --output-mach <machine> Set output machine type to <machine>\n\
903 --input-type <type> Set input file type to <type>\n\
904 --output-type <type> Set output file type to <type>\n\
905 --input-osabi <osabi> Set input OSABI to <osabi>\n\
906 --output-osabi <osabi> Set output OSABI to <osabi>\n"));
907 #ifdef HAVE_MMAP
908 fprintf (stream, _("\
909 --enable-x86-feature <feature>\n\
910 Enable x86 feature <feature>\n\
911 --disable-x86-feature <feature>\n\
912 Disable x86 feature <feature>\n"));
913 #endif
914 fprintf (stream, _("\
915 -h --help Display this information\n\
916 -v --version Display the version number of %s\n\
918 program_name);
919 if (REPORT_BUGS_TO[0] && exit_status == 0)
920 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
921 exit (exit_status);
925 main (int argc, char ** argv)
927 int c, status;
929 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
930 setlocale (LC_MESSAGES, "");
931 #endif
932 #if defined (HAVE_SETLOCALE)
933 setlocale (LC_CTYPE, "");
934 #endif
935 bindtextdomain (PACKAGE, LOCALEDIR);
936 textdomain (PACKAGE);
938 expandargv (&argc, &argv);
940 while ((c = getopt_long (argc, argv, "hv",
941 options, (int *) 0)) != EOF)
943 switch (c)
945 case OPTION_INPUT_MACH:
946 input_elf_machine = elf_machine (optarg);
947 if (input_elf_machine < 0)
948 return 1;
949 input_elf_class = elf_class (input_elf_machine);
950 if (input_elf_class == ELF_CLASS_UNKNOWN)
951 return 1;
952 break;
954 case OPTION_OUTPUT_MACH:
955 output_elf_machine = elf_machine (optarg);
956 if (output_elf_machine < 0)
957 return 1;
958 output_elf_class = elf_class (output_elf_machine);
959 if (output_elf_class == ELF_CLASS_UNKNOWN)
960 return 1;
961 break;
963 case OPTION_INPUT_TYPE:
964 input_elf_type = elf_type (optarg);
965 if (input_elf_type < 0)
966 return 1;
967 break;
969 case OPTION_OUTPUT_TYPE:
970 output_elf_type = elf_type (optarg);
971 if (output_elf_type < 0)
972 return 1;
973 break;
975 case OPTION_INPUT_OSABI:
976 input_elf_osabi = elf_osabi (optarg);
977 if (input_elf_osabi < 0)
978 return 1;
979 break;
981 case OPTION_OUTPUT_OSABI:
982 output_elf_osabi = elf_osabi (optarg);
983 if (output_elf_osabi < 0)
984 return 1;
985 break;
987 #ifdef HAVE_MMAP
988 case OPTION_ENABLE_X86_FEATURE:
989 if (elf_x86_feature (optarg, 1) < 0)
990 return 1;
991 break;
993 case OPTION_DISABLE_X86_FEATURE:
994 if (elf_x86_feature (optarg, 0) < 0)
995 return 1;
996 break;
997 #endif
999 case 'h':
1000 usage (stdout, 0);
1002 case 'v':
1003 print_version (program_name);
1004 break;
1006 default:
1007 usage (stderr, 1);
1011 if (optind == argc
1012 || (output_elf_machine == -1
1013 #ifdef HAVE_MMAP
1014 && ! enable_x86_features
1015 && ! disable_x86_features
1016 #endif
1017 && output_elf_type == -1
1018 && output_elf_osabi == -1))
1019 usage (stderr, 1);
1021 status = 0;
1022 while (optind < argc)
1023 status |= process_file (argv[optind++]);
1025 return status;