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