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