]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/objcopy.c
Update for recent BFD changes to symbol and reloc reading. Rename
[thirdparty/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 mark_symbols_used_in_relocations ();
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 long symcount;
182 {
183 register asymbol **from = isyms, **to = osyms;
184 long src_count = 0, dst_count = 0;
185
186 for (; src_count < symcount; src_count++)
187 {
188 asymbol *sym = from[src_count];
189 flagword flags = sym->flags;
190 int keep;
191
192 if ((flags & BSF_GLOBAL) /* Keep if external. */
193 || (flags & BSF_KEEP) /* Keep if used in a relocation. */
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_is_local_label (abfd, sym));
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 long 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 /* Allow the BFD backend to copy any private data it understands
271 from the input BFD to the output BFD. */
272 if (!bfd_copy_private_bfd_data (ibfd, obfd))
273 {
274 fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
275 program_name, bfd_get_filename (obfd),
276 bfd_errmsg (bfd_get_error ()));
277 status = 1;
278 return;
279 }
280
281 /* bfd mandates that all output sections be created and sizes set before
282 any output is done. Thus, we traverse all sections multiple times. */
283 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
284
285 /* Symbol filtering must happen after the output sections have
286 been created, but before their contents are set. */
287 if (strip_symbols == strip_all && discard_locals == locals_undef)
288 {
289 osympp = isympp = NULL;
290 symcount = 0;
291 }
292 else
293 {
294 long symsize;
295
296 symsize = bfd_get_symtab_upper_bound (ibfd);
297 if (symsize < 0)
298 {
299 nonfatal (bfd_get_filename (ibfd));
300 }
301
302 osympp = isympp = (asymbol **) xmalloc (symsize);
303 symcount = bfd_canonicalize_symtab (ibfd, isympp);
304 if (symcount < 0)
305 {
306 nonfatal (bfd_get_filename (ibfd));
307 }
308
309 if (strip_symbols == strip_debug || discard_locals != locals_undef)
310 {
311 /* Mark symbols used in output relocations so that they
312 are kept, even if they are local labels or static symbols.
313
314 Note we iterate over the input sections examining their
315 relocations since the relocations for the output sections
316 haven't been set yet. mark_symbols_used_in_relocations will
317 ignore input sections which have no corresponding output
318 section. */
319 bfd_map_over_sections (ibfd,
320 mark_symbols_used_in_relocations,
321 (void *)isympp);
322 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
323 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
324 }
325 }
326
327 bfd_set_symtab (obfd, osympp, symcount);
328
329 /* This has to happen after the symbol table has been set. */
330 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
331 }
332
333 static char *
334 cat (a, b, c)
335 char *a;
336 char *b;
337 char *c;
338 {
339 size_t size = strlen (a) + strlen (b) + strlen (c);
340 char *r = xmalloc (size + 1);
341
342 strcpy (r, a);
343 strcat (r, b);
344 strcat (r, c);
345 return r;
346 }
347
348 /* Read each archive element in turn from IBFD, copy the
349 contents to temp file, and keep the temp file handle. */
350
351 static void
352 copy_archive (ibfd, obfd, output_target)
353 bfd *ibfd;
354 bfd *obfd;
355 char *output_target;
356 {
357 bfd **ptr = &obfd->archive_head;
358 bfd *this_element;
359 char *dir = cat ("./#", make_tempname (""), "cd");
360
361 /* Make a temp directory to hold the contents. */
362 mkdir (dir, 0777);
363 obfd->has_armap = ibfd->has_armap;
364
365 this_element = bfd_openr_next_archived_file (ibfd, NULL);
366 ibfd->archive_head = this_element;
367 while (this_element != (bfd *) NULL)
368 {
369 /* Create an output file for this member. */
370 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
371 bfd *output_bfd = bfd_openw (output_name, output_target);
372
373 if (output_bfd == (bfd *) NULL)
374 {
375 nonfatal (output_name);
376 }
377 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
378 {
379 nonfatal (bfd_get_filename (obfd));
380 }
381
382 if (bfd_check_format (this_element, bfd_object) == true)
383 {
384 copy_object (this_element, output_bfd);
385 }
386
387 bfd_close (output_bfd);
388 /* Open the newly output file and attatch to our list. */
389 output_bfd = bfd_openr (output_name, output_target);
390
391 /* Mark it for deletion. */
392 *ptr = output_bfd;
393 ptr = &output_bfd->next;
394 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
395 this_element = this_element->next;
396 }
397 *ptr = (bfd *) NULL;
398
399 if (!bfd_close (obfd))
400 {
401 nonfatal (bfd_get_filename (obfd));
402 }
403
404 /* Delete all the files that we opened.
405 Construct their names again, unfortunately, but
406 we're about to exit anyway. */
407 for (this_element = ibfd->archive_head;
408 this_element != (bfd *) NULL;
409 this_element = this_element->next)
410 {
411 unlink (cat (dir, "/", bfd_get_filename (this_element)));
412 }
413 rmdir (dir);
414 if (!bfd_close (ibfd))
415 {
416 nonfatal (bfd_get_filename (ibfd));
417 }
418 }
419
420 /* The top-level control. */
421
422 static void
423 copy_file (input_filename, output_filename, input_target, output_target)
424 char *input_filename;
425 char *output_filename;
426 char *input_target;
427 char *output_target;
428 {
429 bfd *ibfd;
430 char **matching;
431
432 /* To allow us to do "strip *" without dying on the first
433 non-object file, failures are nonfatal. */
434
435 ibfd = bfd_openr (input_filename, input_target);
436 if (ibfd == NULL)
437 {
438 nonfatal (input_filename);
439 }
440
441 if (bfd_check_format (ibfd, bfd_archive))
442 {
443 bfd *obfd = bfd_openw (output_filename, output_target);
444 if (obfd == NULL)
445 {
446 nonfatal (output_filename);
447 }
448 copy_archive (ibfd, obfd, output_target);
449 }
450 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
451 {
452 bfd *obfd = bfd_openw (output_filename, output_target);
453 if (obfd == NULL)
454 {
455 nonfatal (output_filename);
456 }
457
458 copy_object (ibfd, obfd);
459
460 if (!bfd_close (obfd))
461 {
462 nonfatal (output_filename);
463 }
464
465 if (!bfd_close (ibfd))
466 {
467 nonfatal (input_filename);
468 }
469 }
470 else
471 {
472 bfd_nonfatal (input_filename);
473 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
474 {
475 list_matching_formats (matching);
476 free (matching);
477 }
478 status = 1;
479 }
480 }
481
482 /* Create a section in OBFD with the same name and attributes
483 as ISECTION in IBFD. */
484
485 static void
486 setup_section (ibfd, isection, obfd)
487 bfd *ibfd;
488 sec_ptr isection;
489 bfd *obfd;
490 {
491 sec_ptr osection;
492 char *err;
493
494 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
495 && (strip_symbols == strip_debug
496 || strip_symbols == strip_all
497 || discard_locals == locals_all))
498 return;
499
500 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
501 if (osection == NULL)
502 {
503 err = "making";
504 goto loser;
505 }
506
507 if (!bfd_set_section_size (obfd,
508 osection,
509 bfd_section_size (ibfd, isection)))
510 {
511 err = "size";
512 goto loser;
513 }
514
515 if (bfd_set_section_vma (obfd,
516 osection,
517 bfd_section_vma (ibfd, isection))
518 == false)
519 {
520 err = "vma";
521 goto loser;
522 }
523
524 if (bfd_set_section_alignment (obfd,
525 osection,
526 bfd_section_alignment (ibfd, isection))
527 == false)
528 {
529 err = "alignment";
530 goto loser;
531 }
532
533 if (!bfd_set_section_flags (obfd, osection,
534 bfd_get_section_flags (ibfd, isection)))
535 {
536 err = "flags";
537 goto loser;
538 }
539
540 /* This used to be mangle_section; we do here to avoid using
541 bfd_get_section_by_name since some formats allow multiple
542 sections with the same name. */
543 isection->output_section = osection;
544 isection->output_offset = 0;
545
546 /* Allow the BFD backend to copy any private data it understands
547 from the input section to the output section. */
548 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
549 {
550 err = "private data";
551 goto loser;
552 }
553
554 /* All went well */
555 return;
556
557 loser:
558 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
559 program_name,
560 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
561 err, bfd_errmsg (bfd_get_error ()));
562 status = 1;
563 }
564
565 /* Copy the data of input section ISECTION of IBFD
566 to an output section with the same name in OBFD.
567 If stripping then don't copy any relocation info. */
568
569 static void
570 copy_section (ibfd, isection, obfd)
571 bfd *ibfd;
572 sec_ptr isection;
573 bfd *obfd;
574 {
575 arelent **relpp;
576 long relcount;
577 sec_ptr osection;
578 bfd_size_type size;
579
580 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
581 && (strip_symbols == strip_debug
582 || strip_symbols == strip_all
583 || discard_locals == locals_all))
584 {
585 return;
586 }
587
588 osection = isection->output_section;
589 size = bfd_get_section_size_before_reloc (isection);
590
591 if (size == 0 || osection == 0)
592 return;
593
594 if (strip_symbols == strip_all)
595 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
596 else
597 {
598 long relsize;
599
600 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
601 if (relsize < 0)
602 {
603 nonfatal (bfd_get_filename (ibfd));
604 }
605 if (relsize == 0)
606 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
607 else
608 {
609 relpp = (arelent **) xmalloc (relsize);
610 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
611 if (relcount < 0)
612 {
613 nonfatal (bfd_get_filename (ibfd));
614 }
615 bfd_set_reloc (obfd, osection, relpp, relcount);
616 }
617 }
618
619 isection->_cooked_size = isection->_raw_size;
620 isection->reloc_done = true;
621
622 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
623 {
624 PTR memhunk = (PTR) xmalloc ((unsigned) size);
625
626 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
627 size))
628 {
629 nonfatal (bfd_get_filename (ibfd));
630 }
631
632 if (copy_byte >= 0)
633 filter_bytes (memhunk, &size);
634
635 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
636 size))
637 {
638 nonfatal (bfd_get_filename (obfd));
639 }
640 free (memhunk);
641 }
642 }
643
644 /* Mark all the symbols which will be used in output relocations with
645 the BSF_KEEP flag so that those symbols will not be stripped.
646
647 Ignore relocations which will not appear in the output file. */
648
649 static void
650 mark_symbols_used_in_relocations (ibfd, isection, symbols)
651 bfd *ibfd;
652 sec_ptr isection;
653 asymbol **symbols;
654 {
655 long relsize;
656 arelent **relpp;
657 long relcount, i;
658
659 /* Ignore an input section with no corresponding output section. */
660 if (isection->output_section == NULL)
661 return;
662
663 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
664 if (relsize < 0)
665 bfd_fatal (bfd_get_filename (ibfd));
666
667 relpp = (arelent **) xmalloc (relsize);
668 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
669 if (relcount < 0)
670 bfd_fatal (bfd_get_filename (ibfd));
671
672 /* Examine each symbol used in a relocation. If it's not one of the
673 special bfd section symbols, then mark it with BSF_KEEP. */
674 for (i = 0; i < relcount; i++)
675 {
676 if (*relpp[i]->sym_ptr_ptr != bfd_com_section.symbol
677 && *relpp[i]->sym_ptr_ptr != bfd_abs_section.symbol
678 && *relpp[i]->sym_ptr_ptr != bfd_und_section.symbol)
679 (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
680 }
681
682 if (relpp != NULL)
683 free (relpp);
684 }
685
686 /* The number of bytes to copy at once. */
687 #define COPY_BUF 8192
688
689 /* Copy file FROM to file TO, performing no translations.
690 Return 0 if ok, -1 if error. */
691
692 static int
693 simple_copy (from, to)
694 char *from, *to;
695 {
696 int fromfd, tofd, nread;
697 char buf[COPY_BUF];
698
699 fromfd = open (from, O_RDONLY);
700 if (fromfd < 0)
701 return -1;
702 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
703 if (tofd < 0)
704 {
705 close (fromfd);
706 return -1;
707 }
708 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
709 {
710 if (write (tofd, buf, nread) != nread)
711 {
712 close (fromfd);
713 close (tofd);
714 return -1;
715 }
716 }
717 close (fromfd);
718 close (tofd);
719 if (nread < 0)
720 return -1;
721 return 0;
722 }
723
724 #ifndef S_ISLNK
725 #ifdef S_IFLNK
726 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
727 #else
728 #define S_ISLNK(m) 0
729 #define lstat stat
730 #endif
731 #endif
732
733 /* Rename FROM to TO, copying if TO is a link.
734 Assumes that TO already exists, because FROM is a temp file.
735 Return 0 if ok, -1 if error. */
736
737 static int
738 smart_rename (from, to)
739 char *from, *to;
740 {
741 struct stat s;
742 int ret = 0;
743
744 if (lstat (to, &s))
745 return -1;
746
747 /* Use rename only if TO is not a symbolic link and has
748 only one hard link. */
749 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
750 {
751 ret = rename (from, to);
752 if (ret == 0)
753 {
754 /* Try to preserve the permission bits and ownership of TO. */
755 chmod (to, s.st_mode & 07777);
756 chown (to, s.st_uid, s.st_gid);
757 }
758 }
759 else
760 {
761 ret = simple_copy (from, to);
762 if (ret == 0)
763 unlink (from);
764 }
765 return ret;
766 }
767
768 static int
769 strip_main (argc, argv)
770 int argc;
771 char *argv[];
772 {
773 char *input_target = NULL, *output_target = NULL;
774 boolean show_version = false;
775 int c, i;
776
777 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
778 strip_options, (int *) 0)) != EOF)
779 {
780 switch (c)
781 {
782 case 'I':
783 input_target = optarg;
784 break;
785 case 'O':
786 output_target = optarg;
787 break;
788 case 'F':
789 input_target = output_target = optarg;
790 break;
791 case 's':
792 strip_symbols = strip_all;
793 break;
794 case 'S':
795 case 'g':
796 strip_symbols = strip_debug;
797 break;
798 case 'x':
799 discard_locals = locals_all;
800 break;
801 case 'X':
802 discard_locals = locals_start_L;
803 break;
804 case 'v':
805 verbose = true;
806 break;
807 case 'V':
808 show_version = true;
809 break;
810 case 0:
811 break; /* we've been given a long option */
812 case 'h':
813 strip_usage (stdout, 0);
814 default:
815 strip_usage (stderr, 1);
816 }
817 }
818
819 if (show_version)
820 {
821 printf ("GNU %s version %s\n", program_name, program_version);
822 exit (0);
823 }
824
825 /* Default is to strip all symbols. */
826 if (strip_symbols == strip_undef && discard_locals == locals_undef)
827 strip_symbols = strip_all;
828
829 if (output_target == (char *) NULL)
830 output_target = input_target;
831
832 i = optind;
833 if (i == argc)
834 strip_usage (stderr, 1);
835
836 for (; i < argc; i++)
837 {
838 int hold_status = status;
839
840 char *tmpname = make_tempname (argv[i]);
841 status = 0;
842 copy_file (argv[i], tmpname, input_target, output_target);
843 if (status == 0)
844 {
845 smart_rename (tmpname, argv[i]);
846 status = hold_status;
847 }
848 else
849 unlink (tmpname);
850 free (tmpname);
851 }
852
853 return 0;
854 }
855
856 static int
857 copy_main (argc, argv)
858 int argc;
859 char *argv[];
860 {
861 char *input_filename, *output_filename;
862 char *input_target = NULL, *output_target = NULL;
863 boolean show_version = false;
864 int c;
865
866 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
867 copy_options, (int *) 0)) != EOF)
868 {
869 switch (c)
870 {
871 case 'b':
872 copy_byte = atoi(optarg);
873 if (copy_byte < 0)
874 {
875 fprintf (stderr, "%s: byte number must be non-negative\n",
876 program_name);
877 exit (1);
878 }
879 break;
880 case 'i':
881 interleave = atoi(optarg);
882 if (interleave < 1)
883 {
884 fprintf(stderr, "%s: interleave must be positive\n",
885 program_name);
886 exit (1);
887 }
888 break;
889 case 'I':
890 case 's': /* "source" - 'I' is preferred */
891 input_target = optarg;
892 break;
893 case 'O':
894 case 'd': /* "destination" - 'O' is preferred */
895 output_target = optarg;
896 break;
897 case 'F':
898 input_target = output_target = optarg;
899 break;
900 case 'S':
901 strip_symbols = strip_all;
902 break;
903 case 'g':
904 strip_symbols = strip_debug;
905 break;
906 case 'x':
907 discard_locals = locals_all;
908 break;
909 case 'X':
910 discard_locals = locals_start_L;
911 break;
912 case 'v':
913 verbose = true;
914 break;
915 case 'V':
916 show_version = true;
917 break;
918 case 0:
919 break; /* we've been given a long option */
920 case 'h':
921 copy_usage (stdout, 0);
922 default:
923 copy_usage (stderr, 1);
924 }
925 }
926
927 if (show_version)
928 {
929 printf ("GNU %s version %s\n", program_name, program_version);
930 exit (0);
931 }
932
933 if (copy_byte >= interleave)
934 {
935 fprintf (stderr, "%s: byte number must be less than interleave\n",
936 program_name);
937 exit (1);
938 }
939
940 if (optind == argc || optind + 2 < argc)
941 copy_usage (stderr, 1);
942
943 input_filename = argv[optind];
944 if (optind + 1 < argc)
945 output_filename = argv[optind + 1];
946
947 /* Default is to strip no symbols. */
948 if (strip_symbols == strip_undef && discard_locals == locals_undef)
949 strip_symbols = strip_none;
950
951 if (output_target == (char *) NULL)
952 output_target = input_target;
953
954 /* If there is no destination file then create a temp and rename
955 the result into the input. */
956
957 if (output_filename == (char *) NULL)
958 {
959 char *tmpname = make_tempname (input_filename);
960 copy_file (input_filename, tmpname, input_target, output_target);
961 if (status == 0)
962 smart_rename (tmpname, input_filename);
963 else
964 unlink (tmpname);
965 }
966 else
967 {
968 copy_file (input_filename, output_filename, input_target, output_target);
969 }
970
971 return 0;
972 }
973
974 int
975 main (argc, argv)
976 int argc;
977 char *argv[];
978 {
979 program_name = argv[0];
980 xmalloc_set_program_name (program_name);
981 strip_symbols = strip_undef;
982 discard_locals = locals_undef;
983
984 bfd_init ();
985
986 if (is_strip < 0)
987 {
988 int i = strlen (program_name);
989 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
990 }
991
992 if (is_strip)
993 strip_main (argc, argv);
994 else
995 copy_main (argc, argv);
996
997 return status;
998 }