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