2011-04-01 Tristan Gingold <gingold@adacore.com>
[binutils.git] / binutils / elfedit.c
blob1805ec1b5e91c4a78c4e79ca2cc7d6079ac2bd2a
1 /* elfedit.c -- Update the ELF header of an ELF format file
2 Copyright 2010
3 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 #include "config.h"
23 #include "sysdep.h"
24 #include <assert.h>
25 #include <sys/stat.h>
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
35 #include "bfd.h"
36 #include "elfcomm.h"
37 #include "bucomm.h"
39 #include "elf/common.h"
40 #include "elf/external.h"
41 #include "elf/internal.h"
43 #include "getopt.h"
44 #include "libiberty.h"
45 #include "safe-ctype.h"
46 #include "filenames.h"
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_class = -1;
62 static int
63 update_elf_header (const char *file_name, FILE *file)
65 int class, machine, type, status, osabi;
67 if (elf_header.e_ident[EI_MAG0] != ELFMAG0
68 || elf_header.e_ident[EI_MAG1] != ELFMAG1
69 || elf_header.e_ident[EI_MAG2] != ELFMAG2
70 || elf_header.e_ident[EI_MAG3] != ELFMAG3)
72 error
73 (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
74 file_name);
75 return 0;
78 if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
80 error
81 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
82 file_name, elf_header.e_ident[EI_VERSION],
83 EV_CURRENT);
84 return 0;
87 /* Return if e_machine is the same as output_elf_machine. */
88 if (output_elf_machine == elf_header.e_machine)
89 return 1;
91 class = elf_header.e_ident[EI_CLASS];
93 /* Skip if class doesn't match. */
94 if (input_elf_class != -1 && class != input_elf_class)
96 error
97 (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
98 file_name, class, input_elf_class);
99 return 0;
102 machine = elf_header.e_machine;
104 /* Skip if e_machine doesn't match. */
105 if (input_elf_machine != -1 && machine != input_elf_machine)
107 error
108 (_("%s: Unmatched e_machine: %d is not %d\n"),
109 file_name, machine, input_elf_machine);
110 return 0;
113 type = elf_header.e_type;
115 /* Skip if e_type doesn't match. */
116 if (input_elf_type != -1 && type != input_elf_type)
118 error
119 (_("%s: Unmatched e_type: %d is not %d\n"),
120 file_name, type, input_elf_type);
121 return 0;
124 osabi = elf_header.e_ident[EI_OSABI];
126 /* Skip if OSABI doesn't match. */
127 if (input_elf_osabi != -1 && osabi != input_elf_osabi)
129 error
130 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
131 file_name, osabi, input_elf_osabi);
132 return 0;
135 /* Update e_machine, e_type and EI_OSABI. */
136 switch (class)
138 default:
139 /* We should never get here. */
140 abort ();
141 break;
142 case ELFCLASS32:
143 if (output_elf_machine != -1)
144 BYTE_PUT (ehdr32.e_machine, output_elf_machine);
145 if (output_elf_type != -1)
146 BYTE_PUT (ehdr32.e_type, output_elf_type);
147 if (output_elf_osabi != -1)
148 ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
149 status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
150 break;
151 case ELFCLASS64:
152 if (output_elf_machine != -1)
153 BYTE_PUT (ehdr64.e_machine, output_elf_machine);
154 if (output_elf_type != -1)
155 BYTE_PUT (ehdr64.e_type, output_elf_type);
156 if (output_elf_osabi != -1)
157 ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
158 status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
159 break;
162 if (status != 1)
163 error (_("%s: Failed to update ELF header: %s\n"),
164 file_name, strerror (errno));
166 return status;
169 static int
170 get_file_header (FILE * file)
172 /* Read in the identity array. */
173 if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
174 return 0;
176 /* Determine how to read the rest of the header. */
177 switch (elf_header.e_ident[EI_DATA])
179 default: /* fall through */
180 case ELFDATANONE: /* fall through */
181 case ELFDATA2LSB:
182 byte_get = byte_get_little_endian;
183 byte_put = byte_put_little_endian;
184 break;
185 case ELFDATA2MSB:
186 byte_get = byte_get_big_endian;
187 byte_put = byte_put_big_endian;
188 break;
191 /* Read in the rest of the header. For now we only support 32 bit
192 and 64 bit ELF files. */
193 switch (elf_header.e_ident[EI_CLASS])
195 default:
196 error (_("Unsupported EI_CLASS: %d\n"),
197 elf_header.e_ident[EI_CLASS]);
198 return 0;
200 case ELFCLASS32:
201 if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
202 1, file) != 1)
203 return 0;
205 elf_header.e_type = BYTE_GET (ehdr32.e_type);
206 elf_header.e_machine = BYTE_GET (ehdr32.e_machine);
207 elf_header.e_version = BYTE_GET (ehdr32.e_version);
208 elf_header.e_entry = BYTE_GET (ehdr32.e_entry);
209 elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff);
210 elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff);
211 elf_header.e_flags = BYTE_GET (ehdr32.e_flags);
212 elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize);
213 elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
214 elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum);
215 elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
216 elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum);
217 elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx);
219 memcpy (&ehdr32, &elf_header, EI_NIDENT);
220 break;
222 case ELFCLASS64:
223 /* If we have been compiled with sizeof (bfd_vma) == 4, then
224 we will not be able to cope with the 64bit data found in
225 64 ELF files. Detect this now and abort before we start
226 overwriting things. */
227 if (sizeof (bfd_vma) < 8)
229 error (_("This executable has been built without support for a\n\
230 64 bit data type and so it cannot process 64 bit ELF files.\n"));
231 return 0;
234 if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
235 1, file) != 1)
236 return 0;
238 elf_header.e_type = BYTE_GET (ehdr64.e_type);
239 elf_header.e_machine = BYTE_GET (ehdr64.e_machine);
240 elf_header.e_version = BYTE_GET (ehdr64.e_version);
241 elf_header.e_entry = BYTE_GET (ehdr64.e_entry);
242 elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff);
243 elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff);
244 elf_header.e_flags = BYTE_GET (ehdr64.e_flags);
245 elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize);
246 elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
247 elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum);
248 elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
249 elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum);
250 elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx);
252 memcpy (&ehdr64, &elf_header, EI_NIDENT);
253 break;
255 return 1;
258 /* Process one ELF object file according to the command line options.
259 This file may actually be stored in an archive. The file is
260 positioned at the start of the ELF object. */
262 static int
263 process_object (const char *file_name, FILE *file)
265 /* Rememeber where we are. */
266 long offset = ftell (file);
268 if (! get_file_header (file))
270 error (_("%s: Failed to read ELF header\n"), file_name);
271 return 1;
274 /* Go to the position of the ELF header. */
275 if (fseek (file, offset, SEEK_SET) != 0)
277 error (_("%s: Failed to seek to ELF header\n"), file_name);
280 if (! update_elf_header (file_name, file))
281 return 1;
283 return 0;
286 /* Process an ELF archive.
287 On entry the file is positioned just after the ARMAG string. */
289 static int
290 process_archive (const char * file_name, FILE * file,
291 bfd_boolean is_thin_archive)
293 struct archive_info arch;
294 struct archive_info nested_arch;
295 size_t got;
296 int ret;
298 /* The ARCH structure is used to hold information about this archive. */
299 arch.file_name = NULL;
300 arch.file = NULL;
301 arch.index_array = NULL;
302 arch.sym_table = NULL;
303 arch.longnames = NULL;
305 /* The NESTED_ARCH structure is used as a single-item cache of information
306 about a nested archive (when members of a thin archive reside within
307 another regular archive file). */
308 nested_arch.file_name = NULL;
309 nested_arch.file = NULL;
310 nested_arch.index_array = NULL;
311 nested_arch.sym_table = NULL;
312 nested_arch.longnames = NULL;
314 if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
316 ret = 1;
317 goto out;
320 ret = 0;
322 while (1)
324 char * name;
325 size_t namelen;
326 char * qualified_name;
328 /* Read the next archive header. */
329 if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
331 error (_("%s: failed to seek to next archive header\n"),
332 file_name);
333 return 1;
335 got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
336 if (got != sizeof arch.arhdr)
338 if (got == 0)
339 break;
340 error (_("%s: failed to read archive header\n"),
341 file_name);
342 ret = 1;
343 break;
345 if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
347 error (_("%s: did not find a valid archive header\n"),
348 arch.file_name);
349 ret = 1;
350 break;
353 arch.next_arhdr_offset += sizeof arch.arhdr;
355 archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
356 if (archive_file_size & 01)
357 ++archive_file_size;
359 name = get_archive_member_name (&arch, &nested_arch);
360 if (name == NULL)
362 error (_("%s: bad archive file name\n"), file_name);
363 ret = 1;
364 break;
366 namelen = strlen (name);
368 qualified_name = make_qualified_name (&arch, &nested_arch, name);
369 if (qualified_name == NULL)
371 error (_("%s: bad archive file name\n"), file_name);
372 ret = 1;
373 break;
376 if (is_thin_archive && arch.nested_member_origin == 0)
378 /* This is a proxy for an external member of a thin archive. */
379 FILE *member_file;
380 char *member_file_name = adjust_relative_path (file_name,
381 name, namelen);
382 if (member_file_name == NULL)
384 ret = 1;
385 break;
388 member_file = fopen (member_file_name, "r+b");
389 if (member_file == NULL)
391 error (_("Input file '%s' is not readable\n"),
392 member_file_name);
393 free (member_file_name);
394 ret = 1;
395 break;
398 archive_file_offset = arch.nested_member_origin;
400 ret |= process_object (qualified_name, member_file);
402 fclose (member_file);
403 free (member_file_name);
405 else if (is_thin_archive)
407 /* This is a proxy for a member of a nested archive. */
408 archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
410 /* The nested archive file will have been opened and setup by
411 get_archive_member_name. */
412 if (fseek (nested_arch.file, archive_file_offset,
413 SEEK_SET) != 0)
415 error (_("%s: failed to seek to archive member\n"),
416 nested_arch.file_name);
417 ret = 1;
418 break;
421 ret |= process_object (qualified_name, nested_arch.file);
423 else
425 archive_file_offset = arch.next_arhdr_offset;
426 arch.next_arhdr_offset += archive_file_size;
428 ret |= process_object (qualified_name, file);
431 free (qualified_name);
434 out:
435 if (nested_arch.file != NULL)
436 fclose (nested_arch.file);
437 release_archive (&nested_arch);
438 release_archive (&arch);
440 return ret;
443 static int
444 check_file (const char *file_name, struct stat *statbuf_p)
446 struct stat statbuf;
448 if (statbuf_p == NULL)
449 statbuf_p = &statbuf;
451 if (stat (file_name, statbuf_p) < 0)
453 if (errno == ENOENT)
454 error (_("'%s': No such file\n"), file_name);
455 else
456 error (_("Could not locate '%s'. System error message: %s\n"),
457 file_name, strerror (errno));
458 return 1;
461 if (! S_ISREG (statbuf_p->st_mode))
463 error (_("'%s' is not an ordinary file\n"), file_name);
464 return 1;
467 return 0;
470 static int
471 process_file (const char *file_name)
473 FILE * file;
474 char armag[SARMAG];
475 int ret;
477 if (check_file (file_name, NULL))
478 return 1;
480 file = fopen (file_name, "r+b");
481 if (file == NULL)
483 error (_("Input file '%s' is not readable\n"), file_name);
484 return 1;
487 if (fread (armag, SARMAG, 1, file) != 1)
489 error (_("%s: Failed to read file's magic number\n"),
490 file_name);
491 fclose (file);
492 return 1;
495 if (memcmp (armag, ARMAG, SARMAG) == 0)
496 ret = process_archive (file_name, file, FALSE);
497 else if (memcmp (armag, ARMAGT, SARMAG) == 0)
498 ret = process_archive (file_name, file, TRUE);
499 else
501 rewind (file);
502 archive_file_size = archive_file_offset = 0;
503 ret = process_object (file_name, file);
506 fclose (file);
508 return ret;
511 static const struct
513 int osabi;
514 const char *name;
516 osabis[] =
518 { ELFOSABI_NONE, "none" },
519 { ELFOSABI_HPUX, "HPUX" },
520 { ELFOSABI_NETBSD, "NetBSD" },
521 { ELFOSABI_LINUX, "Linux" },
522 { ELFOSABI_HURD, "Hurd" },
523 { ELFOSABI_SOLARIS, "Solaris" },
524 { ELFOSABI_AIX, "AIX" },
525 { ELFOSABI_IRIX, "Irix" },
526 { ELFOSABI_FREEBSD, "FreeBSD" },
527 { ELFOSABI_TRU64, "TRU64" },
528 { ELFOSABI_MODESTO, "Modesto" },
529 { ELFOSABI_OPENBSD, "OpenBSD" },
530 { ELFOSABI_OPENVMS, "OpenVMS" },
531 { ELFOSABI_NSK, "NSK" },
532 { ELFOSABI_AROS, "AROS" },
533 { ELFOSABI_FENIXOS, "FenixOS" }
536 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
538 static int
539 elf_osabi (const char *osabi)
541 unsigned int i;
543 for (i = 0; i < ARRAY_SIZE (osabis); i++)
544 if (strcasecmp (osabi, osabis[i].name) == 0)
545 return osabis[i].osabi;
547 error (_("Unknown OSABI: %s\n"), osabi);
549 return -1;
552 /* Return EM_XXX for a machine string, MACH. */
554 static int
555 elf_machine (const char *mach)
557 if (strcasecmp (mach, "l1om") == 0)
558 return EM_L1OM;
559 if (strcasecmp (mach, "x86_64") == 0)
560 return EM_X86_64;
561 if (strcasecmp (mach, "x86-64") == 0)
562 return EM_X86_64;
563 if (strcasecmp (mach, "none") == 0)
564 return EM_NONE;
566 error (_("Unknown machine type: %s\n"), mach);
568 return -1;
571 /* Return ELF class for a machine type, MACH. */
573 static int
574 elf_class (int mach)
576 switch (mach)
578 case EM_L1OM:
579 case EM_X86_64:
580 return ELFCLASS64;
581 case EM_NONE:
582 return ELFCLASSNONE;
583 default:
584 error (_("Unknown machine type: %d\n"), mach);
585 return -1;
589 /* Return ET_XXX for a type string, TYPE. */
591 static int
592 elf_type (const char *type)
594 if (strcasecmp (type, "rel") == 0)
595 return ET_REL;
596 if (strcasecmp (type, "exec") == 0)
597 return ET_EXEC;
598 if (strcasecmp (type, "dyn") == 0)
599 return ET_DYN;
600 if (strcasecmp (type, "none") == 0)
601 return ET_NONE;
603 error (_("Unknown type: %s\n"), type);
605 return -1;
608 enum command_line_switch
610 OPTION_INPUT_MACH = 150,
611 OPTION_OUTPUT_MACH,
612 OPTION_INPUT_TYPE,
613 OPTION_OUTPUT_TYPE,
614 OPTION_INPUT_OSABI,
615 OPTION_OUTPUT_OSABI
618 static struct option options[] =
620 {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
621 {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
622 {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
623 {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
624 {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
625 {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
626 {"version", no_argument, 0, 'v'},
627 {"help", no_argument, 0, 'h'},
628 {0, no_argument, 0, 0}
631 static void
632 usage (FILE *stream, int exit_status)
634 fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
635 program_name);
636 fprintf (stream, _(" Update the ELF header of ELF files\n"));
637 fprintf (stream, _(" The options are:\n"));
638 fprintf (stream, _("\
639 --input-mach <machine> Set input machine type to <machine>\n\
640 --output-mach <machine> Set output machine type to <machine>\n\
641 --input-type <type> Set input file type to <type>\n\
642 --output-type <type> Set output file type to <type>\n\
643 --input-osabi <osabi> Set input OSABI to <osabi>\n\
644 --output-osabi <osabi> Set output OSABI to <osabi>\n\
645 -h --help Display this information\n\
646 -v --version Display the version number of %s\n\
648 program_name);
649 if (REPORT_BUGS_TO[0] && exit_status == 0)
650 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
651 exit (exit_status);
655 main (int argc, char ** argv)
657 int c, status;
659 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
660 setlocale (LC_MESSAGES, "");
661 #endif
662 #if defined (HAVE_SETLOCALE)
663 setlocale (LC_CTYPE, "");
664 #endif
665 bindtextdomain (PACKAGE, LOCALEDIR);
666 textdomain (PACKAGE);
668 expandargv (&argc, &argv);
670 while ((c = getopt_long (argc, argv, "hv",
671 options, (int *) 0)) != EOF)
673 switch (c)
675 case OPTION_INPUT_MACH:
676 input_elf_machine = elf_machine (optarg);
677 if (input_elf_machine < 0)
678 return 1;
679 input_elf_class = elf_class (input_elf_machine);
680 if (input_elf_class < 0)
681 return 1;
682 break;
684 case OPTION_OUTPUT_MACH:
685 output_elf_machine = elf_machine (optarg);
686 if (output_elf_machine < 0)
687 return 1;
688 break;
690 case OPTION_INPUT_TYPE:
691 input_elf_type = elf_type (optarg);
692 if (input_elf_type < 0)
693 return 1;
694 break;
696 case OPTION_OUTPUT_TYPE:
697 output_elf_type = elf_type (optarg);
698 if (output_elf_type < 0)
699 return 1;
700 break;
702 case OPTION_INPUT_OSABI:
703 input_elf_osabi = elf_osabi (optarg);
704 if (input_elf_osabi < 0)
705 return 1;
706 break;
708 case OPTION_OUTPUT_OSABI:
709 output_elf_osabi = elf_osabi (optarg);
710 if (output_elf_osabi < 0)
711 return 1;
712 break;
714 case 'h':
715 usage (stdout, 0);
717 case 'v':
718 print_version (program_name);
719 break;
721 default:
722 usage (stderr, 1);
726 if (optind == argc
727 || (output_elf_machine == -1
728 && output_elf_type == -1
729 && output_elf_osabi == -1))
730 usage (stderr, 1);
732 status = 0;
733 while (optind < argc)
734 status |= process_file (argv[optind++]);
736 return status;