* remote.c, remote-mon.c, remote-utils.c, remote-utils.h,
[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 char *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 char **matching;
394
395 /* To allow us to do "strip *" without dying on the first
396 non-object file, failures are nonfatal. */
397
398 ibfd = bfd_openr (input_filename, input_target);
399 if (ibfd == NULL)
400 {
401 nonfatal (input_filename);
402 }
403
404 if (bfd_check_format (ibfd, bfd_archive))
405 {
406 bfd *obfd = bfd_openw (output_filename, output_target);
407 if (obfd == NULL)
408 {
409 nonfatal (output_filename);
410 }
411 copy_archive (ibfd, obfd, output_target);
412 }
413 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
414 {
415 bfd *obfd = bfd_openw (output_filename, output_target);
416 if (obfd == NULL)
417 {
418 nonfatal (output_filename);
419 }
420
421 copy_object (ibfd, obfd);
422
423 if (!bfd_close (obfd))
424 {
425 nonfatal (output_filename);
426 }
427
428 if (!bfd_close (ibfd))
429 {
430 nonfatal (input_filename);
431 }
432 }
433 else
434 {
435 bfd_nonfatal (input_filename);
436 if (bfd_error == file_ambiguously_recognized)
437 {
438 list_matching_formats (matching);
439 free (matching);
440 }
441 status = 1;
442 }
443 }
444
445 /* Create a section in OBFD with the same name and attributes
446 as ISECTION in IBFD. */
447
448 static void
449 setup_section (ibfd, isection, obfd)
450 bfd *ibfd;
451 sec_ptr isection;
452 bfd *obfd;
453 {
454 sec_ptr osection;
455 char *err;
456
457 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
458 && (strip_symbols == strip_debug
459 || strip_symbols == strip_all
460 || discard_locals == locals_all))
461 return;
462
463 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
464 if (osection == NULL)
465 {
466 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
467 if (osection == NULL)
468 {
469 err = "making";
470 goto loser;
471 }
472 }
473
474 if (!bfd_set_section_size (obfd,
475 osection,
476 bfd_section_size (ibfd, isection)))
477 {
478 err = "size";
479 goto loser;
480 }
481
482 if (bfd_set_section_vma (obfd,
483 osection,
484 bfd_section_vma (ibfd, isection))
485 == false)
486 {
487 err = "vma";
488 goto loser;
489 }
490
491 if (bfd_set_section_alignment (obfd,
492 osection,
493 bfd_section_alignment (ibfd, isection))
494 == false)
495 {
496 err = "alignment";
497 goto loser;
498 }
499
500 if (!bfd_set_section_flags (obfd, osection,
501 bfd_get_section_flags (ibfd, isection)))
502 {
503 err = "flags";
504 goto loser;
505 }
506
507 /* All went well */
508 return;
509
510 loser:
511 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
512 program_name,
513 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
514 err, bfd_errmsg (bfd_error));
515 status = 1;
516 }
517
518 /* Copy the data of input section ISECTION of IBFD
519 to an output section with the same name in OBFD.
520 If stripping then don't copy any relocation info. */
521
522 static void
523 copy_section (ibfd, isection, obfd)
524 bfd *ibfd;
525 sec_ptr isection;
526 bfd *obfd;
527 {
528 arelent **relpp;
529 int relcount;
530 sec_ptr osection;
531 bfd_size_type size;
532
533 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
534 && (strip_symbols == strip_debug
535 || strip_symbols == strip_all
536 || discard_locals == locals_all))
537 {
538 return;
539 }
540
541 osection = bfd_get_section_by_name (obfd,
542 bfd_section_name (ibfd, isection));
543
544 size = bfd_get_section_size_before_reloc (isection);
545
546 if (size == 0)
547 return;
548
549 if (strip_symbols == strip_all
550 || bfd_get_reloc_upper_bound (ibfd, isection) == 0)
551 {
552 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
553 }
554 else
555 {
556 relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (ibfd, isection));
557 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
558 bfd_set_reloc (obfd, osection, relpp, relcount);
559 }
560
561 isection->_cooked_size = isection->_raw_size;
562 isection->reloc_done = true;
563
564 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
565 {
566 PTR memhunk = (PTR) xmalloc ((unsigned) size);
567
568 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
569 size))
570 {
571 nonfatal (bfd_get_filename (ibfd));
572 }
573
574 if (copy_byte >= 0)
575 filter_bytes (memhunk, &size);
576
577 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
578 size))
579 {
580 nonfatal (bfd_get_filename (obfd));
581 }
582 free (memhunk);
583 }
584 }
585
586 /* All the symbols have been read in and point to their owning input section.
587 They have been relocated so that they are all relative to the base of
588 their owning section. On the way out, all the symbols will be relocated to
589 their new location in the output file, through some complex sums. */
590
591 static void
592 mangle_section (ibfd, p, obfd)
593 bfd *ibfd;
594 asection *p;
595 bfd *obfd;
596 {
597 p->output_section = bfd_get_section_by_name (obfd, p->name);
598 p->output_offset = 0;
599 }
600
601 /* The number of bytes to copy at once. */
602 #define COPY_BUF 8192
603
604 /* Copy file FROM to file TO, performing no translations.
605 Return 0 if ok, -1 if error. */
606
607 static int
608 simple_copy (from, to)
609 char *from, *to;
610 {
611 int fromfd, tofd, nread;
612 char buf[COPY_BUF];
613
614 fromfd = open (from, O_RDONLY);
615 if (fromfd < 0)
616 return -1;
617 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
618 if (tofd < 0)
619 {
620 close (fromfd);
621 return -1;
622 }
623 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
624 {
625 if (write (tofd, buf, nread) != nread)
626 {
627 close (fromfd);
628 close (tofd);
629 return -1;
630 }
631 }
632 close (fromfd);
633 close (tofd);
634 if (nread < 0)
635 return -1;
636 return 0;
637 }
638
639 #ifndef S_ISLNK
640 #ifdef S_IFLNK
641 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
642 #else
643 #define S_ISLNK(m) 0
644 #define lstat stat
645 #endif
646 #endif
647
648 /* Rename FROM to TO, copying if TO is a link.
649 Assumes that TO already exists, because FROM is a temp file.
650 Return 0 if ok, -1 if error. */
651
652 static int
653 smart_rename (from, to)
654 char *from, *to;
655 {
656 struct stat s;
657 int ret = 0;
658
659 if (lstat (to, &s))
660 return -1;
661
662 /* Use rename only if TO is not a symbolic link and has
663 only one hard link. */
664 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
665 {
666 ret = rename (from, to);
667 if (ret == 0)
668 {
669 /* Try to preserve the permission bits and ownership of TO. */
670 chmod (to, s.st_mode & 07777);
671 chown (to, s.st_uid, s.st_gid);
672 }
673 }
674 else
675 {
676 ret = simple_copy (from, to);
677 if (ret == 0)
678 unlink (from);
679 }
680 return ret;
681 }
682
683 static int
684 strip_main (argc, argv)
685 int argc;
686 char *argv[];
687 {
688 char *input_target = NULL, *output_target = NULL;
689 boolean show_version = false;
690 int c, i;
691
692 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
693 strip_options, (int *) 0)) != EOF)
694 {
695 switch (c)
696 {
697 case 'I':
698 input_target = optarg;
699 break;
700 case 'O':
701 output_target = optarg;
702 break;
703 case 'F':
704 input_target = output_target = optarg;
705 break;
706 case 's':
707 strip_symbols = strip_all;
708 break;
709 case 'S':
710 case 'g':
711 strip_symbols = strip_debug;
712 break;
713 case 'x':
714 discard_locals = locals_all;
715 break;
716 case 'X':
717 discard_locals = locals_start_L;
718 break;
719 case 'v':
720 verbose = true;
721 break;
722 case 'V':
723 show_version = true;
724 break;
725 case 0:
726 break; /* we've been given a long option */
727 case 'h':
728 strip_usage (stdout, 0);
729 default:
730 strip_usage (stderr, 1);
731 }
732 }
733
734 if (show_version)
735 {
736 printf ("GNU %s version %s\n", program_name, program_version);
737 exit (0);
738 }
739
740 /* Default is to strip all symbols. */
741 if (strip_symbols == strip_undef && discard_locals == locals_undef)
742 strip_symbols = strip_all;
743
744 if (output_target == (char *) NULL)
745 output_target = input_target;
746
747 i = optind;
748 if (i == argc)
749 strip_usage (stderr, 1);
750
751 for (; i < argc; i++)
752 {
753 int hold_status = status;
754
755 char *tmpname = make_tempname (argv[i]);
756 status = 0;
757 copy_file (argv[i], tmpname, input_target, output_target);
758 if (status == 0)
759 {
760 smart_rename (tmpname, argv[i]);
761 status = hold_status;
762 }
763 else
764 unlink (tmpname);
765 free (tmpname);
766 }
767
768 return 0;
769 }
770
771 static int
772 copy_main (argc, argv)
773 int argc;
774 char *argv[];
775 {
776 char *input_filename, *output_filename;
777 char *input_target = NULL, *output_target = NULL;
778 boolean show_version = false;
779 int c;
780
781 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
782 copy_options, (int *) 0)) != EOF)
783 {
784 switch (c)
785 {
786 case 'b':
787 copy_byte = atoi(optarg);
788 if (copy_byte < 0)
789 {
790 fprintf (stderr, "%s: byte number must be non-negative\n",
791 program_name);
792 exit (1);
793 }
794 break;
795 case 'i':
796 interleave = atoi(optarg);
797 if (interleave < 1)
798 {
799 fprintf(stderr, "%s: interleave must be positive\n",
800 program_name);
801 exit (1);
802 }
803 break;
804 case 'I':
805 case 's': /* "source" - 'I' is preferred */
806 input_target = optarg;
807 break;
808 case 'O':
809 case 'd': /* "destination" - 'O' is preferred */
810 output_target = optarg;
811 break;
812 case 'F':
813 input_target = output_target = optarg;
814 break;
815 case 'S':
816 strip_symbols = strip_all;
817 break;
818 case 'g':
819 strip_symbols = strip_debug;
820 break;
821 case 'x':
822 discard_locals = locals_all;
823 break;
824 case 'X':
825 discard_locals = locals_start_L;
826 break;
827 case 'v':
828 verbose = true;
829 break;
830 case 'V':
831 show_version = true;
832 break;
833 case 0:
834 break; /* we've been given a long option */
835 case 'h':
836 copy_usage (stdout, 0);
837 default:
838 copy_usage (stderr, 1);
839 }
840 }
841
842 if (show_version)
843 {
844 printf ("GNU %s version %s\n", program_name, program_version);
845 exit (0);
846 }
847
848 if (copy_byte >= interleave)
849 {
850 fprintf (stderr, "%s: byte number must be less than interleave\n",
851 program_name);
852 exit (1);
853 }
854
855 if (optind == argc || optind + 2 < argc)
856 copy_usage (stderr, 1);
857
858 input_filename = argv[optind];
859 if (optind + 1 < argc)
860 output_filename = argv[optind + 1];
861
862 /* Default is to strip no symbols. */
863 if (strip_symbols == strip_undef && discard_locals == locals_undef)
864 strip_symbols = strip_none;
865
866 if (output_target == (char *) NULL)
867 output_target = input_target;
868
869 /* If there is no destination file then create a temp and rename
870 the result into the input. */
871
872 if (output_filename == (char *) NULL)
873 {
874 char *tmpname = make_tempname (input_filename);
875 copy_file (input_filename, tmpname, input_target, output_target);
876 if (status == 0)
877 smart_rename (tmpname, input_filename);
878 else
879 unlink (tmpname);
880 }
881 else
882 {
883 copy_file (input_filename, output_filename, input_target, output_target);
884 }
885
886 return 0;
887 }
888
889 int
890 main (argc, argv)
891 int argc;
892 char *argv[];
893 {
894 program_name = argv[0];
895 xmalloc_set_program_name (program_name);
896 strip_symbols = strip_undef;
897 discard_locals = locals_undef;
898
899 bfd_init ();
900
901 if (is_strip < 0)
902 {
903 int i = strlen (program_name);
904 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
905 }
906
907 if (is_strip)
908 strip_main (argc, argv);
909 else
910 copy_main (argc, argv);
911
912 return status;
913 }
This page took 0.049804 seconds and 4 git commands to generate.