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