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