]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/elfedit.c
asan: more readelf leaks
[thirdparty/binutils-gdb.git] / binutils / elfedit.c
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 \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, 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 free (name);
620 ret = 1;
621 break;
622 }
623
624 if (is_thin_archive && arch.nested_member_origin == 0)
625 {
626 /* This is a proxy for an external member of a thin archive. */
627 FILE *member_file;
628 char *member_file_name = adjust_relative_path (file_name,
629 name, namelen);
630 free (name);
631 if (member_file_name == NULL)
632 {
633 free (qualified_name);
634 ret = 1;
635 break;
636 }
637
638 member_file = fopen (member_file_name, "r+b");
639 if (member_file == NULL)
640 {
641 error (_("Input file '%s' is not readable\n"),
642 member_file_name);
643 free (member_file_name);
644 free (qualified_name);
645 ret = 1;
646 break;
647 }
648
649 archive_file_offset = arch.nested_member_origin;
650
651 ret |= process_object (qualified_name, member_file);
652
653 fclose (member_file);
654 free (member_file_name);
655 free (qualified_name);
656 }
657 else if (is_thin_archive)
658 {
659 free (name);
660
661 /* This is a proxy for a member of a nested archive. */
662 archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
663
664 /* The nested archive file will have been opened and setup by
665 get_archive_member_name. */
666 if (fseek (nested_arch.file, archive_file_offset,
667 SEEK_SET) != 0)
668 {
669 error (_("%s: failed to seek to archive member\n"),
670 nested_arch.file_name);
671 free (qualified_name);
672 ret = 1;
673 break;
674 }
675
676 ret |= process_object (qualified_name, nested_arch.file);
677 }
678 else
679 {
680 free (name);
681 archive_file_offset = arch.next_arhdr_offset;
682 arch.next_arhdr_offset += archive_file_size;
683
684 ret |= process_object (qualified_name, file);
685 }
686
687 free (qualified_name);
688 }
689
690 out:
691 if (nested_arch.file != NULL)
692 fclose (nested_arch.file);
693 release_archive (&nested_arch);
694 release_archive (&arch);
695
696 return ret;
697 }
698
699 static int
700 check_file (const char *file_name, struct stat *statbuf_p)
701 {
702 struct stat statbuf;
703
704 if (statbuf_p == NULL)
705 statbuf_p = &statbuf;
706
707 if (stat (file_name, statbuf_p) < 0)
708 {
709 if (errno == ENOENT)
710 error (_("'%s': No such file\n"), file_name);
711 else
712 error (_("Could not locate '%s'. System error message: %s\n"),
713 file_name, strerror (errno));
714 return 1;
715 }
716
717 if (! S_ISREG (statbuf_p->st_mode))
718 {
719 error (_("'%s' is not an ordinary file\n"), file_name);
720 return 1;
721 }
722
723 return 0;
724 }
725
726 static int
727 process_file (const char *file_name)
728 {
729 FILE * file;
730 char armag[SARMAG];
731 int ret;
732
733 if (check_file (file_name, NULL))
734 return 1;
735
736 file = fopen (file_name, "r+b");
737 if (file == NULL)
738 {
739 error (_("Input file '%s' is not readable\n"), file_name);
740 return 1;
741 }
742
743 if (fread (armag, SARMAG, 1, file) != 1)
744 {
745 error (_("%s: Failed to read file's magic number\n"),
746 file_name);
747 fclose (file);
748 return 1;
749 }
750
751 if (memcmp (armag, ARMAG, SARMAG) == 0)
752 ret = process_archive (file_name, file, FALSE);
753 else if (memcmp (armag, ARMAGT, SARMAG) == 0)
754 ret = process_archive (file_name, file, TRUE);
755 else
756 {
757 rewind (file);
758 archive_file_size = archive_file_offset = 0;
759 ret = process_object (file_name, file);
760 #ifdef HAVE_MMAP
761 if (!ret
762 && (elf_header.e_type == ET_EXEC
763 || elf_header.e_type == ET_DYN))
764 ret = update_gnu_property (file_name, file);
765 #endif
766 }
767
768 fclose (file);
769
770 return ret;
771 }
772
773 static const struct
774 {
775 int osabi;
776 const char *name;
777 }
778 osabis[] =
779 {
780 { ELFOSABI_NONE, "none" },
781 { ELFOSABI_HPUX, "HPUX" },
782 { ELFOSABI_NETBSD, "NetBSD" },
783 { ELFOSABI_GNU, "GNU" },
784 { ELFOSABI_GNU, "Linux" },
785 { ELFOSABI_SOLARIS, "Solaris" },
786 { ELFOSABI_AIX, "AIX" },
787 { ELFOSABI_IRIX, "Irix" },
788 { ELFOSABI_FREEBSD, "FreeBSD" },
789 { ELFOSABI_TRU64, "TRU64" },
790 { ELFOSABI_MODESTO, "Modesto" },
791 { ELFOSABI_OPENBSD, "OpenBSD" },
792 { ELFOSABI_OPENVMS, "OpenVMS" },
793 { ELFOSABI_NSK, "NSK" },
794 { ELFOSABI_AROS, "AROS" },
795 { ELFOSABI_FENIXOS, "FenixOS" }
796 };
797
798 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
799
800 static int
801 elf_osabi (const char *osabi)
802 {
803 unsigned int i;
804
805 for (i = 0; i < ARRAY_SIZE (osabis); i++)
806 if (strcasecmp (osabi, osabis[i].name) == 0)
807 return osabis[i].osabi;
808
809 error (_("Unknown OSABI: %s\n"), osabi);
810
811 return -1;
812 }
813
814 /* Return EM_XXX for a machine string, MACH. */
815
816 static int
817 elf_machine (const char *mach)
818 {
819 if (strcasecmp (mach, "i386") == 0)
820 return EM_386;
821 if (strcasecmp (mach, "iamcu") == 0)
822 return EM_IAMCU;
823 if (strcasecmp (mach, "l1om") == 0)
824 return EM_L1OM;
825 if (strcasecmp (mach, "k1om") == 0)
826 return EM_K1OM;
827 if (strcasecmp (mach, "x86_64") == 0)
828 return EM_X86_64;
829 if (strcasecmp (mach, "x86-64") == 0)
830 return EM_X86_64;
831 if (strcasecmp (mach, "none") == 0)
832 return EM_NONE;
833
834 error (_("Unknown machine type: %s\n"), mach);
835
836 return -1;
837 }
838
839 /* Return ET_XXX for a type string, TYPE. */
840
841 static int
842 elf_type (const char *type)
843 {
844 if (strcasecmp (type, "rel") == 0)
845 return ET_REL;
846 if (strcasecmp (type, "exec") == 0)
847 return ET_EXEC;
848 if (strcasecmp (type, "dyn") == 0)
849 return ET_DYN;
850 if (strcasecmp (type, "none") == 0)
851 return ET_NONE;
852
853 error (_("Unknown type: %s\n"), type);
854
855 return -1;
856 }
857
858 enum command_line_switch
859 {
860 OPTION_INPUT_MACH = 150,
861 OPTION_OUTPUT_MACH,
862 OPTION_INPUT_TYPE,
863 OPTION_OUTPUT_TYPE,
864 OPTION_INPUT_OSABI,
865 OPTION_OUTPUT_OSABI,
866 #ifdef HAVE_MMAP
867 OPTION_ENABLE_X86_FEATURE,
868 OPTION_DISABLE_X86_FEATURE,
869 #endif
870 };
871
872 static struct option options[] =
873 {
874 {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
875 {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
876 {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
877 {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
878 {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
879 {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
880 #ifdef HAVE_MMAP
881 {"enable-x86-feature",
882 required_argument, 0, OPTION_ENABLE_X86_FEATURE},
883 {"disable-x86-feature",
884 required_argument, 0, OPTION_DISABLE_X86_FEATURE},
885 #endif
886 {"version", no_argument, 0, 'v'},
887 {"help", no_argument, 0, 'h'},
888 {0, no_argument, 0, 0}
889 };
890
891 ATTRIBUTE_NORETURN static void
892 usage (FILE *stream, int exit_status)
893 {
894 fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
895 program_name);
896 fprintf (stream, _(" Update the ELF header of ELF files\n"));
897 fprintf (stream, _(" The options are:\n"));
898 fprintf (stream, _("\
899 --input-mach <machine> Set input machine type to <machine>\n\
900 --output-mach <machine> Set output machine type to <machine>\n\
901 --input-type <type> Set input file type to <type>\n\
902 --output-type <type> Set output file type to <type>\n\
903 --input-osabi <osabi> Set input OSABI to <osabi>\n\
904 --output-osabi <osabi> Set output OSABI to <osabi>\n"));
905 #ifdef HAVE_MMAP
906 fprintf (stream, _("\
907 --enable-x86-feature <feature>\n\
908 Enable x86 feature <feature>\n\
909 --disable-x86-feature <feature>\n\
910 Disable x86 feature <feature>\n"));
911 #endif
912 fprintf (stream, _("\
913 -h --help Display this information\n\
914 -v --version Display the version number of %s\n\
915 "),
916 program_name);
917 if (REPORT_BUGS_TO[0] && exit_status == 0)
918 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
919 exit (exit_status);
920 }
921
922 int
923 main (int argc, char ** argv)
924 {
925 int c, status;
926
927 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
928 setlocale (LC_MESSAGES, "");
929 #endif
930 #if defined (HAVE_SETLOCALE)
931 setlocale (LC_CTYPE, "");
932 #endif
933 bindtextdomain (PACKAGE, LOCALEDIR);
934 textdomain (PACKAGE);
935
936 expandargv (&argc, &argv);
937
938 while ((c = getopt_long (argc, argv, "hv",
939 options, (int *) 0)) != EOF)
940 {
941 switch (c)
942 {
943 case OPTION_INPUT_MACH:
944 input_elf_machine = elf_machine (optarg);
945 if (input_elf_machine < 0)
946 return 1;
947 input_elf_class = elf_class (input_elf_machine);
948 if (input_elf_class == ELF_CLASS_UNKNOWN)
949 return 1;
950 break;
951
952 case OPTION_OUTPUT_MACH:
953 output_elf_machine = elf_machine (optarg);
954 if (output_elf_machine < 0)
955 return 1;
956 output_elf_class = elf_class (output_elf_machine);
957 if (output_elf_class == ELF_CLASS_UNKNOWN)
958 return 1;
959 break;
960
961 case OPTION_INPUT_TYPE:
962 input_elf_type = elf_type (optarg);
963 if (input_elf_type < 0)
964 return 1;
965 break;
966
967 case OPTION_OUTPUT_TYPE:
968 output_elf_type = elf_type (optarg);
969 if (output_elf_type < 0)
970 return 1;
971 break;
972
973 case OPTION_INPUT_OSABI:
974 input_elf_osabi = elf_osabi (optarg);
975 if (input_elf_osabi < 0)
976 return 1;
977 break;
978
979 case OPTION_OUTPUT_OSABI:
980 output_elf_osabi = elf_osabi (optarg);
981 if (output_elf_osabi < 0)
982 return 1;
983 break;
984
985 #ifdef HAVE_MMAP
986 case OPTION_ENABLE_X86_FEATURE:
987 if (elf_x86_feature (optarg, 1) < 0)
988 return 1;
989 break;
990
991 case OPTION_DISABLE_X86_FEATURE:
992 if (elf_x86_feature (optarg, 0) < 0)
993 return 1;
994 break;
995 #endif
996
997 case 'h':
998 usage (stdout, 0);
999
1000 case 'v':
1001 print_version (program_name);
1002 break;
1003
1004 default:
1005 usage (stderr, 1);
1006 }
1007 }
1008
1009 if (optind == argc
1010 || (output_elf_machine == -1
1011 #ifdef HAVE_MMAP
1012 && ! enable_x86_features
1013 && ! disable_x86_features
1014 #endif
1015 && output_elf_type == -1
1016 && output_elf_osabi == -1))
1017 usage (stderr, 1);
1018
1019 status = 0;
1020 while (optind < argc)
1021 status |= process_file (argv[optind++]);
1022
1023 return status;
1024 }