removed rcs cruft
[deliverable/binutils-gdb.git] / binutils / objcopy.c
1 /* objcopy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 \f
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "bucomm.h"
23 #include <getopt.h>
24
25 static void setup_section ();
26 static void copy_section ();
27 static void mangle_section ();
28
29 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
30
31 static asymbol **isympp = NULL; /* Input symbols */
32 static asymbol **osympp = NULL; /* Output symbols that survive stripping */
33
34 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
35 static int copy_byte = -1;
36 static int interleave = 4;
37
38 static boolean verbose; /* Print file and target names. */
39 static int status = 0; /* Exit status. */
40
41 enum strip_action
42 {
43 strip_undef,
44 strip_none, /* don't strip */
45 strip_debug, /* strip all debugger symbols */
46 strip_all /* strip all symbols */
47 };
48
49 /* Which symbols to remove. */
50 static enum strip_action strip_symbols;
51
52 enum locals_action
53 {
54 locals_undef,
55 locals_start_L, /* discard locals starting with L */
56 locals_all /* discard all locals */
57 };
58
59 /* Which local symbols to remove. Overrides strip_all. */
60 static enum locals_action discard_locals;
61
62 /* Options to handle if running as "strip". */
63
64 static struct option strip_options[] =
65 {
66 {"discard-all", no_argument, 0, 'x'},
67 {"discard-locals", no_argument, 0, 'X'},
68 {"format", required_argument, 0, 'F'}, /* Obsolete */
69 {"help", no_argument, 0, 'h'},
70 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
71 {"input-target", required_argument, 0, 'I'},
72 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
73 {"output-target", required_argument, 0, 'O'},
74 {"strip-all", no_argument, 0, 's'},
75 {"strip-debug", no_argument, 0, 'S'},
76 {"target", required_argument, 0, 'F'},
77 {"verbose", no_argument, 0, 'v'},
78 {"version", no_argument, 0, 'V'},
79 {0, no_argument, 0, 0}
80 };
81
82 /* Options to handle if running as "objcopy". */
83
84 static struct option copy_options[] =
85 {
86 {"byte", required_argument, 0, 'b'},
87 {"discard-all", no_argument, 0, 'x'},
88 {"discard-locals", no_argument, 0, 'X'},
89 {"format", required_argument, 0, 'F'}, /* Obsolete */
90 {"help", no_argument, 0, 'h'},
91 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
92 {"input-target", required_argument, 0, 'I'},
93 {"interleave", required_argument, 0, 'i'},
94 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
95 {"output-target", required_argument, 0, 'O'},
96 {"strip-all", no_argument, 0, 'S'},
97 {"strip-debug", no_argument, 0, 'g'},
98 {"target", required_argument, 0, 'F'},
99 {"verbose", no_argument, 0, 'v'},
100 {"version", no_argument, 0, 'V'},
101 {0, no_argument, 0, 0}
102 };
103
104 /* IMPORTS */
105 extern char *program_name;
106 extern char *program_version;
107
108 /* This flag distinguishes between strip and objcopy:
109 1 means this is 'strip'; 0 means this is 'objcopy'.
110 -1 means if we should use argv[0] to decide. */
111 extern int is_strip;
112
113
114 static void
115 copy_usage (stream, status)
116 FILE *stream;
117 int status;
118 {
119 fprintf (stream, "\
120 Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
121 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
122 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
123 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
124 [--verbose] [--version] [--help] in-file [out-file]\n",
125 program_name);
126 exit (status);
127 }
128
129 static void
130 strip_usage (stream, status)
131 FILE *stream;
132 int status;
133 {
134 fprintf (stream, "\
135 Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
136 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
137 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
138 [--verbose] [--version] [--help] file...\n",
139 program_name);
140 exit (status);
141 }
142
143
144 /* Return the name of a temporary file in the same directory as FILENAME. */
145
146 static char *
147 make_tempname (filename)
148 char *filename;
149 {
150 static char template[] = "stXXXXXX";
151 char *tmpname;
152 char *slash = strrchr (filename, '/');
153
154 if (slash != (char *) NULL)
155 {
156 *slash = 0;
157 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
158 strcpy (tmpname, filename);
159 strcat (tmpname, "/");
160 strcat (tmpname, template);
161 mktemp (tmpname);
162 *slash = '/';
163 }
164 else
165 {
166 tmpname = xmalloc (sizeof (template));
167 strcpy (tmpname, template);
168 mktemp (tmpname);
169 }
170 return tmpname;
171 }
172
173 /* Choose which symbol entries to copy; put the result in OSYMS.
174 We don't copy in place, because that confuses the relocs.
175 Return the number of symbols to print. */
176
177 static unsigned int
178 filter_symbols (abfd, osyms, isyms, symcount)
179 bfd *abfd;
180 asymbol **osyms, **isyms;
181 unsigned long symcount;
182 {
183 register asymbol **from = isyms, **to = osyms;
184 char locals_prefix = bfd_get_symbol_leading_char (abfd) == '_' ? 'L' : '.';
185 unsigned int src_count = 0, dst_count = 0;
186
187 for (; src_count < symcount; src_count++)
188 {
189 asymbol *sym = from[src_count];
190 flagword flags = sym->flags;
191 int keep;
192
193 if ((flags & BSF_GLOBAL) /* Keep if external. */
194 || bfd_get_section (sym) == &bfd_und_section
195 || bfd_is_com_section (bfd_get_section (sym)))
196 keep = 1;
197 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
198 keep = strip_symbols != strip_debug;
199 else /* Local symbol. */
200 keep = discard_locals != locals_all
201 && (discard_locals != locals_start_L ||
202 bfd_asymbol_name (sym)[0] != locals_prefix);
203 if (keep)
204 to[dst_count++] = sym;
205 }
206
207 return dst_count;
208 }
209
210 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
211 Adjust *SIZE. */
212
213 void
214 filter_bytes (memhunk, size)
215 PTR memhunk;
216 bfd_size_type *size;
217 {
218 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
219
220 for (; from < end; from += interleave)
221 *to++ = *from;
222 *size /= interleave;
223 }
224
225 /* Copy object file IBFD onto OBFD. */
226
227 static void
228 copy_object (ibfd, obfd)
229 bfd *ibfd;
230 bfd *obfd;
231 {
232 unsigned int symcount;
233
234 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
235 {
236 nonfatal (bfd_get_filename (obfd));
237 }
238
239 if (verbose)
240 printf ("copy from %s(%s) to %s(%s)\n",
241 bfd_get_filename(ibfd), bfd_get_target(ibfd),
242 bfd_get_filename(obfd), bfd_get_target(obfd));
243
244 if (!bfd_set_start_address (obfd, bfd_get_start_address (ibfd))
245 || !bfd_set_file_flags (obfd,
246 (bfd_get_file_flags (ibfd)
247 & bfd_applicable_file_flags (obfd))))
248 {
249 nonfatal (bfd_get_filename (ibfd));
250 }
251
252 /* Copy architecture of input file to output file */
253 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
254 bfd_get_mach (ibfd)))
255 {
256 fprintf (stderr, "Output file cannot represent architecture %s\n",
257 bfd_printable_arch_mach (bfd_get_arch (ibfd),
258 bfd_get_mach (ibfd)));
259 }
260 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
261 {
262 nonfatal (bfd_get_filename(ibfd));
263 }
264
265 if (isympp)
266 free (isympp);
267 if (osympp != isympp)
268 free (osympp);
269
270 if (strip_symbols == strip_all && discard_locals == locals_undef)
271 {
272 osympp = isympp = NULL;
273 symcount = 0;
274 }
275 else
276 {
277 osympp = isympp = (asymbol **) xmalloc (get_symtab_upper_bound (ibfd));
278 symcount = bfd_canonicalize_symtab (ibfd, isympp);
279
280 if (strip_symbols == strip_debug || discard_locals != locals_undef)
281 {
282 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
283 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
284 }
285 }
286
287 bfd_set_symtab (obfd, osympp, symcount);
288
289 /* bfd mandates that all output sections be created and sizes set before
290 any output is done. Thus, we traverse all sections multiple times. */
291 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
292 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
293 bfd_map_over_sections (ibfd, mangle_section, (void *) obfd);
294 }
295
296 static char *
297 cat (a, b, c)
298 char *a;
299 char *b;
300 char *c;
301 {
302 size_t size = strlen (a) + strlen (b) + strlen (c);
303 char *r = xmalloc (size + 1);
304
305 strcpy (r, a);
306 strcat (r, b);
307 strcat (r, c);
308 return r;
309 }
310
311 /* Read each archive element in turn from IBFD, copy the
312 contents to temp file, and keep the temp file handle. */
313
314 static void
315 copy_archive (ibfd, obfd, output_target)
316 bfd *ibfd;
317 bfd *obfd;
318 char *output_target;
319 {
320 bfd **ptr = &obfd->archive_head;
321 bfd *this_element;
322 char *dir = cat ("./#", make_tempname (""), "cd");
323
324 /* Make a temp directory to hold the contents. */
325 mkdir (dir, 0777);
326 obfd->has_armap = ibfd->has_armap;
327
328 this_element = bfd_openr_next_archived_file (ibfd, NULL);
329 ibfd->archive_head = this_element;
330 while (this_element != (bfd *) NULL)
331 {
332 /* Create an output file for this member. */
333 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
334 bfd *output_bfd = bfd_openw (output_name, output_target);
335
336 if (output_bfd == (bfd *) NULL)
337 {
338 nonfatal (output_name);
339 }
340 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
341 {
342 nonfatal (bfd_get_filename (obfd));
343 }
344
345 if (bfd_check_format (this_element, bfd_object) == true)
346 {
347 copy_object (this_element, output_bfd);
348 }
349
350 bfd_close (output_bfd);
351 /* Open the newly output file and attatch to our list. */
352 output_bfd = bfd_openr (output_name, output_target);
353
354 /* Mark it for deletion. */
355 *ptr = output_bfd;
356 ptr = &output_bfd->next;
357 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
358 this_element = this_element->next;
359 }
360 *ptr = (bfd *) NULL;
361
362 if (!bfd_close (obfd))
363 {
364 nonfatal (bfd_get_filename (obfd));
365 }
366
367 /* Delete all the files that we opened.
368 Construct their names again, unfortunately, but
369 we're about to exit anyway. */
370 for (this_element = ibfd->archive_head;
371 this_element != (bfd *) NULL;
372 this_element = this_element->next)
373 {
374 unlink (cat (dir, "/", bfd_get_filename (this_element)));
375 }
376 rmdir (dir);
377 if (!bfd_close (ibfd))
378 {
379 nonfatal (bfd_get_filename (ibfd));
380 }
381 }
382
383 /* The top-level control. */
384
385 static void
386 copy_file (input_filename, output_filename, input_target, output_target)
387 char *input_filename;
388 char *output_filename;
389 char *input_target;
390 char *output_target;
391 {
392 bfd *ibfd;
393
394 /* To allow us to do "strip *" without dying on the first
395 non-object file, failures are nonfatal. */
396
397 ibfd = bfd_openr (input_filename, input_target);
398 if (ibfd == NULL)
399 {
400 nonfatal (input_filename);
401 }
402
403 if (bfd_check_format (ibfd, bfd_object))
404 {
405 bfd *obfd = bfd_openw (output_filename, output_target);
406 if (obfd == NULL)
407 {
408 nonfatal (output_filename);
409 }
410
411 copy_object (ibfd, obfd);
412
413 if (!bfd_close (obfd))
414 {
415 nonfatal (output_filename);
416 }
417
418 if (!bfd_close (ibfd))
419 {
420 nonfatal (input_filename);
421 }
422 }
423 else if (bfd_check_format (ibfd, bfd_archive))
424 {
425 bfd *obfd = bfd_openw (output_filename, output_target);
426 if (obfd == NULL)
427 {
428 nonfatal (output_filename);
429 }
430 copy_archive (ibfd, obfd, output_target);
431 }
432 else
433 {
434 /* Get the right error message. */
435 bfd_check_format (ibfd, bfd_object);
436 nonfatal (input_filename);
437 }
438 }
439
440 /* Create a section in OBFD with the same name and attributes
441 as ISECTION in IBFD. */
442
443 static void
444 setup_section (ibfd, isection, obfd)
445 bfd *ibfd;
446 sec_ptr isection;
447 bfd *obfd;
448 {
449 sec_ptr osection;
450 char *err;
451
452 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
453 && (strip_symbols == strip_debug
454 || strip_symbols == strip_all
455 || discard_locals == locals_all))
456 return;
457
458 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
459 if (osection == NULL)
460 {
461 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
462 if (osection == NULL)
463 {
464 err = "making";
465 goto loser;
466 }
467 }
468
469 if (!bfd_set_section_size (obfd,
470 osection,
471 bfd_section_size (ibfd, isection)))
472 {
473 err = "size";
474 goto loser;
475 }
476
477 if (bfd_set_section_vma (obfd,
478 osection,
479 bfd_section_vma (ibfd, isection))
480 == false)
481 {
482 err = "vma";
483 goto loser;
484 }
485
486 if (bfd_set_section_alignment (obfd,
487 osection,
488 bfd_section_alignment (ibfd, isection))
489 == false)
490 {
491 err = "alignment";
492 goto loser;
493 }
494
495 if (!bfd_set_section_flags (obfd, osection,
496 bfd_get_section_flags (ibfd, isection)))
497 {
498 err = "flags";
499 goto loser;
500 }
501
502 /* All went well */
503 return;
504
505 loser:
506 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
507 program_name,
508 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
509 err, bfd_errmsg (bfd_error));
510 status = 1;
511 }
512
513 /* Copy the data of input section ISECTION of IBFD
514 to an output section with the same name in OBFD.
515 If stripping then don't copy any relocation info. */
516
517 static void
518 copy_section (ibfd, isection, obfd)
519 bfd *ibfd;
520 sec_ptr isection;
521 bfd *obfd;
522 {
523 arelent **relpp;
524 int relcount;
525 sec_ptr osection;
526 bfd_size_type size;
527
528 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
529 && (strip_symbols == strip_debug
530 || strip_symbols == strip_all
531 || discard_locals == locals_all))
532 {
533 return;
534 }
535
536 osection = bfd_get_section_by_name (obfd,
537 bfd_section_name (ibfd, isection));
538
539 size = bfd_get_section_size_before_reloc (isection);
540
541 if (size == 0)
542 return;
543
544 if (strip_symbols == strip_all
545 || bfd_get_reloc_upper_bound (ibfd, isection) == 0)
546 {
547 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
548 }
549 else
550 {
551 relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (ibfd, isection));
552 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
553 bfd_set_reloc (obfd, osection, relpp, relcount);
554 }
555
556 isection->_cooked_size = isection->_raw_size;
557 isection->reloc_done = true;
558
559 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
560 {
561 PTR memhunk = (PTR) xmalloc ((unsigned) size);
562
563 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
564 size))
565 {
566 nonfatal (bfd_get_filename (ibfd));
567 }
568
569 if (copy_byte >= 0)
570 filter_bytes (memhunk, &size);
571
572 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
573 size))
574 {
575 nonfatal (bfd_get_filename (obfd));
576 }
577 free (memhunk);
578 }
579 }
580
581 /* All the symbols have been read in and point to their owning input section.
582 They have been relocated so that they are all relative to the base of
583 their owning section. On the way out, all the symbols will be relocated to
584 their new location in the output file, through some complex sums. */
585
586 static void
587 mangle_section (ibfd, p, obfd)
588 bfd *ibfd;
589 asection *p;
590 bfd *obfd;
591 {
592 p->output_section = bfd_get_section_by_name (obfd, p->name);
593 p->output_offset = 0;
594 }
595
596 /* The number of bytes to copy at once. */
597 #define COPY_BUF 8192
598
599 /* Copy file FROM to file TO, performing no translations.
600 Return 0 if ok, -1 if error. */
601
602 static int
603 simple_copy (from, to)
604 char *from, *to;
605 {
606 int fromfd, tofd, nread;
607 char buf[COPY_BUF];
608
609 fromfd = open (from, O_RDONLY);
610 if (fromfd < 0)
611 return -1;
612 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
613 if (tofd < 0)
614 {
615 close (fromfd);
616 return -1;
617 }
618 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
619 {
620 if (write (tofd, buf, nread) != nread)
621 {
622 close (fromfd);
623 close (tofd);
624 return -1;
625 }
626 }
627 close (fromfd);
628 close (tofd);
629 if (nread < 0)
630 return -1;
631 return 0;
632 }
633
634 #ifndef S_ISLNK
635 #ifdef S_IFLNK
636 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
637 #else
638 #define S_ISLNK(m) 0
639 #define lstat stat
640 #endif
641 #endif
642
643 /* Rename FROM to TO, copying if TO is a link.
644 Assumes that TO already exists, because FROM is a temp file.
645 Return 0 if ok, -1 if error. */
646
647 static int
648 smart_rename (from, to)
649 char *from, *to;
650 {
651 struct stat s;
652 int ret = 0;
653
654 if (lstat (to, &s))
655 return -1;
656
657 /* Use rename only if TO is not a symbolic link and has
658 only one hard link. */
659 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
660 {
661 ret = rename (from, to);
662 if (ret == 0)
663 {
664 /* Try to preserve the permission bits and ownership of TO. */
665 chmod (to, s.st_mode & 07777);
666 chown (to, s.st_uid, s.st_gid);
667 }
668 }
669 else
670 {
671 ret = simple_copy (from, to);
672 if (ret == 0)
673 unlink (from);
674 }
675 return ret;
676 }
677
678 static int
679 strip_main (argc, argv)
680 int argc;
681 char *argv[];
682 {
683 char *input_target = NULL, *output_target = NULL;
684 boolean show_version = false;
685 int c, i;
686
687 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
688 strip_options, (int *) 0)) != EOF)
689 {
690 switch (c)
691 {
692 case 'I':
693 input_target = optarg;
694 case 'O':
695 output_target = optarg;
696 break;
697 case 'F':
698 input_target = output_target = optarg;
699 break;
700 case 's':
701 strip_symbols = strip_all;
702 break;
703 case 'S':
704 case 'g':
705 strip_symbols = strip_debug;
706 break;
707 case 'x':
708 discard_locals = locals_all;
709 break;
710 case 'X':
711 discard_locals = locals_start_L;
712 break;
713 case 'v':
714 verbose = true;
715 break;
716 case 'V':
717 show_version = true;
718 break;
719 case 0:
720 break; /* we've been given a long option */
721 case 'h':
722 strip_usage (stdout, 0);
723 default:
724 strip_usage (stderr, 1);
725 }
726 }
727
728 if (show_version)
729 {
730 printf ("GNU %s version %s\n", program_name, program_version);
731 exit (0);
732 }
733
734 /* Default is to strip all symbols. */
735 if (strip_symbols == strip_undef && discard_locals == locals_undef)
736 strip_symbols = strip_all;
737
738 if (output_target == (char *) NULL)
739 output_target = input_target;
740
741 i = optind;
742 if (i == argc)
743 strip_usage (stderr, 1);
744
745 for (; i < argc; i++)
746 {
747 int hold_status = status;
748
749 char *tmpname = make_tempname (argv[i]);
750 status = 0;
751 copy_file (argv[i], tmpname, input_target, output_target);
752 if (status == 0)
753 {
754 smart_rename (tmpname, argv[i]);
755 status = hold_status;
756 }
757 else
758 unlink (tmpname);
759 free (tmpname);
760 }
761
762 return 0;
763 }
764
765 static int
766 copy_main (argc, argv)
767 int argc;
768 char *argv[];
769 {
770 char *input_filename, *output_filename;
771 char *input_target = NULL, *output_target = NULL;
772 boolean show_version = false;
773 int c;
774
775 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
776 copy_options, (int *) 0)) != EOF)
777 {
778 switch (c)
779 {
780 case 'b':
781 copy_byte = atoi(optarg);
782 if (copy_byte < 0)
783 {
784 fprintf (stderr, "%s: byte number must be non-negative\n",
785 program_name);
786 exit (1);
787 }
788 break;
789 case 'i':
790 interleave = atoi(optarg);
791 if (interleave < 1)
792 {
793 fprintf(stderr, "%s: interleave must be positive\n",
794 program_name);
795 exit (1);
796 }
797 break;
798 case 'I':
799 case 's': /* "source" - 'I' is preferred */
800 input_target = optarg;
801 case 'O':
802 case 'd': /* "destination" - 'O' is preferred */
803 output_target = optarg;
804 break;
805 case 'F':
806 input_target = output_target = optarg;
807 break;
808 case 'S':
809 strip_symbols = strip_all;
810 break;
811 case 'g':
812 strip_symbols = strip_debug;
813 break;
814 case 'x':
815 discard_locals = locals_all;
816 break;
817 case 'X':
818 discard_locals = locals_start_L;
819 break;
820 case 'v':
821 verbose = true;
822 break;
823 case 'V':
824 show_version = true;
825 break;
826 case 0:
827 break; /* we've been given a long option */
828 case 'h':
829 copy_usage (stdout, 0);
830 default:
831 copy_usage (stderr, 1);
832 }
833 }
834
835 if (show_version)
836 {
837 printf ("GNU %s version %s\n", program_name, program_version);
838 exit (0);
839 }
840
841 if (copy_byte >= interleave)
842 {
843 fprintf (stderr, "%s: byte number must be less than interleave\n",
844 program_name);
845 exit (1);
846 }
847
848 if (optind == argc || optind + 2 < argc)
849 copy_usage (stderr, 1);
850
851 input_filename = argv[optind];
852 if (optind + 1 < argc)
853 output_filename = argv[optind + 1];
854
855 /* Default is to strip no symbols. */
856 if (strip_symbols == strip_undef && discard_locals == locals_undef)
857 strip_symbols = strip_none;
858
859 if (output_target == (char *) NULL)
860 output_target = input_target;
861
862 /* If there is no destination file then create a temp and rename
863 the result into the input. */
864
865 if (output_filename == (char *) NULL)
866 {
867 char *tmpname = make_tempname (input_filename);
868 copy_file (input_filename, tmpname, input_target, output_target);
869 if (status == 0)
870 smart_rename (tmpname, input_filename);
871 else
872 unlink (tmpname);
873 }
874 else
875 {
876 copy_file (input_filename, output_filename, input_target, output_target);
877 }
878
879 return 0;
880 }
881
882 int
883 main (argc, argv)
884 int argc;
885 char *argv[];
886 {
887 program_name = argv[0];
888 strip_symbols = strip_undef;
889 discard_locals = locals_undef;
890
891 bfd_init ();
892
893 if (is_strip < 0)
894 {
895 int i = strlen (program_name);
896 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
897 }
898
899 if (is_strip)
900 strip_main (argc, argv);
901 else
902 copy_main (argc, argv);
903
904 return status;
905 }
This page took 0.049956 seconds and 4 git commands to generate.