1 /* elfedit.c -- Update the ELF header of an ELF format file
2 Copyright (C) 2010-2017 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
25 /* Define BFD64 here, even if our default architecture is 32 bit ELF
26 as this will allow us to read in and parse 64bit and 32bit ELF files.
27 Only do this if we believe that the compiler can support a 64 bit
28 data type. For now we only rely on GCC being able to do this. */
36 #include "elf/common.h"
37 #include "elf/external.h"
38 #include "elf/internal.h"
41 #include "libiberty.h"
42 #include "safe-ctype.h"
43 #include "filenames.h"
45 char * program_name
= "elfedit";
46 static long archive_file_offset
;
47 static unsigned long archive_file_size
;
48 static Elf_Internal_Ehdr elf_header
;
49 static Elf32_External_Ehdr ehdr32
;
50 static Elf64_External_Ehdr ehdr64
;
51 static int input_elf_machine
= -1;
52 static int output_elf_machine
= -1;
53 static int input_elf_type
= -1;
54 static int output_elf_type
= -1;
55 static int input_elf_osabi
= -1;
56 static int output_elf_osabi
= -1;
59 ELF_CLASS_UNKNOWN
= -1,
60 ELF_CLASS_NONE
= ELFCLASSNONE
,
61 ELF_CLASS_32
= ELFCLASS32
,
62 ELF_CLASS_64
= ELFCLASS64
,
65 static enum elfclass input_elf_class
= ELF_CLASS_UNKNOWN
;
66 static enum elfclass output_elf_class
= ELF_CLASS_BOTH
;
68 /* Return ELF class for a machine type, MACH. */
83 return ELF_CLASS_BOTH
;
85 return ELF_CLASS_BOTH
;
90 update_elf_header (const char *file_name
, FILE *file
)
92 int class, machine
, type
, status
, osabi
;
94 if (elf_header
.e_ident
[EI_MAG0
] != ELFMAG0
95 || elf_header
.e_ident
[EI_MAG1
] != ELFMAG1
96 || elf_header
.e_ident
[EI_MAG2
] != ELFMAG2
97 || elf_header
.e_ident
[EI_MAG3
] != ELFMAG3
)
100 (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
105 if (elf_header
.e_ident
[EI_VERSION
] != EV_CURRENT
)
108 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
109 file_name
, elf_header
.e_ident
[EI_VERSION
],
114 /* Return if e_machine is the same as output_elf_machine. */
115 if (output_elf_machine
== elf_header
.e_machine
)
118 class = elf_header
.e_ident
[EI_CLASS
];
119 machine
= elf_header
.e_machine
;
121 /* Skip if class doesn't match. */
122 if (input_elf_class
== ELF_CLASS_UNKNOWN
)
123 input_elf_class
= elf_class (machine
);
125 if (input_elf_class
!= ELF_CLASS_BOTH
126 && (int) input_elf_class
!= class)
129 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
130 file_name
, class, input_elf_class
);
134 if (output_elf_class
!= ELF_CLASS_BOTH
135 && (int) output_elf_class
!= class)
138 (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
139 file_name
, class, output_elf_class
);
143 /* Skip if e_machine doesn't match. */
144 if (input_elf_machine
!= -1 && machine
!= input_elf_machine
)
147 (_("%s: Unmatched e_machine: %d is not %d\n"),
148 file_name
, machine
, input_elf_machine
);
152 type
= elf_header
.e_type
;
154 /* Skip if e_type doesn't match. */
155 if (input_elf_type
!= -1 && type
!= input_elf_type
)
158 (_("%s: Unmatched e_type: %d is not %d\n"),
159 file_name
, type
, input_elf_type
);
163 osabi
= elf_header
.e_ident
[EI_OSABI
];
165 /* Skip if OSABI doesn't match. */
166 if (input_elf_osabi
!= -1 && osabi
!= input_elf_osabi
)
169 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
170 file_name
, osabi
, input_elf_osabi
);
174 /* Update e_machine, e_type and EI_OSABI. */
178 /* We should never get here. */
182 if (output_elf_machine
!= -1)
183 BYTE_PUT (ehdr32
.e_machine
, output_elf_machine
);
184 if (output_elf_type
!= -1)
185 BYTE_PUT (ehdr32
.e_type
, output_elf_type
);
186 if (output_elf_osabi
!= -1)
187 ehdr32
.e_ident
[EI_OSABI
] = output_elf_osabi
;
188 status
= fwrite (&ehdr32
, sizeof (ehdr32
), 1, file
) == 1;
191 if (output_elf_machine
!= -1)
192 BYTE_PUT (ehdr64
.e_machine
, output_elf_machine
);
193 if (output_elf_type
!= -1)
194 BYTE_PUT (ehdr64
.e_type
, output_elf_type
);
195 if (output_elf_osabi
!= -1)
196 ehdr64
.e_ident
[EI_OSABI
] = output_elf_osabi
;
197 status
= fwrite (&ehdr64
, sizeof (ehdr64
), 1, file
) == 1;
202 error (_("%s: Failed to update ELF header: %s\n"),
203 file_name
, strerror (errno
));
209 get_file_header (FILE * file
)
211 /* Read in the identity array. */
212 if (fread (elf_header
.e_ident
, EI_NIDENT
, 1, file
) != 1)
215 /* Determine how to read the rest of the header. */
216 switch (elf_header
.e_ident
[EI_DATA
])
218 default: /* fall through */
219 case ELFDATANONE
: /* fall through */
221 byte_get
= byte_get_little_endian
;
222 byte_put
= byte_put_little_endian
;
225 byte_get
= byte_get_big_endian
;
226 byte_put
= byte_put_big_endian
;
230 /* Read in the rest of the header. For now we only support 32 bit
231 and 64 bit ELF files. */
232 switch (elf_header
.e_ident
[EI_CLASS
])
235 error (_("Unsupported EI_CLASS: %d\n"),
236 elf_header
.e_ident
[EI_CLASS
]);
240 if (fread (ehdr32
.e_type
, sizeof (ehdr32
) - EI_NIDENT
,
244 elf_header
.e_type
= BYTE_GET (ehdr32
.e_type
);
245 elf_header
.e_machine
= BYTE_GET (ehdr32
.e_machine
);
246 elf_header
.e_version
= BYTE_GET (ehdr32
.e_version
);
247 elf_header
.e_entry
= BYTE_GET (ehdr32
.e_entry
);
248 elf_header
.e_phoff
= BYTE_GET (ehdr32
.e_phoff
);
249 elf_header
.e_shoff
= BYTE_GET (ehdr32
.e_shoff
);
250 elf_header
.e_flags
= BYTE_GET (ehdr32
.e_flags
);
251 elf_header
.e_ehsize
= BYTE_GET (ehdr32
.e_ehsize
);
252 elf_header
.e_phentsize
= BYTE_GET (ehdr32
.e_phentsize
);
253 elf_header
.e_phnum
= BYTE_GET (ehdr32
.e_phnum
);
254 elf_header
.e_shentsize
= BYTE_GET (ehdr32
.e_shentsize
);
255 elf_header
.e_shnum
= BYTE_GET (ehdr32
.e_shnum
);
256 elf_header
.e_shstrndx
= BYTE_GET (ehdr32
.e_shstrndx
);
258 memcpy (&ehdr32
, &elf_header
, EI_NIDENT
);
262 /* If we have been compiled with sizeof (bfd_vma) == 4, then
263 we will not be able to cope with the 64bit data found in
264 64 ELF files. Detect this now and abort before we start
265 overwriting things. */
266 if (sizeof (bfd_vma
) < 8)
268 error (_("This executable has been built without support for a\n\
269 64 bit data type and so it cannot process 64 bit ELF files.\n"));
273 if (fread (ehdr64
.e_type
, sizeof (ehdr64
) - EI_NIDENT
,
277 elf_header
.e_type
= BYTE_GET (ehdr64
.e_type
);
278 elf_header
.e_machine
= BYTE_GET (ehdr64
.e_machine
);
279 elf_header
.e_version
= BYTE_GET (ehdr64
.e_version
);
280 elf_header
.e_entry
= BYTE_GET (ehdr64
.e_entry
);
281 elf_header
.e_phoff
= BYTE_GET (ehdr64
.e_phoff
);
282 elf_header
.e_shoff
= BYTE_GET (ehdr64
.e_shoff
);
283 elf_header
.e_flags
= BYTE_GET (ehdr64
.e_flags
);
284 elf_header
.e_ehsize
= BYTE_GET (ehdr64
.e_ehsize
);
285 elf_header
.e_phentsize
= BYTE_GET (ehdr64
.e_phentsize
);
286 elf_header
.e_phnum
= BYTE_GET (ehdr64
.e_phnum
);
287 elf_header
.e_shentsize
= BYTE_GET (ehdr64
.e_shentsize
);
288 elf_header
.e_shnum
= BYTE_GET (ehdr64
.e_shnum
);
289 elf_header
.e_shstrndx
= BYTE_GET (ehdr64
.e_shstrndx
);
291 memcpy (&ehdr64
, &elf_header
, EI_NIDENT
);
297 /* Process one ELF object file according to the command line options.
298 This file may actually be stored in an archive. The file is
299 positioned at the start of the ELF object. */
302 process_object (const char *file_name
, FILE *file
)
304 /* Rememeber where we are. */
305 long offset
= ftell (file
);
307 if (! get_file_header (file
))
309 error (_("%s: Failed to read ELF header\n"), file_name
);
313 /* Go to the position of the ELF header. */
314 if (fseek (file
, offset
, SEEK_SET
) != 0)
316 error (_("%s: Failed to seek to ELF header\n"), file_name
);
319 if (! update_elf_header (file_name
, file
))
325 /* Process an ELF archive.
326 On entry the file is positioned just after the ARMAG string. */
329 process_archive (const char * file_name
, FILE * file
,
330 bfd_boolean is_thin_archive
)
332 struct archive_info arch
;
333 struct archive_info nested_arch
;
337 /* The ARCH structure is used to hold information about this archive. */
338 arch
.file_name
= NULL
;
340 arch
.index_array
= NULL
;
341 arch
.sym_table
= NULL
;
342 arch
.longnames
= NULL
;
344 /* The NESTED_ARCH structure is used as a single-item cache of information
345 about a nested archive (when members of a thin archive reside within
346 another regular archive file). */
347 nested_arch
.file_name
= NULL
;
348 nested_arch
.file
= NULL
;
349 nested_arch
.index_array
= NULL
;
350 nested_arch
.sym_table
= NULL
;
351 nested_arch
.longnames
= NULL
;
353 if (setup_archive (&arch
, file_name
, file
, is_thin_archive
, FALSE
) != 0)
365 char * qualified_name
;
367 /* Read the next archive header. */
368 if (fseek (file
, arch
.next_arhdr_offset
, SEEK_SET
) != 0)
370 error (_("%s: failed to seek to next archive header\n"),
374 got
= fread (&arch
.arhdr
, 1, sizeof arch
.arhdr
, file
);
375 if (got
!= sizeof arch
.arhdr
)
379 error (_("%s: failed to read archive header\n"),
384 if (memcmp (arch
.arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
386 error (_("%s: did not find a valid archive header\n"),
392 arch
.next_arhdr_offset
+= sizeof arch
.arhdr
;
394 archive_file_size
= strtoul (arch
.arhdr
.ar_size
, NULL
, 10);
395 if (archive_file_size
& 01)
398 name
= get_archive_member_name (&arch
, &nested_arch
);
401 error (_("%s: bad archive file name\n"), file_name
);
405 namelen
= strlen (name
);
407 qualified_name
= make_qualified_name (&arch
, &nested_arch
, name
);
408 if (qualified_name
== NULL
)
410 error (_("%s: bad archive file name\n"), file_name
);
415 if (is_thin_archive
&& arch
.nested_member_origin
== 0)
417 /* This is a proxy for an external member of a thin archive. */
419 char *member_file_name
= adjust_relative_path (file_name
,
421 if (member_file_name
== NULL
)
427 member_file
= fopen (member_file_name
, "r+b");
428 if (member_file
== NULL
)
430 error (_("Input file '%s' is not readable\n"),
432 free (member_file_name
);
437 archive_file_offset
= arch
.nested_member_origin
;
439 ret
|= process_object (qualified_name
, member_file
);
441 fclose (member_file
);
442 free (member_file_name
);
444 else if (is_thin_archive
)
446 /* This is a proxy for a member of a nested archive. */
447 archive_file_offset
= arch
.nested_member_origin
+ sizeof arch
.arhdr
;
449 /* The nested archive file will have been opened and setup by
450 get_archive_member_name. */
451 if (fseek (nested_arch
.file
, archive_file_offset
,
454 error (_("%s: failed to seek to archive member\n"),
455 nested_arch
.file_name
);
460 ret
|= process_object (qualified_name
, nested_arch
.file
);
464 archive_file_offset
= arch
.next_arhdr_offset
;
465 arch
.next_arhdr_offset
+= archive_file_size
;
467 ret
|= process_object (qualified_name
, file
);
470 free (qualified_name
);
474 if (nested_arch
.file
!= NULL
)
475 fclose (nested_arch
.file
);
476 release_archive (&nested_arch
);
477 release_archive (&arch
);
483 check_file (const char *file_name
, struct stat
*statbuf_p
)
487 if (statbuf_p
== NULL
)
488 statbuf_p
= &statbuf
;
490 if (stat (file_name
, statbuf_p
) < 0)
493 error (_("'%s': No such file\n"), file_name
);
495 error (_("Could not locate '%s'. System error message: %s\n"),
496 file_name
, strerror (errno
));
500 if (! S_ISREG (statbuf_p
->st_mode
))
502 error (_("'%s' is not an ordinary file\n"), file_name
);
510 process_file (const char *file_name
)
516 if (check_file (file_name
, NULL
))
519 file
= fopen (file_name
, "r+b");
522 error (_("Input file '%s' is not readable\n"), file_name
);
526 if (fread (armag
, SARMAG
, 1, file
) != 1)
528 error (_("%s: Failed to read file's magic number\n"),
534 if (memcmp (armag
, ARMAG
, SARMAG
) == 0)
535 ret
= process_archive (file_name
, file
, FALSE
);
536 else if (memcmp (armag
, ARMAGT
, SARMAG
) == 0)
537 ret
= process_archive (file_name
, file
, TRUE
);
541 archive_file_size
= archive_file_offset
= 0;
542 ret
= process_object (file_name
, file
);
557 { ELFOSABI_NONE
, "none" },
558 { ELFOSABI_HPUX
, "HPUX" },
559 { ELFOSABI_NETBSD
, "NetBSD" },
560 { ELFOSABI_GNU
, "GNU" },
561 { ELFOSABI_GNU
, "Linux" },
562 { ELFOSABI_SOLARIS
, "Solaris" },
563 { ELFOSABI_AIX
, "AIX" },
564 { ELFOSABI_IRIX
, "Irix" },
565 { ELFOSABI_FREEBSD
, "FreeBSD" },
566 { ELFOSABI_TRU64
, "TRU64" },
567 { ELFOSABI_MODESTO
, "Modesto" },
568 { ELFOSABI_OPENBSD
, "OpenBSD" },
569 { ELFOSABI_OPENVMS
, "OpenVMS" },
570 { ELFOSABI_NSK
, "NSK" },
571 { ELFOSABI_AROS
, "AROS" },
572 { ELFOSABI_FENIXOS
, "FenixOS" }
575 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
578 elf_osabi (const char *osabi
)
582 for (i
= 0; i
< ARRAY_SIZE (osabis
); i
++)
583 if (strcasecmp (osabi
, osabis
[i
].name
) == 0)
584 return osabis
[i
].osabi
;
586 error (_("Unknown OSABI: %s\n"), osabi
);
591 /* Return EM_XXX for a machine string, MACH. */
594 elf_machine (const char *mach
)
596 if (strcasecmp (mach
, "i386") == 0)
598 if (strcasecmp (mach
, "iamcu") == 0)
600 if (strcasecmp (mach
, "l1om") == 0)
602 if (strcasecmp (mach
, "k1om") == 0)
604 if (strcasecmp (mach
, "x86_64") == 0)
606 if (strcasecmp (mach
, "x86-64") == 0)
608 if (strcasecmp (mach
, "none") == 0)
611 error (_("Unknown machine type: %s\n"), mach
);
616 /* Return ET_XXX for a type string, TYPE. */
619 elf_type (const char *type
)
621 if (strcasecmp (type
, "rel") == 0)
623 if (strcasecmp (type
, "exec") == 0)
625 if (strcasecmp (type
, "dyn") == 0)
627 if (strcasecmp (type
, "none") == 0)
630 error (_("Unknown type: %s\n"), type
);
635 enum command_line_switch
637 OPTION_INPUT_MACH
= 150,
645 static struct option options
[] =
647 {"input-mach", required_argument
, 0, OPTION_INPUT_MACH
},
648 {"output-mach", required_argument
, 0, OPTION_OUTPUT_MACH
},
649 {"input-type", required_argument
, 0, OPTION_INPUT_TYPE
},
650 {"output-type", required_argument
, 0, OPTION_OUTPUT_TYPE
},
651 {"input-osabi", required_argument
, 0, OPTION_INPUT_OSABI
},
652 {"output-osabi", required_argument
, 0, OPTION_OUTPUT_OSABI
},
653 {"version", no_argument
, 0, 'v'},
654 {"help", no_argument
, 0, 'h'},
655 {0, no_argument
, 0, 0}
658 ATTRIBUTE_NORETURN
static void
659 usage (FILE *stream
, int exit_status
)
661 fprintf (stream
, _("Usage: %s <option(s)> elffile(s)\n"),
663 fprintf (stream
, _(" Update the ELF header of ELF files\n"));
664 fprintf (stream
, _(" The options are:\n"));
665 fprintf (stream
, _("\
666 --input-mach <machine> Set input machine type to <machine>\n\
667 --output-mach <machine> Set output machine type to <machine>\n\
668 --input-type <type> Set input file type to <type>\n\
669 --output-type <type> Set output file type to <type>\n\
670 --input-osabi <osabi> Set input OSABI to <osabi>\n\
671 --output-osabi <osabi> Set output OSABI to <osabi>\n\
672 -h --help Display this information\n\
673 -v --version Display the version number of %s\n\
676 if (REPORT_BUGS_TO
[0] && exit_status
== 0)
677 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);
682 main (int argc
, char ** argv
)
686 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
687 setlocale (LC_MESSAGES
, "");
689 #if defined (HAVE_SETLOCALE)
690 setlocale (LC_CTYPE
, "");
692 bindtextdomain (PACKAGE
, LOCALEDIR
);
693 textdomain (PACKAGE
);
695 expandargv (&argc
, &argv
);
697 while ((c
= getopt_long (argc
, argv
, "hv",
698 options
, (int *) 0)) != EOF
)
702 case OPTION_INPUT_MACH
:
703 input_elf_machine
= elf_machine (optarg
);
704 if (input_elf_machine
< 0)
706 input_elf_class
= elf_class (input_elf_machine
);
707 if (input_elf_class
== ELF_CLASS_UNKNOWN
)
711 case OPTION_OUTPUT_MACH
:
712 output_elf_machine
= elf_machine (optarg
);
713 if (output_elf_machine
< 0)
715 output_elf_class
= elf_class (output_elf_machine
);
716 if (output_elf_class
== ELF_CLASS_UNKNOWN
)
720 case OPTION_INPUT_TYPE
:
721 input_elf_type
= elf_type (optarg
);
722 if (input_elf_type
< 0)
726 case OPTION_OUTPUT_TYPE
:
727 output_elf_type
= elf_type (optarg
);
728 if (output_elf_type
< 0)
732 case OPTION_INPUT_OSABI
:
733 input_elf_osabi
= elf_osabi (optarg
);
734 if (input_elf_osabi
< 0)
738 case OPTION_OUTPUT_OSABI
:
739 output_elf_osabi
= elf_osabi (optarg
);
740 if (output_elf_osabi
< 0)
748 print_version (program_name
);
757 || (output_elf_machine
== -1
758 && output_elf_type
== -1
759 && output_elf_osabi
== -1))
763 while (optind
< argc
)
764 status
|= process_file (argv
[optind
++]);