1 /* elfedit.c -- Update the ELF header of an ELF format file
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
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. */
39 #include "elf/common.h"
40 #include "elf/external.h"
41 #include "elf/internal.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;
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
)
73 (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
78 if (elf_header
.e_ident
[EI_VERSION
] != EV_CURRENT
)
81 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
82 file_name
, elf_header
.e_ident
[EI_VERSION
],
87 /* Return if e_machine is the same as output_elf_machine. */
88 if (output_elf_machine
== elf_header
.e_machine
)
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
)
97 (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
98 file_name
, class, input_elf_class
);
102 machine
= elf_header
.e_machine
;
104 /* Skip if e_machine doesn't match. */
105 if (input_elf_machine
!= -1 && machine
!= input_elf_machine
)
108 (_("%s: Unmatched e_machine: %d is not %d\n"),
109 file_name
, machine
, input_elf_machine
);
113 type
= elf_header
.e_type
;
115 /* Skip if e_type doesn't match. */
116 if (input_elf_type
!= -1 && type
!= input_elf_type
)
119 (_("%s: Unmatched e_type: %d is not %d\n"),
120 file_name
, type
, input_elf_type
);
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
)
130 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
131 file_name
, osabi
, input_elf_osabi
);
135 /* Update e_machine, e_type and EI_OSABI. */
139 /* We should never get here. */
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;
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;
163 error (_("%s: Failed to update ELF header: %s\n"),
164 file_name
, strerror (errno
));
170 get_file_header (FILE * file
)
172 /* Read in the identity array. */
173 if (fread (elf_header
.e_ident
, EI_NIDENT
, 1, file
) != 1)
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 */
182 byte_get
= byte_get_little_endian
;
183 byte_put
= byte_put_little_endian
;
186 byte_get
= byte_get_big_endian
;
187 byte_put
= byte_put_big_endian
;
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
])
196 error (_("Unsupported EI_CLASS: %d\n"),
197 elf_header
.e_ident
[EI_CLASS
]);
201 if (fread (ehdr32
.e_type
, sizeof (ehdr32
) - EI_NIDENT
,
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
);
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"));
234 if (fread (ehdr64
.e_type
, sizeof (ehdr64
) - EI_NIDENT
,
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
);
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. */
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
);
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
))
286 /* Process an ELF archive.
287 On entry the file is positioned just after the ARMAG string. */
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
;
298 /* The ARCH structure is used to hold information about this archive. */
299 arch
.file_name
= 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)
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"),
335 got
= fread (&arch
.arhdr
, 1, sizeof arch
.arhdr
, file
);
336 if (got
!= sizeof arch
.arhdr
)
340 error (_("%s: failed to read archive header\n"),
345 if (memcmp (arch
.arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
347 error (_("%s: did not find a valid archive header\n"),
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)
359 name
= get_archive_member_name (&arch
, &nested_arch
);
362 error (_("%s: bad archive file name\n"), file_name
);
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
);
376 if (is_thin_archive
&& arch
.nested_member_origin
== 0)
378 /* This is a proxy for an external member of a thin archive. */
380 char *member_file_name
= adjust_relative_path (file_name
,
382 if (member_file_name
== NULL
)
388 member_file
= fopen (member_file_name
, "r+b");
389 if (member_file
== NULL
)
391 error (_("Input file '%s' is not readable\n"),
393 free (member_file_name
);
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
,
415 error (_("%s: failed to seek to archive member\n"),
416 nested_arch
.file_name
);
421 ret
|= process_object (qualified_name
, nested_arch
.file
);
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
);
435 if (nested_arch
.file
!= NULL
)
436 fclose (nested_arch
.file
);
437 release_archive (&nested_arch
);
438 release_archive (&arch
);
444 check_file (const char *file_name
, struct stat
*statbuf_p
)
448 if (statbuf_p
== NULL
)
449 statbuf_p
= &statbuf
;
451 if (stat (file_name
, statbuf_p
) < 0)
454 error (_("'%s': No such file\n"), file_name
);
456 error (_("Could not locate '%s'. System error message: %s\n"),
457 file_name
, strerror (errno
));
461 if (! S_ISREG (statbuf_p
->st_mode
))
463 error (_("'%s' is not an ordinary file\n"), file_name
);
471 process_file (const char *file_name
)
477 if (check_file (file_name
, NULL
))
480 file
= fopen (file_name
, "r+b");
483 error (_("Input file '%s' is not readable\n"), file_name
);
487 if (fread (armag
, SARMAG
, 1, file
) != 1)
489 error (_("%s: Failed to read file's magic number\n"),
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
);
502 archive_file_size
= archive_file_offset
= 0;
503 ret
= process_object (file_name
, file
);
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. */
539 elf_osabi (const char *osabi
)
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
);
552 /* Return EM_XXX for a machine string, MACH. */
555 elf_machine (const char *mach
)
557 if (strcasecmp (mach
, "l1om") == 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. */
584 error (_("Unknown machine type: %d\n"), mach
);
589 /* Return ET_XXX for a type string, TYPE. */
592 elf_type (const char *type
)
594 if (strcasecmp (type
, "rel") == 0)
596 if (strcasecmp (type
, "exec") == 0)
598 if (strcasecmp (type
, "dyn") == 0)
600 if (strcasecmp (type
, "none") == 0)
603 error (_("Unknown type: %s\n"), type
);
608 enum command_line_switch
610 OPTION_INPUT_MACH
= 150,
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}
632 usage (FILE *stream
, int exit_status
)
634 fprintf (stream
, _("Usage: %s <option(s)> elffile(s)\n"),
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\
649 if (REPORT_BUGS_TO
[0] && exit_status
== 0)
650 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);
655 main (int argc
, char ** argv
)
659 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
660 setlocale (LC_MESSAGES
, "");
662 #if defined (HAVE_SETLOCALE)
663 setlocale (LC_CTYPE
, "");
665 bindtextdomain (PACKAGE
, LOCALEDIR
);
666 textdomain (PACKAGE
);
668 expandargv (&argc
, &argv
);
670 while ((c
= getopt_long (argc
, argv
, "hv",
671 options
, (int *) 0)) != EOF
)
675 case OPTION_INPUT_MACH
:
676 input_elf_machine
= elf_machine (optarg
);
677 if (input_elf_machine
< 0)
679 input_elf_class
= elf_class (input_elf_machine
);
680 if (input_elf_class
< 0)
684 case OPTION_OUTPUT_MACH
:
685 output_elf_machine
= elf_machine (optarg
);
686 if (output_elf_machine
< 0)
690 case OPTION_INPUT_TYPE
:
691 input_elf_type
= elf_type (optarg
);
692 if (input_elf_type
< 0)
696 case OPTION_OUTPUT_TYPE
:
697 output_elf_type
= elf_type (optarg
);
698 if (output_elf_type
< 0)
702 case OPTION_INPUT_OSABI
:
703 input_elf_osabi
= elf_osabi (optarg
);
704 if (input_elf_osabi
< 0)
708 case OPTION_OUTPUT_OSABI
:
709 output_elf_osabi
= elf_osabi (optarg
);
710 if (output_elf_osabi
< 0)
718 print_version (program_name
);
727 || (output_elf_machine
== -1
728 && output_elf_type
== -1
729 && output_elf_osabi
== -1))
733 while (optind
< argc
)
734 status
|= process_file (argv
[optind
++]);