Merge branch 'vendor/TCPDUMP'
[dragonfly.git] / contrib / binutils-2.22 / binutils / elfedit.c
1 /* elfedit.c -- Update the ELF header of an ELF format file
2    Copyright 2010
3    Free Software Foundation, Inc.
4
5    This file is part of GNU Binutils.
6
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.
11
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.
16
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.  */
21 \f
22 #include "config.h"
23 #include "sysdep.h"
24 #include <assert.h>
25 #include <sys/stat.h>
26
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
34
35 #include "bfd.h"
36 #include "elfcomm.h"
37 #include "bucomm.h"
38
39 #include "elf/common.h"
40 #include "elf/external.h"
41 #include "elf/internal.h"
42
43 #include "getopt.h"
44 #include "libiberty.h"
45 #include "safe-ctype.h"
46 #include "filenames.h"
47
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;
61
62 static int
63 update_elf_header (const char *file_name, FILE *file)
64 {
65   int class, machine, type, status, osabi;
66
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)
71     {
72       error
73         (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
74          file_name);
75       return 0;
76     }
77
78   if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
79     {
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;
85     }
86
87   /* Return if e_machine is the same as output_elf_machine.  */
88   if (output_elf_machine == elf_header.e_machine)
89     return 1;
90
91   class = elf_header.e_ident[EI_CLASS];
92
93   /* Skip if class doesn't match. */
94   if (input_elf_class != -1 && class != input_elf_class)
95     {
96       error
97         (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
98          file_name, class, input_elf_class);
99       return 0;
100     }
101
102   machine = elf_header.e_machine;
103
104   /* Skip if e_machine doesn't match. */
105   if (input_elf_machine != -1 && machine != input_elf_machine)
106     {
107       error
108         (_("%s: Unmatched e_machine: %d is not %d\n"),
109          file_name, machine, input_elf_machine);
110       return 0;
111     }
112
113   type = elf_header.e_type;
114
115   /* Skip if e_type doesn't match. */
116   if (input_elf_type != -1 && type != input_elf_type)
117     {
118       error
119         (_("%s: Unmatched e_type: %d is not %d\n"),
120          file_name, type, input_elf_type);
121       return 0;
122     }
123
124   osabi = elf_header.e_ident[EI_OSABI];
125
126   /* Skip if OSABI doesn't match. */
127   if (input_elf_osabi != -1 && osabi != input_elf_osabi)
128     {
129       error
130         (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
131          file_name, osabi, input_elf_osabi);
132       return 0;
133     }
134
135   /* Update e_machine, e_type and EI_OSABI.  */
136   switch (class)
137     {
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;
160     }
161
162   if (status != 1)
163     error (_("%s: Failed to update ELF header: %s\n"),
164                file_name, strerror (errno));
165
166   return status;
167 }
168
169 static int
170 get_file_header (FILE * file)
171 {
172   /* Read in the identity array.  */
173   if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
174     return 0;
175
176   /* Determine how to read the rest of the header.  */
177   switch (elf_header.e_ident[EI_DATA])
178     {
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;
189     }
190
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])
194     {
195     default:
196       error (_("Unsupported EI_CLASS: %d\n"),
197                  elf_header.e_ident[EI_CLASS]);
198       return 0;
199
200     case ELFCLASS32:
201       if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
202                  1, file) != 1)
203         return 0;
204
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);
218
219       memcpy (&ehdr32, &elf_header, EI_NIDENT);
220       break;
221
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)
228         {
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;
232         }
233
234       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
235                  1, file) != 1)
236         return 0;
237
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);
251
252       memcpy (&ehdr64, &elf_header, EI_NIDENT);
253       break;
254     }
255   return 1;
256 }
257
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.  */
261
262 static int
263 process_object (const char *file_name, FILE *file)
264 {
265   /* Rememeber where we are.  */
266   long offset = ftell (file);
267
268   if (! get_file_header (file))
269     {
270       error (_("%s: Failed to read ELF header\n"), file_name);
271       return 1;
272     }
273
274   /* Go to the position of the ELF header.  */
275   if (fseek (file, offset, SEEK_SET) != 0)
276     {
277       error (_("%s: Failed to seek to ELF header\n"), file_name);
278     }
279
280   if (! update_elf_header (file_name, file))
281     return 1;
282
283   return 0;
284 }
285
286 /* Process an ELF archive.
287    On entry the file is positioned just after the ARMAG string.  */
288
289 static int
290 process_archive (const char * file_name, FILE * file,
291                  bfd_boolean is_thin_archive)
292 {
293   struct archive_info arch;
294   struct archive_info nested_arch;
295   size_t got;
296   int ret;
297
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;
304
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;
313
314   if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
315     {
316       ret = 1;
317       goto out;
318     }
319
320   ret = 0;
321
322   while (1)
323     {
324       char * name;
325       size_t namelen;
326       char * qualified_name;
327
328       /* Read the next archive header.  */
329       if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
330         {
331           error (_("%s: failed to seek to next archive header\n"),
332                      file_name);
333           return 1;
334         }
335       got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
336       if (got != sizeof arch.arhdr)
337         {
338           if (got == 0)
339             break;
340           error (_("%s: failed to read archive header\n"),
341                      file_name);
342           ret = 1;
343           break;
344         }
345       if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
346         {
347           error (_("%s: did not find a valid archive header\n"),
348                      arch.file_name);
349           ret = 1;
350           break;
351         }
352
353       arch.next_arhdr_offset += sizeof arch.arhdr;
354
355       archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
356       if (archive_file_size & 01)
357         ++archive_file_size;
358
359       name = get_archive_member_name (&arch, &nested_arch);
360       if (name == NULL)
361         {
362           error (_("%s: bad archive file name\n"), file_name);
363           ret = 1;
364           break;
365         }
366       namelen = strlen (name);
367
368       qualified_name = make_qualified_name (&arch, &nested_arch, name);
369       if (qualified_name == NULL)
370         {
371           error (_("%s: bad archive file name\n"), file_name);
372           ret = 1;
373           break;
374         }
375
376       if (is_thin_archive && arch.nested_member_origin == 0)
377         {
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)
383             {
384               ret = 1;
385               break;
386             }
387
388           member_file = fopen (member_file_name, "r+b");
389           if (member_file == NULL)
390             {
391               error (_("Input file '%s' is not readable\n"),
392                          member_file_name);
393               free (member_file_name);
394               ret = 1;
395               break;
396             }
397
398           archive_file_offset = arch.nested_member_origin;
399
400           ret |= process_object (qualified_name, member_file);
401
402           fclose (member_file);
403           free (member_file_name);
404         }
405       else if (is_thin_archive)
406         {
407           /* This is a proxy for a member of a nested archive.  */
408           archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
409
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)
414             {
415               error (_("%s: failed to seek to archive member\n"),
416                          nested_arch.file_name);
417               ret = 1;
418               break;
419             }
420
421           ret |= process_object (qualified_name, nested_arch.file);
422         }
423       else
424         {
425           archive_file_offset = arch.next_arhdr_offset;
426           arch.next_arhdr_offset += archive_file_size;
427
428           ret |= process_object (qualified_name, file);
429         }
430
431       free (qualified_name);
432     }
433
434  out:
435   if (nested_arch.file != NULL)
436     fclose (nested_arch.file);
437   release_archive (&nested_arch);
438   release_archive (&arch);
439
440   return ret;
441 }
442
443 static int
444 check_file (const char *file_name, struct stat *statbuf_p)
445 {
446   struct stat statbuf;
447
448   if (statbuf_p == NULL)
449     statbuf_p = &statbuf;
450
451   if (stat (file_name, statbuf_p) < 0)
452     {
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;
459     }
460
461   if (! S_ISREG (statbuf_p->st_mode))
462     {
463       error (_("'%s' is not an ordinary file\n"), file_name);
464       return 1;
465     }
466
467   return 0;
468 }
469
470 static int
471 process_file (const char *file_name)
472 {
473   FILE * file;
474   char armag[SARMAG];
475   int ret;
476
477   if (check_file (file_name, NULL))
478     return 1;
479
480   file = fopen (file_name, "r+b");
481   if (file == NULL)
482     {
483       error (_("Input file '%s' is not readable\n"), file_name);
484       return 1;
485     }
486
487   if (fread (armag, SARMAG, 1, file) != 1)
488     {
489       error (_("%s: Failed to read file's magic number\n"),
490                  file_name);
491       fclose (file);
492       return 1;
493     }
494
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
500     {
501       rewind (file);
502       archive_file_size = archive_file_offset = 0;
503       ret = process_object (file_name, file);
504     }
505
506   fclose (file);
507
508   return ret;
509 }
510
511 static const struct
512 {
513   int osabi;
514   const char *name;
515 }
516 osabis[] =
517 {
518   { ELFOSABI_NONE, "none" },
519   { ELFOSABI_HPUX, "HPUX" },
520   { ELFOSABI_NETBSD, "NetBSD" },
521   { ELFOSABI_GNU, "GNU" },
522   { ELFOSABI_GNU, "Linux" },
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" }
534 };
535
536 /* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
537
538 static int
539 elf_osabi (const char *osabi)
540 {
541   unsigned int i;
542
543   for (i = 0; i < ARRAY_SIZE (osabis); i++)
544     if (strcasecmp (osabi, osabis[i].name) == 0)
545       return osabis[i].osabi;
546
547   error (_("Unknown OSABI: %s\n"), osabi);
548
549   return -1;
550 }
551
552 /* Return EM_XXX for a machine string, MACH.  */
553
554 static int
555 elf_machine (const char *mach)
556 {
557   if (strcasecmp (mach, "l1om") == 0)
558     return EM_L1OM;
559   if (strcasecmp (mach, "k1om") == 0)
560     return EM_K1OM;
561   if (strcasecmp (mach, "x86_64") == 0)
562     return EM_X86_64;
563   if (strcasecmp (mach, "x86-64") == 0)
564     return EM_X86_64;
565   if (strcasecmp (mach, "none") == 0)
566     return EM_NONE;
567
568   error (_("Unknown machine type: %s\n"), mach);
569
570   return -1;
571 }
572
573 /* Return ELF class for a machine type, MACH.  */
574
575 static int
576 elf_class (int mach)
577 {
578   switch (mach)
579     {
580     case EM_L1OM:
581     case EM_K1OM:
582     case EM_X86_64:
583       return ELFCLASS64;
584     case EM_NONE:
585       return ELFCLASSNONE;
586     default:
587       error (_("Unknown machine type: %d\n"), mach);
588       return -1;
589     }
590 }
591
592 /* Return ET_XXX for a type string, TYPE.  */
593
594 static int
595 elf_type (const char *type)
596 {
597   if (strcasecmp (type, "rel") == 0)
598     return ET_REL;
599   if (strcasecmp (type, "exec") == 0)
600     return ET_EXEC;
601   if (strcasecmp (type, "dyn") == 0)
602     return ET_DYN;
603   if (strcasecmp (type, "none") == 0)
604     return ET_NONE;
605
606   error (_("Unknown type: %s\n"), type);
607
608   return -1;
609 }
610
611 enum command_line_switch
612   {
613     OPTION_INPUT_MACH = 150,
614     OPTION_OUTPUT_MACH,
615     OPTION_INPUT_TYPE,
616     OPTION_OUTPUT_TYPE,
617     OPTION_INPUT_OSABI,
618     OPTION_OUTPUT_OSABI
619   };
620
621 static struct option options[] =
622 {
623   {"input-mach",        required_argument, 0, OPTION_INPUT_MACH},
624   {"output-mach",       required_argument, 0, OPTION_OUTPUT_MACH},
625   {"input-type",        required_argument, 0, OPTION_INPUT_TYPE},
626   {"output-type",       required_argument, 0, OPTION_OUTPUT_TYPE},
627   {"input-osabi",       required_argument, 0, OPTION_INPUT_OSABI},
628   {"output-osabi",      required_argument, 0, OPTION_OUTPUT_OSABI},
629   {"version",           no_argument, 0, 'v'},
630   {"help",              no_argument, 0, 'h'},
631   {0,                   no_argument, 0, 0}
632 };
633
634 static void
635 usage (FILE *stream, int exit_status)
636 {
637   fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
638            program_name);
639   fprintf (stream, _(" Update the ELF header of ELF files\n"));
640   fprintf (stream, _(" The options are:\n"));
641   fprintf (stream, _("\
642   --input-mach <machine>      Set input machine type to <machine>\n\
643   --output-mach <machine>     Set output machine type to <machine>\n\
644   --input-type <type>         Set input file type to <type>\n\
645   --output-type <type>        Set output file type to <type>\n\
646   --input-osabi <osabi>       Set input OSABI to <osabi>\n\
647   --output-osabi <osabi>      Set output OSABI to <osabi>\n\
648   -h --help                   Display this information\n\
649   -v --version                Display the version number of %s\n\
650 "),
651            program_name);
652   if (REPORT_BUGS_TO[0] && exit_status == 0)
653     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
654   exit (exit_status);
655 }
656
657 int
658 main (int argc, char ** argv)
659 {
660   int c, status;
661
662 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
663   setlocale (LC_MESSAGES, "");
664 #endif
665 #if defined (HAVE_SETLOCALE)
666   setlocale (LC_CTYPE, "");
667 #endif
668   bindtextdomain (PACKAGE, LOCALEDIR);
669   textdomain (PACKAGE);
670
671   expandargv (&argc, &argv);
672
673   while ((c = getopt_long (argc, argv, "hv",
674                            options, (int *) 0)) != EOF)
675     {
676       switch (c)
677         {
678         case OPTION_INPUT_MACH:
679           input_elf_machine = elf_machine (optarg);
680           if (input_elf_machine < 0)
681             return 1;
682           input_elf_class = elf_class (input_elf_machine);
683           if (input_elf_class < 0)
684             return 1;
685           break;
686
687         case OPTION_OUTPUT_MACH:
688           output_elf_machine = elf_machine (optarg);
689           if (output_elf_machine < 0)
690             return 1;
691           break;
692
693         case OPTION_INPUT_TYPE:
694           input_elf_type = elf_type (optarg);
695           if (input_elf_type < 0)
696             return 1;
697           break;
698
699         case OPTION_OUTPUT_TYPE:
700           output_elf_type = elf_type (optarg);
701           if (output_elf_type < 0)
702             return 1;
703           break;
704
705         case OPTION_INPUT_OSABI:
706           input_elf_osabi = elf_osabi (optarg);
707           if (input_elf_osabi < 0)
708             return 1;
709           break;
710
711         case OPTION_OUTPUT_OSABI:
712           output_elf_osabi = elf_osabi (optarg);
713           if (output_elf_osabi < 0)
714             return 1;
715           break;
716
717         case 'h':
718           usage (stdout, 0);
719
720         case 'v':
721           print_version (program_name);
722           break;
723
724         default:
725           usage (stderr, 1);
726         }
727     }
728
729   if (optind == argc
730       || (output_elf_machine == -1
731           && output_elf_type == -1
732           && output_elf_osabi == -1))
733     usage (stderr, 1);
734
735   status = 0;
736   while (optind < argc)
737     status |= process_file (argv[optind++]);
738
739   return status;
740 }