Annotation of src/external/gpl3/binutils.old/dist/binutils/elfedit.c, Revision 1.5
1.1 christos 1: /* elfedit.c -- Update the ELF header of an ELF format file
1.5 ! christos 2: Copyright (C) 2010-2016 Free Software Foundation, Inc.
1.1 christos 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 "sysdep.h"
22: #include <assert.h>
23:
24: #if __GNUC__ >= 2
25: /* Define BFD64 here, even if our default architecture is 32 bit ELF
26: as this will allow us to read in and parse 64bit and 32bit ELF files.
27: Only do this if we believe that the compiler can support a 64 bit
28: data type. For now we only rely on GCC being able to do this. */
29: #define BFD64
30: #endif
31:
32: #include "bfd.h"
33: #include "elfcomm.h"
34: #include "bucomm.h"
35:
36: #include "elf/common.h"
37: #include "elf/external.h"
38: #include "elf/internal.h"
39:
40: #include "getopt.h"
41: #include "libiberty.h"
42: #include "safe-ctype.h"
43: #include "filenames.h"
44:
45: char * program_name = "elfedit";
46: static long archive_file_offset;
47: static unsigned long archive_file_size;
48: static Elf_Internal_Ehdr elf_header;
49: static Elf32_External_Ehdr ehdr32;
50: static Elf64_External_Ehdr ehdr64;
51: static int input_elf_machine = -1;
52: static int output_elf_machine = -1;
53: static int input_elf_type = -1;
54: static int output_elf_type = -1;
55: static int input_elf_osabi = -1;
56: static int output_elf_osabi = -1;
1.3 christos 57: enum elfclass
58: {
59: ELF_CLASS_UNKNOWN = -1,
60: ELF_CLASS_NONE = ELFCLASSNONE,
61: ELF_CLASS_32 = ELFCLASS32,
62: ELF_CLASS_64 = ELFCLASS64,
63: ELF_CLASS_BOTH
64: };
65: static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
66: static enum elfclass output_elf_class = ELF_CLASS_BOTH;
67:
68: /* Return ELF class for a machine type, MACH. */
69:
70: static enum elfclass
71: elf_class (int mach)
72: {
73: switch (mach)
74: {
75: case EM_386:
76: case EM_IAMCU:
77: return ELF_CLASS_32;
78: case EM_L1OM:
79: case EM_K1OM:
80: return ELF_CLASS_64;
81: case EM_X86_64:
82: case EM_NONE:
83: return ELF_CLASS_BOTH;
84: default:
85: return ELF_CLASS_BOTH;
86: }
87: }
1.1 christos 88:
89: static int
90: update_elf_header (const char *file_name, FILE *file)
91: {
92: int class, machine, type, status, osabi;
93:
94: if (elf_header.e_ident[EI_MAG0] != ELFMAG0
95: || elf_header.e_ident[EI_MAG1] != ELFMAG1
96: || elf_header.e_ident[EI_MAG2] != ELFMAG2
97: || elf_header.e_ident[EI_MAG3] != ELFMAG3)
98: {
99: error
100: (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
101: file_name);
102: return 0;
103: }
104:
105: if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
106: {
107: error
108: (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
109: file_name, elf_header.e_ident[EI_VERSION],
110: EV_CURRENT);
111: return 0;
112: }
113:
114: /* Return if e_machine is the same as output_elf_machine. */
115: if (output_elf_machine == elf_header.e_machine)
116: return 1;
117:
118: class = elf_header.e_ident[EI_CLASS];
1.3 christos 119: machine = elf_header.e_machine;
1.1 christos 120:
121: /* Skip if class doesn't match. */
1.3 christos 122: if (input_elf_class == ELF_CLASS_UNKNOWN)
123: input_elf_class = elf_class (machine);
124:
125: if (input_elf_class != ELF_CLASS_BOTH
126: && (int) input_elf_class != class)
1.1 christos 127: {
128: error
1.3 christos 129: (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
1.1 christos 130: file_name, class, input_elf_class);
131: return 0;
132: }
133:
1.3 christos 134: if (output_elf_class != ELF_CLASS_BOTH
135: && (int) output_elf_class != class)
136: {
137: error
138: (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
139: file_name, class, output_elf_class);
140: return 0;
141: }
1.1 christos 142:
143: /* Skip if e_machine doesn't match. */
144: if (input_elf_machine != -1 && machine != input_elf_machine)
145: {
146: error
147: (_("%s: Unmatched e_machine: %d is not %d\n"),
148: file_name, machine, input_elf_machine);
149: return 0;
150: }
151:
152: type = elf_header.e_type;
153:
154: /* Skip if e_type doesn't match. */
155: if (input_elf_type != -1 && type != input_elf_type)
156: {
157: error
158: (_("%s: Unmatched e_type: %d is not %d\n"),
159: file_name, type, input_elf_type);
160: return 0;
161: }
162:
163: osabi = elf_header.e_ident[EI_OSABI];
164:
165: /* Skip if OSABI doesn't match. */
166: if (input_elf_osabi != -1 && osabi != input_elf_osabi)
167: {
168: error
169: (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
170: file_name, osabi, input_elf_osabi);
171: return 0;
172: }
173:
174: /* Update e_machine, e_type and EI_OSABI. */
175: switch (class)
176: {
177: default:
178: /* We should never get here. */
179: abort ();
180: break;
181: case ELFCLASS32:
182: if (output_elf_machine != -1)
183: BYTE_PUT (ehdr32.e_machine, output_elf_machine);
184: if (output_elf_type != -1)
185: BYTE_PUT (ehdr32.e_type, output_elf_type);
186: if (output_elf_osabi != -1)
187: ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
188: status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
189: break;
190: case ELFCLASS64:
191: if (output_elf_machine != -1)
192: BYTE_PUT (ehdr64.e_machine, output_elf_machine);
193: if (output_elf_type != -1)
194: BYTE_PUT (ehdr64.e_type, output_elf_type);
195: if (output_elf_osabi != -1)
196: ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
197: status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
198: break;
199: }
200:
201: if (status != 1)
202: error (_("%s: Failed to update ELF header: %s\n"),
203: file_name, strerror (errno));
204:
205: return status;
206: }
207:
208: static int
209: get_file_header (FILE * file)
210: {
211: /* Read in the identity array. */
212: if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
213: return 0;
214:
215: /* Determine how to read the rest of the header. */
216: switch (elf_header.e_ident[EI_DATA])
217: {
218: default: /* fall through */
219: case ELFDATANONE: /* fall through */
220: case ELFDATA2LSB:
221: byte_get = byte_get_little_endian;
222: byte_put = byte_put_little_endian;
223: break;
224: case ELFDATA2MSB:
225: byte_get = byte_get_big_endian;
226: byte_put = byte_put_big_endian;
227: break;
228: }
229:
230: /* Read in the rest of the header. For now we only support 32 bit
231: and 64 bit ELF files. */
232: switch (elf_header.e_ident[EI_CLASS])
233: {
234: default:
235: error (_("Unsupported EI_CLASS: %d\n"),
236: elf_header.e_ident[EI_CLASS]);
237: return 0;
238:
239: case ELFCLASS32:
240: if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
241: 1, file) != 1)
242: return 0;
243:
244: elf_header.e_type = BYTE_GET (ehdr32.e_type);
245: elf_header.e_machine = BYTE_GET (ehdr32.e_machine);
246: elf_header.e_version = BYTE_GET (ehdr32.e_version);
247: elf_header.e_entry = BYTE_GET (ehdr32.e_entry);
248: elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff);
249: elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff);
250: elf_header.e_flags = BYTE_GET (ehdr32.e_flags);
251: elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize);
252: elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
253: elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum);
254: elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
255: elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum);
256: elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx);
257:
258: memcpy (&ehdr32, &elf_header, EI_NIDENT);
259: break;
260:
261: case ELFCLASS64:
262: /* If we have been compiled with sizeof (bfd_vma) == 4, then
263: we will not be able to cope with the 64bit data found in
264: 64 ELF files. Detect this now and abort before we start
265: overwriting things. */
266: if (sizeof (bfd_vma) < 8)
267: {
268: error (_("This executable has been built without support for a\n\
269: 64 bit data type and so it cannot process 64 bit ELF files.\n"));
270: return 0;
271: }
272:
273: if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
274: 1, file) != 1)
275: return 0;
276:
277: elf_header.e_type = BYTE_GET (ehdr64.e_type);
278: elf_header.e_machine = BYTE_GET (ehdr64.e_machine);
279: elf_header.e_version = BYTE_GET (ehdr64.e_version);
280: elf_header.e_entry = BYTE_GET (ehdr64.e_entry);
281: elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff);
282: elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff);
283: elf_header.e_flags = BYTE_GET (ehdr64.e_flags);
284: elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize);
285: elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
286: elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum);
287: elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
288: elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum);
289: elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx);
290:
291: memcpy (&ehdr64, &elf_header, EI_NIDENT);
292: break;
293: }
294: return 1;
295: }
296:
297: /* Process one ELF object file according to the command line options.
298: This file may actually be stored in an archive. The file is
299: positioned at the start of the ELF object. */
300:
301: static int
302: process_object (const char *file_name, FILE *file)
303: {
304: /* Rememeber where we are. */
305: long offset = ftell (file);
306:
307: if (! get_file_header (file))
308: {
309: error (_("%s: Failed to read ELF header\n"), file_name);
310: return 1;
311: }
312:
313: /* Go to the position of the ELF header. */
314: if (fseek (file, offset, SEEK_SET) != 0)
315: {
316: error (_("%s: Failed to seek to ELF header\n"), file_name);
317: }
318:
319: if (! update_elf_header (file_name, file))
320: return 1;
321:
322: return 0;
323: }
324:
325: /* Process an ELF archive.
326: On entry the file is positioned just after the ARMAG string. */
327:
328: static int
329: process_archive (const char * file_name, FILE * file,
330: bfd_boolean is_thin_archive)
331: {
332: struct archive_info arch;
333: struct archive_info nested_arch;
334: size_t got;
335: int ret;
336:
337: /* The ARCH structure is used to hold information about this archive. */
338: arch.file_name = NULL;
339: arch.file = NULL;
340: arch.index_array = NULL;
341: arch.sym_table = NULL;
342: arch.longnames = NULL;
343:
344: /* The NESTED_ARCH structure is used as a single-item cache of information
345: about a nested archive (when members of a thin archive reside within
346: another regular archive file). */
347: nested_arch.file_name = NULL;
348: nested_arch.file = NULL;
349: nested_arch.index_array = NULL;
350: nested_arch.sym_table = NULL;
351: nested_arch.longnames = NULL;
352:
353: if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0)
354: {
355: ret = 1;
356: goto out;
357: }
358:
359: ret = 0;
360:
361: while (1)
362: {
363: char * name;
364: size_t namelen;
365: char * qualified_name;
366:
367: /* Read the next archive header. */
368: if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
369: {
370: error (_("%s: failed to seek to next archive header\n"),
371: file_name);
372: return 1;
373: }
374: got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
375: if (got != sizeof arch.arhdr)
376: {
377: if (got == 0)
378: break;
379: error (_("%s: failed to read archive header\n"),
380: file_name);
381: ret = 1;
382: break;
383: }
384: if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
385: {
386: error (_("%s: did not find a valid archive header\n"),
387: arch.file_name);
388: ret = 1;
389: break;
390: }
391:
392: arch.next_arhdr_offset += sizeof arch.arhdr;
393:
394: archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
395: if (archive_file_size & 01)
396: ++archive_file_size;
397:
398: name = get_archive_member_name (&arch, &nested_arch);
399: if (name == NULL)
400: {
401: error (_("%s: bad archive file name\n"), file_name);
402: ret = 1;
403: break;
404: }
405: namelen = strlen (name);
406:
407: qualified_name = make_qualified_name (&arch, &nested_arch, name);
408: if (qualified_name == NULL)
409: {
410: error (_("%s: bad archive file name\n"), file_name);
411: ret = 1;
412: break;
413: }
414:
415: if (is_thin_archive && arch.nested_member_origin == 0)
416: {
417: /* This is a proxy for an external member of a thin archive. */
418: FILE *member_file;
419: char *member_file_name = adjust_relative_path (file_name,
420: name, namelen);
421: if (member_file_name == NULL)
422: {
423: ret = 1;
424: break;
425: }
426:
427: member_file = fopen (member_file_name, "r+b");
428: if (member_file == NULL)
429: {
430: error (_("Input file '%s' is not readable\n"),
431: member_file_name);
432: free (member_file_name);
433: ret = 1;
434: break;
435: }
436:
437: archive_file_offset = arch.nested_member_origin;
438:
439: ret |= process_object (qualified_name, member_file);
440:
441: fclose (member_file);
442: free (member_file_name);
443: }
444: else if (is_thin_archive)
445: {
446: /* This is a proxy for a member of a nested archive. */
447: archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
448:
449: /* The nested archive file will have been opened and setup by
450: get_archive_member_name. */
451: if (fseek (nested_arch.file, archive_file_offset,
452: SEEK_SET) != 0)
453: {
454: error (_("%s: failed to seek to archive member\n"),
455: nested_arch.file_name);
456: ret = 1;
457: break;
458: }
459:
460: ret |= process_object (qualified_name, nested_arch.file);
461: }
462: else
463: {
464: archive_file_offset = arch.next_arhdr_offset;
465: arch.next_arhdr_offset += archive_file_size;
466:
467: ret |= process_object (qualified_name, file);
468: }
469:
470: free (qualified_name);
471: }
472:
473: out:
474: if (nested_arch.file != NULL)
475: fclose (nested_arch.file);
476: release_archive (&nested_arch);
477: release_archive (&arch);
478:
479: return ret;
480: }
481:
482: static int
483: check_file (const char *file_name, struct stat *statbuf_p)
484: {
485: struct stat statbuf;
486:
487: if (statbuf_p == NULL)
488: statbuf_p = &statbuf;
489:
490: if (stat (file_name, statbuf_p) < 0)
491: {
492: if (errno == ENOENT)
493: error (_("'%s': No such file\n"), file_name);
494: else
495: error (_("Could not locate '%s'. System error message: %s\n"),
496: file_name, strerror (errno));
497: return 1;
498: }
499:
500: if (! S_ISREG (statbuf_p->st_mode))
501: {
502: error (_("'%s' is not an ordinary file\n"), file_name);
503: return 1;
504: }
505:
506: return 0;
507: }
508:
509: static int
510: process_file (const char *file_name)
511: {
512: FILE * file;
513: char armag[SARMAG];
514: int ret;
515:
516: if (check_file (file_name, NULL))
517: return 1;
518:
519: file = fopen (file_name, "r+b");
520: if (file == NULL)
521: {
522: error (_("Input file '%s' is not readable\n"), file_name);
523: return 1;
524: }
525:
526: if (fread (armag, SARMAG, 1, file) != 1)
527: {
528: error (_("%s: Failed to read file's magic number\n"),
529: file_name);
530: fclose (file);
531: return 1;
532: }
533:
534: if (memcmp (armag, ARMAG, SARMAG) == 0)
535: ret = process_archive (file_name, file, FALSE);
536: else if (memcmp (armag, ARMAGT, SARMAG) == 0)
537: ret = process_archive (file_name, file, TRUE);
538: else
539: {
540: rewind (file);
541: archive_file_size = archive_file_offset = 0;
542: ret = process_object (file_name, file);
543: }
544:
545: fclose (file);
546:
547: return ret;
548: }
549:
550: static const struct
551: {
552: int osabi;
553: const char *name;
554: }
555: osabis[] =
556: {
557: { ELFOSABI_NONE, "none" },
558: { ELFOSABI_HPUX, "HPUX" },
559: { ELFOSABI_NETBSD, "NetBSD" },
560: { ELFOSABI_GNU, "GNU" },
561: { ELFOSABI_GNU, "Linux" },
562: { ELFOSABI_SOLARIS, "Solaris" },
563: { ELFOSABI_AIX, "AIX" },
564: { ELFOSABI_IRIX, "Irix" },
565: { ELFOSABI_FREEBSD, "FreeBSD" },
566: { ELFOSABI_TRU64, "TRU64" },
567: { ELFOSABI_MODESTO, "Modesto" },
568: { ELFOSABI_OPENBSD, "OpenBSD" },
569: { ELFOSABI_OPENVMS, "OpenVMS" },
570: { ELFOSABI_NSK, "NSK" },
571: { ELFOSABI_AROS, "AROS" },
572: { ELFOSABI_FENIXOS, "FenixOS" }
573: };
574:
575: /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
576:
577: static int
578: elf_osabi (const char *osabi)
579: {
580: unsigned int i;
581:
582: for (i = 0; i < ARRAY_SIZE (osabis); i++)
583: if (strcasecmp (osabi, osabis[i].name) == 0)
584: return osabis[i].osabi;
585:
586: error (_("Unknown OSABI: %s\n"), osabi);
587:
588: return -1;
589: }
590:
591: /* Return EM_XXX for a machine string, MACH. */
592:
593: static int
594: elf_machine (const char *mach)
595: {
1.3 christos 596: if (strcasecmp (mach, "i386") == 0)
597: return EM_386;
598: if (strcasecmp (mach, "iamcu") == 0)
599: return EM_IAMCU;
1.1 christos 600: if (strcasecmp (mach, "l1om") == 0)
601: return EM_L1OM;
602: if (strcasecmp (mach, "k1om") == 0)
603: return EM_K1OM;
604: if (strcasecmp (mach, "x86_64") == 0)
605: return EM_X86_64;
606: if (strcasecmp (mach, "x86-64") == 0)
607: return EM_X86_64;
608: if (strcasecmp (mach, "none") == 0)
609: return EM_NONE;
610:
611: error (_("Unknown machine type: %s\n"), mach);
612:
613: return -1;
614: }
615:
616: /* Return ET_XXX for a type string, TYPE. */
617:
618: static int
619: elf_type (const char *type)
620: {
621: if (strcasecmp (type, "rel") == 0)
622: return ET_REL;
623: if (strcasecmp (type, "exec") == 0)
624: return ET_EXEC;
625: if (strcasecmp (type, "dyn") == 0)
626: return ET_DYN;
627: if (strcasecmp (type, "none") == 0)
628: return ET_NONE;
629:
630: error (_("Unknown type: %s\n"), type);
631:
632: return -1;
633: }
634:
635: enum command_line_switch
636: {
637: OPTION_INPUT_MACH = 150,
638: OPTION_OUTPUT_MACH,
639: OPTION_INPUT_TYPE,
640: OPTION_OUTPUT_TYPE,
641: OPTION_INPUT_OSABI,
642: OPTION_OUTPUT_OSABI
643: };
644:
645: static struct option options[] =
646: {
647: {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
648: {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
649: {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
650: {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
651: {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
652: {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
653: {"version", no_argument, 0, 'v'},
654: {"help", no_argument, 0, 'h'},
655: {0, no_argument, 0, 0}
656: };
657:
658: static void
659: usage (FILE *stream, int exit_status)
660: {
661: fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
662: program_name);
663: fprintf (stream, _(" Update the ELF header of ELF files\n"));
664: fprintf (stream, _(" The options are:\n"));
665: fprintf (stream, _("\
666: --input-mach <machine> Set input machine type to <machine>\n\
667: --output-mach <machine> Set output machine type to <machine>\n\
668: --input-type <type> Set input file type to <type>\n\
669: --output-type <type> Set output file type to <type>\n\
670: --input-osabi <osabi> Set input OSABI to <osabi>\n\
671: --output-osabi <osabi> Set output OSABI to <osabi>\n\
672: -h --help Display this information\n\
673: -v --version Display the version number of %s\n\
674: "),
675: program_name);
676: if (REPORT_BUGS_TO[0] && exit_status == 0)
677: fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
678: exit (exit_status);
679: }
680:
681: int
682: main (int argc, char ** argv)
683: {
684: int c, status;
685:
686: #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
687: setlocale (LC_MESSAGES, "");
688: #endif
689: #if defined (HAVE_SETLOCALE)
690: setlocale (LC_CTYPE, "");
691: #endif
692: bindtextdomain (PACKAGE, LOCALEDIR);
693: textdomain (PACKAGE);
694:
695: expandargv (&argc, &argv);
696:
697: while ((c = getopt_long (argc, argv, "hv",
698: options, (int *) 0)) != EOF)
699: {
700: switch (c)
701: {
702: case OPTION_INPUT_MACH:
703: input_elf_machine = elf_machine (optarg);
704: if (input_elf_machine < 0)
705: return 1;
706: input_elf_class = elf_class (input_elf_machine);
1.3 christos 707: if (input_elf_class == ELF_CLASS_UNKNOWN)
1.1 christos 708: return 1;
709: break;
710:
711: case OPTION_OUTPUT_MACH:
712: output_elf_machine = elf_machine (optarg);
713: if (output_elf_machine < 0)
714: return 1;
1.3 christos 715: output_elf_class = elf_class (output_elf_machine);
716: if (output_elf_class == ELF_CLASS_UNKNOWN)
717: return 1;
1.1 christos 718: break;
719:
720: case OPTION_INPUT_TYPE:
721: input_elf_type = elf_type (optarg);
722: if (input_elf_type < 0)
723: return 1;
724: break;
725:
726: case OPTION_OUTPUT_TYPE:
727: output_elf_type = elf_type (optarg);
728: if (output_elf_type < 0)
729: return 1;
730: break;
731:
732: case OPTION_INPUT_OSABI:
733: input_elf_osabi = elf_osabi (optarg);
734: if (input_elf_osabi < 0)
735: return 1;
736: break;
737:
738: case OPTION_OUTPUT_OSABI:
739: output_elf_osabi = elf_osabi (optarg);
740: if (output_elf_osabi < 0)
741: return 1;
742: break;
743:
744: case 'h':
745: usage (stdout, 0);
746:
747: case 'v':
748: print_version (program_name);
749: break;
750:
751: default:
752: usage (stderr, 1);
753: }
754: }
755:
756: if (optind == argc
757: || (output_elf_machine == -1
758: && output_elf_type == -1
759: && output_elf_osabi == -1))
760: usage (stderr, 1);
761:
762: status = 0;
763: while (optind < argc)
764: status |= process_file (argv[optind++]);
765:
766: return status;
767: }
CVSweb <webmaster@jp.NetBSD.org>