]> Git Repo - binutils.git/blob - binutils/objcopy.c
* objcopy.c (struct section_list): Add fields remove, set_flags,
[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 "progress.h"
23 #include "bucomm.h"
24 #include <getopt.h>
25 #include "libiberty.h"
26
27 static bfd_vma parse_vma PARAMS ((const char *, const char *));
28 static flagword parse_flags PARAMS ((const char *));
29 static char *make_tempname PARAMS ((char *));
30 static struct section_list *find_section_list PARAMS ((const char *, boolean));
31 static void setup_section PARAMS ((bfd *, asection *, PTR));
32 static void copy_section PARAMS ((bfd *, asection *, PTR));
33 static void get_sections PARAMS ((bfd *, asection *, PTR));
34 static int compare_section_vma PARAMS ((const PTR, const PTR));
35 static void add_strip_symbol PARAMS ((const char *));
36 static boolean is_strip_symbol PARAMS ((const char *));
37 static boolean is_strip_section PARAMS ((bfd *, asection *));
38 static unsigned int filter_symbols
39   PARAMS ((bfd *, asymbol **, asymbol **, long));
40 static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
41
42 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
43
44 static asymbol **isympp = NULL; /* Input symbols */
45 static asymbol **osympp = NULL; /* Output symbols that survive stripping */
46
47 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
48 static int copy_byte = -1;
49 static int interleave = 4;
50
51 static boolean verbose;         /* Print file and target names. */
52 static int status = 0;          /* Exit status.  */
53
54 enum strip_action
55   {
56     strip_undef,
57     strip_none,                 /* don't strip */
58     strip_debug,                /* strip all debugger symbols */
59     strip_all                   /* strip all symbols */
60   };
61
62 /* Which symbols to remove. */
63 static enum strip_action strip_symbols;
64
65 enum locals_action
66   {
67     locals_undef,
68     locals_start_L,             /* discard locals starting with L */
69     locals_all                  /* discard all locals */
70   };
71
72 /* Which local symbols to remove.  Overrides strip_all.  */
73 static enum locals_action discard_locals;
74
75 /* Structure used to hold lists of sections and actions to take.  */
76
77 struct section_list
78 {
79   /* Next section to adjust.  */
80   struct section_list *next;
81   /* Section name.  */
82   const char *name;
83   /* Whether this entry was used.  */
84   boolean used;
85   /* Whether to remove this section.  */
86   boolean remove;
87   /* Whether to adjust or set VMA.  */
88   enum { ignore_vma, adjust_vma, set_vma } adjust;
89   /* Amount to adjust by or set to.  */
90   bfd_vma val;
91   /* Whether to set the section flags.  */
92   boolean set_flags;
93   /* What to set the section flags to.  */
94   flagword flags;
95 };
96
97 static struct section_list *adjust_sections;
98 static boolean sections_removed;
99
100 /* Adjustments to the start address.  */
101 static bfd_vma adjust_start = 0;
102 static boolean set_start_set = false;
103 static bfd_vma set_start;
104
105 /* Adjustments to section VMA's.  */
106 static bfd_vma adjust_section_vma = 0;
107
108 /* Filling gaps between sections.  */
109 static boolean gap_fill_set = false;
110 static bfd_byte gap_fill = 0;
111
112 /* Pad to a given address.  */
113 static boolean pad_to_set = false;
114 static bfd_vma pad_to;
115
116 /* List of sections to add.  */
117
118 struct section_add
119 {
120   /* Next section to add.  */
121   struct section_add *next;
122   /* Name of section to add.  */
123   const char *name;
124   /* Name of file holding section contents.  */
125   const char *filename;
126   /* Size of file.  */
127   size_t size;
128   /* Contents of file.  */
129   bfd_byte *contents;
130   /* BFD section, after it has been added.  */
131   asection *section;
132 };
133
134 static struct section_add *add_sections;
135
136 /* Options to handle if running as "strip".  */
137
138 static struct option strip_options[] =
139 {
140   {"discard-all", no_argument, 0, 'x'},
141   {"discard-locals", no_argument, 0, 'X'},
142   {"format", required_argument, 0, 'F'}, /* Obsolete */
143   {"help", no_argument, 0, 'h'},
144   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
145   {"input-target", required_argument, 0, 'I'},
146   {"output-format", required_argument, 0, 'O'}, /* Obsolete */
147   {"output-target", required_argument, 0, 'O'},
148   {"remove-section", required_argument, 0, 'R'},
149   {"strip-all", no_argument, 0, 's'},
150   {"strip-debug", no_argument, 0, 'S'},
151   {"strip-symbol", required_argument, 0, 'N'},
152   {"target", required_argument, 0, 'F'},
153   {"verbose", no_argument, 0, 'v'},
154   {"version", no_argument, 0, 'V'},
155   {0, no_argument, 0, 0}
156 };
157
158 /* Options to handle if running as "objcopy".  */
159
160 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
161
162 #define OPTION_ADD_SECTION 150
163 #define OPTION_ADJUST_START (OPTION_ADD_SECTION + 1)
164 #define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1)
165 #define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1)
166 #define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1)
167 #define OPTION_GAP_FILL (OPTION_ADJUST_WARNINGS + 1)
168 #define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1)
169 #define OPTION_PAD_TO (OPTION_NO_ADJUST_WARNINGS + 1)
170 #define OPTION_SET_SECTION_FLAGS (OPTION_PAD_TO + 1)
171 #define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1)
172
173 static struct option copy_options[] =
174 {
175   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
176   {"adjust-start", required_argument, 0, OPTION_ADJUST_START},
177   {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA},
178   {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA},
179   {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS},
180   {"byte", required_argument, 0, 'b'},
181   {"discard-all", no_argument, 0, 'x'},
182   {"discard-locals", no_argument, 0, 'X'},
183   {"format", required_argument, 0, 'F'}, /* Obsolete */
184   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
185   {"help", no_argument, 0, 'h'},
186   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
187   {"input-target", required_argument, 0, 'I'},
188   {"interleave", required_argument, 0, 'i'},
189   {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS},
190   {"output-format", required_argument, 0, 'O'}, /* Obsolete */
191   {"output-target", required_argument, 0, 'O'},
192   {"pad-to", required_argument, 0, OPTION_PAD_TO},
193   {"remove-section", required_argument, 0, 'R'},
194   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
195   {"set-start", required_argument, 0, OPTION_SET_START},
196   {"strip-all", no_argument, 0, 'S'},
197   {"strip-debug", no_argument, 0, 'g'},
198   {"strip-symbol", required_argument, 0, 'N'},
199   {"target", required_argument, 0, 'F'},
200   {"verbose", no_argument, 0, 'v'},
201   {"version", no_argument, 0, 'V'},
202   {0, no_argument, 0, 0}
203 };
204
205 /* IMPORTS */
206 extern char *program_name;
207 extern char *program_version;
208
209 /* This flag distinguishes between strip and objcopy:
210    1 means this is 'strip'; 0 means this is 'objcopy'.
211    -1 means if we should use argv[0] to decide. */
212 extern int is_strip;
213
214
215 static void
216 copy_usage (stream, exit_status)
217      FILE *stream;
218      int exit_status;
219 {
220   fprintf (stream, "\
221 Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
222        [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
223        [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
224        [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
225        [--remove-section=section] [--gap-fill=val] [--pad-to=address]\n",
226            program_name);
227   fprintf (stream, "\
228        [--set-start=val] [--adjust-start=incr] [--adjust-vma=incr]\n\
229        [--adjust-section-vma=section{=,+,-}val] [--adjust-warnings]\n\
230        [--no-adjust-warnings] [--set-section-flags=section=flags]\n\
231        [--add-section=sectionname=filename]\n\
232        [--strip-symbol symbol] [-N symbol] [--verbose]\n\
233        [--version] [--help]\n\
234        in-file [out-file]\n");
235   exit (exit_status);
236 }
237
238 static void
239 strip_usage (stream, exit_status)
240      FILE *stream;
241      int exit_status;
242 {
243   fprintf (stream, "\
244 Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
245        [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
246        [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
247        [--strip-symbol symbol] [-N symbol]\n\
248        [--remove-section=section] [--verbose] [--version] [--help] file...\n",
249            program_name);
250   exit (exit_status);
251 }
252
253 /* Parse a string into a VMA, with a fatal error if it can't be
254    parsed.  */
255
256 static bfd_vma
257 parse_vma (s, arg)
258      const char *s;
259      const char *arg;
260 {
261   bfd_vma ret;
262   const char *end;
263
264   ret = bfd_scan_vma (s, &end, 0);
265   if (*end != '\0')
266     {
267       fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s);
268       exit (1);
269     }
270   return ret;
271 }
272
273 /* Parse section flags into a flagword, with a fatal error if the
274    string can't be parsed.  */
275
276 static flagword
277 parse_flags (s)
278      const char *s;
279 {
280   flagword ret;
281   const char *snext;
282   int len;
283
284   ret = SEC_NO_FLAGS;
285
286   do
287     {
288       snext = strchr (s, ',');
289       if (snext == NULL)
290         len = strlen (s);
291       else
292         {
293           len = snext - s;
294           ++snext;
295         }
296
297 #define PARSE_FLAG(fname,fval) if (strncmp (fname, s, len) == 0) ret |= fval;
298       PARSE_FLAG ("alloc", SEC_ALLOC);
299       PARSE_FLAG ("load", SEC_LOAD);
300       PARSE_FLAG ("readonly", SEC_READONLY);
301       PARSE_FLAG ("code", SEC_CODE);
302       PARSE_FLAG ("data", SEC_DATA);
303       PARSE_FLAG ("rom", SEC_ROM);
304 #undef PARSE_FLAG
305
306       s = snext;
307     }
308   while (s != NULL);
309
310   return ret;
311 }
312
313 /* Return the name of a temporary file in the same directory as FILENAME.  */
314
315 static char *
316 make_tempname (filename)
317      char *filename;
318 {
319   static char template[] = "stXXXXXX";
320   char *tmpname;
321   char *slash = strrchr (filename, '/');
322
323   if (slash != (char *) NULL)
324     {
325       *slash = 0;
326       tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
327       strcpy (tmpname, filename);
328       strcat (tmpname, "/");
329       strcat (tmpname, template);
330       mktemp (tmpname);
331       *slash = '/';
332     }
333   else
334     {
335       tmpname = xmalloc (sizeof (template));
336       strcpy (tmpname, template);
337       mktemp (tmpname);
338     }
339   return tmpname;
340 }
341
342 /* Find and optionally add an entry in the adjust_sections list.  */
343
344 static struct section_list *
345 find_section_list (name, add)
346      const char *name;
347      boolean add;
348 {
349   register struct section_list *p;
350
351   for (p = adjust_sections; p != NULL; p = p->next)
352     if (strcmp (p->name, name) == 0)
353       return p;
354
355   if (! add)
356     return NULL;
357
358   p = (struct section_list *) xmalloc (sizeof (struct section_list));
359   p->name = name;
360   p->used = false;
361   p->remove = false;
362   p->adjust = ignore_vma;
363   p->val = 0;
364   p->set_flags = false;
365   p->flags = 0;
366
367   p->next = adjust_sections;
368   adjust_sections = p;
369
370   return p;
371 }
372
373 /* Make a list of symbols to explicitly strip out. A linked list is 
374    good enough for a small number from the command line, but this will
375    slow things down a lot if many symbols are being deleted. */
376
377 struct symlist
378 {
379   const char *name;
380   struct symlist *next;
381 };
382
383 static struct symlist *strip_specific_list = NULL;
384
385 static void 
386 add_strip_symbol (name)
387      const char *name;
388 {
389   struct symlist *tmp_list;
390
391   tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist));
392   tmp_list->name = name;
393   tmp_list->next = strip_specific_list;
394   strip_specific_list = tmp_list;
395 }
396
397 static boolean
398 is_strip_symbol (name)
399      const char *name;
400 {
401   struct symlist *tmp_list;
402
403   for (tmp_list = strip_specific_list; tmp_list; tmp_list = tmp_list->next)
404     {
405       if (strcmp (name, tmp_list->name) == 0)
406         return true;
407     }
408   return false;
409 }
410
411 /* See if a section is being removed.  */
412
413 static boolean
414 is_strip_section (abfd, sec)
415      bfd *abfd;
416      asection *sec;
417 {
418   struct section_list *p;
419
420   if (! sections_removed)
421     return false;
422   p = find_section_list (bfd_get_section_name (abfd, sec), false);
423   return p != NULL && p->remove ? true : false;
424 }
425
426 /* Choose which symbol entries to copy; put the result in OSYMS.
427    We don't copy in place, because that confuses the relocs.
428    Return the number of symbols to print.  */
429
430 static unsigned int
431 filter_symbols (abfd, osyms, isyms, symcount)
432      bfd *abfd;
433      asymbol **osyms, **isyms;
434      long symcount;
435 {
436   register asymbol **from = isyms, **to = osyms;
437   long src_count = 0, dst_count = 0;
438
439   for (; src_count < symcount; src_count++)
440     {
441       asymbol *sym = from[src_count];
442       flagword flags = sym->flags;
443       int keep;
444
445       if ((flags & BSF_GLOBAL)  /* Keep if external.  */
446           || (flags & BSF_KEEP) /* Keep if used in a relocation.  */
447           || bfd_is_und_section (bfd_get_section (sym))
448           || bfd_is_com_section (bfd_get_section (sym)))
449         keep = 1;
450       else if ((flags & BSF_DEBUGGING) != 0)    /* Debugging symbol.  */
451         keep = strip_symbols != strip_debug;
452       else                      /* Local symbol.  */
453         keep = discard_locals != locals_all
454           && (discard_locals != locals_start_L ||
455               ! bfd_is_local_label (abfd, sym));
456
457       if (keep && is_strip_symbol (bfd_asymbol_name (sym)))
458         keep = 0;
459       if (keep && is_strip_section (abfd, bfd_get_section (sym)))
460         keep = 0;
461
462       if (keep)
463         to[dst_count++] = sym;
464     }
465
466   return dst_count;
467 }
468
469 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
470    Adjust *SIZE.  */
471
472 void
473 filter_bytes (memhunk, size)
474      char *memhunk;
475      bfd_size_type *size;
476 {
477   char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
478
479   for (; from < end; from += interleave)
480     *to++ = *from;
481   *size /= interleave;
482 }
483
484 /* Copy object file IBFD onto OBFD.  */
485
486 static void
487 copy_object (ibfd, obfd)
488      bfd *ibfd;
489      bfd *obfd;
490 {
491   bfd_vma start;
492   long symcount;
493   asection **osections = NULL;
494   bfd_size_type *gaps = NULL;
495   bfd_size_type max_gap = 0;
496
497   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
498     {
499       nonfatal (bfd_get_filename (obfd));
500     }
501
502   if (verbose)
503     printf ("copy from %s(%s) to %s(%s)\n",
504             bfd_get_filename(ibfd), bfd_get_target(ibfd),
505             bfd_get_filename(obfd), bfd_get_target(obfd));
506
507   if (set_start_set)
508     start = set_start;
509   else
510     start = bfd_get_start_address (ibfd);
511   start += adjust_start;
512
513   if (!bfd_set_start_address (obfd, start)
514       || !bfd_set_file_flags (obfd,
515                               (bfd_get_file_flags (ibfd)
516                                & bfd_applicable_file_flags (obfd))))
517     {
518       nonfatal (bfd_get_filename (ibfd));
519     }
520
521   /* Copy architecture of input file to output file */
522   if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
523                           bfd_get_mach (ibfd)))
524     {
525       fprintf (stderr, "Output file cannot represent architecture %s\n",
526                bfd_printable_arch_mach (bfd_get_arch (ibfd),
527                                         bfd_get_mach (ibfd)));
528     }
529   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
530     {
531       nonfatal (bfd_get_filename(ibfd));
532     }
533
534   if (isympp)
535     free (isympp);
536   if (osympp != isympp)
537     free (osympp);
538
539   /* bfd mandates that all output sections be created and sizes set before
540      any output is done.  Thus, we traverse all sections multiple times.  */
541   bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
542
543   if (add_sections != NULL)
544     {
545       struct section_add *padd;
546       struct section_list *pset;
547
548       for (padd = add_sections; padd != NULL; padd = padd->next)
549         {
550           padd->section = bfd_make_section (obfd, padd->name);
551           if (padd->section == NULL)
552             {
553               fprintf (stderr, "%s: can't create section `%s': %s\n",
554                        program_name, padd->name,
555                        bfd_errmsg (bfd_get_error ()));
556               status = 1;
557               return;
558             }
559           else
560             {
561               flagword flags;
562               
563               if (! bfd_set_section_size (obfd, padd->section, padd->size))
564                 nonfatal (bfd_get_filename (obfd));
565
566               pset = find_section_list (padd->name, false);
567               if (pset != NULL)
568                 pset->used = true;
569
570               if (pset != NULL && pset->set_flags)
571                 flags = pset->flags | SEC_HAS_CONTENTS;
572               else
573                 flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
574               if (! bfd_set_section_flags (obfd, padd->section, flags))
575                 nonfatal (bfd_get_filename (obfd));
576
577               if (pset != NULL
578                   && (pset->adjust == adjust_vma
579                       || pset->adjust == set_vma))
580                 {
581                   if (! bfd_set_section_vma (obfd, padd->section, pset->val))
582                     nonfatal (bfd_get_filename (obfd));
583                 }
584             }
585         }
586     }
587
588   if (gap_fill_set || pad_to_set)
589     {
590       asection **set;
591       unsigned int c, i;
592
593       /* We must fill in gaps between the sections and/or we must pad
594          the last section to a specified address.  We do this by
595          grabbing a list of the sections, sorting them by VMA, and
596          increasing the section sizes as required to fill the gaps.
597          We write out the gap contents below.  */
598
599       c = bfd_count_sections (obfd);
600       osections = (asection **) xmalloc (c * sizeof (asection *));
601       set = osections;
602       bfd_map_over_sections (obfd, get_sections, (void *) &set);
603
604       qsort (osections, c, sizeof (asection *), compare_section_vma);
605
606       gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
607       memset (gaps, 0, c * sizeof (bfd_size_type));
608
609       if (gap_fill_set)
610         {
611           for (i = 0; i < c - 1; i++)
612             {
613               flagword flags;
614               bfd_size_type size;
615               bfd_vma gap_start, gap_stop;
616
617               flags = bfd_get_section_flags (obfd, osections[i]);
618               if ((flags & SEC_HAS_CONTENTS) == 0
619                   || (flags & SEC_LOAD) == 0)
620                 continue;
621
622               size = bfd_section_size (obfd, osections[i]);
623               gap_start = bfd_section_vma (obfd, osections[i]) + size;
624               gap_stop = bfd_section_vma (obfd, osections[i + 1]);
625               if (gap_start < gap_stop)
626                 {
627                   if (! bfd_set_section_size (obfd, osections[i],
628                                               size + (gap_stop - gap_start)))
629                     {
630                       fprintf (stderr, "%s: Can't fill gap after %s: %s\n",
631                                program_name,
632                                bfd_get_section_name (obfd, osections[i]),
633                                bfd_errmsg (bfd_get_error()));
634                       status = 1;
635                       break;
636                     }
637                   gaps[i] = gap_stop - gap_start;
638                   if (max_gap < gap_stop - gap_start)
639                     max_gap = gap_stop - gap_start;
640                 }
641             }
642         }
643
644       if (pad_to_set)
645         {
646           bfd_vma vma;
647           bfd_size_type size;
648
649           vma = bfd_section_vma (obfd, osections[c - 1]);
650           size = bfd_section_size (obfd, osections[c - 1]);
651           if (vma + size < pad_to)
652             {
653               if (! bfd_set_section_size (obfd, osections[c - 1],
654                                           pad_to - vma))
655                 {
656                   fprintf (stderr, "%s: Can't add padding to %s: %s\n",
657                            program_name,
658                            bfd_get_section_name (obfd, osections[c - 1]),
659                            bfd_errmsg (bfd_get_error ()));
660                   status = 1;
661                 }
662               else
663                 {
664                   gaps[c - 1] = pad_to - (vma + size);
665                   if (max_gap < pad_to - (vma + size))
666                     max_gap = pad_to - (vma + size);
667                 }
668             }
669         }             
670     }
671
672   /* Symbol filtering must happen after the output sections have
673      been created, but before their contents are set.  */
674   if (strip_symbols == strip_all && discard_locals == locals_undef)
675     {
676       osympp = isympp = NULL;
677       symcount = 0;
678     }
679   else
680     {
681       long symsize;
682
683       symsize = bfd_get_symtab_upper_bound (ibfd);
684       if (symsize < 0)
685         {
686           nonfatal (bfd_get_filename (ibfd));
687         }
688
689       osympp = isympp = (asymbol **) xmalloc (symsize);
690       symcount = bfd_canonicalize_symtab (ibfd, isympp);
691       if (symcount < 0)
692         {
693           nonfatal (bfd_get_filename (ibfd));
694         }
695
696       if (strip_symbols == strip_debug 
697           || discard_locals != locals_undef
698           || strip_specific_list
699           || sections_removed)
700         {
701           /* Mark symbols used in output relocations so that they
702              are kept, even if they are local labels or static symbols.
703
704              Note we iterate over the input sections examining their
705              relocations since the relocations for the output sections
706              haven't been set yet.  mark_symbols_used_in_relocations will
707              ignore input sections which have no corresponding output
708              section.  */
709           bfd_map_over_sections (ibfd,
710                                  mark_symbols_used_in_relocations,
711                                  (PTR)isympp);
712           osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
713           symcount = filter_symbols (ibfd, osympp, isympp, symcount);
714         }
715     }
716
717   bfd_set_symtab (obfd, osympp, symcount);
718
719   /* This has to happen after the symbol table has been set.  */
720   bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
721
722   if (add_sections != NULL)
723     {
724       struct section_add *padd;
725
726       for (padd = add_sections; padd != NULL; padd = padd->next)
727         {
728           if (! bfd_set_section_contents (obfd, padd->section,
729                                           (PTR) padd->contents,
730                                           (file_ptr) 0,
731                                           (bfd_size_type) padd->size))
732             nonfatal (bfd_get_filename (obfd));
733         }
734     }
735
736   if (gap_fill_set || pad_to_set)
737     {
738       bfd_byte *buf;
739       int c, i;
740
741       /* Fill in the gaps.  */
742
743       if (max_gap > 8192)
744         max_gap = 8192;
745       buf = (bfd_byte *) xmalloc (max_gap);
746       memset (buf, gap_fill, max_gap);
747
748       c = bfd_count_sections (obfd);
749       for (i = 0; i < c; i++)
750         {
751           if (gaps[i] != 0)
752             {
753               bfd_size_type left;
754               file_ptr off;
755
756               left = gaps[i];
757               off = bfd_section_size (obfd, osections[i]) - left;
758               while (left > 0)
759                 {
760                   bfd_size_type now;
761
762                   if (left > 8192)
763                     now = 8192;
764                   else
765                     now = left;
766                   if (! bfd_set_section_contents (obfd, osections[i], buf,
767                                                   off, now))
768                     {
769                       nonfatal (bfd_get_filename (obfd));
770                     }
771                   left -= now;
772                   off += now;
773                 }
774             }
775         }
776     }
777
778   /* Allow the BFD backend to copy any private data it understands
779      from the input BFD to the output BFD.  This is done last to
780      permit the routine to look at the filtered symbol table, which is
781      important for the ECOFF code at least.  */
782   if (!bfd_copy_private_bfd_data (ibfd, obfd))
783     {
784       fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
785                program_name, bfd_get_filename (obfd),
786                bfd_errmsg (bfd_get_error ()));
787       status = 1;
788       return;
789     }
790 }
791
792 static char *
793 cat (a, b, c)
794      char *a;
795      char *b;
796      char *c;
797 {
798   size_t size = strlen (a) + strlen (b) + strlen (c);
799   char *r = xmalloc (size + 1);
800
801   strcpy (r, a);
802   strcat (r, b);
803   strcat (r, c);
804   return r;
805 }
806
807 /* Read each archive element in turn from IBFD, copy the
808    contents to temp file, and keep the temp file handle.  */
809
810 static void
811 copy_archive (ibfd, obfd, output_target)
812      bfd *ibfd;
813      bfd *obfd;
814      char *output_target;
815 {
816   struct name_list
817     {
818       struct name_list *next;
819       char *name;
820     } *list, *l;
821   bfd **ptr = &obfd->archive_head;
822   bfd *this_element;
823   char *dir = make_tempname (bfd_get_filename (obfd));
824
825   /* Make a temp directory to hold the contents.  */
826   mkdir (dir, 0700);
827   obfd->has_armap = ibfd->has_armap;
828
829   list = NULL;
830
831   this_element = bfd_openr_next_archived_file (ibfd, NULL);
832   while (this_element != (bfd *) NULL)
833     {
834       /* Create an output file for this member.  */
835       char *output_name = cat (dir, "/", bfd_get_filename(this_element));
836       bfd *output_bfd = bfd_openw (output_name, output_target);
837       bfd *last_element;
838
839       l = (struct name_list *) xmalloc (sizeof (struct name_list));
840       l->name = output_name;
841       l->next = list;
842       list = l;
843
844       if (output_bfd == (bfd *) NULL)
845         {
846           nonfatal (output_name);
847         }
848       if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
849         {
850           nonfatal (bfd_get_filename (obfd));
851         }
852
853       if (bfd_check_format (this_element, bfd_object) == true)
854         {
855           copy_object (this_element, output_bfd);
856         }
857
858       bfd_close (output_bfd);
859
860       /* Open the newly output file and attach to our list.  */
861       output_bfd = bfd_openr (output_name, output_target);
862
863       *ptr = output_bfd;
864       ptr = &output_bfd->next;
865
866       last_element = this_element;
867
868       this_element = bfd_openr_next_archived_file (ibfd, last_element);
869
870       bfd_close (last_element);
871     }
872   *ptr = (bfd *) NULL;
873
874   if (!bfd_close (obfd))
875     {
876       nonfatal (bfd_get_filename (obfd));
877     }
878
879   /* Delete all the files that we opened.  */
880   for (l = list; l != NULL; l = l->next)
881     unlink (l->name);
882   rmdir (dir);
883
884   if (!bfd_close (ibfd))
885     {
886       nonfatal (bfd_get_filename (ibfd));
887     }
888 }
889
890 /* The top-level control.  */
891
892 static void
893 copy_file (input_filename, output_filename, input_target, output_target)
894      char *input_filename;
895      char *output_filename;
896      char *input_target;
897      char *output_target;
898 {
899   bfd *ibfd;
900   char **matching;
901
902   /* To allow us to do "strip *" without dying on the first
903      non-object file, failures are nonfatal.  */
904
905   ibfd = bfd_openr (input_filename, input_target);
906   if (ibfd == NULL)
907     {
908       nonfatal (input_filename);
909     }
910
911   if (bfd_check_format (ibfd, bfd_archive))
912     {
913       bfd *obfd;
914
915       /* bfd_get_target does not return the correct value until
916          bfd_check_format succeeds.  */
917       if (output_target == NULL)
918         output_target = bfd_get_target (ibfd);
919
920       obfd = bfd_openw (output_filename, output_target);
921       if (obfd == NULL)
922         {
923           nonfatal (output_filename);
924         }
925       copy_archive (ibfd, obfd, output_target);
926     }
927   else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
928     {
929       bfd *obfd;
930
931       /* bfd_get_target does not return the correct value until
932          bfd_check_format succeeds.  */
933       if (output_target == NULL)
934         output_target = bfd_get_target (ibfd);
935
936       obfd = bfd_openw (output_filename, output_target);
937       if (obfd == NULL)
938         {
939           nonfatal (output_filename);
940         }
941
942       copy_object (ibfd, obfd);
943
944       if (!bfd_close (obfd))
945         {
946           nonfatal (output_filename);
947         }
948
949       if (!bfd_close (ibfd))
950         {
951           nonfatal (input_filename);
952         }
953     }
954   else
955     {
956       bfd_nonfatal (input_filename);
957       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
958         {
959           list_matching_formats (matching);
960           free (matching);
961         }
962       status = 1;
963     }
964 }
965
966 /* Create a section in OBFD with the same name and attributes
967    as ISECTION in IBFD.  */
968
969 static void
970 setup_section (ibfd, isection, obfdarg)
971      bfd *ibfd;
972      sec_ptr isection;
973      PTR obfdarg;
974 {
975   bfd *obfd = (bfd *) obfdarg;
976   struct section_list *p;
977   sec_ptr osection;
978   bfd_vma vma;
979   flagword flags;
980   char *err;
981
982   if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
983       && (strip_symbols == strip_debug
984           || strip_symbols == strip_all
985           || discard_locals == locals_all))
986     return;
987
988   p = find_section_list (bfd_section_name (ibfd, isection), false);
989   if (p != NULL)
990     p->used = true;
991
992   if (p != NULL && p->remove)
993     return;
994
995   osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
996   if (osection == NULL)
997     {
998       err = "making";
999       goto loser;
1000     }
1001
1002   if (!bfd_set_section_size (obfd,
1003                              osection,
1004                              bfd_section_size (ibfd, isection)))
1005     {
1006       err = "size";
1007       goto loser;
1008     }
1009
1010   vma = bfd_section_vma (ibfd, isection);
1011   if (p != NULL && p->adjust == adjust_vma)
1012     vma += p->val;
1013   else if (p != NULL && p->adjust == set_vma)
1014     vma = p->val;
1015   else
1016     vma += adjust_section_vma;
1017   if (! bfd_set_section_vma (obfd, osection, vma))
1018     {
1019       err = "vma";
1020       goto loser;
1021     }
1022
1023   if (bfd_set_section_alignment (obfd,
1024                                  osection,
1025                                  bfd_section_alignment (ibfd, isection))
1026       == false)
1027     {
1028       err = "alignment";
1029       goto loser;
1030     }
1031
1032   if (p != NULL && p->set_flags)
1033     flags = p->flags;
1034   else
1035     flags = bfd_get_section_flags (ibfd, isection);
1036   if (!bfd_set_section_flags (obfd, osection, flags))
1037     {
1038       err = "flags";
1039       goto loser;
1040     }
1041
1042   /* This used to be mangle_section; we do here to avoid using
1043      bfd_get_section_by_name since some formats allow multiple
1044      sections with the same name.  */
1045   isection->output_section = osection;
1046   isection->output_offset = 0;
1047
1048   /* Allow the BFD backend to copy any private data it understands
1049      from the input section to the output section.  */
1050   if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
1051     {
1052       err = "private data";
1053       goto loser;
1054     }
1055
1056   /* All went well */
1057   return;
1058
1059 loser:
1060   fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
1061            program_name,
1062            bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
1063            err, bfd_errmsg (bfd_get_error ()));
1064   status = 1;
1065 }
1066
1067 /* Copy the data of input section ISECTION of IBFD
1068    to an output section with the same name in OBFD.
1069    If stripping then don't copy any relocation info.  */
1070
1071 static void
1072 copy_section (ibfd, isection, obfdarg)
1073      bfd *ibfd;
1074      sec_ptr isection;
1075      PTR obfdarg;
1076 {
1077   bfd *obfd = (bfd *) obfdarg;
1078   struct section_list *p;
1079   arelent **relpp;
1080   long relcount;
1081   sec_ptr osection;
1082   bfd_size_type size;
1083
1084   if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
1085       && (strip_symbols == strip_debug
1086           || strip_symbols == strip_all
1087           || discard_locals == locals_all))
1088     {
1089       return;
1090     }
1091
1092   p = find_section_list (bfd_section_name (ibfd, isection), false);
1093
1094   if (p != NULL && p->remove)
1095     return;
1096
1097   osection = isection->output_section;
1098   size = bfd_get_section_size_before_reloc (isection);
1099
1100   if (size == 0 || osection == 0)
1101     return;
1102
1103   if (strip_symbols == strip_all)
1104     bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
1105   else
1106     {
1107       long relsize;
1108
1109       relsize = bfd_get_reloc_upper_bound (ibfd, isection);
1110       if (relsize < 0)
1111         {
1112           nonfatal (bfd_get_filename (ibfd));
1113         }
1114       if (relsize == 0)
1115         bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
1116       else
1117         {
1118           relpp = (arelent **) xmalloc (relsize);
1119           relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
1120           if (relcount < 0)
1121             {
1122               nonfatal (bfd_get_filename (ibfd));
1123             }
1124           bfd_set_reloc (obfd, osection, relpp, relcount);
1125         }
1126     }
1127
1128   isection->_cooked_size = isection->_raw_size;
1129   isection->reloc_done = true;
1130
1131   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
1132     {
1133       PTR memhunk = (PTR) xmalloc ((unsigned) size);
1134
1135       if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
1136                                      size))
1137         {
1138           nonfatal (bfd_get_filename (ibfd));
1139         }
1140
1141       if (copy_byte >= 0) 
1142         {
1143           filter_bytes (memhunk, &size);
1144               /* The section has gotten smaller. */
1145           if (!bfd_set_section_size (obfd, osection, size))
1146             nonfatal (bfd_get_filename (obfd));
1147         }
1148
1149       if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
1150                                      size))
1151         {
1152           nonfatal (bfd_get_filename (obfd));
1153         }
1154       free (memhunk);
1155     }
1156 }
1157
1158 /* Get all the sections.  This is used when --gap-fill or --pad-to is
1159    used.  */
1160
1161 static void
1162 get_sections (obfd, osection, secppparg)
1163      bfd *obfd;
1164      asection *osection;
1165      PTR secppparg;
1166 {
1167   asection ***secppp = (asection ***) secppparg;
1168
1169   **secppp = osection;
1170   ++(*secppp);
1171 }
1172
1173 /* Sort sections by VMA.  This is called via qsort, and is used when
1174    --gap-fill or --pad-to is used.  We force non loadable or empty
1175    sections to the front, where they are easier to ignore.  */
1176
1177 static int
1178 compare_section_vma (arg1, arg2)
1179      const PTR arg1;
1180      const PTR arg2;
1181 {
1182   const asection **sec1 = (const asection **) arg1;
1183   const asection **sec2 = (const asection **) arg2;
1184   flagword flags1, flags2;
1185
1186   /* Sort non loadable sections to the front.  */
1187   flags1 = (*sec1)->flags;
1188   flags2 = (*sec2)->flags;
1189   if ((flags1 & SEC_HAS_CONTENTS) == 0
1190       || (flags1 & SEC_LOAD) == 0)
1191     {
1192       if ((flags2 & SEC_HAS_CONTENTS) != 0
1193           && (flags2 & SEC_LOAD) != 0)
1194         return -1;
1195     }
1196   else
1197     {
1198       if ((flags2 & SEC_HAS_CONTENTS) == 0
1199           || (flags2 & SEC_LOAD) == 0)
1200         return 1;
1201     }
1202
1203   /* Sort sections by VMA.  */
1204   if ((*sec1)->vma > (*sec2)->vma)
1205     return 1;
1206   else if ((*sec1)->vma < (*sec2)->vma)
1207     return -1;
1208
1209   /* Sort sections with the same VMA by size.  */
1210   if ((*sec1)->_raw_size > (*sec2)->_raw_size)
1211     return 1;
1212   else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
1213     return -1;
1214
1215   return 0;
1216 }
1217
1218 /* Mark all the symbols which will be used in output relocations with
1219    the BSF_KEEP flag so that those symbols will not be stripped.
1220
1221    Ignore relocations which will not appear in the output file.  */
1222
1223 static void
1224 mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
1225      bfd *ibfd;
1226      sec_ptr isection;
1227      PTR symbolsarg;
1228 {
1229   asymbol **symbols = (asymbol **) symbolsarg;
1230   long relsize;
1231   arelent **relpp;
1232   long relcount, i;
1233
1234   /* Ignore an input section with no corresponding output section.  */
1235   if (isection->output_section == NULL)
1236     return;
1237
1238   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
1239   if (relsize < 0)
1240     bfd_fatal (bfd_get_filename (ibfd));
1241
1242   relpp = (arelent **) xmalloc (relsize);
1243   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
1244   if (relcount < 0)
1245     bfd_fatal (bfd_get_filename (ibfd));
1246
1247   /* Examine each symbol used in a relocation.  If it's not one of the
1248      special bfd section symbols, then mark it with BSF_KEEP.  */
1249   for (i = 0; i < relcount; i++)
1250     {
1251       if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
1252           && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
1253           && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
1254         (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
1255     }
1256
1257   if (relpp != NULL)
1258     free (relpp);
1259 }
1260
1261 /* The number of bytes to copy at once.  */
1262 #define COPY_BUF 8192
1263
1264 /* Copy file FROM to file TO, performing no translations.
1265    Return 0 if ok, -1 if error.  */
1266
1267 static int
1268 simple_copy (from, to)
1269      char *from, *to;
1270 {
1271   int fromfd, tofd, nread;
1272   char buf[COPY_BUF];
1273
1274   fromfd = open (from, O_RDONLY);
1275   if (fromfd < 0)
1276     return -1;
1277   tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
1278   if (tofd < 0)
1279     {
1280       close (fromfd);
1281       return -1;
1282     }
1283   while ((nread = read (fromfd, buf, sizeof buf)) > 0)
1284     {
1285       if (write (tofd, buf, nread) != nread)
1286         {
1287           close (fromfd);
1288           close (tofd);
1289           return -1;
1290         }
1291     }
1292   close (fromfd);
1293   close (tofd);
1294   if (nread < 0)
1295     return -1;
1296   return 0;
1297 }
1298
1299 #ifndef S_ISLNK
1300 #ifdef S_IFLNK
1301 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1302 #else
1303 #define S_ISLNK(m) 0
1304 #define lstat stat
1305 #endif
1306 #endif
1307
1308 /* Rename FROM to TO, copying if TO is a link.
1309    Assumes that TO already exists, because FROM is a temp file.
1310    Return 0 if ok, -1 if error.  */
1311
1312 static int
1313 smart_rename (from, to)
1314      char *from, *to;
1315 {
1316   struct stat s;
1317   int ret = 0;
1318
1319   if (lstat (to, &s))
1320     return -1;
1321
1322   /* Use rename only if TO is not a symbolic link and has
1323      only one hard link.  */
1324   if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
1325     {
1326       ret = rename (from, to);
1327       if (ret == 0)
1328         {
1329           /* Try to preserve the permission bits and ownership of TO.  */
1330           chmod (to, s.st_mode & 07777);
1331           chown (to, s.st_uid, s.st_gid);
1332         }
1333     }
1334   else
1335     {
1336       ret = simple_copy (from, to);
1337       if (ret == 0)
1338         unlink (from);
1339     }
1340   return ret;
1341 }
1342
1343 static int
1344 strip_main (argc, argv)
1345      int argc;
1346      char *argv[];
1347 {
1348   char *input_target = NULL, *output_target = NULL;
1349   boolean show_version = false;
1350   int c, i;
1351   struct section_list *p;
1352
1353   while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVvN:",
1354                            strip_options, (int *) 0)) != EOF)
1355     {
1356       switch (c)
1357         {
1358         case 'I':
1359           input_target = optarg;
1360           break;
1361         case 'O':
1362           output_target = optarg;
1363           break;
1364         case 'F':
1365           input_target = output_target = optarg;
1366           break;
1367         case 'R':
1368           p = find_section_list (optarg, true);
1369           p->remove = true;
1370           sections_removed = true;
1371           break;
1372         case 's':
1373           strip_symbols = strip_all;
1374           break;
1375         case 'S':
1376         case 'g':
1377           strip_symbols = strip_debug;
1378           break;
1379         case 'N':
1380           add_strip_symbol (optarg);
1381           break;
1382         case 'x':
1383           discard_locals = locals_all;
1384           break;
1385         case 'X':
1386           discard_locals = locals_start_L;
1387           break;
1388         case 'v':
1389           verbose = true;
1390           break;
1391         case 'V':
1392           show_version = true;
1393           break;
1394         case 0:
1395           break;                /* we've been given a long option */
1396         case 'h':
1397           strip_usage (stdout, 0);
1398         default:
1399           strip_usage (stderr, 1);
1400         }
1401     }
1402
1403   if (show_version)
1404     {
1405       printf ("GNU %s version %s\n", program_name, program_version);
1406       exit (0);
1407     }
1408
1409   /* Default is to strip all symbols.  */
1410   if (strip_symbols == strip_undef
1411       && discard_locals == locals_undef
1412       && strip_specific_list == NULL)
1413     strip_symbols = strip_all;
1414
1415   if (output_target == (char *) NULL)
1416     output_target = input_target;
1417
1418   i = optind;
1419   if (i == argc)
1420     strip_usage (stderr, 1);
1421
1422   for (; i < argc; i++)
1423     {
1424       int hold_status = status;
1425
1426       char *tmpname = make_tempname (argv[i]);
1427       status = 0;
1428       copy_file (argv[i], tmpname, input_target, output_target);
1429       if (status == 0)
1430         {
1431           smart_rename (tmpname, argv[i]);
1432           status = hold_status;
1433         }
1434       else
1435         unlink (tmpname);
1436       free (tmpname);
1437     }
1438
1439   return 0;
1440 }
1441
1442 static int
1443 copy_main (argc, argv)
1444      int argc;
1445      char *argv[];
1446 {
1447   char *input_filename = NULL, *output_filename = NULL;
1448   char *input_target = NULL, *output_target = NULL;
1449   boolean show_version = false;
1450   boolean adjust_warn = true;
1451   int c;
1452   struct section_list *p;
1453
1454   while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVvN:",
1455                            copy_options, (int *) 0)) != EOF)
1456     {
1457       switch (c)
1458         {
1459         case 'b':
1460           copy_byte = atoi(optarg);
1461           if (copy_byte < 0)
1462             {
1463               fprintf (stderr, "%s: byte number must be non-negative\n",
1464                        program_name);
1465               exit (1);
1466             }
1467           break;
1468         case 'i':
1469           interleave = atoi(optarg);
1470           if (interleave < 1)
1471             {
1472               fprintf(stderr, "%s: interleave must be positive\n",
1473                       program_name);
1474               exit (1);
1475             }
1476           break;
1477         case 'I':
1478         case 's':               /* "source" - 'I' is preferred */
1479           input_target = optarg;
1480           break;
1481         case 'O':
1482         case 'd':               /* "destination" - 'O' is preferred */
1483           output_target = optarg;
1484           break;
1485         case 'F':
1486           input_target = output_target = optarg;
1487           break;
1488         case 'R':
1489           p = find_section_list (optarg, true);
1490           p->remove = true;
1491           sections_removed = true;
1492           break;
1493         case 'S':
1494           strip_symbols = strip_all;
1495           break;
1496         case 'g':
1497           strip_symbols = strip_debug;
1498           break;
1499         case 'N':
1500           add_strip_symbol (optarg);
1501           break;
1502         case 'x':
1503           discard_locals = locals_all;
1504           break;
1505         case 'X':
1506           discard_locals = locals_start_L;
1507           break;
1508         case 'v':
1509           verbose = true;
1510           break;
1511         case 'V':
1512           show_version = true;
1513           break;
1514         case OPTION_ADD_SECTION:
1515           {
1516             const char *s;
1517             struct stat st;
1518             struct section_add *pa;
1519             int len;
1520             char *name;
1521             FILE *f;
1522
1523             s = strchr (optarg, '=');
1524             if (s == NULL)
1525               {
1526                 fprintf (stderr,
1527                          "%s: bad format for --add-section NAME=FILENAME\n",
1528                          program_name);
1529                 exit (1);
1530               }
1531
1532             if (stat (s + 1, &st) < 0)
1533               {
1534                 fprintf (stderr, "%s: ", program_name);
1535                 perror (s + 1);
1536                 exit (1);
1537               }
1538
1539             pa = (struct section_add *) xmalloc (sizeof (struct section_add));
1540
1541             len = s - optarg;
1542             name = (char *) xmalloc (len + 1);
1543             strncpy (name, optarg, len);
1544             name[len] = '\0';
1545             pa->name = name;
1546
1547             pa->filename = s + 1;
1548
1549             pa->size = st.st_size;
1550
1551             pa->contents = xmalloc (pa->size);
1552             f = fopen (pa->filename, FOPEN_RB);
1553             if (f == NULL)
1554               {
1555                 fprintf (stderr, "%s: ", program_name);
1556                 perror (pa->filename);
1557                 exit (1);
1558               }
1559             if (fread (pa->contents, 1, pa->size, f) == 0
1560                 || ferror (f))
1561               {
1562                 fprintf (stderr, "%s: %s: fread failed\n",
1563                          program_name, pa->filename);
1564                 exit (1);
1565               }
1566             fclose (f);
1567
1568             pa->next = add_sections;
1569             add_sections = pa;
1570           }
1571           break;
1572         case OPTION_ADJUST_START:
1573           adjust_start = parse_vma (optarg, "--adjust-start");
1574           break;
1575         case OPTION_ADJUST_SECTION_VMA:
1576           {
1577             const char *s;
1578             int len;
1579             char *name;
1580
1581             s = strchr (optarg, '=');
1582             if (s == NULL)
1583               {
1584                 s = strchr (optarg, '+');
1585                 if (s == NULL)
1586                   {
1587                     s = strchr (optarg, '-');
1588                     if (s == NULL)
1589                       {
1590                         fprintf (stderr,
1591                                  "%s: bad format for --adjust-section-vma\n",
1592                                  program_name);
1593                         exit (1);
1594                       }
1595                   }
1596               }
1597
1598             len = s - optarg;
1599             name = (char *) xmalloc (len + 1);
1600             strncpy (name, optarg, len);
1601             name[len] = '\0';
1602
1603             p = find_section_list (name, true);
1604
1605             p->val = parse_vma (s + 1, "--adjust-section-vma");
1606
1607             if (*s == '=')
1608               p->adjust = set_vma;
1609             else
1610               {
1611                 p->adjust = adjust_vma;
1612                 if (*s == '-')
1613                   p->val = - p->val;
1614               }
1615           }
1616           break;
1617         case OPTION_ADJUST_VMA:
1618           adjust_section_vma = parse_vma (optarg, "--adjust-vma");
1619           adjust_start = adjust_section_vma;
1620           break;
1621         case OPTION_ADJUST_WARNINGS:
1622           adjust_warn = true;
1623           break;
1624         case OPTION_GAP_FILL:
1625           {
1626             bfd_vma gap_fill_vma;
1627
1628             gap_fill_vma = parse_vma (optarg, "--gap-fill");
1629             gap_fill = (bfd_byte) gap_fill_vma;
1630             if ((bfd_vma) gap_fill != gap_fill_vma)
1631               {
1632                 fprintf (stderr, "%s: warning: truncating gap-fill from 0x",
1633                          program_name);
1634                 fprintf_vma (stderr, gap_fill_vma);
1635                 fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill);
1636               }
1637             gap_fill_set = true;
1638           }
1639           break;
1640         case OPTION_NO_ADJUST_WARNINGS:
1641           adjust_warn = false;
1642           break;
1643         case OPTION_PAD_TO:
1644           pad_to = parse_vma (optarg, "--pad-to");
1645           pad_to_set = true;
1646           break;
1647         case OPTION_SET_SECTION_FLAGS:
1648           {
1649             const char *s;
1650             int len;
1651             char *name;
1652
1653             s = strchr (optarg, '=');
1654             if (s == NULL)
1655               {
1656                 fprintf (stderr, "%s: bad format for --set-section-flags\n",
1657                          program_name);
1658                 exit (1);
1659               }
1660
1661             len = s - optarg;
1662             name = (char *) xmalloc (len + 1);
1663             strncpy (name, optarg, len);
1664             name[len] = '\0';
1665
1666             p = find_section_list (name, true);
1667
1668             p->set_flags = true;
1669             p->flags = parse_flags (s + 1);
1670           }
1671           break;
1672         case OPTION_SET_START:
1673           set_start = parse_vma (optarg, "--set-start");
1674           set_start_set = true;
1675           break;
1676         case 0:
1677           break;                /* we've been given a long option */
1678         case 'h':
1679           copy_usage (stdout, 0);
1680         default:
1681           copy_usage (stderr, 1);
1682         }
1683     }
1684
1685   if (show_version)
1686     {
1687       printf ("GNU %s version %s\n", program_name, program_version);
1688       exit (0);
1689     }
1690
1691   if (copy_byte >= interleave)
1692     {
1693       fprintf (stderr, "%s: byte number must be less than interleave\n",
1694                program_name);
1695       exit (1);
1696     }
1697
1698   if (optind == argc || optind + 2 < argc)
1699     copy_usage (stderr, 1);
1700
1701   input_filename = argv[optind];
1702   if (optind + 1 < argc)
1703     output_filename = argv[optind + 1];
1704
1705   /* Default is to strip no symbols.  */
1706   if (strip_symbols == strip_undef && discard_locals == locals_undef)
1707     strip_symbols = strip_none;
1708
1709   if (output_target == (char *) NULL)
1710     output_target = input_target;
1711
1712   /* If there is no destination file then create a temp and rename
1713      the result into the input.  */
1714
1715   if (output_filename == (char *) NULL)
1716     {
1717       char *tmpname = make_tempname (input_filename);
1718       copy_file (input_filename, tmpname, input_target, output_target);
1719       if (status == 0)
1720         smart_rename (tmpname, input_filename);
1721       else
1722         unlink (tmpname);
1723     }
1724   else
1725     {
1726       copy_file (input_filename, output_filename, input_target, output_target);
1727     }
1728
1729   if (adjust_warn)
1730     {
1731       for (p = adjust_sections; p != NULL; p = p->next)
1732         {
1733           if (! p->used && p->adjust != ignore_vma)
1734             {
1735               fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x",
1736                        program_name, p->name,
1737                        p->adjust == set_vma ? '=' : '+');
1738               fprintf_vma (stderr, p->val);
1739               fprintf (stderr, " never used\n");
1740             }
1741         }
1742     }
1743
1744   return 0;
1745 }
1746
1747 int
1748 main (argc, argv)
1749      int argc;
1750      char *argv[];
1751 {
1752   program_name = argv[0];
1753   xmalloc_set_program_name (program_name);
1754
1755   START_PROGRESS (program_name, 0);
1756
1757   strip_symbols = strip_undef;
1758   discard_locals = locals_undef;
1759
1760   bfd_init ();
1761
1762   if (is_strip < 0)
1763     {
1764       int i = strlen (program_name);
1765       is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0);
1766     }
1767
1768   if (is_strip)
1769     strip_main (argc, argv);
1770   else
1771     copy_main (argc, argv);
1772
1773   END_PROGRESS (program_name);
1774
1775   return status;
1776 }
This page took 0.1218 seconds and 4 git commands to generate.