1 /* elfedit.c -- Update the ELF header of an ELF format file
2    Copyright (C) 2010-2020 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 
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, 4);
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     {
264       error (_("Unknown x86 feature: %s\n"), feature);
265       return -1;
266     }
267 
268   if (enable)
269     {
270       enable_x86_features |= x86_feature;
271       disable_x86_features &= ~x86_feature;
272     }
273   else
274     {
275       disable_x86_features |= x86_feature;
276       enable_x86_features &= ~x86_feature;
277     }
278 
279   return 0;
280 }
281 #endif
282 
283 /* Return ELF class for a machine type, MACH.  */
284 
285 static enum elfclass
286 elf_class (int mach)
287 {
288   switch (mach)
289     {
290     case EM_386:
291     case EM_IAMCU:
292       return ELF_CLASS_32;
293     case EM_L1OM:
294     case EM_K1OM:
295       return ELF_CLASS_64;
296     case EM_X86_64:
297     case EM_NONE:
298       return ELF_CLASS_BOTH;
299     default:
300       return ELF_CLASS_BOTH;
301     }
302 }
303 
304 static int
305 update_elf_header (const char *file_name, FILE *file)
306 {
307   int class, machine, type, status, osabi;
308 
309   if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
310     {
311       error
312 	(_("%s: Unsupported EI_VERSION: %d is not %d\n"),
313 	 file_name, elf_header.e_ident[EI_VERSION],
314 	 EV_CURRENT);
315       return 0;
316     }
317 
318   /* Return if e_machine is the same as output_elf_machine.  */
319   if (output_elf_machine == elf_header.e_machine)
320     return 1;
321 
322   class = elf_header.e_ident[EI_CLASS];
323   machine = elf_header.e_machine;
324 
325   /* Skip if class doesn't match. */
326   if (input_elf_class == ELF_CLASS_UNKNOWN)
327     input_elf_class = elf_class (machine);
328 
329   if (input_elf_class != ELF_CLASS_BOTH
330       && (int) input_elf_class != class)
331     {
332       error
333 	(_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
334 	 file_name, class, input_elf_class);
335       return 0;
336     }
337 
338   if (output_elf_class != ELF_CLASS_BOTH
339       && (int) output_elf_class != class)
340     {
341       error
342 	(_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
343 	 file_name, class, output_elf_class);
344       return 0;
345     }
346 
347   /* Skip if e_machine doesn't match. */
348   if (input_elf_machine != -1 && machine != input_elf_machine)
349     {
350       error
351 	(_("%s: Unmatched e_machine: %d is not %d\n"),
352 	 file_name, machine, input_elf_machine);
353       return 0;
354     }
355 
356   type = elf_header.e_type;
357 
358   /* Skip if e_type doesn't match. */
359   if (input_elf_type != -1 && type != input_elf_type)
360     {
361       error
362 	(_("%s: Unmatched e_type: %d is not %d\n"),
363 	 file_name, type, input_elf_type);
364       return 0;
365     }
366 
367   osabi = elf_header.e_ident[EI_OSABI];
368 
369   /* Skip if OSABI doesn't match. */
370   if (input_elf_osabi != -1 && osabi != input_elf_osabi)
371     {
372       error
373 	(_("%s: Unmatched EI_OSABI: %d is not %d\n"),
374 	 file_name, osabi, input_elf_osabi);
375       return 0;
376     }
377 
378   /* Update e_machine, e_type and EI_OSABI.  */
379   switch (class)
380     {
381     default:
382       /* We should never get here.  */
383       abort ();
384       break;
385     case ELFCLASS32:
386       if (output_elf_machine != -1)
387 	BYTE_PUT (ehdr32.e_machine, output_elf_machine);
388       if (output_elf_type != -1)
389 	BYTE_PUT (ehdr32.e_type, output_elf_type);
390       if (output_elf_osabi != -1)
391 	ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
392       status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
393       break;
394     case ELFCLASS64:
395       if (output_elf_machine != -1)
396 	BYTE_PUT (ehdr64.e_machine, output_elf_machine);
397       if (output_elf_type != -1)
398 	BYTE_PUT (ehdr64.e_type, output_elf_type);
399       if (output_elf_osabi != -1)
400 	ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
401       status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
402       break;
403     }
404 
405   if (status != 1)
406     error (_("%s: Failed to update ELF header: %s\n"),
407 	       file_name, strerror (errno));
408 
409   return status;
410 }
411 
412 static int
413 get_file_header (FILE * file)
414 {
415   /* Read in the identity array.  */
416   if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
417     return 0;
418 
419   if (elf_header.e_ident[EI_MAG0] != ELFMAG0
420       || elf_header.e_ident[EI_MAG1] != ELFMAG1
421       || elf_header.e_ident[EI_MAG2] != ELFMAG2
422       || elf_header.e_ident[EI_MAG3] != ELFMAG3)
423     return 0;
424 
425   /* Determine how to read the rest of the header.  */
426   switch (elf_header.e_ident[EI_DATA])
427     {
428     default: /* fall through */
429     case ELFDATANONE: /* fall through */
430     case ELFDATA2LSB:
431       byte_get = byte_get_little_endian;
432       byte_put = byte_put_little_endian;
433       break;
434     case ELFDATA2MSB:
435       byte_get = byte_get_big_endian;
436       byte_put = byte_put_big_endian;
437       break;
438     }
439 
440   /* Read in the rest of the header.  For now we only support 32 bit
441      and 64 bit ELF files.  */
442   switch (elf_header.e_ident[EI_CLASS])
443     {
444     default:
445       return 0;
446 
447     case ELFCLASS32:
448       if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
449 		 1, file) != 1)
450 	return 0;
451 
452       elf_header.e_type      = BYTE_GET (ehdr32.e_type);
453       elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
454       elf_header.e_version   = BYTE_GET (ehdr32.e_version);
455       elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
456       elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
457       elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
458       elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
459       elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
460       elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
461       elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
462       elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
463       elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
464       elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
465 
466       memcpy (&ehdr32, &elf_header, EI_NIDENT);
467       break;
468 
469     case ELFCLASS64:
470       /* If we have been compiled with sizeof (bfd_vma) == 4, then
471 	 we will not be able to cope with the 64bit data found in
472 	 64 ELF files.  Detect this now and abort before we start
473 	 overwriting things.  */
474       if (sizeof (bfd_vma) < 8)
475 	{
476 	  error (_("This executable has been built without support for a\n\
477 64 bit data type and so it cannot process 64 bit ELF files.\n"));
478 	  return 0;
479 	}
480 
481       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
482 		 1, file) != 1)
483 	return 0;
484 
485       elf_header.e_type      = BYTE_GET (ehdr64.e_type);
486       elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
487       elf_header.e_version   = BYTE_GET (ehdr64.e_version);
488       elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
489       elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
490       elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
491       elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
492       elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
493       elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
494       elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
495       elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
496       elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
497       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
498 
499       memcpy (&ehdr64, &elf_header, EI_NIDENT);
500       break;
501     }
502   return 1;
503 }
504 
505 /* Process one ELF object file according to the command line options.
506    This file may actually be stored in an archive.  The file is
507    positioned at the start of the ELF object.  */
508 
509 static int
510 process_object (const char *file_name, FILE *file)
511 {
512   /* Rememeber where we are.  */
513   long offset = ftell (file);
514 
515   if (! get_file_header (file))
516     {
517       error (_("%s: Failed to read ELF header\n"), file_name);
518       return 1;
519     }
520 
521   /* Go to the position of the ELF header.  */
522   if (fseek (file, offset, SEEK_SET) != 0)
523     {
524       error (_("%s: Failed to seek to ELF header\n"), file_name);
525     }
526 
527   if (! update_elf_header (file_name, file))
528     return 1;
529 
530   return 0;
531 }
532 
533 /* Process an ELF archive.
534    On entry the file is positioned just after the ARMAG string.  */
535 
536 static int
537 process_archive (const char * file_name, FILE * file,
538 		 bfd_boolean is_thin_archive)
539 {
540   struct archive_info arch;
541   struct archive_info nested_arch;
542   size_t got;
543   int ret;
544 
545   /* The ARCH structure is used to hold information about this archive.  */
546   arch.file_name = NULL;
547   arch.file = NULL;
548   arch.index_array = NULL;
549   arch.sym_table = NULL;
550   arch.longnames = NULL;
551 
552   /* The NESTED_ARCH structure is used as a single-item cache of information
553      about a nested archive (when members of a thin archive reside within
554      another regular archive file).  */
555   nested_arch.file_name = NULL;
556   nested_arch.file = NULL;
557   nested_arch.index_array = NULL;
558   nested_arch.sym_table = NULL;
559   nested_arch.longnames = NULL;
560 
561   if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
562     {
563       ret = 1;
564       goto out;
565     }
566 
567   ret = 0;
568 
569   while (1)
570     {
571       char * name;
572       size_t namelen;
573       char * qualified_name;
574 
575       /* Read the next archive header.  */
576       if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
577         {
578           error (_("%s: failed to seek to next archive header\n"),
579 		     file_name);
580           return 1;
581         }
582       got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
583       if (got != sizeof arch.arhdr)
584         {
585           if (got == 0)
586 	    break;
587           error (_("%s: failed to read archive header\n"),
588 		     file_name);
589           ret = 1;
590           break;
591         }
592       if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
593         {
594           error (_("%s: did not find a valid archive header\n"),
595 		     arch.file_name);
596           ret = 1;
597           break;
598         }
599 
600       arch.next_arhdr_offset += sizeof arch.arhdr;
601 
602       archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
603       if (archive_file_size & 01)
604         ++archive_file_size;
605 
606       name = get_archive_member_name (&arch, &nested_arch);
607       if (name == NULL)
608 	{
609 	  error (_("%s: bad archive file name\n"), file_name);
610 	  ret = 1;
611 	  break;
612 	}
613       namelen = strlen (name);
614 
615       qualified_name = make_qualified_name (&arch, &nested_arch, name);
616       if (qualified_name == NULL)
617 	{
618 	  error (_("%s: bad archive file name\n"), file_name);
619 	  ret = 1;
620 	  break;
621 	}
622 
623       if (is_thin_archive && arch.nested_member_origin == 0)
624         {
625           /* This is a proxy for an external member of a thin archive.  */
626           FILE *member_file;
627           char *member_file_name = adjust_relative_path (file_name,
628 							 name, namelen);
629           if (member_file_name == NULL)
630             {
631               ret = 1;
632               break;
633             }
634 
635           member_file = fopen (member_file_name, "r+b");
636           if (member_file == NULL)
637             {
638               error (_("Input file '%s' is not readable\n"),
639 			 member_file_name);
640               free (member_file_name);
641               ret = 1;
642               break;
643             }
644 
645           archive_file_offset = arch.nested_member_origin;
646 
647           ret |= process_object (qualified_name, member_file);
648 
649           fclose (member_file);
650           free (member_file_name);
651         }
652       else if (is_thin_archive)
653         {
654           /* This is a proxy for a member of a nested archive.  */
655           archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
656 
657           /* The nested archive file will have been opened and setup by
658              get_archive_member_name.  */
659           if (fseek (nested_arch.file, archive_file_offset,
660 		     SEEK_SET) != 0)
661             {
662               error (_("%s: failed to seek to archive member\n"),
663 			 nested_arch.file_name);
664               ret = 1;
665               break;
666             }
667 
668           ret |= process_object (qualified_name, nested_arch.file);
669         }
670       else
671         {
672           archive_file_offset = arch.next_arhdr_offset;
673           arch.next_arhdr_offset += archive_file_size;
674 
675           ret |= process_object (qualified_name, file);
676         }
677 
678       free (qualified_name);
679     }
680 
681  out:
682   if (nested_arch.file != NULL)
683     fclose (nested_arch.file);
684   release_archive (&nested_arch);
685   release_archive (&arch);
686 
687   return ret;
688 }
689 
690 static int
691 check_file (const char *file_name, struct stat *statbuf_p)
692 {
693   struct stat statbuf;
694 
695   if (statbuf_p == NULL)
696     statbuf_p = &statbuf;
697 
698   if (stat (file_name, statbuf_p) < 0)
699     {
700       if (errno == ENOENT)
701 	error (_("'%s': No such file\n"), file_name);
702       else
703 	error (_("Could not locate '%s'.  System error message: %s\n"),
704 		   file_name, strerror (errno));
705       return 1;
706     }
707 
708   if (! S_ISREG (statbuf_p->st_mode))
709     {
710       error (_("'%s' is not an ordinary file\n"), file_name);
711       return 1;
712     }
713 
714   return 0;
715 }
716 
717 static int
718 process_file (const char *file_name)
719 {
720   FILE * file;
721   char armag[SARMAG];
722   int ret;
723 
724   if (check_file (file_name, NULL))
725     return 1;
726 
727   file = fopen (file_name, "r+b");
728   if (file == NULL)
729     {
730       error (_("Input file '%s' is not readable\n"), file_name);
731       return 1;
732     }
733 
734   if (fread (armag, SARMAG, 1, file) != 1)
735     {
736       error (_("%s: Failed to read file's magic number\n"),
737 		 file_name);
738       fclose (file);
739       return 1;
740     }
741 
742   if (memcmp (armag, ARMAG, SARMAG) == 0)
743     ret = process_archive (file_name, file, FALSE);
744   else if (memcmp (armag, ARMAGT, SARMAG) == 0)
745     ret = process_archive (file_name, file, TRUE);
746   else
747     {
748       rewind (file);
749       archive_file_size = archive_file_offset = 0;
750       ret = process_object (file_name, file);
751 #ifdef HAVE_MMAP
752       if (!ret
753 	  && (elf_header.e_type == ET_EXEC
754 	      || elf_header.e_type == ET_DYN))
755 	ret = update_gnu_property (file_name, file);
756 #endif
757     }
758 
759   fclose (file);
760 
761   return ret;
762 }
763 
764 static const struct
765 {
766   int osabi;
767   const char *name;
768 }
769 osabis[] =
770 {
771   { ELFOSABI_NONE, "none" },
772   { ELFOSABI_HPUX, "HPUX" },
773   { ELFOSABI_NETBSD, "NetBSD" },
774   { ELFOSABI_GNU, "GNU" },
775   { ELFOSABI_GNU, "Linux" },
776   { ELFOSABI_SOLARIS, "Solaris" },
777   { ELFOSABI_AIX, "AIX" },
778   { ELFOSABI_IRIX, "Irix" },
779   { ELFOSABI_FREEBSD, "FreeBSD" },
780   { ELFOSABI_TRU64, "TRU64" },
781   { ELFOSABI_MODESTO, "Modesto" },
782   { ELFOSABI_OPENBSD, "OpenBSD" },
783   { ELFOSABI_OPENVMS, "OpenVMS" },
784   { ELFOSABI_NSK, "NSK" },
785   { ELFOSABI_AROS, "AROS" },
786   { ELFOSABI_FENIXOS, "FenixOS" }
787 };
788 
789 /* Return ELFOSABI_XXX for an OSABI string, OSABI.  */
790 
791 static int
792 elf_osabi (const char *osabi)
793 {
794   unsigned int i;
795 
796   for (i = 0; i < ARRAY_SIZE (osabis); i++)
797     if (strcasecmp (osabi, osabis[i].name) == 0)
798       return osabis[i].osabi;
799 
800   error (_("Unknown OSABI: %s\n"), osabi);
801 
802   return -1;
803 }
804 
805 /* Return EM_XXX for a machine string, MACH.  */
806 
807 static int
808 elf_machine (const char *mach)
809 {
810   if (strcasecmp (mach, "i386") == 0)
811     return EM_386;
812   if (strcasecmp (mach, "iamcu") == 0)
813     return EM_IAMCU;
814   if (strcasecmp (mach, "l1om") == 0)
815     return EM_L1OM;
816   if (strcasecmp (mach, "k1om") == 0)
817     return EM_K1OM;
818   if (strcasecmp (mach, "x86_64") == 0)
819     return EM_X86_64;
820   if (strcasecmp (mach, "x86-64") == 0)
821     return EM_X86_64;
822   if (strcasecmp (mach, "none") == 0)
823     return EM_NONE;
824 
825   error (_("Unknown machine type: %s\n"), mach);
826 
827   return -1;
828 }
829 
830 /* Return ET_XXX for a type string, TYPE.  */
831 
832 static int
833 elf_type (const char *type)
834 {
835   if (strcasecmp (type, "rel") == 0)
836     return ET_REL;
837   if (strcasecmp (type, "exec") == 0)
838     return ET_EXEC;
839   if (strcasecmp (type, "dyn") == 0)
840     return ET_DYN;
841   if (strcasecmp (type, "none") == 0)
842     return ET_NONE;
843 
844   error (_("Unknown type: %s\n"), type);
845 
846   return -1;
847 }
848 
849 enum command_line_switch
850   {
851     OPTION_INPUT_MACH = 150,
852     OPTION_OUTPUT_MACH,
853     OPTION_INPUT_TYPE,
854     OPTION_OUTPUT_TYPE,
855     OPTION_INPUT_OSABI,
856     OPTION_OUTPUT_OSABI,
857 #ifdef HAVE_MMAP
858     OPTION_ENABLE_X86_FEATURE,
859     OPTION_DISABLE_X86_FEATURE,
860 #endif
861   };
862 
863 static struct option options[] =
864 {
865   {"input-mach",	required_argument, 0, OPTION_INPUT_MACH},
866   {"output-mach",	required_argument, 0, OPTION_OUTPUT_MACH},
867   {"input-type",	required_argument, 0, OPTION_INPUT_TYPE},
868   {"output-type",	required_argument, 0, OPTION_OUTPUT_TYPE},
869   {"input-osabi",	required_argument, 0, OPTION_INPUT_OSABI},
870   {"output-osabi",	required_argument, 0, OPTION_OUTPUT_OSABI},
871 #ifdef HAVE_MMAP
872   {"enable-x86-feature",
873 			required_argument, 0, OPTION_ENABLE_X86_FEATURE},
874   {"disable-x86-feature",
875 			required_argument, 0, OPTION_DISABLE_X86_FEATURE},
876 #endif
877   {"version",		no_argument, 0, 'v'},
878   {"help",		no_argument, 0, 'h'},
879   {0,			no_argument, 0, 0}
880 };
881 
882 ATTRIBUTE_NORETURN static void
883 usage (FILE *stream, int exit_status)
884 {
885   fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
886 	   program_name);
887   fprintf (stream, _(" Update the ELF header of ELF files\n"));
888   fprintf (stream, _(" The options are:\n"));
889   fprintf (stream, _("\
890   --input-mach <machine>      Set input machine type to <machine>\n\
891   --output-mach <machine>     Set output machine type to <machine>\n\
892   --input-type <type>         Set input file type to <type>\n\
893   --output-type <type>        Set output file type to <type>\n\
894   --input-osabi <osabi>       Set input OSABI to <osabi>\n\
895   --output-osabi <osabi>      Set output OSABI to <osabi>\n"));
896 #ifdef HAVE_MMAP
897   fprintf (stream, _("\
898   --enable-x86-feature <feature>\n\
899                               Enable x86 feature <feature>\n\
900   --disable-x86-feature <feature>\n\
901                               Disable x86 feature <feature>\n"));
902 #endif
903   fprintf (stream, _("\
904   -h --help                   Display this information\n\
905   -v --version                Display the version number of %s\n\
906 "),
907 	   program_name);
908   if (REPORT_BUGS_TO[0] && exit_status == 0)
909     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
910   exit (exit_status);
911 }
912 
913 int
914 main (int argc, char ** argv)
915 {
916   int c, status;
917 
918 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
919   setlocale (LC_MESSAGES, "");
920 #endif
921 #if defined (HAVE_SETLOCALE)
922   setlocale (LC_CTYPE, "");
923 #endif
924   bindtextdomain (PACKAGE, LOCALEDIR);
925   textdomain (PACKAGE);
926 
927   expandargv (&argc, &argv);
928 
929   while ((c = getopt_long (argc, argv, "hv",
930 			   options, (int *) 0)) != EOF)
931     {
932       switch (c)
933 	{
934 	case OPTION_INPUT_MACH:
935 	  input_elf_machine = elf_machine (optarg);
936 	  if (input_elf_machine < 0)
937 	    return 1;
938 	  input_elf_class = elf_class (input_elf_machine);
939 	  if (input_elf_class == ELF_CLASS_UNKNOWN)
940 	    return 1;
941 	  break;
942 
943 	case OPTION_OUTPUT_MACH:
944 	  output_elf_machine = elf_machine (optarg);
945 	  if (output_elf_machine < 0)
946 	    return 1;
947 	  output_elf_class = elf_class (output_elf_machine);
948 	  if (output_elf_class == ELF_CLASS_UNKNOWN)
949 	    return 1;
950 	  break;
951 
952 	case OPTION_INPUT_TYPE:
953 	  input_elf_type = elf_type (optarg);
954 	  if (input_elf_type < 0)
955 	    return 1;
956 	  break;
957 
958 	case OPTION_OUTPUT_TYPE:
959 	  output_elf_type = elf_type (optarg);
960 	  if (output_elf_type < 0)
961 	    return 1;
962 	  break;
963 
964 	case OPTION_INPUT_OSABI:
965 	  input_elf_osabi = elf_osabi (optarg);
966 	  if (input_elf_osabi < 0)
967 	    return 1;
968 	  break;
969 
970 	case OPTION_OUTPUT_OSABI:
971 	  output_elf_osabi = elf_osabi (optarg);
972 	  if (output_elf_osabi < 0)
973 	    return 1;
974 	  break;
975 
976 #ifdef HAVE_MMAP
977 	case OPTION_ENABLE_X86_FEATURE:
978 	  if (elf_x86_feature (optarg, 1) < 0)
979 	    return 1;
980 	  break;
981 
982 	case OPTION_DISABLE_X86_FEATURE:
983 	  if (elf_x86_feature (optarg, 0) < 0)
984 	    return 1;
985 	  break;
986 #endif
987 
988 	case 'h':
989 	  usage (stdout, 0);
990 
991 	case 'v':
992 	  print_version (program_name);
993 	  break;
994 
995 	default:
996 	  usage (stderr, 1);
997 	}
998     }
999 
1000   if (optind == argc
1001       || (output_elf_machine == -1
1002 #ifdef HAVE_MMAP
1003 	 && ! enable_x86_features
1004 	 && ! disable_x86_features
1005 #endif
1006 	  && output_elf_type == -1
1007 	  && output_elf_osabi == -1))
1008     usage (stderr, 1);
1009 
1010   status = 0;
1011   while (optind < argc)
1012     status |= process_file (argv[optind++]);
1013 
1014   return status;
1015 }
1016