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