]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/elfedit.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / binutils / elfedit.c
CommitLineData
30fd33bb 1/* elfedit.c -- Update the ELF header of an ELF format file
250d07de 2 Copyright (C) 2010-2021 Free Software Foundation, Inc.
30fd33bb
L
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
8a6b075b 21#include "config.h"
30fd33bb 22#include "sysdep.h"
9c905051 23#include "libiberty.h"
30fd33bb 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
dc1e8a47 242 out:
8a6b075b
L
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;
279d901e
L
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;
8a6b075b 267 else
760ddef4
L
268 {
269 error (_("Unknown x86 feature: %s\n"), feature);
270 return -1;
271 }
8a6b075b
L
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
6c14750f
L
288/* Return ELF class for a machine type, MACH. */
289
290static enum elfclass
291elf_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:
aa9f7286 305 return ELF_CLASS_BOTH;
6c14750f
L
306 }
307}
30fd33bb 308
30fd33bb
L
309static int
310update_elf_header (const char *file_name, FILE *file)
311{
d0514c49 312 int class, machine, type, status, osabi;
30fd33bb 313
30fd33bb
L
314 if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
315 {
3284fe0c 316 error
30fd33bb
L
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
2dc654c3
L
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];
6c14750f 328 machine = elf_header.e_machine;
2dc654c3 329
30fd33bb 330 /* Skip if class doesn't match. */
6c14750f
L
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)
30fd33bb 336 {
3284fe0c 337 error
6c14750f 338 (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
2dc654c3 339 file_name, class, input_elf_class);
30fd33bb
L
340 return 0;
341 }
342
6c14750f
L
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 }
30fd33bb
L
351
352 /* Skip if e_machine doesn't match. */
2dc654c3 353 if (input_elf_machine != -1 && machine != input_elf_machine)
30fd33bb 354 {
3284fe0c 355 error
30fd33bb 356 (_("%s: Unmatched e_machine: %d is not %d\n"),
2dc654c3 357 file_name, machine, input_elf_machine);
30fd33bb
L
358 return 0;
359 }
360
dd35de74
L
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 {
3284fe0c 366 error
dd35de74
L
367 (_("%s: Unmatched e_type: %d is not %d\n"),
368 file_name, type, input_elf_type);
369 return 0;
370 }
371
d0514c49
L
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 {
3284fe0c 377 error
d0514c49
L
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. */
2dc654c3 384 switch (class)
30fd33bb
L
385 {
386 default:
387 /* We should never get here. */
388 abort ();
389 break;
390 case ELFCLASS32:
dd35de74
L
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);
d0514c49
L
395 if (output_elf_osabi != -1)
396 ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
30fd33bb
L
397 status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
398 break;
399 case ELFCLASS64:
dd35de74
L
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);
d0514c49
L
404 if (output_elf_osabi != -1)
405 ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
30fd33bb
L
406 status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
407 break;
408 }
409
410 if (status != 1)
3284fe0c 411 error (_("%s: Failed to update ELF header: %s\n"),
30fd33bb
L
412 file_name, strerror (errno));
413
414 return status;
415}
416
417static int
418get_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
675accbd
L
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
30fd33bb
L
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:
30fd33bb
L
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 {
3284fe0c 481 error (_("This executable has been built without support for a\n\
30fd33bb
L
48264 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
514static int
515process_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 {
3284fe0c 522 error (_("%s: Failed to read ELF header\n"), file_name);
30fd33bb
L
523 return 1;
524 }
525
526 /* Go to the position of the ELF header. */
527 if (fseek (file, offset, SEEK_SET) != 0)
528 {
3284fe0c 529 error (_("%s: Failed to seek to ELF header\n"), file_name);
30fd33bb
L
530 }
531
532 if (! update_elf_header (file_name, file))
533 return 1;
534
535 return 0;
536}
537
30fd33bb
L
538/* Process an ELF archive.
539 On entry the file is positioned just after the ARMAG string. */
540
541static int
542process_archive (const char * file_name, FILE * file,
543 bfd_boolean is_thin_archive)
544{
545 struct archive_info arch;
546 struct archive_info nested_arch;
547 size_t got;
30fd33bb 548 int ret;
780f96ae 549 struct stat statbuf;
30fd33bb
L
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
780f96ae
AM
567 if (fstat (fileno (file), &statbuf) < 0
568 || setup_archive (&arch, file_name, file, statbuf.st_size,
569 is_thin_archive, FALSE) != 0)
30fd33bb
L
570 {
571 ret = 1;
572 goto out;
573 }
574
30fd33bb
L
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 {
3284fe0c 586 error (_("%s: failed to seek to next archive header\n"),
30fd33bb
L
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;
3284fe0c 595 error (_("%s: failed to read archive header\n"),
30fd33bb
L
596 file_name);
597 ret = 1;
598 break;
599 }
600 if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
601 {
3284fe0c 602 error (_("%s: did not find a valid archive header\n"),
30fd33bb
L
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 {
3284fe0c 617 error (_("%s: bad archive file name\n"), file_name);
30fd33bb
L
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 {
3284fe0c 626 error (_("%s: bad archive file name\n"), file_name);
fd486f32 627 free (name);
30fd33bb
L
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);
fd486f32 638 free (name);
30fd33bb
L
639 if (member_file_name == NULL)
640 {
fd486f32 641 free (qualified_name);
30fd33bb
L
642 ret = 1;
643 break;
644 }
645
646 member_file = fopen (member_file_name, "r+b");
647 if (member_file == NULL)
648 {
3284fe0c 649 error (_("Input file '%s' is not readable\n"),
30fd33bb
L
650 member_file_name);
651 free (member_file_name);
fd486f32 652 free (qualified_name);
30fd33bb
L
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 {
fd486f32
AM
666 free (name);
667
30fd33bb
L
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 {
3284fe0c 676 error (_("%s: failed to seek to archive member\n"),
30fd33bb 677 nested_arch.file_name);
fd486f32 678 free (qualified_name);
30fd33bb
L
679 ret = 1;
680 break;
681 }
682
683 ret |= process_object (qualified_name, nested_arch.file);
684 }
685 else
686 {
fd486f32 687 free (name);
30fd33bb
L
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
706static int
707check_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)
3284fe0c 717 error (_("'%s': No such file\n"), file_name);
30fd33bb 718 else
3284fe0c 719 error (_("Could not locate '%s'. System error message: %s\n"),
30fd33bb
L
720 file_name, strerror (errno));
721 return 1;
722 }
723
724 if (! S_ISREG (statbuf_p->st_mode))
725 {
3284fe0c 726 error (_("'%s' is not an ordinary file\n"), file_name);
30fd33bb
L
727 return 1;
728 }
729
730 return 0;
731}
732
733static int
734process_file (const char *file_name)
735{
736 FILE * file;
737 char armag[SARMAG];
738 int ret;
739
740 if (check_file (file_name, NULL))
741 return 1;
742
743 file = fopen (file_name, "r+b");
744 if (file == NULL)
745 {
3284fe0c 746 error (_("Input file '%s' is not readable\n"), file_name);
30fd33bb
L
747 return 1;
748 }
749
750 if (fread (armag, SARMAG, 1, file) != 1)
751 {
3284fe0c 752 error (_("%s: Failed to read file's magic number\n"),
30fd33bb
L
753 file_name);
754 fclose (file);
755 return 1;
756 }
757
758 if (memcmp (armag, ARMAG, SARMAG) == 0)
759 ret = process_archive (file_name, file, FALSE);
760 else if (memcmp (armag, ARMAGT, SARMAG) == 0)
761 ret = process_archive (file_name, file, TRUE);
762 else
763 {
764 rewind (file);
765 archive_file_size = archive_file_offset = 0;
766 ret = process_object (file_name, file);
8a6b075b
L
767#ifdef HAVE_MMAP
768 if (!ret
769 && (elf_header.e_type == ET_EXEC
770 || elf_header.e_type == ET_DYN))
771 ret = update_gnu_property (file_name, file);
772#endif
30fd33bb
L
773 }
774
775 fclose (file);
776
777 return ret;
778}
779
d0514c49
L
780static const struct
781{
782 int osabi;
783 const char *name;
784}
785osabis[] =
786{
787 { ELFOSABI_NONE, "none" },
788 { ELFOSABI_HPUX, "HPUX" },
789 { ELFOSABI_NETBSD, "NetBSD" },
9c55345c
TS
790 { ELFOSABI_GNU, "GNU" },
791 { ELFOSABI_GNU, "Linux" },
d0514c49
L
792 { ELFOSABI_SOLARIS, "Solaris" },
793 { ELFOSABI_AIX, "AIX" },
794 { ELFOSABI_IRIX, "Irix" },
795 { ELFOSABI_FREEBSD, "FreeBSD" },
796 { ELFOSABI_TRU64, "TRU64" },
797 { ELFOSABI_MODESTO, "Modesto" },
798 { ELFOSABI_OPENBSD, "OpenBSD" },
799 { ELFOSABI_OPENVMS, "OpenVMS" },
800 { ELFOSABI_NSK, "NSK" },
801 { ELFOSABI_AROS, "AROS" },
802 { ELFOSABI_FENIXOS, "FenixOS" }
803};
804
805/* Return ELFOSABI_XXX for an OSABI string, OSABI. */
806
807static int
808elf_osabi (const char *osabi)
809{
810 unsigned int i;
811
812 for (i = 0; i < ARRAY_SIZE (osabis); i++)
813 if (strcasecmp (osabi, osabis[i].name) == 0)
814 return osabis[i].osabi;
815
3284fe0c 816 error (_("Unknown OSABI: %s\n"), osabi);
d0514c49
L
817
818 return -1;
819}
820
30fd33bb
L
821/* Return EM_XXX for a machine string, MACH. */
822
823static int
824elf_machine (const char *mach)
825{
6c14750f
L
826 if (strcasecmp (mach, "i386") == 0)
827 return EM_386;
828 if (strcasecmp (mach, "iamcu") == 0)
829 return EM_IAMCU;
30fd33bb
L
830 if (strcasecmp (mach, "l1om") == 0)
831 return EM_L1OM;
7a9068fe
L
832 if (strcasecmp (mach, "k1om") == 0)
833 return EM_K1OM;
30fd33bb
L
834 if (strcasecmp (mach, "x86_64") == 0)
835 return EM_X86_64;
836 if (strcasecmp (mach, "x86-64") == 0)
837 return EM_X86_64;
838 if (strcasecmp (mach, "none") == 0)
839 return EM_NONE;
840
3284fe0c 841 error (_("Unknown machine type: %s\n"), mach);
30fd33bb
L
842
843 return -1;
844}
845
dd35de74
L
846/* Return ET_XXX for a type string, TYPE. */
847
848static int
849elf_type (const char *type)
850{
851 if (strcasecmp (type, "rel") == 0)
852 return ET_REL;
853 if (strcasecmp (type, "exec") == 0)
854 return ET_EXEC;
855 if (strcasecmp (type, "dyn") == 0)
856 return ET_DYN;
857 if (strcasecmp (type, "none") == 0)
858 return ET_NONE;
859
3284fe0c 860 error (_("Unknown type: %s\n"), type);
dd35de74
L
861
862 return -1;
863}
864
30fd33bb
L
865enum command_line_switch
866 {
867 OPTION_INPUT_MACH = 150,
dd35de74
L
868 OPTION_OUTPUT_MACH,
869 OPTION_INPUT_TYPE,
d0514c49
L
870 OPTION_OUTPUT_TYPE,
871 OPTION_INPUT_OSABI,
8a6b075b
L
872 OPTION_OUTPUT_OSABI,
873#ifdef HAVE_MMAP
874 OPTION_ENABLE_X86_FEATURE,
875 OPTION_DISABLE_X86_FEATURE,
876#endif
30fd33bb
L
877 };
878
879static struct option options[] =
880{
881 {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
882 {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
dd35de74
L
883 {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
884 {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
d0514c49
L
885 {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
886 {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
8a6b075b
L
887#ifdef HAVE_MMAP
888 {"enable-x86-feature",
889 required_argument, 0, OPTION_ENABLE_X86_FEATURE},
890 {"disable-x86-feature",
891 required_argument, 0, OPTION_DISABLE_X86_FEATURE},
892#endif
30fd33bb
L
893 {"version", no_argument, 0, 'v'},
894 {"help", no_argument, 0, 'h'},
895 {0, no_argument, 0, 0}
896};
897
1e0f0b4d 898ATTRIBUTE_NORETURN static void
30fd33bb
L
899usage (FILE *stream, int exit_status)
900{
9c905051 901 unsigned int i;
a4e91c46 902 char *osabi = concat (osabis[0].name, NULL);
9c905051 903
a4e91c46 904 for (i = 1; i < ARRAY_SIZE (osabis); i++)
2e635a01 905 osabi = reconcat (osabi, osabi, "|", osabis[i].name, NULL);
9c905051 906
d0514c49 907 fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
30fd33bb
L
908 program_name);
909 fprintf (stream, _(" Update the ELF header of ELF files\n"));
910 fprintf (stream, _(" The options are:\n"));
911 fprintf (stream, _("\
9c905051
L
912 --input-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
913 Set input machine type\n\
914 --output-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
915 Set output machine type\n\
916 --input-type [none|rel|exec|dyn]\n\
917 Set input file type\n\
918 --output-type [none|rel|exec|dyn]\n\
919 Set output file type\n\
920 --input-osabi [%s]\n\
921 Set input OSABI\n\
922 --output-osabi [%s]\n\
923 Set output OSABI\n"),
924 osabi, osabi);
8a6b075b
L
925#ifdef HAVE_MMAP
926 fprintf (stream, _("\
279d901e 927 --enable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
9c905051 928 Enable x86 feature\n\
279d901e 929 --disable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
9c905051 930 Disable x86 feature\n"));
8a6b075b
L
931#endif
932 fprintf (stream, _("\
30fd33bb
L
933 -h --help Display this information\n\
934 -v --version Display the version number of %s\n\
935"),
936 program_name);
937 if (REPORT_BUGS_TO[0] && exit_status == 0)
938 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
9c905051 939 free (osabi);
30fd33bb
L
940 exit (exit_status);
941}
942
943int
944main (int argc, char ** argv)
945{
946 int c, status;
947
948#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
949 setlocale (LC_MESSAGES, "");
950#endif
951#if defined (HAVE_SETLOCALE)
952 setlocale (LC_CTYPE, "");
953#endif
954 bindtextdomain (PACKAGE, LOCALEDIR);
955 textdomain (PACKAGE);
956
957 expandargv (&argc, &argv);
958
959 while ((c = getopt_long (argc, argv, "hv",
960 options, (int *) 0)) != EOF)
961 {
962 switch (c)
963 {
964 case OPTION_INPUT_MACH:
965 input_elf_machine = elf_machine (optarg);
966 if (input_elf_machine < 0)
967 return 1;
968 input_elf_class = elf_class (input_elf_machine);
6c14750f 969 if (input_elf_class == ELF_CLASS_UNKNOWN)
30fd33bb
L
970 return 1;
971 break;
972
973 case OPTION_OUTPUT_MACH:
974 output_elf_machine = elf_machine (optarg);
975 if (output_elf_machine < 0)
976 return 1;
6c14750f
L
977 output_elf_class = elf_class (output_elf_machine);
978 if (output_elf_class == ELF_CLASS_UNKNOWN)
979 return 1;
30fd33bb
L
980 break;
981
dd35de74
L
982 case OPTION_INPUT_TYPE:
983 input_elf_type = elf_type (optarg);
984 if (input_elf_type < 0)
985 return 1;
986 break;
987
988 case OPTION_OUTPUT_TYPE:
989 output_elf_type = elf_type (optarg);
990 if (output_elf_type < 0)
991 return 1;
992 break;
993
d0514c49
L
994 case OPTION_INPUT_OSABI:
995 input_elf_osabi = elf_osabi (optarg);
996 if (input_elf_osabi < 0)
997 return 1;
998 break;
999
1000 case OPTION_OUTPUT_OSABI:
1001 output_elf_osabi = elf_osabi (optarg);
1002 if (output_elf_osabi < 0)
1003 return 1;
1004 break;
1005
8a6b075b
L
1006#ifdef HAVE_MMAP
1007 case OPTION_ENABLE_X86_FEATURE:
1008 if (elf_x86_feature (optarg, 1) < 0)
1009 return 1;
1010 break;
1011
1012 case OPTION_DISABLE_X86_FEATURE:
1013 if (elf_x86_feature (optarg, 0) < 0)
1014 return 1;
1015 break;
1016#endif
1017
30fd33bb
L
1018 case 'h':
1019 usage (stdout, 0);
1020
1021 case 'v':
1022 print_version (program_name);
1023 break;
1024
1025 default:
1026 usage (stderr, 1);
1027 }
1028 }
1029
dd35de74
L
1030 if (optind == argc
1031 || (output_elf_machine == -1
8a6b075b
L
1032#ifdef HAVE_MMAP
1033 && ! enable_x86_features
1034 && ! disable_x86_features
1035#endif
d0514c49
L
1036 && output_elf_type == -1
1037 && output_elf_osabi == -1))
30fd33bb
L
1038 usage (stderr, 1);
1039
1040 status = 0;
1041 while (optind < argc)
1042 status |= process_file (argv[optind++]);
1043
1044 return status;
1045}