]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/elfedit.c
Automatic date update in version.in
[thirdparty/binutils-gdb.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 }