1 /* elfedit.c -- Update the ELF header of an ELF format file
2 Copyright (C) 2010-2024 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
23 #include "libiberty.h"
27 /* Define BFD64 here, even if our default architecture is 32 bit ELF
28 as this will allow us to read in and parse 64bit and 32bit ELF files.
29 Only do this if we believe that the compiler can support a 64 bit
30 data type. For now we only rely on GCC being able to do this. */
38 #include "elf/common.h"
39 #include "elf/external.h"
40 #include "elf/internal.h"
43 #include "libiberty.h"
44 #include "safe-ctype.h"
45 #include "filenames.h"
47 char * program_name
= "elfedit";
48 static long archive_file_offset
;
49 static unsigned long archive_file_size
;
50 static Elf_Internal_Ehdr elf_header
;
51 static Elf32_External_Ehdr ehdr32
;
52 static Elf64_External_Ehdr ehdr64
;
53 static int input_elf_machine
= -1;
54 static int output_elf_machine
= -1;
55 static int input_elf_type
= -1;
56 static int output_elf_type
= -1;
57 static int input_elf_osabi
= -1;
58 static int output_elf_osabi
= -1;
59 static int input_elf_abiversion
= -1;
60 static int output_elf_abiversion
= -1;
63 ELF_CLASS_UNKNOWN
= -1,
64 ELF_CLASS_NONE
= ELFCLASSNONE
,
65 ELF_CLASS_32
= ELFCLASS32
,
66 ELF_CLASS_64
= ELFCLASS64
,
69 static enum elfclass input_elf_class
= ELF_CLASS_UNKNOWN
;
70 static enum elfclass output_elf_class
= ELF_CLASS_BOTH
;
75 static unsigned int enable_x86_features
;
76 static unsigned int disable_x86_features
;
79 update_gnu_property (const char *file_name
, FILE *file
)
82 Elf_Internal_Phdr
*phdrs
;
87 if (!enable_x86_features
&& !disable_x86_features
)
90 if (elf_header
.e_machine
!= EM_386
91 && elf_header
.e_machine
!= EM_X86_64
)
93 error (_("%s: Not an i386 nor x86-64 ELF file\n"), file_name
);
97 if (fstat (fileno (file
), &st_buf
) < 0)
99 error (_("%s: stat () failed\n"), file_name
);
103 map
= mmap (NULL
, st_buf
.st_size
, PROT_READ
| PROT_WRITE
,
104 MAP_SHARED
, fileno (file
), 0);
105 if (map
== MAP_FAILED
)
107 error (_("%s: mmap () failed\n"), file_name
);
111 phdrs
= xmalloc (elf_header
.e_phnum
* sizeof (*phdrs
));
113 if (elf_header
.e_ident
[EI_CLASS
] == ELFCLASS32
)
115 Elf32_External_Phdr
*phdrs32
116 = (Elf32_External_Phdr
*) (map
+ elf_header
.e_phoff
);
117 for (i
= 0; i
< elf_header
.e_phnum
; i
++)
119 phdrs
[i
].p_type
= BYTE_GET (phdrs32
[i
].p_type
);
120 phdrs
[i
].p_offset
= BYTE_GET (phdrs32
[i
].p_offset
);
121 phdrs
[i
].p_vaddr
= BYTE_GET (phdrs32
[i
].p_vaddr
);
122 phdrs
[i
].p_paddr
= BYTE_GET (phdrs32
[i
].p_paddr
);
123 phdrs
[i
].p_filesz
= BYTE_GET (phdrs32
[i
].p_filesz
);
124 phdrs
[i
].p_memsz
= BYTE_GET (phdrs32
[i
].p_memsz
);
125 phdrs
[i
].p_flags
= BYTE_GET (phdrs32
[i
].p_flags
);
126 phdrs
[i
].p_align
= BYTE_GET (phdrs32
[i
].p_align
);
131 Elf64_External_Phdr
*phdrs64
132 = (Elf64_External_Phdr
*) (map
+ elf_header
.e_phoff
);
133 for (i
= 0; i
< elf_header
.e_phnum
; i
++)
135 phdrs
[i
].p_type
= BYTE_GET (phdrs64
[i
].p_type
);
136 phdrs
[i
].p_offset
= BYTE_GET (phdrs64
[i
].p_offset
);
137 phdrs
[i
].p_vaddr
= BYTE_GET (phdrs64
[i
].p_vaddr
);
138 phdrs
[i
].p_paddr
= BYTE_GET (phdrs64
[i
].p_paddr
);
139 phdrs
[i
].p_filesz
= BYTE_GET (phdrs64
[i
].p_filesz
);
140 phdrs
[i
].p_memsz
= BYTE_GET (phdrs64
[i
].p_memsz
);
141 phdrs
[i
].p_flags
= BYTE_GET (phdrs64
[i
].p_flags
);
142 phdrs
[i
].p_align
= BYTE_GET (phdrs64
[i
].p_align
);
147 for (i
= 0; i
< elf_header
.e_phnum
; i
++)
148 if (phdrs
[i
].p_type
== PT_NOTE
)
150 size_t offset
= phdrs
[i
].p_offset
;
151 size_t size
= phdrs
[i
].p_filesz
;
152 size_t align
= phdrs
[i
].p_align
;
153 char *buf
= map
+ offset
;
156 while (p
< buf
+ size
)
158 Elf_External_Note
*xnp
= (Elf_External_Note
*) p
;
159 Elf_Internal_Note in
;
161 if (offsetof (Elf_External_Note
, name
) > buf
- p
+ size
)
167 in
.type
= BYTE_GET (xnp
->type
);
168 in
.namesz
= BYTE_GET (xnp
->namesz
);
169 in
.namedata
= xnp
->name
;
170 if (in
.namesz
> buf
- in
.namedata
+ size
)
176 in
.descsz
= BYTE_GET (xnp
->descsz
);
177 in
.descdata
= p
+ ELF_NOTE_DESC_OFFSET (in
.namesz
, align
);
178 in
.descpos
= offset
+ (in
.descdata
- buf
);
180 && (in
.descdata
>= buf
+ size
181 || in
.descsz
> buf
- in
.descdata
+ size
))
187 if (in
.namesz
== sizeof "GNU"
188 && strcmp (in
.namedata
, "GNU") == 0
189 && in
.type
== NT_GNU_PROPERTY_TYPE_0
)
192 unsigned char *ptr_end
;
194 if (in
.descsz
< 8 || (in
.descsz
% align
) != 0)
200 ptr
= (unsigned char *) in
.descdata
;
201 ptr_end
= ptr
+ in
.descsz
;
205 unsigned int type
= byte_get (ptr
, 4);
206 unsigned int datasz
= byte_get (ptr
+ 4, 4);
207 unsigned int bitmask
, old_bitmask
;
210 if ((ptr
+ datasz
) > ptr_end
)
216 if (type
== GNU_PROPERTY_X86_FEATURE_1_AND
)
224 old_bitmask
= byte_get (ptr
, 4);
225 bitmask
= old_bitmask
;
226 if (enable_x86_features
)
227 bitmask
|= enable_x86_features
;
228 if (disable_x86_features
)
229 bitmask
&= ~disable_x86_features
;
230 if (old_bitmask
!= bitmask
)
231 byte_put (ptr
, bitmask
, 4);
235 ptr
+= ELF_ALIGN_UP (datasz
, align
);
237 while ((ptr_end
- ptr
) >= 8);
240 p
+= ELF_NOTE_NEXT_OFFSET (in
.namesz
, in
.descsz
, align
);
246 error (_("%s: Invalid PT_NOTE segment\n"), file_name
);
249 munmap (map
, st_buf
.st_size
);
254 /* Set enable_x86_features and disable_x86_features for a feature
258 elf_x86_feature (const char *feature
, int enable
)
260 unsigned int x86_feature
;
261 if (strcasecmp (feature
, "ibt") == 0)
262 x86_feature
= GNU_PROPERTY_X86_FEATURE_1_IBT
;
263 else if (strcasecmp (feature
, "shstk") == 0)
264 x86_feature
= GNU_PROPERTY_X86_FEATURE_1_SHSTK
;
265 else if (strcasecmp (feature
, "lam_u48") == 0)
266 x86_feature
= GNU_PROPERTY_X86_FEATURE_1_LAM_U48
;
267 else if (strcasecmp (feature
, "lam_u57") == 0)
268 x86_feature
= GNU_PROPERTY_X86_FEATURE_1_LAM_U57
;
271 error (_("Unknown x86 feature: %s\n"), feature
);
277 enable_x86_features
|= x86_feature
;
278 disable_x86_features
&= ~x86_feature
;
282 disable_x86_features
|= x86_feature
;
283 enable_x86_features
&= ~x86_feature
;
290 /* Return ELF class for a machine type, MACH. */
305 return ELF_CLASS_BOTH
;
307 return ELF_CLASS_BOTH
;
312 update_elf_header (const char *file_name
, FILE *file
)
314 int class, machine
, type
, status
, osabi
, abiversion
;
316 if (elf_header
.e_ident
[EI_VERSION
] != EV_CURRENT
)
319 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
320 file_name
, elf_header
.e_ident
[EI_VERSION
],
325 /* Return if e_machine is the same as output_elf_machine. */
326 if (output_elf_machine
== elf_header
.e_machine
)
329 class = elf_header
.e_ident
[EI_CLASS
];
330 machine
= elf_header
.e_machine
;
332 /* Skip if class doesn't match. */
333 if (input_elf_class
== ELF_CLASS_UNKNOWN
)
334 input_elf_class
= elf_class (machine
);
336 if (input_elf_class
!= ELF_CLASS_BOTH
337 && (int) input_elf_class
!= class)
340 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
341 file_name
, class, input_elf_class
);
345 if (output_elf_class
!= ELF_CLASS_BOTH
346 && (int) output_elf_class
!= class)
349 (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
350 file_name
, class, output_elf_class
);
354 /* Skip if e_machine doesn't match. */
355 if (input_elf_machine
!= -1 && machine
!= input_elf_machine
)
358 (_("%s: Unmatched e_machine: %d is not %d\n"),
359 file_name
, machine
, input_elf_machine
);
363 type
= elf_header
.e_type
;
365 /* Skip if e_type doesn't match. */
366 if (input_elf_type
!= -1 && type
!= input_elf_type
)
369 (_("%s: Unmatched e_type: %d is not %d\n"),
370 file_name
, type
, input_elf_type
);
374 osabi
= elf_header
.e_ident
[EI_OSABI
];
376 /* Skip if OSABI doesn't match. */
377 if (input_elf_osabi
!= -1 && osabi
!= input_elf_osabi
)
380 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
381 file_name
, osabi
, input_elf_osabi
);
385 abiversion
= elf_header
.e_ident
[EI_ABIVERSION
];
387 /* Skip if ABIVERSION doesn't match. */
388 if (input_elf_abiversion
!= -1
389 && abiversion
!= input_elf_abiversion
)
392 (_("%s: Unmatched EI_ABIVERSION: %d is not %d\n"),
393 file_name
, abiversion
, input_elf_abiversion
);
397 /* Update e_machine, e_type and EI_OSABI. */
401 /* We should never get here. */
405 if (output_elf_machine
!= -1)
406 BYTE_PUT (ehdr32
.e_machine
, output_elf_machine
);
407 if (output_elf_type
!= -1)
408 BYTE_PUT (ehdr32
.e_type
, output_elf_type
);
409 if (output_elf_osabi
!= -1)
410 ehdr32
.e_ident
[EI_OSABI
] = output_elf_osabi
;
411 if (output_elf_abiversion
!= -1)
412 ehdr32
.e_ident
[EI_ABIVERSION
] = output_elf_abiversion
;
413 status
= fwrite (&ehdr32
, sizeof (ehdr32
), 1, file
) == 1;
416 if (output_elf_machine
!= -1)
417 BYTE_PUT (ehdr64
.e_machine
, output_elf_machine
);
418 if (output_elf_type
!= -1)
419 BYTE_PUT (ehdr64
.e_type
, output_elf_type
);
420 if (output_elf_osabi
!= -1)
421 ehdr64
.e_ident
[EI_OSABI
] = output_elf_osabi
;
422 if (output_elf_abiversion
!= -1)
423 ehdr64
.e_ident
[EI_ABIVERSION
] = output_elf_abiversion
;
424 status
= fwrite (&ehdr64
, sizeof (ehdr64
), 1, file
) == 1;
429 error (_("%s: Failed to update ELF header: %s\n"),
430 file_name
, strerror (errno
));
436 get_file_header (FILE * file
)
438 /* Read in the identity array. */
439 if (fread (elf_header
.e_ident
, EI_NIDENT
, 1, file
) != 1)
442 if (elf_header
.e_ident
[EI_MAG0
] != ELFMAG0
443 || elf_header
.e_ident
[EI_MAG1
] != ELFMAG1
444 || elf_header
.e_ident
[EI_MAG2
] != ELFMAG2
445 || elf_header
.e_ident
[EI_MAG3
] != ELFMAG3
)
448 /* Determine how to read the rest of the header. */
449 switch (elf_header
.e_ident
[EI_DATA
])
451 default: /* fall through */
452 case ELFDATANONE
: /* fall through */
454 byte_get
= byte_get_little_endian
;
455 byte_put
= byte_put_little_endian
;
458 byte_get
= byte_get_big_endian
;
459 byte_put
= byte_put_big_endian
;
463 /* Read in the rest of the header. For now we only support 32 bit
464 and 64 bit ELF files. */
465 switch (elf_header
.e_ident
[EI_CLASS
])
471 if (fread (ehdr32
.e_type
, sizeof (ehdr32
) - EI_NIDENT
,
475 elf_header
.e_type
= BYTE_GET (ehdr32
.e_type
);
476 elf_header
.e_machine
= BYTE_GET (ehdr32
.e_machine
);
477 elf_header
.e_version
= BYTE_GET (ehdr32
.e_version
);
478 elf_header
.e_entry
= BYTE_GET (ehdr32
.e_entry
);
479 elf_header
.e_phoff
= BYTE_GET (ehdr32
.e_phoff
);
480 elf_header
.e_shoff
= BYTE_GET (ehdr32
.e_shoff
);
481 elf_header
.e_flags
= BYTE_GET (ehdr32
.e_flags
);
482 elf_header
.e_ehsize
= BYTE_GET (ehdr32
.e_ehsize
);
483 elf_header
.e_phentsize
= BYTE_GET (ehdr32
.e_phentsize
);
484 elf_header
.e_phnum
= BYTE_GET (ehdr32
.e_phnum
);
485 elf_header
.e_shentsize
= BYTE_GET (ehdr32
.e_shentsize
);
486 elf_header
.e_shnum
= BYTE_GET (ehdr32
.e_shnum
);
487 elf_header
.e_shstrndx
= BYTE_GET (ehdr32
.e_shstrndx
);
489 memcpy (&ehdr32
, &elf_header
, EI_NIDENT
);
493 /* If we have been compiled with sizeof (bfd_vma) == 4, then
494 we will not be able to cope with the 64bit data found in
495 64 ELF files. Detect this now and abort before we start
496 overwriting things. */
497 if (sizeof (bfd_vma
) < 8)
499 error (_("This executable has been built without support for a\n\
500 64 bit data type and so it cannot process 64 bit ELF files.\n"));
504 if (fread (ehdr64
.e_type
, sizeof (ehdr64
) - EI_NIDENT
,
508 elf_header
.e_type
= BYTE_GET (ehdr64
.e_type
);
509 elf_header
.e_machine
= BYTE_GET (ehdr64
.e_machine
);
510 elf_header
.e_version
= BYTE_GET (ehdr64
.e_version
);
511 elf_header
.e_entry
= BYTE_GET (ehdr64
.e_entry
);
512 elf_header
.e_phoff
= BYTE_GET (ehdr64
.e_phoff
);
513 elf_header
.e_shoff
= BYTE_GET (ehdr64
.e_shoff
);
514 elf_header
.e_flags
= BYTE_GET (ehdr64
.e_flags
);
515 elf_header
.e_ehsize
= BYTE_GET (ehdr64
.e_ehsize
);
516 elf_header
.e_phentsize
= BYTE_GET (ehdr64
.e_phentsize
);
517 elf_header
.e_phnum
= BYTE_GET (ehdr64
.e_phnum
);
518 elf_header
.e_shentsize
= BYTE_GET (ehdr64
.e_shentsize
);
519 elf_header
.e_shnum
= BYTE_GET (ehdr64
.e_shnum
);
520 elf_header
.e_shstrndx
= BYTE_GET (ehdr64
.e_shstrndx
);
522 memcpy (&ehdr64
, &elf_header
, EI_NIDENT
);
528 /* Process one ELF object file according to the command line options.
529 This file may actually be stored in an archive. The file is
530 positioned at the start of the ELF object. */
533 process_object (const char *file_name
, FILE *file
)
535 /* Rememeber where we are. */
536 long offset
= ftell (file
);
538 if (! get_file_header (file
))
540 error (_("%s: Failed to read ELF header\n"), file_name
);
544 /* Go to the position of the ELF header. */
545 if (fseek (file
, offset
, SEEK_SET
) != 0)
547 error (_("%s: Failed to seek to ELF header\n"), file_name
);
550 if (! update_elf_header (file_name
, file
))
556 /* Process an ELF archive.
557 On entry the file is positioned just after the ARMAG string. */
560 process_archive (const char * file_name
, FILE * file
,
561 bool is_thin_archive
)
563 struct archive_info arch
;
564 struct archive_info nested_arch
;
569 /* The ARCH structure is used to hold information about this archive. */
570 arch
.file_name
= NULL
;
572 arch
.index_array
= NULL
;
573 arch
.sym_table
= NULL
;
574 arch
.longnames
= NULL
;
576 /* The NESTED_ARCH structure is used as a single-item cache of information
577 about a nested archive (when members of a thin archive reside within
578 another regular archive file). */
579 nested_arch
.file_name
= NULL
;
580 nested_arch
.file
= NULL
;
581 nested_arch
.index_array
= NULL
;
582 nested_arch
.sym_table
= NULL
;
583 nested_arch
.longnames
= NULL
;
585 if (fstat (fileno (file
), &statbuf
) < 0
586 || setup_archive (&arch
, file_name
, file
, statbuf
.st_size
,
587 is_thin_archive
, false) != 0)
599 char * qualified_name
;
601 /* Read the next archive header. */
602 if (fseek (file
, arch
.next_arhdr_offset
, SEEK_SET
) != 0)
604 error (_("%s: failed to seek to next archive header\n"),
608 got
= fread (&arch
.arhdr
, 1, sizeof arch
.arhdr
, file
);
609 if (got
!= sizeof arch
.arhdr
)
613 error (_("%s: failed to read archive header\n"),
618 if (memcmp (arch
.arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
620 error (_("%s: did not find a valid archive header\n"),
626 arch
.next_arhdr_offset
+= sizeof arch
.arhdr
;
628 archive_file_size
= strtoul (arch
.arhdr
.ar_size
, NULL
, 10);
629 if (archive_file_size
& 01)
632 name
= get_archive_member_name (&arch
, &nested_arch
);
635 error (_("%s: bad archive file name\n"), file_name
);
639 namelen
= strlen (name
);
641 qualified_name
= make_qualified_name (&arch
, &nested_arch
, name
);
642 if (qualified_name
== NULL
)
644 error (_("%s: bad archive file name\n"), file_name
);
650 if (is_thin_archive
&& arch
.nested_member_origin
== 0)
652 /* This is a proxy for an external member of a thin archive. */
654 char *member_file_name
= adjust_relative_path (file_name
,
657 if (member_file_name
== NULL
)
659 free (qualified_name
);
664 member_file
= fopen (member_file_name
, "r+b");
665 if (member_file
== NULL
)
667 error (_("Input file '%s' is not readable\n"),
669 free (member_file_name
);
670 free (qualified_name
);
675 archive_file_offset
= arch
.nested_member_origin
;
677 ret
|= process_object (qualified_name
, member_file
);
679 fclose (member_file
);
680 free (member_file_name
);
682 else if (is_thin_archive
)
686 /* This is a proxy for a member of a nested archive. */
687 archive_file_offset
= arch
.nested_member_origin
+ sizeof arch
.arhdr
;
689 /* The nested archive file will have been opened and setup by
690 get_archive_member_name. */
691 if (fseek (nested_arch
.file
, archive_file_offset
,
694 error (_("%s: failed to seek to archive member\n"),
695 nested_arch
.file_name
);
696 free (qualified_name
);
701 ret
|= process_object (qualified_name
, nested_arch
.file
);
706 archive_file_offset
= arch
.next_arhdr_offset
;
707 arch
.next_arhdr_offset
+= archive_file_size
;
709 ret
|= process_object (qualified_name
, file
);
712 free (qualified_name
);
716 if (nested_arch
.file
!= NULL
)
717 fclose (nested_arch
.file
);
718 release_archive (&nested_arch
);
719 release_archive (&arch
);
725 check_file (const char *file_name
, struct stat
*statbuf_p
)
729 if (statbuf_p
== NULL
)
730 statbuf_p
= &statbuf
;
732 if (stat (file_name
, statbuf_p
) < 0)
735 error (_("'%s': No such file\n"), file_name
);
737 error (_("Could not locate '%s'. System error message: %s\n"),
738 file_name
, strerror (errno
));
742 #if defined (_WIN32) && !defined (__CYGWIN__)
743 else if (statbuf_p
->st_size
== 0)
745 /* MS-Windows 'stat' reports the null device as a regular file;
747 int fd
= open (file_name
, O_RDONLY
| O_BINARY
);
750 statbuf_p
->st_mode
&= ~S_IFREG
;
751 statbuf_p
->st_mode
|= S_IFCHR
;
756 if (! S_ISREG (statbuf_p
->st_mode
))
758 error (_("'%s' is not an ordinary file\n"), file_name
);
766 process_file (const char *file_name
)
772 if (check_file (file_name
, NULL
))
775 file
= fopen (file_name
, "r+b");
778 error (_("Input file '%s' is not readable\n"), file_name
);
782 if (fread (armag
, SARMAG
, 1, file
) != 1)
784 error (_("%s: Failed to read file's magic number\n"),
790 if (memcmp (armag
, ARMAG
, SARMAG
) == 0)
791 ret
= process_archive (file_name
, file
, false);
792 else if (memcmp (armag
, ARMAGT
, SARMAG
) == 0)
793 ret
= process_archive (file_name
, file
, true);
797 archive_file_size
= archive_file_offset
= 0;
798 ret
= process_object (file_name
, file
);
801 && (elf_header
.e_type
== ET_EXEC
802 || elf_header
.e_type
== ET_DYN
))
803 ret
= update_gnu_property (file_name
, file
);
819 { ELFOSABI_NONE
, "none" },
820 { ELFOSABI_HPUX
, "HPUX" },
821 { ELFOSABI_NETBSD
, "NetBSD" },
822 { ELFOSABI_GNU
, "GNU" },
823 { ELFOSABI_GNU
, "Linux" },
824 { ELFOSABI_SOLARIS
, "Solaris" },
825 { ELFOSABI_AIX
, "AIX" },
826 { ELFOSABI_IRIX
, "Irix" },
827 { ELFOSABI_FREEBSD
, "FreeBSD" },
828 { ELFOSABI_TRU64
, "TRU64" },
829 { ELFOSABI_MODESTO
, "Modesto" },
830 { ELFOSABI_OPENBSD
, "OpenBSD" },
831 { ELFOSABI_OPENVMS
, "OpenVMS" },
832 { ELFOSABI_NSK
, "NSK" },
833 { ELFOSABI_AROS
, "AROS" },
834 { ELFOSABI_FENIXOS
, "FenixOS" }
837 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
840 elf_osabi (const char *osabi
)
844 for (i
= 0; i
< ARRAY_SIZE (osabis
); i
++)
845 if (strcasecmp (osabi
, osabis
[i
].name
) == 0)
846 return osabis
[i
].osabi
;
848 error (_("Unknown OSABI: %s\n"), osabi
);
853 /* Return EM_XXX for a machine string, MACH. */
856 elf_machine (const char *mach
)
858 if (strcasecmp (mach
, "i386") == 0)
860 if (strcasecmp (mach
, "iamcu") == 0)
862 if (strcasecmp (mach
, "l1om") == 0)
864 if (strcasecmp (mach
, "k1om") == 0)
866 if (strcasecmp (mach
, "x86_64") == 0)
868 if (strcasecmp (mach
, "x86-64") == 0)
870 if (strcasecmp (mach
, "none") == 0)
873 error (_("Unknown machine type: %s\n"), mach
);
878 /* Return ET_XXX for a type string, TYPE. */
881 elf_type (const char *type
)
883 if (strcasecmp (type
, "rel") == 0)
885 if (strcasecmp (type
, "exec") == 0)
887 if (strcasecmp (type
, "dyn") == 0)
889 if (strcasecmp (type
, "none") == 0)
892 error (_("Unknown type: %s\n"), type
);
897 enum command_line_switch
899 OPTION_INPUT_MACH
= 150,
905 OPTION_INPUT_ABIVERSION
,
906 OPTION_OUTPUT_ABIVERSION
,
908 OPTION_ENABLE_X86_FEATURE
,
909 OPTION_DISABLE_X86_FEATURE
,
913 static struct option options
[] =
915 {"input-mach", required_argument
, 0, OPTION_INPUT_MACH
},
916 {"output-mach", required_argument
, 0, OPTION_OUTPUT_MACH
},
917 {"input-type", required_argument
, 0, OPTION_INPUT_TYPE
},
918 {"output-type", required_argument
, 0, OPTION_OUTPUT_TYPE
},
919 {"input-osabi", required_argument
, 0, OPTION_INPUT_OSABI
},
920 {"output-osabi", required_argument
, 0, OPTION_OUTPUT_OSABI
},
921 {"input-abiversion", required_argument
, 0, OPTION_INPUT_ABIVERSION
},
922 {"output-abiversion", required_argument
, 0, OPTION_OUTPUT_ABIVERSION
},
924 {"enable-x86-feature",
925 required_argument
, 0, OPTION_ENABLE_X86_FEATURE
},
926 {"disable-x86-feature",
927 required_argument
, 0, OPTION_DISABLE_X86_FEATURE
},
929 {"version", no_argument
, 0, 'v'},
930 {"help", no_argument
, 0, 'h'},
931 {0, no_argument
, 0, 0}
934 ATTRIBUTE_NORETURN
static void
935 usage (FILE *stream
, int exit_status
)
938 char *osabi
= concat (osabis
[0].name
, NULL
);
940 for (i
= 1; i
< ARRAY_SIZE (osabis
); i
++)
941 osabi
= reconcat (osabi
, osabi
, "|", osabis
[i
].name
, NULL
);
943 fprintf (stream
, _("Usage: %s <option(s)> elffile(s)\n"),
945 fprintf (stream
, _(" Update the ELF header of ELF files\n"));
946 fprintf (stream
, _(" The options are:\n"));
947 fprintf (stream
, _("\
948 --input-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
949 Set input machine type\n\
950 --output-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
951 Set output machine type\n\
952 --input-type [none|rel|exec|dyn]\n\
953 Set input file type\n\
954 --output-type [none|rel|exec|dyn]\n\
955 Set output file type\n\
956 --input-osabi [%s]\n\
958 --output-osabi [%s]\n\
960 --input-abiversion [0-255] Set input ABIVERSION\n\
961 --output-abiversion [0-255] Set output ABIVERSION\n"),
964 fprintf (stream
, _("\
965 --enable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
966 Enable x86 feature\n\
967 --disable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
968 Disable x86 feature\n"));
970 fprintf (stream
, _("\
971 -h --help Display this information\n\
972 -v --version Display the version number of %s\n\
975 if (REPORT_BUGS_TO
[0] && exit_status
== 0)
976 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);
982 main (int argc
, char ** argv
)
987 #ifdef HAVE_LC_MESSAGES
988 setlocale (LC_MESSAGES
, "");
990 setlocale (LC_CTYPE
, "");
991 bindtextdomain (PACKAGE
, LOCALEDIR
);
992 textdomain (PACKAGE
);
994 expandargv (&argc
, &argv
);
996 while ((c
= getopt_long (argc
, argv
, "hv",
997 options
, (int *) 0)) != EOF
)
1001 case OPTION_INPUT_MACH
:
1002 input_elf_machine
= elf_machine (optarg
);
1003 if (input_elf_machine
< 0)
1005 input_elf_class
= elf_class (input_elf_machine
);
1006 if (input_elf_class
== ELF_CLASS_UNKNOWN
)
1010 case OPTION_OUTPUT_MACH
:
1011 output_elf_machine
= elf_machine (optarg
);
1012 if (output_elf_machine
< 0)
1014 output_elf_class
= elf_class (output_elf_machine
);
1015 if (output_elf_class
== ELF_CLASS_UNKNOWN
)
1019 case OPTION_INPUT_TYPE
:
1020 input_elf_type
= elf_type (optarg
);
1021 if (input_elf_type
< 0)
1025 case OPTION_OUTPUT_TYPE
:
1026 output_elf_type
= elf_type (optarg
);
1027 if (output_elf_type
< 0)
1031 case OPTION_INPUT_OSABI
:
1032 input_elf_osabi
= elf_osabi (optarg
);
1033 if (input_elf_osabi
< 0)
1037 case OPTION_OUTPUT_OSABI
:
1038 output_elf_osabi
= elf_osabi (optarg
);
1039 if (output_elf_osabi
< 0)
1043 case OPTION_INPUT_ABIVERSION
:
1044 input_elf_abiversion
= strtoul (optarg
, &end
, 0);
1046 || input_elf_abiversion
< 0
1047 || input_elf_abiversion
> 255)
1049 error (_("Invalid ABIVERSION: %s\n"), optarg
);
1054 case OPTION_OUTPUT_ABIVERSION
:
1055 output_elf_abiversion
= strtoul (optarg
, &end
, 0);
1057 || output_elf_abiversion
< 0
1058 || output_elf_abiversion
> 255)
1060 error (_("Invalid ABIVERSION: %s\n"), optarg
);
1066 case OPTION_ENABLE_X86_FEATURE
:
1067 if (elf_x86_feature (optarg
, 1) < 0)
1071 case OPTION_DISABLE_X86_FEATURE
:
1072 if (elf_x86_feature (optarg
, 0) < 0)
1081 print_version (program_name
);
1090 || (output_elf_machine
== -1
1092 && ! enable_x86_features
1093 && ! disable_x86_features
1095 && output_elf_type
== -1
1096 && output_elf_osabi
== -1
1097 && output_elf_abiversion
== -1))
1101 while (optind
< argc
)
1102 status
|= process_file (argv
[optind
++]);