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