Release 2.33.1
[external/binutils.git] / binutils / elfedit.c
1 /* elfedit.c -- Update the ELF header of an ELF format file
2    Copyright (C) 2010-2019 Free Software Foundation, Inc.
3
4    This file is part of GNU Binutils.
5
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.
10
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.
15
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
19    02110-1301, USA.  */
20 \f
21 #include "config.h"
22 #include "sysdep.h"
23 #include <assert.h>
24
25 #if __GNUC__ >= 2
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.  */
30 #define BFD64
31 #endif
32
33 #include "bfd.h"
34 #include "elfcomm.h"
35 #include "bucomm.h"
36
37 #include "elf/common.h"
38 #include "elf/external.h"
39 #include "elf/internal.h"
40
41 #include "getopt.h"
42 #include "libiberty.h"
43 #include "safe-ctype.h"
44 #include "filenames.h"
45
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 enum elfclass
59   {
60     ELF_CLASS_UNKNOWN = -1,
61     ELF_CLASS_NONE = ELFCLASSNONE,
62     ELF_CLASS_32 = ELFCLASS32,
63     ELF_CLASS_64 = ELFCLASS64,
64     ELF_CLASS_BOTH
65   };
66 static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
67 static enum elfclass output_elf_class = ELF_CLASS_BOTH;
68
69 #ifdef HAVE_MMAP
70 #include <sys/mman.h>
71
72 static unsigned int enable_x86_features;
73 static unsigned int disable_x86_features;
74
75 static int
76 update_gnu_property (const char *file_name, FILE *file)
77 {
78   char *map;
79   Elf_Internal_Phdr *phdrs;
80   struct stat st_buf;
81   unsigned int i;
82   int ret;
83
84   if (!enable_x86_features && !disable_x86_features)
85     return 0;
86
87   if (elf_header.e_machine != EM_386
88       && elf_header.e_machine != EM_X86_64)
89     {
90       error (_("%s: Not an i386 nor x86-64 ELF file\n"), file_name);
91       return 0;
92     }
93
94   if (fstat (fileno (file), &st_buf) < 0)
95     {
96       error (_("%s: stat () failed\n"), file_name);
97       return 1;
98     }
99
100   map = mmap (NULL, st_buf.st_size, PROT_READ | PROT_WRITE,
101               MAP_SHARED, fileno (file), 0);
102   if (map == MAP_FAILED)
103     {
104       error (_("%s: mmap () failed\n"), file_name);
105       return 0;
106     }
107
108   phdrs = xmalloc (elf_header.e_phnum * sizeof (*phdrs));
109
110   if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
111     {
112       Elf32_External_Phdr *phdrs32
113         = (Elf32_External_Phdr *) (map + elf_header.e_phoff);
114       for (i = 0; i < elf_header.e_phnum; i++)
115         {
116           phdrs[i].p_type = BYTE_GET (phdrs32[i].p_type);
117           phdrs[i].p_offset = BYTE_GET (phdrs32[i].p_offset);
118           phdrs[i].p_vaddr = BYTE_GET (phdrs32[i].p_vaddr);
119           phdrs[i].p_paddr = BYTE_GET (phdrs32[i].p_paddr);
120           phdrs[i].p_filesz = BYTE_GET (phdrs32[i].p_filesz);
121           phdrs[i].p_memsz = BYTE_GET (phdrs32[i].p_memsz);
122           phdrs[i].p_flags = BYTE_GET (phdrs32[i].p_flags);
123           phdrs[i].p_align = BYTE_GET (phdrs32[i].p_align);
124         }
125     }
126   else
127     {
128       Elf64_External_Phdr *phdrs64
129         = (Elf64_External_Phdr *) (map + elf_header.e_phoff);
130       for (i = 0; i < elf_header.e_phnum; i++)
131         {
132           phdrs[i].p_type = BYTE_GET (phdrs64[i].p_type);
133           phdrs[i].p_offset = BYTE_GET (phdrs64[i].p_offset);
134           phdrs[i].p_vaddr = BYTE_GET (phdrs64[i].p_vaddr);
135           phdrs[i].p_paddr = BYTE_GET (phdrs64[i].p_paddr);
136           phdrs[i].p_filesz = BYTE_GET (phdrs64[i].p_filesz);
137           phdrs[i].p_memsz = BYTE_GET (phdrs64[i].p_memsz);
138           phdrs[i].p_flags = BYTE_GET (phdrs64[i].p_flags);
139           phdrs[i].p_align = BYTE_GET (phdrs64[i].p_align);
140         }
141     }
142
143   ret = 0;
144   for (i = 0; i < elf_header.e_phnum; i++)
145     if (phdrs[i].p_type == PT_NOTE)
146       {
147         size_t offset = phdrs[i].p_offset;
148         size_t size = phdrs[i].p_filesz;
149         size_t align = phdrs[i].p_align;
150         char *buf = map + offset;
151         char *p = buf;
152
153         while (p < buf + size)
154           {
155             Elf_External_Note *xnp = (Elf_External_Note *) p;
156             Elf_Internal_Note in;
157
158             if (offsetof (Elf_External_Note, name) > buf - p + size)
159               {
160                 ret = 1;
161                 goto out;
162               }
163
164             in.type = BYTE_GET (xnp->type);
165             in.namesz = BYTE_GET (xnp->namesz);
166             in.namedata = xnp->name;
167             if (in.namesz > buf - in.namedata + size)
168               {
169                 ret = 1;
170                 goto out;
171               }
172
173             in.descsz = BYTE_GET (xnp->descsz);
174             in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align);
175             in.descpos = offset + (in.descdata - buf);
176             if (in.descsz != 0
177                 && (in.descdata >= buf + size
178                     || in.descsz > buf - in.descdata + size))
179               {
180                 ret = 1;
181                 goto out;
182               }
183
184             if (in.namesz == sizeof "GNU"
185                 && strcmp (in.namedata, "GNU") == 0
186                 && in.type == NT_GNU_PROPERTY_TYPE_0)
187               {
188                 unsigned char *ptr;
189                 unsigned char *ptr_end;
190
191                 if (in.descsz < 8 || (in.descsz % align) != 0)
192                   {
193                     ret = 1;
194                     goto out;
195                   }
196
197                 ptr = (unsigned char *) in.descdata;
198                 ptr_end = ptr + in.descsz;
199
200                 do
201                   {
202                     unsigned int type = byte_get (ptr, 4);
203                     unsigned int datasz = byte_get (ptr + 4, 4);
204                     unsigned int bitmask, old_bitmask;
205
206                     ptr += 8;
207                     if ((ptr + datasz) > ptr_end)
208                       {
209                         ret = 1;
210                         goto out;
211                       }
212
213                     if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
214                       {
215                         if (datasz != 4)
216                           {
217                             ret = 1;
218                             goto out;
219                           }
220
221                         old_bitmask = byte_get (ptr, 4);
222                         bitmask = old_bitmask;
223                         if (enable_x86_features)
224                           bitmask |= enable_x86_features;
225                         if (disable_x86_features)
226                           bitmask &= ~disable_x86_features;
227                         if (old_bitmask != bitmask)
228                           BYTE_PUT (ptr, bitmask);
229                         goto out;
230                       }
231
232                     ptr += ELF_ALIGN_UP (datasz, align);
233                   }
234                 while ((ptr_end - ptr) >= 8);
235               }
236
237             p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
238           }
239       }
240
241 out:
242   if (ret != 0)
243     error (_("%s: Invalid PT_NOTE segment\n"), file_name);
244
245   free (phdrs);
246   munmap (map, st_buf.st_size);
247
248   return ret;
249 }
250
251 /* Set enable_x86_features and disable_x86_features for a feature
252    string, FEATURE.  */
253
254 static int
255 elf_x86_feature (const char *feature, int enable)
256 {
257   unsigned int x86_feature;
258   if (strcasecmp (feature, "ibt") == 0)
259     x86_feature = GNU_PROPERTY_X86_FEATURE_1_IBT;
260   else if (strcasecmp (feature, "shstk") == 0)
261     x86_feature = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
262   else
263     return -1;
264
265   if (enable)
266     {
267       enable_x86_features |= x86_feature;
268       disable_x86_features &= ~x86_feature;
269     }
270   else
271     {
272       disable_x86_features |= x86_feature;
273       enable_x86_features &= ~x86_feature;
274     }
275
276   return 0;
277 }
278 #endif
279
280 /* Return ELF class for a machine type, MACH.  */
281
282 static enum elfclass
283 elf_class (int mach)
284 {
285   switch (mach)
286     {
287     case EM_386:
288     case EM_IAMCU:
289       return ELF_CLASS_32;
290     case EM_L1OM:
291     case EM_K1OM:
292       return ELF_CLASS_64;
293     case EM_X86_64:
294     case EM_NONE:
295       return ELF_CLASS_BOTH;
296     default:
297       return ELF_CLASS_BOTH;
298     }
299 }
300
301 static int
302 update_elf_header (const char *file_name, FILE *file)
303 {
304   int class, machine, type, status, osabi;
305
306   if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
307     {
308       error
309         (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
310          file_name, elf_header.e_ident[EI_VERSION],
311          EV_CURRENT);
312       return 0;
313     }
314
315   /* Return if e_machine is the same as output_elf_machine.  */
316   if (output_elf_machine == elf_header.e_machine)
317     return 1;
318
319   class = elf_header.e_ident[EI_CLASS];
320   machine = elf_header.e_machine;
321
322   /* Skip if class doesn't match. */
323   if (input_elf_class == ELF_CLASS_UNKNOWN)
324     input_elf_class = elf_class (machine);
325
326   if (input_elf_class != ELF_CLASS_BOTH
327       && (int) input_elf_class != class)
328     {
329       error
330         (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
331          file_name, class, input_elf_class);
332       return 0;
333     }
334
335   if (output_elf_class != ELF_CLASS_BOTH
336       && (int) output_elf_class != class)
337     {
338       error
339         (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
340          file_name, class, output_elf_class);
341       return 0;
342     }
343
344   /* Skip if e_machine doesn't match. */
345   if (input_elf_machine != -1 && machine != input_elf_machine)
346     {
347       error
348         (_("%s: Unmatched e_machine: %d is not %d\n"),
349          file_name, machine, input_elf_machine);
350       return 0;
351     }
352
353   type = elf_header.e_type;
354
355   /* Skip if e_type doesn't match. */
356   if (input_elf_type != -1 && type != input_elf_type)
357     {
358       error
359         (_("%s: Unmatched e_type: %d is not %d\n"),
360          file_name, type, input_elf_type);
361       return 0;
362     }
363
364   osabi = elf_header.e_ident[EI_OSABI];
365
366   /* Skip if OSABI doesn't match. */
367   if (input_elf_osabi != -1 && osabi != input_elf_osabi)
368     {
369       error
370         (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
371          file_name, osabi, input_elf_osabi);
372       return 0;
373     }
374
375   /* Update e_machine, e_type and EI_OSABI.  */
376   switch (class)
377     {
378     default:
379       /* We should never get here.  */
380       abort ();
381       break;
382     case ELFCLASS32:
383       if (output_elf_machine != -1)
384         BYTE_PUT (ehdr32.e_machine, output_elf_machine);
385       if (output_elf_type != -1)
386         BYTE_PUT (ehdr32.e_type, output_elf_type);
387       if (output_elf_osabi != -1)
388         ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
389       status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
390       break;
391     case ELFCLASS64:
392       if (output_elf_machine != -1)
393         BYTE_PUT (ehdr64.e_machine, output_elf_machine);
394       if (output_elf_type != -1)
395         BYTE_PUT (ehdr64.e_type, output_elf_type);
396       if (output_elf_osabi != -1)
397         ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
398       status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
399       break;
400     }
401
402   if (status != 1)
403     error (_("%s: Failed to update ELF header: %s\n"),
404                file_name, strerror (errno));
405
406   return status;
407 }
408
409 static int
410 get_file_header (FILE * file)
411 {
412   /* Read in the identity array.  */
413   if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
414     return 0;
415
416   if (elf_header.e_ident[EI_MAG0] != ELFMAG0
417       || elf_header.e_ident[EI_MAG1] != ELFMAG1
418       || elf_header.e_ident[EI_MAG2] != ELFMAG2
419       || elf_header.e_ident[EI_MAG3] != ELFMAG3)
420     return 0;
421
422   /* Determine how to read the rest of the header.  */
423   switch (elf_header.e_ident[EI_DATA])
424     {
425     default: /* fall through */
426     case ELFDATANONE: /* fall through */
427     case ELFDATA2LSB:
428       byte_get = byte_get_little_endian;
429       byte_put = byte_put_little_endian;
430       break;
431     case ELFDATA2MSB:
432       byte_get = byte_get_big_endian;
433       byte_put = byte_put_big_endian;
434       break;
435     }
436
437   /* Read in the rest of the header.  For now we only support 32 bit
438      and 64 bit ELF files.  */
439   switch (elf_header.e_ident[EI_CLASS])
440     {
441     default:
442       return 0;
443
444     case ELFCLASS32:
445       if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
446                  1, file) != 1)
447         return 0;
448
449       elf_header.e_type      = BYTE_GET (ehdr32.e_type);
450       elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
451       elf_header.e_version   = BYTE_GET (ehdr32.e_version);
452       elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
453       elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
454       elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
455       elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
456       elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
457       elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
458       elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
459       elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
460       elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
461       elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
462
463       memcpy (&ehdr32, &elf_header, EI_NIDENT);
464       break;
465
466     case ELFCLASS64:
467       /* If we have been compiled with sizeof (bfd_vma) == 4, then
468          we will not be able to cope with the 64bit data found in
469          64 ELF files.  Detect this now and abort before we start
470          overwriting things.  */
471       if (sizeof (bfd_vma) < 8)
472         {
473           error (_("This executable has been built without support for a\n\
474 64 bit data type and so it cannot process 64 bit ELF files.\n"));
475           return 0;
476         }
477
478       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
479                  1, file) != 1)
480         return 0;
481
482       elf_header.e_type      = BYTE_GET (ehdr64.e_type);
483       elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
484       elf_header.e_version   = BYTE_GET (ehdr64.e_version);
485       elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
486       elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
487       elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
488       elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
489       elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
490       elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
491       elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
492       elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
493       elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
494       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
495
496       memcpy (&ehdr64, &elf_header, EI_NIDENT);
497       break;
498     }
499   return 1;
500 }
501
502 /* Process one ELF object file according to the command line options.
503    This file may actually be stored in an archive.  The file is
504    positioned at the start of the ELF object.  */
505
506 static int
507 process_object (const char *file_name, FILE *file)
508 {
509   /* Rememeber where we are.  */
510   long offset = ftell (file);
511
512   if (! get_file_header (file))
513     {
514       error (_("%s: Failed to read ELF header\n"), file_name);
515       return 1;
516     }
517
518   /* Go to the position of the ELF header.  */
519   if (fseek (file, offset, SEEK_SET) != 0)
520     {
521       error (_("%s: Failed to seek to ELF header\n"), file_name);
522     }
523
524   if (! update_elf_header (file_name, file))
525     return 1;
526
527   return 0;
528 }
529
530 /* Process an ELF archive.
531    On entry the file is positioned just after the ARMAG string.  */
532
533 static int
534 process_archive (const char * file_name, FILE * file,
535                  bfd_boolean is_thin_archive)
536 {
537   struct archive_info arch;
538   struct archive_info nested_arch;
539   size_t got;
540   int ret;
541
542   /* The ARCH structure is used to hold information about this archive.  */
543   arch.file_name = NULL;
544   arch.file = NULL;
545   arch.index_array = NULL;
546   arch.sym_table = NULL;
547   arch.longnames = NULL;
548
549   /* The NESTED_ARCH structure is used as a single-item cache of information
550      about a nested archive (when members of a thin archive reside within
551      another regular archive file).  */
552   nested_arch.file_name = NULL;
553   nested_arch.file = NULL;
554   nested_arch.index_array = NULL;
555   nested_arch.sym_table = NULL;
556   nested_arch.longnames = NULL;
557
558   if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
559     {
560       ret = 1;
561       goto out;
562     }
563
564   ret = 0;
565
566   while (1)
567     {
568       char * name;
569       size_t namelen;
570       char * qualified_name;
571
572       /* Read the next archive header.  */
573       if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
574         {
575           error (_("%s: failed to seek to next archive header\n"),
576                      file_name);
577           return 1;
578         }
579       got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
580       if (got != sizeof arch.arhdr)
581         {
582           if (got == 0)
583             break;
584           error (_("%s: failed to read archive header\n"),
585                      file_name);
586           ret = 1;
587           break;
588         }
589       if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
590         {
591           error (_("%s: did not find a valid archive header\n"),
592                      arch.file_name);
593           ret = 1;
594           break;
595         }
596
597       arch.next_arhdr_offset += sizeof arch.arhdr;
598
599       archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
600       if (archive_file_size & 01)
601         ++archive_file_size;
602
603       name = get_archive_member_name (&arch, &nested_arch);
604       if (name == NULL)
605         {
606           error (_("%s: bad archive file name\n"), file_name);
607           ret = 1;
608           break;
609         }
610       namelen = strlen (name);
611
612       qualified_name = make_qualified_name (&arch, &nested_arch, name);
613       if (qualified_name == NULL)
614         {
615           error (_("%s: bad archive file name\n"), file_name);
616           ret = 1;
617           break;
618         }
619
620       if (is_thin_archive && arch.nested_member_origin == 0)
621         {
622           /* This is a proxy for an external member of a thin archive.  */
623           FILE *member_file;
624           char *member_file_name = adjust_relative_path (file_name,
625                                                          name, namelen);
626           if (member_file_name == NULL)
627             {
628               ret = 1;
629               break;
630             }
631
632           member_file = fopen (member_file_name, "r+b");
633           if (member_file == NULL)
634             {
635               error (_("Input file '%s' is not readable\n"),
636                          member_file_name);
637               free (member_file_name);
638               ret = 1;
639               break;
640             }
641
642           archive_file_offset = arch.nested_member_origin;
643
644           ret |= process_object (qualified_name, member_file);
645
646           fclose (member_file);
647           free (member_file_name);
648         }
649       else if (is_thin_archive)
650         {
651           /* This is a proxy for a member of a nested archive.  */
652           archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
653
654           /* The nested archive file will have been opened and setup by
655              get_archive_member_name.  */
656           if (fseek (nested_arch.file, archive_file_offset,
657                      SEEK_SET) != 0)
658             {
659               error (_("%s: failed to seek to archive member\n"),
660                          nested_arch.file_name);
661               ret = 1;
662               break;
663             }
664
665           ret |= process_object (qualified_name, nested_arch.file);
666         }
667       else
668         {
669           archive_file_offset = arch.next_arhdr_offset;
670           arch.next_arhdr_offset += archive_file_size;
671
672           ret |= process_object (qualified_name, file);
673         }
674
675       free (qualified_name);
676     }
677
678  out:
679   if (nested_arch.file != NULL)
680     fclose (nested_arch.file);
681   release_archive (&nested_arch);
682   release_archive (&arch);
683
684   return ret;
685 }
686
687 static int
688 check_file (const char *file_name, struct stat *statbuf_p)
689 {
690   struct stat statbuf;
691
692   if (statbuf_p == NULL)
693     statbuf_p = &statbuf;
694
695   if (stat (file_name, statbuf_p) < 0)
696     {
697       if (errno == ENOENT)
698         error (_("'%s': No such file\n"), file_name);
699       else
700         error (_("Could not locate '%s'.  System error message: %s\n"),
701                    file_name, strerror (errno));
702       return 1;
703     }
704
705   if (! S_ISREG (statbuf_p->st_mode))
706     {
707       error (_("'%s' is not an ordinary file\n"), file_name);
708       return 1;
709     }
710
711   return 0;
712 }
713
714 static int
715 process_file (const char *file_name)
716 {
717   FILE * file;
718   char armag[SARMAG];
719   int ret;
720
721   if (check_file (file_name, NULL))
722     return 1;
723
724   file = fopen (file_name, "r+b");
725   if (file == NULL)
726     {
727       error (_("Input file '%s' is not readable\n"), file_name);
728       return 1;
729     }
730
731   if (fread (armag, SARMAG, 1, file) != 1)
732     {
733       error (_("%s: Failed to read file's magic number\n"),
734                  file_name);
735       fclose (file);
736       return 1;
737     }
738
739   if (memcmp (armag, ARMAG, SARMAG) == 0)
740     ret = process_archive (file_name, file, FALSE);
741   else if (memcmp (armag, ARMAGT, SARMAG) == 0)
742     ret = process_archive (file_name, file, TRUE);
743   else
744     {
745       rewind (file);
746       archive_file_size = archive_file_offset = 0;
747       ret = process_object (file_name, file);
748 #ifdef HAVE_MMAP
749       if (!ret
750           && (elf_header.e_type == ET_EXEC
751               || elf_header.e_type == ET_DYN))
752         ret = update_gnu_property (file_name, file);
753 #endif
754     }
755
756   fclose (file);
757
758   return ret;
759 }
760
761 static const struct
762 {
763   int osabi;
764   const char *name;
765 }
766 osabis[] =
767 {
768   { ELFOSABI_NONE, "none" },
769   { ELFOSABI_HPUX, "HPUX" },
770   { ELFOSABI_NETBSD, "NetBSD" },
771   { ELFOSABI_GNU, "GNU" },
772   { ELFOSABI_GNU, "Linux" },
773   { ELFOSABI_SOLARIS, "Solaris" },
774   { ELFOSABI_AIX, "AIX" },
775   { ELFOSABI_IRIX, "Irix" },
776   { ELFOSABI_FREEBSD, "FreeBSD" },
777   { ELFOSABI_TRU64, "TRU64" },
778   { ELFOSABI_MODESTO, "Modesto" },
779   { ELFOSABI_OPENBSD, "OpenBSD" },
780   { ELFOSABI_OPENVMS, "OpenVMS" },
781   { ELFOSABI_NSK, "NSK" },
782   { ELFOSABI_AROS, "AROS" },
783   { ELFOSABI_FENIXOS, "FenixOS" }
784 };
785
786 /* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
787
788 static int
789 elf_osabi (const char *osabi)
790 {
791   unsigned int i;
792
793   for (i = 0; i < ARRAY_SIZE (osabis); i++)
794     if (strcasecmp (osabi, osabis[i].name) == 0)
795       return osabis[i].osabi;
796
797   error (_("Unknown OSABI: %s\n"), osabi);
798
799   return -1;
800 }
801
802 /* Return EM_XXX for a machine string, MACH.  */
803
804 static int
805 elf_machine (const char *mach)
806 {
807   if (strcasecmp (mach, "i386") == 0)
808     return EM_386;
809   if (strcasecmp (mach, "iamcu") == 0)
810     return EM_IAMCU;
811   if (strcasecmp (mach, "l1om") == 0)
812     return EM_L1OM;
813   if (strcasecmp (mach, "k1om") == 0)
814     return EM_K1OM;
815   if (strcasecmp (mach, "x86_64") == 0)
816     return EM_X86_64;
817   if (strcasecmp (mach, "x86-64") == 0)
818     return EM_X86_64;
819   if (strcasecmp (mach, "none") == 0)
820     return EM_NONE;
821
822   error (_("Unknown machine type: %s\n"), mach);
823
824   return -1;
825 }
826
827 /* Return ET_XXX for a type string, TYPE.  */
828
829 static int
830 elf_type (const char *type)
831 {
832   if (strcasecmp (type, "rel") == 0)
833     return ET_REL;
834   if (strcasecmp (type, "exec") == 0)
835     return ET_EXEC;
836   if (strcasecmp (type, "dyn") == 0)
837     return ET_DYN;
838   if (strcasecmp (type, "none") == 0)
839     return ET_NONE;
840
841   error (_("Unknown type: %s\n"), type);
842
843   return -1;
844 }
845
846 enum command_line_switch
847   {
848     OPTION_INPUT_MACH = 150,
849     OPTION_OUTPUT_MACH,
850     OPTION_INPUT_TYPE,
851     OPTION_OUTPUT_TYPE,
852     OPTION_INPUT_OSABI,
853     OPTION_OUTPUT_OSABI,
854 #ifdef HAVE_MMAP
855     OPTION_ENABLE_X86_FEATURE,
856     OPTION_DISABLE_X86_FEATURE,
857 #endif
858   };
859
860 static struct option options[] =
861 {
862   {"input-mach",        required_argument, 0, OPTION_INPUT_MACH},
863   {"output-mach",       required_argument, 0, OPTION_OUTPUT_MACH},
864   {"input-type",        required_argument, 0, OPTION_INPUT_TYPE},
865   {"output-type",       required_argument, 0, OPTION_OUTPUT_TYPE},
866   {"input-osabi",       required_argument, 0, OPTION_INPUT_OSABI},
867   {"output-osabi",      required_argument, 0, OPTION_OUTPUT_OSABI},
868 #ifdef HAVE_MMAP
869   {"enable-x86-feature",
870                         required_argument, 0, OPTION_ENABLE_X86_FEATURE},
871   {"disable-x86-feature",
872                         required_argument, 0, OPTION_DISABLE_X86_FEATURE},
873 #endif
874   {"version",           no_argument, 0, 'v'},
875   {"help",              no_argument, 0, 'h'},
876   {0,                   no_argument, 0, 0}
877 };
878
879 ATTRIBUTE_NORETURN static void
880 usage (FILE *stream, int exit_status)
881 {
882   fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
883            program_name);
884   fprintf (stream, _(" Update the ELF header of ELF files\n"));
885   fprintf (stream, _(" The options are:\n"));
886   fprintf (stream, _("\
887   --input-mach <machine>      Set input machine type to <machine>\n\
888   --output-mach <machine>     Set output machine type to <machine>\n\
889   --input-type <type>         Set input file type to <type>\n\
890   --output-type <type>        Set output file type to <type>\n\
891   --input-osabi <osabi>       Set input OSABI to <osabi>\n\
892   --output-osabi <osabi>      Set output OSABI to <osabi>\n"));
893 #ifdef HAVE_MMAP
894   fprintf (stream, _("\
895   --enable-x86-feature <feature>\n\
896                               Enable x86 feature <feature>\n\
897   --disable-x86-feature <feature>\n\
898                               Disable x86 feature <feature>\n"));
899 #endif
900   fprintf (stream, _("\
901   -h --help                   Display this information\n\
902   -v --version                Display the version number of %s\n\
903 "),
904            program_name);
905   if (REPORT_BUGS_TO[0] && exit_status == 0)
906     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
907   exit (exit_status);
908 }
909
910 int
911 main (int argc, char ** argv)
912 {
913   int c, status;
914
915 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
916   setlocale (LC_MESSAGES, "");
917 #endif
918 #if defined (HAVE_SETLOCALE)
919   setlocale (LC_CTYPE, "");
920 #endif
921   bindtextdomain (PACKAGE, LOCALEDIR);
922   textdomain (PACKAGE);
923
924   expandargv (&argc, &argv);
925
926   while ((c = getopt_long (argc, argv, "hv",
927                            options, (int *) 0)) != EOF)
928     {
929       switch (c)
930         {
931         case OPTION_INPUT_MACH:
932           input_elf_machine = elf_machine (optarg);
933           if (input_elf_machine < 0)
934             return 1;
935           input_elf_class = elf_class (input_elf_machine);
936           if (input_elf_class == ELF_CLASS_UNKNOWN)
937             return 1;
938           break;
939
940         case OPTION_OUTPUT_MACH:
941           output_elf_machine = elf_machine (optarg);
942           if (output_elf_machine < 0)
943             return 1;
944           output_elf_class = elf_class (output_elf_machine);
945           if (output_elf_class == ELF_CLASS_UNKNOWN)
946             return 1;
947           break;
948
949         case OPTION_INPUT_TYPE:
950           input_elf_type = elf_type (optarg);
951           if (input_elf_type < 0)
952             return 1;
953           break;
954
955         case OPTION_OUTPUT_TYPE:
956           output_elf_type = elf_type (optarg);
957           if (output_elf_type < 0)
958             return 1;
959           break;
960
961         case OPTION_INPUT_OSABI:
962           input_elf_osabi = elf_osabi (optarg);
963           if (input_elf_osabi < 0)
964             return 1;
965           break;
966
967         case OPTION_OUTPUT_OSABI:
968           output_elf_osabi = elf_osabi (optarg);
969           if (output_elf_osabi < 0)
970             return 1;
971           break;
972
973 #ifdef HAVE_MMAP
974         case OPTION_ENABLE_X86_FEATURE:
975           if (elf_x86_feature (optarg, 1) < 0)
976             return 1;
977           break;
978
979         case OPTION_DISABLE_X86_FEATURE:
980           if (elf_x86_feature (optarg, 0) < 0)
981             return 1;
982           break;
983 #endif
984
985         case 'h':
986           usage (stdout, 0);
987
988         case 'v':
989           print_version (program_name);
990           break;
991
992         default:
993           usage (stderr, 1);
994         }
995     }
996
997   if (optind == argc
998       || (output_elf_machine == -1
999 #ifdef HAVE_MMAP
1000          && ! enable_x86_features
1001          && ! disable_x86_features
1002 #endif
1003           && output_elf_type == -1
1004           && output_elf_osabi == -1))
1005     usage (stderr, 1);
1006
1007   status = 0;
1008   while (optind < argc)
1009     status |= process_file (argv[optind++]);
1010
1011   return status;
1012 }