]> Git Repo - binutils.git/blob - binutils/objcopy.c
More testcases.
[binutils.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 }
This page took 0.081301 seconds and 4 git commands to generate.