1 /* elfedit.c -- Update the ELF header of an ELF format file
2 Copyright 2010, 2011, 2012
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
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. */
37 #include "elf/common.h"
38 #include "elf/external.h"
39 #include "elf/internal.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 static int input_elf_class
= -1;
61 update_elf_header (const char *file_name
, FILE *file
)
63 int class, machine
, type
, status
, osabi
;
65 if (elf_header
.e_ident
[EI_MAG0
] != ELFMAG0
66 || elf_header
.e_ident
[EI_MAG1
] != ELFMAG1
67 || elf_header
.e_ident
[EI_MAG2
] != ELFMAG2
68 || elf_header
.e_ident
[EI_MAG3
] != ELFMAG3
)
71 (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
76 if (elf_header
.e_ident
[EI_VERSION
] != EV_CURRENT
)
79 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
80 file_name
, elf_header
.e_ident
[EI_VERSION
],
85 /* Return if e_machine is the same as output_elf_machine. */
86 if (output_elf_machine
== elf_header
.e_machine
)
89 class = elf_header
.e_ident
[EI_CLASS
];
91 /* Skip if class doesn't match. */
92 if (input_elf_class
!= -1 && class != input_elf_class
)
95 (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
96 file_name
, class, input_elf_class
);
100 machine
= elf_header
.e_machine
;
102 /* Skip if e_machine doesn't match. */
103 if (input_elf_machine
!= -1 && machine
!= input_elf_machine
)
106 (_("%s: Unmatched e_machine: %d is not %d\n"),
107 file_name
, machine
, input_elf_machine
);
111 type
= elf_header
.e_type
;
113 /* Skip if e_type doesn't match. */
114 if (input_elf_type
!= -1 && type
!= input_elf_type
)
117 (_("%s: Unmatched e_type: %d is not %d\n"),
118 file_name
, type
, input_elf_type
);
122 osabi
= elf_header
.e_ident
[EI_OSABI
];
124 /* Skip if OSABI doesn't match. */
125 if (input_elf_osabi
!= -1 && osabi
!= input_elf_osabi
)
128 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
129 file_name
, osabi
, input_elf_osabi
);
133 /* Update e_machine, e_type and EI_OSABI. */
137 /* We should never get here. */
141 if (output_elf_machine
!= -1)
142 BYTE_PUT (ehdr32
.e_machine
, output_elf_machine
);
143 if (output_elf_type
!= -1)
144 BYTE_PUT (ehdr32
.e_type
, output_elf_type
);
145 if (output_elf_osabi
!= -1)
146 ehdr32
.e_ident
[EI_OSABI
] = output_elf_osabi
;
147 status
= fwrite (&ehdr32
, sizeof (ehdr32
), 1, file
) == 1;
150 if (output_elf_machine
!= -1)
151 BYTE_PUT (ehdr64
.e_machine
, output_elf_machine
);
152 if (output_elf_type
!= -1)
153 BYTE_PUT (ehdr64
.e_type
, output_elf_type
);
154 if (output_elf_osabi
!= -1)
155 ehdr64
.e_ident
[EI_OSABI
] = output_elf_osabi
;
156 status
= fwrite (&ehdr64
, sizeof (ehdr64
), 1, file
) == 1;
161 error (_("%s: Failed to update ELF header: %s\n"),
162 file_name
, strerror (errno
));
168 get_file_header (FILE * file
)
170 /* Read in the identity array. */
171 if (fread (elf_header
.e_ident
, EI_NIDENT
, 1, file
) != 1)
174 /* Determine how to read the rest of the header. */
175 switch (elf_header
.e_ident
[EI_DATA
])
177 default: /* fall through */
178 case ELFDATANONE
: /* fall through */
180 byte_get
= byte_get_little_endian
;
181 byte_put
= byte_put_little_endian
;
184 byte_get
= byte_get_big_endian
;
185 byte_put
= byte_put_big_endian
;
189 /* Read in the rest of the header. For now we only support 32 bit
190 and 64 bit ELF files. */
191 switch (elf_header
.e_ident
[EI_CLASS
])
194 error (_("Unsupported EI_CLASS: %d\n"),
195 elf_header
.e_ident
[EI_CLASS
]);
199 if (fread (ehdr32
.e_type
, sizeof (ehdr32
) - EI_NIDENT
,
203 elf_header
.e_type
= BYTE_GET (ehdr32
.e_type
);
204 elf_header
.e_machine
= BYTE_GET (ehdr32
.e_machine
);
205 elf_header
.e_version
= BYTE_GET (ehdr32
.e_version
);
206 elf_header
.e_entry
= BYTE_GET (ehdr32
.e_entry
);
207 elf_header
.e_phoff
= BYTE_GET (ehdr32
.e_phoff
);
208 elf_header
.e_shoff
= BYTE_GET (ehdr32
.e_shoff
);
209 elf_header
.e_flags
= BYTE_GET (ehdr32
.e_flags
);
210 elf_header
.e_ehsize
= BYTE_GET (ehdr32
.e_ehsize
);
211 elf_header
.e_phentsize
= BYTE_GET (ehdr32
.e_phentsize
);
212 elf_header
.e_phnum
= BYTE_GET (ehdr32
.e_phnum
);
213 elf_header
.e_shentsize
= BYTE_GET (ehdr32
.e_shentsize
);
214 elf_header
.e_shnum
= BYTE_GET (ehdr32
.e_shnum
);
215 elf_header
.e_shstrndx
= BYTE_GET (ehdr32
.e_shstrndx
);
217 memcpy (&ehdr32
, &elf_header
, EI_NIDENT
);
221 /* If we have been compiled with sizeof (bfd_vma) == 4, then
222 we will not be able to cope with the 64bit data found in
223 64 ELF files. Detect this now and abort before we start
224 overwriting things. */
225 if (sizeof (bfd_vma
) < 8)
227 error (_("This executable has been built without support for a\n\
228 64 bit data type and so it cannot process 64 bit ELF files.\n"));
232 if (fread (ehdr64
.e_type
, sizeof (ehdr64
) - EI_NIDENT
,
236 elf_header
.e_type
= BYTE_GET (ehdr64
.e_type
);
237 elf_header
.e_machine
= BYTE_GET (ehdr64
.e_machine
);
238 elf_header
.e_version
= BYTE_GET (ehdr64
.e_version
);
239 elf_header
.e_entry
= BYTE_GET (ehdr64
.e_entry
);
240 elf_header
.e_phoff
= BYTE_GET (ehdr64
.e_phoff
);
241 elf_header
.e_shoff
= BYTE_GET (ehdr64
.e_shoff
);
242 elf_header
.e_flags
= BYTE_GET (ehdr64
.e_flags
);
243 elf_header
.e_ehsize
= BYTE_GET (ehdr64
.e_ehsize
);
244 elf_header
.e_phentsize
= BYTE_GET (ehdr64
.e_phentsize
);
245 elf_header
.e_phnum
= BYTE_GET (ehdr64
.e_phnum
);
246 elf_header
.e_shentsize
= BYTE_GET (ehdr64
.e_shentsize
);
247 elf_header
.e_shnum
= BYTE_GET (ehdr64
.e_shnum
);
248 elf_header
.e_shstrndx
= BYTE_GET (ehdr64
.e_shstrndx
);
250 memcpy (&ehdr64
, &elf_header
, EI_NIDENT
);
256 /* Process one ELF object file according to the command line options.
257 This file may actually be stored in an archive. The file is
258 positioned at the start of the ELF object. */
261 process_object (const char *file_name
, FILE *file
)
263 /* Rememeber where we are. */
264 long offset
= ftell (file
);
266 if (! get_file_header (file
))
268 error (_("%s: Failed to read ELF header\n"), file_name
);
272 /* Go to the position of the ELF header. */
273 if (fseek (file
, offset
, SEEK_SET
) != 0)
275 error (_("%s: Failed to seek to ELF header\n"), file_name
);
278 if (! update_elf_header (file_name
, file
))
284 /* Process an ELF archive.
285 On entry the file is positioned just after the ARMAG string. */
288 process_archive (const char * file_name
, FILE * file
,
289 bfd_boolean is_thin_archive
)
291 struct archive_info arch
;
292 struct archive_info nested_arch
;
296 /* The ARCH structure is used to hold information about this archive. */
297 arch
.file_name
= NULL
;
299 arch
.index_array
= NULL
;
300 arch
.sym_table
= NULL
;
301 arch
.longnames
= NULL
;
303 /* The NESTED_ARCH structure is used as a single-item cache of information
304 about a nested archive (when members of a thin archive reside within
305 another regular archive file). */
306 nested_arch
.file_name
= NULL
;
307 nested_arch
.file
= NULL
;
308 nested_arch
.index_array
= NULL
;
309 nested_arch
.sym_table
= NULL
;
310 nested_arch
.longnames
= NULL
;
312 if (setup_archive (&arch
, file_name
, file
, is_thin_archive
, FALSE
) != 0)
324 char * qualified_name
;
326 /* Read the next archive header. */
327 if (fseek (file
, arch
.next_arhdr_offset
, SEEK_SET
) != 0)
329 error (_("%s: failed to seek to next archive header\n"),
333 got
= fread (&arch
.arhdr
, 1, sizeof arch
.arhdr
, file
);
334 if (got
!= sizeof arch
.arhdr
)
338 error (_("%s: failed to read archive header\n"),
343 if (memcmp (arch
.arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
345 error (_("%s: did not find a valid archive header\n"),
351 arch
.next_arhdr_offset
+= sizeof arch
.arhdr
;
353 archive_file_size
= strtoul (arch
.arhdr
.ar_size
, NULL
, 10);
354 if (archive_file_size
& 01)
357 name
= get_archive_member_name (&arch
, &nested_arch
);
360 error (_("%s: bad archive file name\n"), file_name
);
364 namelen
= strlen (name
);
366 qualified_name
= make_qualified_name (&arch
, &nested_arch
, name
);
367 if (qualified_name
== NULL
)
369 error (_("%s: bad archive file name\n"), file_name
);
374 if (is_thin_archive
&& arch
.nested_member_origin
== 0)
376 /* This is a proxy for an external member of a thin archive. */
378 char *member_file_name
= adjust_relative_path (file_name
,
380 if (member_file_name
== NULL
)
386 member_file
= fopen (member_file_name
, "r+b");
387 if (member_file
== NULL
)
389 error (_("Input file '%s' is not readable\n"),
391 free (member_file_name
);
396 archive_file_offset
= arch
.nested_member_origin
;
398 ret
|= process_object (qualified_name
, member_file
);
400 fclose (member_file
);
401 free (member_file_name
);
403 else if (is_thin_archive
)
405 /* This is a proxy for a member of a nested archive. */
406 archive_file_offset
= arch
.nested_member_origin
+ sizeof arch
.arhdr
;
408 /* The nested archive file will have been opened and setup by
409 get_archive_member_name. */
410 if (fseek (nested_arch
.file
, archive_file_offset
,
413 error (_("%s: failed to seek to archive member\n"),
414 nested_arch
.file_name
);
419 ret
|= process_object (qualified_name
, nested_arch
.file
);
423 archive_file_offset
= arch
.next_arhdr_offset
;
424 arch
.next_arhdr_offset
+= archive_file_size
;
426 ret
|= process_object (qualified_name
, file
);
429 free (qualified_name
);
433 if (nested_arch
.file
!= NULL
)
434 fclose (nested_arch
.file
);
435 release_archive (&nested_arch
);
436 release_archive (&arch
);
442 check_file (const char *file_name
, struct stat
*statbuf_p
)
446 if (statbuf_p
== NULL
)
447 statbuf_p
= &statbuf
;
449 if (stat (file_name
, statbuf_p
) < 0)
452 error (_("'%s': No such file\n"), file_name
);
454 error (_("Could not locate '%s'. System error message: %s\n"),
455 file_name
, strerror (errno
));
459 if (! S_ISREG (statbuf_p
->st_mode
))
461 error (_("'%s' is not an ordinary file\n"), file_name
);
469 process_file (const char *file_name
)
475 if (check_file (file_name
, NULL
))
478 file
= fopen (file_name
, "r+b");
481 error (_("Input file '%s' is not readable\n"), file_name
);
485 if (fread (armag
, SARMAG
, 1, file
) != 1)
487 error (_("%s: Failed to read file's magic number\n"),
493 if (memcmp (armag
, ARMAG
, SARMAG
) == 0)
494 ret
= process_archive (file_name
, file
, FALSE
);
495 else if (memcmp (armag
, ARMAGT
, SARMAG
) == 0)
496 ret
= process_archive (file_name
, file
, TRUE
);
500 archive_file_size
= archive_file_offset
= 0;
501 ret
= process_object (file_name
, file
);
516 { ELFOSABI_NONE
, "none" },
517 { ELFOSABI_HPUX
, "HPUX" },
518 { ELFOSABI_NETBSD
, "NetBSD" },
519 { ELFOSABI_GNU
, "GNU" },
520 { ELFOSABI_GNU
, "Linux" },
521 { ELFOSABI_SOLARIS
, "Solaris" },
522 { ELFOSABI_AIX
, "AIX" },
523 { ELFOSABI_IRIX
, "Irix" },
524 { ELFOSABI_FREEBSD
, "FreeBSD" },
525 { ELFOSABI_TRU64
, "TRU64" },
526 { ELFOSABI_MODESTO
, "Modesto" },
527 { ELFOSABI_OPENBSD
, "OpenBSD" },
528 { ELFOSABI_OPENVMS
, "OpenVMS" },
529 { ELFOSABI_NSK
, "NSK" },
530 { ELFOSABI_AROS
, "AROS" },
531 { ELFOSABI_FENIXOS
, "FenixOS" }
534 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
537 elf_osabi (const char *osabi
)
541 for (i
= 0; i
< ARRAY_SIZE (osabis
); i
++)
542 if (strcasecmp (osabi
, osabis
[i
].name
) == 0)
543 return osabis
[i
].osabi
;
545 error (_("Unknown OSABI: %s\n"), osabi
);
550 /* Return EM_XXX for a machine string, MACH. */
553 elf_machine (const char *mach
)
555 if (strcasecmp (mach
, "l1om") == 0)
557 if (strcasecmp (mach
, "k1om") == 0)
559 if (strcasecmp (mach
, "x86_64") == 0)
561 if (strcasecmp (mach
, "x86-64") == 0)
563 if (strcasecmp (mach
, "none") == 0)
566 error (_("Unknown machine type: %s\n"), mach
);
571 /* Return ELF class for a machine type, MACH. */
585 error (_("Unknown machine type: %d\n"), mach
);
590 /* Return ET_XXX for a type string, TYPE. */
593 elf_type (const char *type
)
595 if (strcasecmp (type
, "rel") == 0)
597 if (strcasecmp (type
, "exec") == 0)
599 if (strcasecmp (type
, "dyn") == 0)
601 if (strcasecmp (type
, "none") == 0)
604 error (_("Unknown type: %s\n"), type
);
609 enum command_line_switch
611 OPTION_INPUT_MACH
= 150,
619 static struct option options
[] =
621 {"input-mach", required_argument
, 0, OPTION_INPUT_MACH
},
622 {"output-mach", required_argument
, 0, OPTION_OUTPUT_MACH
},
623 {"input-type", required_argument
, 0, OPTION_INPUT_TYPE
},
624 {"output-type", required_argument
, 0, OPTION_OUTPUT_TYPE
},
625 {"input-osabi", required_argument
, 0, OPTION_INPUT_OSABI
},
626 {"output-osabi", required_argument
, 0, OPTION_OUTPUT_OSABI
},
627 {"version", no_argument
, 0, 'v'},
628 {"help", no_argument
, 0, 'h'},
629 {0, no_argument
, 0, 0}
633 usage (FILE *stream
, int exit_status
)
635 fprintf (stream
, _("Usage: %s <option(s)> elffile(s)\n"),
637 fprintf (stream
, _(" Update the ELF header of ELF files\n"));
638 fprintf (stream
, _(" The options are:\n"));
639 fprintf (stream
, _("\
640 --input-mach <machine> Set input machine type to <machine>\n\
641 --output-mach <machine> Set output machine type to <machine>\n\
642 --input-type <type> Set input file type to <type>\n\
643 --output-type <type> Set output file type to <type>\n\
644 --input-osabi <osabi> Set input OSABI to <osabi>\n\
645 --output-osabi <osabi> Set output OSABI to <osabi>\n\
646 -h --help Display this information\n\
647 -v --version Display the version number of %s\n\
650 if (REPORT_BUGS_TO
[0] && exit_status
== 0)
651 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);
656 main (int argc
, char ** argv
)
660 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
661 setlocale (LC_MESSAGES
, "");
663 #if defined (HAVE_SETLOCALE)
664 setlocale (LC_CTYPE
, "");
666 bindtextdomain (PACKAGE
, LOCALEDIR
);
667 textdomain (PACKAGE
);
669 expandargv (&argc
, &argv
);
671 while ((c
= getopt_long (argc
, argv
, "hv",
672 options
, (int *) 0)) != EOF
)
676 case OPTION_INPUT_MACH
:
677 input_elf_machine
= elf_machine (optarg
);
678 if (input_elf_machine
< 0)
680 input_elf_class
= elf_class (input_elf_machine
);
681 if (input_elf_class
< 0)
685 case OPTION_OUTPUT_MACH
:
686 output_elf_machine
= elf_machine (optarg
);
687 if (output_elf_machine
< 0)
691 case OPTION_INPUT_TYPE
:
692 input_elf_type
= elf_type (optarg
);
693 if (input_elf_type
< 0)
697 case OPTION_OUTPUT_TYPE
:
698 output_elf_type
= elf_type (optarg
);
699 if (output_elf_type
< 0)
703 case OPTION_INPUT_OSABI
:
704 input_elf_osabi
= elf_osabi (optarg
);
705 if (input_elf_osabi
< 0)
709 case OPTION_OUTPUT_OSABI
:
710 output_elf_osabi
= elf_osabi (optarg
);
711 if (output_elf_osabi
< 0)
719 print_version (program_name
);
728 || (output_elf_machine
== -1
729 && output_elf_type
== -1
730 && output_elf_osabi
== -1))
734 while (optind
< argc
)
735 status
|= process_file (argv
[optind
++]);