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