]> Git Repo - binutils.git/blob - binutils/objcopy.c
* objcopy.c (struct section_list): Add fields used, adjust, val.
[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 #include "libiberty.h"
25
26 static bfd_vma parse_vma PARAMS ((const char *, const char *));
27 static void setup_section PARAMS ((bfd *, asection *, PTR));
28 static void copy_section PARAMS ((bfd *, asection *, PTR));
29 static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
30
31 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
32
33 static asymbol **isympp = NULL; /* Input symbols */
34 static asymbol **osympp = NULL; /* Output symbols that survive stripping */
35
36 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
37 static int copy_byte = -1;
38 static int interleave = 4;
39
40 static boolean verbose;         /* Print file and target names. */
41 static int status = 0;          /* Exit status.  */
42
43 enum strip_action
44   {
45     strip_undef,
46     strip_none,                 /* don't strip */
47     strip_debug,                /* strip all debugger symbols */
48     strip_all                   /* strip all symbols */
49   };
50
51 /* Which symbols to remove. */
52 static enum strip_action strip_symbols;
53
54 enum locals_action
55   {
56     locals_undef,
57     locals_start_L,             /* discard locals starting with L */
58     locals_all                  /* discard all locals */
59   };
60
61 /* Which local symbols to remove.  Overrides strip_all.  */
62 static enum locals_action discard_locals;
63
64 /* Structure used to hold lists of sections and actions to take.  */
65
66 struct section_list
67 {
68   /* Next section to adjust.  */
69   struct section_list *next;
70   /* Section name.  */
71   const char *name;
72   /* Whether this entry was used.  */
73   boolean used;
74   /* Remaining fields only used if not on remove_sections list.  */
75   /* Whether to adjust or set VMA.  */
76   boolean adjust;
77   /* Amount to adjust by or set to.  */
78   bfd_vma val;
79 };
80
81 /* List of sections to remove.  */
82
83 static struct section_list *remove_sections;
84
85 /* Adjustments to the start address.  */
86 static bfd_vma adjust_start = 0;
87 static boolean set_start_set = false;
88 static bfd_vma set_start;
89
90 /* Adjustments to section VMA's.  */
91 static bfd_vma adjust_section_vma = 0;
92 static struct section_list *adjust_sections;
93
94 /* Options to handle if running as "strip".  */
95
96 static struct option strip_options[] =
97 {
98   {"discard-all", no_argument, 0, 'x'},
99   {"discard-locals", no_argument, 0, 'X'},
100   {"format", required_argument, 0, 'F'}, /* Obsolete */
101   {"help", no_argument, 0, 'h'},
102   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
103   {"input-target", required_argument, 0, 'I'},
104   {"output-format", required_argument, 0, 'O'}, /* Obsolete */
105   {"output-target", required_argument, 0, 'O'},
106   {"remove-section", required_argument, 0, 'R'},
107   {"strip-all", no_argument, 0, 's'},
108   {"strip-debug", no_argument, 0, 'S'},
109   {"target", required_argument, 0, 'F'},
110   {"verbose", no_argument, 0, 'v'},
111   {"version", no_argument, 0, 'V'},
112   {0, no_argument, 0, 0}
113 };
114
115 /* Options to handle if running as "objcopy".  */
116
117 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
118
119 #define OPTION_ADJUST_START 150
120 #define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1)
121 #define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1)
122 #define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1)
123 #define OPTION_NO_ADJUST_WARNINGS (OPTION_ADJUST_WARNINGS + 1)
124 #define OPTION_SET_START (OPTION_NO_ADJUST_WARNINGS + 1)
125
126 static struct option copy_options[] =
127 {
128   {"adjust-start", required_argument, 0, OPTION_ADJUST_START},
129   {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA},
130   {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA},
131   {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS},
132   {"byte", required_argument, 0, 'b'},
133   {"discard-all", no_argument, 0, 'x'},
134   {"discard-locals", no_argument, 0, 'X'},
135   {"format", required_argument, 0, 'F'}, /* Obsolete */
136   {"help", no_argument, 0, 'h'},
137   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
138   {"input-target", required_argument, 0, 'I'},
139   {"interleave", required_argument, 0, 'i'},
140   {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS},
141   {"output-format", required_argument, 0, 'O'}, /* Obsolete */
142   {"output-target", required_argument, 0, 'O'},
143   {"remove-section", required_argument, 0, 'R'},
144   {"set-start", required_argument, 0, OPTION_SET_START},
145   {"strip-all", no_argument, 0, 'S'},
146   {"strip-debug", no_argument, 0, 'g'},
147   {"target", required_argument, 0, 'F'},
148   {"verbose", no_argument, 0, 'v'},
149   {"version", no_argument, 0, 'V'},
150   {0, no_argument, 0, 0}
151 };
152
153 /* IMPORTS */
154 extern char *program_name;
155 extern char *program_version;
156
157 /* This flag distinguishes between strip and objcopy:
158    1 means this is 'strip'; 0 means this is 'objcopy'.
159    -1 means if we should use argv[0] to decide. */
160 extern int is_strip;
161
162
163 static void
164 copy_usage (stream, status)
165      FILE *stream;
166      int status;
167 {
168   fprintf (stream, "\
169 Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
170        [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
171        [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
172        [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
173        [--remove-section=section] [--set-start=val] [--adjust-start=incr]\n\
174        [--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\
175        [--adjust-warnings] [--no-adjust-warnings] [--verbose] [--version]\n\
176        [--help] in-file [out-file]\n",
177            program_name);
178   exit (status);
179 }
180
181 static void
182 strip_usage (stream, status)
183      FILE *stream;
184      int status;
185 {
186   fprintf (stream, "\
187 Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
188        [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
189        [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
190        [--remove-section=section] [--verbose] [--version] [--help] file...\n",
191            program_name);
192   exit (status);
193 }
194
195 /* Parse a string into a VMA, with a fatal error if it can't be
196    parsed.  */
197
198 static bfd_vma
199 parse_vma (s, arg)
200      const char *s;
201      const char *arg;
202 {
203   bfd_vma ret;
204   const char *end;
205
206   ret = bfd_scan_vma (s, &end, 0);
207   if (*end != '\0')
208     {
209       fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s);
210       exit (1);
211     }
212   return ret;
213 }
214
215 /* Return the name of a temporary file in the same directory as FILENAME.  */
216
217 static char *
218 make_tempname (filename)
219      char *filename;
220 {
221   static char template[] = "stXXXXXX";
222   char *tmpname;
223   char *slash = strrchr (filename, '/');
224
225   if (slash != (char *) NULL)
226     {
227       *slash = 0;
228       tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
229       strcpy (tmpname, filename);
230       strcat (tmpname, "/");
231       strcat (tmpname, template);
232       mktemp (tmpname);
233       *slash = '/';
234     }
235   else
236     {
237       tmpname = xmalloc (sizeof (template));
238       strcpy (tmpname, template);
239       mktemp (tmpname);
240     }
241   return tmpname;
242 }
243
244 /* Choose which symbol entries to copy; put the result in OSYMS.
245    We don't copy in place, because that confuses the relocs.
246    Return the number of symbols to print.  */
247
248 static unsigned int
249 filter_symbols (abfd, osyms, isyms, symcount)
250      bfd *abfd;
251      asymbol **osyms, **isyms;
252      long symcount;
253 {
254   register asymbol **from = isyms, **to = osyms;
255   long src_count = 0, dst_count = 0;
256
257   for (; src_count < symcount; src_count++)
258     {
259       asymbol *sym = from[src_count];
260       flagword flags = sym->flags;
261       int keep;
262
263       if ((flags & BSF_GLOBAL)  /* Keep if external.  */
264           || (flags & BSF_KEEP) /* Keep if used in a relocation.  */
265           || bfd_is_und_section (bfd_get_section (sym))
266           || bfd_is_com_section (bfd_get_section (sym)))
267         keep = 1;
268       else if ((flags & BSF_DEBUGGING) != 0)    /* Debugging symbol.  */
269         keep = strip_symbols != strip_debug;
270       else                      /* Local symbol.  */
271         keep = discard_locals != locals_all
272           && (discard_locals != locals_start_L ||
273               ! bfd_is_local_label (abfd, sym));
274       if (keep)
275         to[dst_count++] = sym;
276     }
277
278   return dst_count;
279 }
280
281 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
282    Adjust *SIZE.  */
283
284 void
285 filter_bytes (memhunk, size)
286      char *memhunk;
287      bfd_size_type *size;
288 {
289   char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
290
291   for (; from < end; from += interleave)
292     *to++ = *from;
293   *size /= interleave;
294 }
295
296 /* Copy object file IBFD onto OBFD.  */
297
298 static void
299 copy_object (ibfd, obfd)
300      bfd *ibfd;
301      bfd *obfd;
302 {
303   bfd_vma start;
304   long symcount;
305
306   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
307     {
308       nonfatal (bfd_get_filename (obfd));
309     }
310
311   if (verbose)
312     printf ("copy from %s(%s) to %s(%s)\n",
313             bfd_get_filename(ibfd), bfd_get_target(ibfd),
314             bfd_get_filename(obfd), bfd_get_target(obfd));
315
316   if (set_start_set)
317     start = set_start;
318   else
319     start = bfd_get_start_address (ibfd);
320   start += adjust_start;
321
322   if (!bfd_set_start_address (obfd, start)
323       || !bfd_set_file_flags (obfd,
324                               (bfd_get_file_flags (ibfd)
325                                & bfd_applicable_file_flags (obfd))))
326     {
327       nonfatal (bfd_get_filename (ibfd));
328     }
329
330   /* Copy architecture of input file to output file */
331   if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
332                           bfd_get_mach (ibfd)))
333     {
334       fprintf (stderr, "Output file cannot represent architecture %s\n",
335                bfd_printable_arch_mach (bfd_get_arch (ibfd),
336                                         bfd_get_mach (ibfd)));
337     }
338   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
339     {
340       nonfatal (bfd_get_filename(ibfd));
341     }
342
343   if (isympp)
344     free (isympp);
345   if (osympp != isympp)
346     free (osympp);
347
348   /* bfd mandates that all output sections be created and sizes set before
349      any output is done.  Thus, we traverse all sections multiple times.  */
350   bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
351
352   /* Symbol filtering must happen after the output sections have
353      been created, but before their contents are set.  */
354   if (strip_symbols == strip_all && discard_locals == locals_undef)
355     {
356       osympp = isympp = NULL;
357       symcount = 0;
358     }
359   else
360     {
361       long symsize;
362
363       symsize = bfd_get_symtab_upper_bound (ibfd);
364       if (symsize < 0)
365         {
366           nonfatal (bfd_get_filename (ibfd));
367         }
368
369       osympp = isympp = (asymbol **) xmalloc (symsize);
370       symcount = bfd_canonicalize_symtab (ibfd, isympp);
371       if (symcount < 0)
372         {
373           nonfatal (bfd_get_filename (ibfd));
374         }
375
376       if (strip_symbols == strip_debug || discard_locals != locals_undef)
377         {
378           /* Mark symbols used in output relocations so that they
379              are kept, even if they are local labels or static symbols.
380
381              Note we iterate over the input sections examining their
382              relocations since the relocations for the output sections
383              haven't been set yet.  mark_symbols_used_in_relocations will
384              ignore input sections which have no corresponding output
385              section.  */
386           bfd_map_over_sections (ibfd,
387                                  mark_symbols_used_in_relocations,
388                                  (PTR)isympp);
389           osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
390           symcount = filter_symbols (ibfd, osympp, isympp, symcount);
391         }
392     }
393
394   bfd_set_symtab (obfd, osympp, symcount);
395
396   /* This has to happen after the symbol table has been set.  */
397   bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
398
399   /* Allow the BFD backend to copy any private data it understands
400      from the input BFD to the output BFD.  This is done last to
401      permit the routine to look at the filtered symbol table, which is
402      important for the ECOFF code at least.  */
403   if (!bfd_copy_private_bfd_data (ibfd, obfd))
404     {
405       fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
406                program_name, bfd_get_filename (obfd),
407                bfd_errmsg (bfd_get_error ()));
408       status = 1;
409       return;
410     }
411 }
412
413 static char *
414 cat (a, b, c)
415      char *a;
416      char *b;
417      char *c;
418 {
419   size_t size = strlen (a) + strlen (b) + strlen (c);
420   char *r = xmalloc (size + 1);
421
422   strcpy (r, a);
423   strcat (r, b);
424   strcat (r, c);
425   return r;
426 }
427
428 /* Read each archive element in turn from IBFD, copy the
429    contents to temp file, and keep the temp file handle.  */
430
431 static void
432 copy_archive (ibfd, obfd, output_target)
433      bfd *ibfd;
434      bfd *obfd;
435      char *output_target;
436 {
437   bfd **ptr = &obfd->archive_head;
438   bfd *this_element;
439   char *dir = make_tempname (bfd_get_filename (obfd));
440
441   /* Make a temp directory to hold the contents.  */
442   mkdir (dir, 0700);
443   obfd->has_armap = ibfd->has_armap;
444
445   this_element = bfd_openr_next_archived_file (ibfd, NULL);
446   ibfd->archive_head = this_element;
447   while (this_element != (bfd *) NULL)
448     {
449       /* Create an output file for this member.  */
450       char *output_name = cat (dir, "/", bfd_get_filename(this_element));
451       bfd *output_bfd = bfd_openw (output_name, output_target);
452
453       if (output_bfd == (bfd *) NULL)
454         {
455           nonfatal (output_name);
456         }
457       if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
458         {
459           nonfatal (bfd_get_filename (obfd));
460         }
461
462       if (bfd_check_format (this_element, bfd_object) == true)
463         {
464           copy_object (this_element, output_bfd);
465         }
466
467       bfd_close (output_bfd);
468       /* Open the newly output file and attatch to our list.  */
469       output_bfd = bfd_openr (output_name, output_target);
470
471       /* Mark it for deletion.  */
472       *ptr = output_bfd;
473       ptr = &output_bfd->next;
474       this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
475       this_element = this_element->next;
476     }
477   *ptr = (bfd *) NULL;
478
479   if (!bfd_close (obfd))
480     {
481       nonfatal (bfd_get_filename (obfd));
482     }
483
484   /* Delete all the files that we opened.
485      Construct their names again, unfortunately, but
486      we're about to exit anyway.  */
487   for (this_element = ibfd->archive_head;
488        this_element != (bfd *) NULL;
489        this_element = this_element->next)
490     {
491       unlink (cat (dir, "/", bfd_get_filename (this_element)));
492     }
493   rmdir (dir);
494   if (!bfd_close (ibfd))
495     {
496       nonfatal (bfd_get_filename (ibfd));
497     }
498 }
499
500 /* The top-level control.  */
501
502 static void
503 copy_file (input_filename, output_filename, input_target, output_target)
504      char *input_filename;
505      char *output_filename;
506      char *input_target;
507      char *output_target;
508 {
509   bfd *ibfd;
510   char **matching;
511
512   /* To allow us to do "strip *" without dying on the first
513      non-object file, failures are nonfatal.  */
514
515   ibfd = bfd_openr (input_filename, input_target);
516   if (ibfd == NULL)
517     {
518       nonfatal (input_filename);
519     }
520
521   if (bfd_check_format (ibfd, bfd_archive))
522     {
523       bfd *obfd;
524
525       /* bfd_get_target does not return the correct value until
526          bfd_check_format succeeds.  */
527       if (output_target == NULL)
528         output_target = bfd_get_target (ibfd);
529
530       obfd = bfd_openw (output_filename, output_target);
531       if (obfd == NULL)
532         {
533           nonfatal (output_filename);
534         }
535       copy_archive (ibfd, obfd, output_target);
536     }
537   else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
538     {
539       bfd *obfd;
540
541       /* bfd_get_target does not return the correct value until
542          bfd_check_format succeeds.  */
543       if (output_target == NULL)
544         output_target = bfd_get_target (ibfd);
545
546       obfd = bfd_openw (output_filename, output_target);
547       if (obfd == NULL)
548         {
549           nonfatal (output_filename);
550         }
551
552       copy_object (ibfd, obfd);
553
554       if (!bfd_close (obfd))
555         {
556           nonfatal (output_filename);
557         }
558
559       if (!bfd_close (ibfd))
560         {
561           nonfatal (input_filename);
562         }
563     }
564   else
565     {
566       bfd_nonfatal (input_filename);
567       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
568         {
569           list_matching_formats (matching);
570           free (matching);
571         }
572       status = 1;
573     }
574 }
575
576 /* Create a section in OBFD with the same name and attributes
577    as ISECTION in IBFD.  */
578
579 static void
580 setup_section (ibfd, isection, obfdarg)
581      bfd *ibfd;
582      sec_ptr isection;
583      PTR obfdarg;
584 {
585   bfd *obfd = (bfd *) obfdarg;
586   struct section_list *p;
587   sec_ptr osection;
588   bfd_vma vma;
589   char *err;
590
591   if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
592       && (strip_symbols == strip_debug
593           || strip_symbols == strip_all
594           || discard_locals == locals_all))
595     return;
596
597   for (p = remove_sections; p != NULL; p = p->next)
598     {
599       if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
600         {
601           p->used = true;
602           return;
603         }
604     }
605
606   osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
607   if (osection == NULL)
608     {
609       err = "making";
610       goto loser;
611     }
612
613   if (!bfd_set_section_size (obfd,
614                              osection,
615                              bfd_section_size (ibfd, isection)))
616     {
617       err = "size";
618       goto loser;
619     }
620
621   vma = bfd_section_vma (ibfd, isection);
622   for (p = adjust_sections; p != NULL; p = p->next)
623     {
624       if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
625         {
626           if (p->adjust)
627             vma += p->val;
628           else
629             vma = p->val;
630           p->used = true;
631           break;
632         }
633     }
634   if (p == NULL)
635     vma += adjust_section_vma;
636
637   if (! bfd_set_section_vma (obfd, osection, vma))
638     {
639       err = "vma";
640       goto loser;
641     }
642
643   if (bfd_set_section_alignment (obfd,
644                                  osection,
645                                  bfd_section_alignment (ibfd, isection))
646       == false)
647     {
648       err = "alignment";
649       goto loser;
650     }
651
652   if (!bfd_set_section_flags (obfd, osection,
653                               bfd_get_section_flags (ibfd, isection)))
654     {
655       err = "flags";
656       goto loser;
657     }
658
659   /* This used to be mangle_section; we do here to avoid using
660      bfd_get_section_by_name since some formats allow multiple
661      sections with the same name.  */
662   isection->output_section = osection;
663   isection->output_offset = 0;
664
665   /* Allow the BFD backend to copy any private data it understands
666      from the input section to the output section.  */
667   if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
668     {
669       err = "private data";
670       goto loser;
671     }
672
673   /* All went well */
674   return;
675
676 loser:
677   fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
678            program_name,
679            bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
680            err, bfd_errmsg (bfd_get_error ()));
681   status = 1;
682 }
683
684 /* Copy the data of input section ISECTION of IBFD
685    to an output section with the same name in OBFD.
686    If stripping then don't copy any relocation info.  */
687
688 static void
689 copy_section (ibfd, isection, obfdarg)
690      bfd *ibfd;
691      sec_ptr isection;
692      PTR obfdarg;
693 {
694   bfd *obfd = (bfd *) obfdarg;
695   struct section_list *p;
696   arelent **relpp;
697   long relcount;
698   sec_ptr osection;
699   bfd_size_type size;
700
701   if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
702       && (strip_symbols == strip_debug
703           || strip_symbols == strip_all
704           || discard_locals == locals_all))
705     {
706       return;
707     }
708
709   for (p = remove_sections; p != NULL; p = p->next)
710     if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
711       return;
712
713   osection = isection->output_section;
714   size = bfd_get_section_size_before_reloc (isection);
715
716   if (size == 0 || osection == 0)
717     return;
718
719   if (strip_symbols == strip_all)
720     bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
721   else
722     {
723       long relsize;
724
725       relsize = bfd_get_reloc_upper_bound (ibfd, isection);
726       if (relsize < 0)
727         {
728           nonfatal (bfd_get_filename (ibfd));
729         }
730       if (relsize == 0)
731         bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
732       else
733         {
734           relpp = (arelent **) xmalloc (relsize);
735           relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
736           if (relcount < 0)
737             {
738               nonfatal (bfd_get_filename (ibfd));
739             }
740           bfd_set_reloc (obfd, osection, relpp, relcount);
741         }
742     }
743
744   isection->_cooked_size = isection->_raw_size;
745   isection->reloc_done = true;
746
747   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
748     {
749       PTR memhunk = (PTR) xmalloc ((unsigned) size);
750
751       if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
752                                      size))
753         {
754           nonfatal (bfd_get_filename (ibfd));
755         }
756
757       if (copy_byte >= 0) 
758         {
759           filter_bytes (memhunk, &size);
760               /* The section has gotten smaller. */
761           if (!bfd_set_section_size (obfd, osection, size))
762             nonfatal (bfd_get_filename (obfd));
763         }
764
765       if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
766                                      size))
767         {
768           nonfatal (bfd_get_filename (obfd));
769         }
770       free (memhunk);
771     }
772 }
773
774 /* Mark all the symbols which will be used in output relocations with
775    the BSF_KEEP flag so that those symbols will not be stripped.
776
777    Ignore relocations which will not appear in the output file.  */
778
779 static void
780 mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
781      bfd *ibfd;
782      sec_ptr isection;
783      PTR symbolsarg;
784 {
785   asymbol **symbols = (asymbol **) symbolsarg;
786   long relsize;
787   arelent **relpp;
788   long relcount, i;
789
790   /* Ignore an input section with no corresponding output section.  */
791   if (isection->output_section == NULL)
792     return;
793
794   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
795   if (relsize < 0)
796     bfd_fatal (bfd_get_filename (ibfd));
797
798   relpp = (arelent **) xmalloc (relsize);
799   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
800   if (relcount < 0)
801     bfd_fatal (bfd_get_filename (ibfd));
802
803   /* Examine each symbol used in a relocation.  If it's not one of the
804      special bfd section symbols, then mark it with BSF_KEEP.  */
805   for (i = 0; i < relcount; i++)
806     {
807       if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
808           && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
809           && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
810         (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
811     }
812
813   if (relpp != NULL)
814     free (relpp);
815 }
816
817 /* The number of bytes to copy at once.  */
818 #define COPY_BUF 8192
819
820 /* Copy file FROM to file TO, performing no translations.
821    Return 0 if ok, -1 if error.  */
822
823 static int
824 simple_copy (from, to)
825      char *from, *to;
826 {
827   int fromfd, tofd, nread;
828   char buf[COPY_BUF];
829
830   fromfd = open (from, O_RDONLY);
831   if (fromfd < 0)
832     return -1;
833   tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
834   if (tofd < 0)
835     {
836       close (fromfd);
837       return -1;
838     }
839   while ((nread = read (fromfd, buf, sizeof buf)) > 0)
840     {
841       if (write (tofd, buf, nread) != nread)
842         {
843           close (fromfd);
844           close (tofd);
845           return -1;
846         }
847     }
848   close (fromfd);
849   close (tofd);
850   if (nread < 0)
851     return -1;
852   return 0;
853 }
854
855 #ifndef S_ISLNK
856 #ifdef S_IFLNK
857 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
858 #else
859 #define S_ISLNK(m) 0
860 #define lstat stat
861 #endif
862 #endif
863
864 /* Rename FROM to TO, copying if TO is a link.
865    Assumes that TO already exists, because FROM is a temp file.
866    Return 0 if ok, -1 if error.  */
867
868 static int
869 smart_rename (from, to)
870      char *from, *to;
871 {
872   struct stat s;
873   int ret = 0;
874
875   if (lstat (to, &s))
876     return -1;
877
878   /* Use rename only if TO is not a symbolic link and has
879      only one hard link.  */
880   if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
881     {
882       ret = rename (from, to);
883       if (ret == 0)
884         {
885           /* Try to preserve the permission bits and ownership of TO.  */
886           chmod (to, s.st_mode & 07777);
887           chown (to, s.st_uid, s.st_gid);
888         }
889     }
890   else
891     {
892       ret = simple_copy (from, to);
893       if (ret == 0)
894         unlink (from);
895     }
896   return ret;
897 }
898
899 static int
900 strip_main (argc, argv)
901      int argc;
902      char *argv[];
903 {
904   char *input_target = NULL, *output_target = NULL;
905   boolean show_version = false;
906   int c, i;
907
908   while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVv",
909                            strip_options, (int *) 0)) != EOF)
910     {
911       switch (c)
912         {
913         case 'I':
914           input_target = optarg;
915           break;
916         case 'O':
917           output_target = optarg;
918           break;
919         case 'F':
920           input_target = output_target = optarg;
921           break;
922         case 'R':
923           {
924             struct section_list *n;
925
926             n = (struct section_list *) xmalloc (sizeof (struct section_list));
927             n->name = optarg;
928             n->used = false;
929             n->next = remove_sections;
930             remove_sections = n;
931           }
932           break;
933         case 's':
934           strip_symbols = strip_all;
935           break;
936         case 'S':
937         case 'g':
938           strip_symbols = strip_debug;
939           break;
940         case 'x':
941           discard_locals = locals_all;
942           break;
943         case 'X':
944           discard_locals = locals_start_L;
945           break;
946         case 'v':
947           verbose = true;
948           break;
949         case 'V':
950           show_version = true;
951           break;
952         case 0:
953           break;                /* we've been given a long option */
954         case 'h':
955           strip_usage (stdout, 0);
956         default:
957           strip_usage (stderr, 1);
958         }
959     }
960
961   if (show_version)
962     {
963       printf ("GNU %s version %s\n", program_name, program_version);
964       exit (0);
965     }
966
967   /* Default is to strip all symbols.  */
968   if (strip_symbols == strip_undef && discard_locals == locals_undef)
969     strip_symbols = strip_all;
970
971   if (output_target == (char *) NULL)
972     output_target = input_target;
973
974   i = optind;
975   if (i == argc)
976     strip_usage (stderr, 1);
977
978   for (; i < argc; i++)
979     {
980       int hold_status = status;
981
982       char *tmpname = make_tempname (argv[i]);
983       status = 0;
984       copy_file (argv[i], tmpname, input_target, output_target);
985       if (status == 0)
986         {
987           smart_rename (tmpname, argv[i]);
988           status = hold_status;
989         }
990       else
991         unlink (tmpname);
992       free (tmpname);
993     }
994
995   return 0;
996 }
997
998 static int
999 copy_main (argc, argv)
1000      int argc;
1001      char *argv[];
1002 {
1003   char *input_filename = NULL, *output_filename = NULL;
1004   char *input_target = NULL, *output_target = NULL;
1005   boolean show_version = false;
1006   boolean adjust_warn = true;
1007   int c;
1008   struct section_list *p;
1009
1010   while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVv",
1011                            copy_options, (int *) 0)) != EOF)
1012     {
1013       switch (c)
1014         {
1015         case 'b':
1016           copy_byte = atoi(optarg);
1017           if (copy_byte < 0)
1018             {
1019               fprintf (stderr, "%s: byte number must be non-negative\n",
1020                        program_name);
1021               exit (1);
1022             }
1023           break;
1024         case 'i':
1025           interleave = atoi(optarg);
1026           if (interleave < 1)
1027             {
1028               fprintf(stderr, "%s: interleave must be positive\n",
1029                       program_name);
1030               exit (1);
1031             }
1032           break;
1033         case 'I':
1034         case 's':               /* "source" - 'I' is preferred */
1035           input_target = optarg;
1036           break;
1037         case 'O':
1038         case 'd':               /* "destination" - 'O' is preferred */
1039           output_target = optarg;
1040           break;
1041         case 'F':
1042           input_target = output_target = optarg;
1043           break;
1044         case 'R':
1045           p = (struct section_list *) xmalloc (sizeof (struct section_list));
1046           p->name = optarg;
1047           p->used = false;
1048           p->next = remove_sections;
1049           remove_sections = p;
1050           break;
1051         case 'S':
1052           strip_symbols = strip_all;
1053           break;
1054         case 'g':
1055           strip_symbols = strip_debug;
1056           break;
1057         case 'x':
1058           discard_locals = locals_all;
1059           break;
1060         case 'X':
1061           discard_locals = locals_start_L;
1062           break;
1063         case 'v':
1064           verbose = true;
1065           break;
1066         case 'V':
1067           show_version = true;
1068           break;
1069         case OPTION_ADJUST_START:
1070           adjust_start = parse_vma (optarg, "--adjust-start");
1071           break;
1072         case OPTION_ADJUST_SECTION_VMA:
1073           {
1074             const char *s;
1075             int len;
1076             char *name;
1077
1078             p = (struct section_list *) xmalloc (sizeof (struct section_list));
1079             s = strchr (optarg, '=');
1080             if (s != NULL)
1081               {
1082                 p->adjust = false;
1083                 p->val = parse_vma (s + 1, "--adjust-section-vma");
1084               }
1085             else
1086               {
1087                 s = strchr (optarg, '+');
1088                 if (s == NULL)
1089                   {
1090                     s = strchr (optarg, '-');
1091                     if (s == NULL)
1092                       {
1093                         fprintf (stderr,
1094                                  "%s: bad format for --adjust-section-vma\n",
1095                                  program_name);
1096                         exit (1);
1097                       }
1098                   }
1099                 p->adjust = true;
1100                 p->val = parse_vma (s + 1, "--adjust-section-vma");
1101                 if (*s == '-')
1102                   p->val = - p->val;
1103               }
1104
1105             len = s - optarg;
1106             name = (char *) xmalloc (len + 1);
1107             strncpy (name, optarg, len);
1108             name[len] = '\0';
1109             p->name = name;
1110
1111             p->used = false;
1112
1113             p->next = adjust_sections;
1114             adjust_sections = p;
1115           }
1116           break;
1117         case OPTION_ADJUST_VMA:
1118           adjust_section_vma = parse_vma (optarg, "--adjust-vma");
1119           adjust_start = adjust_section_vma;
1120           break;
1121         case OPTION_ADJUST_WARNINGS:
1122           adjust_warn = true;
1123           break;
1124         case OPTION_NO_ADJUST_WARNINGS:
1125           adjust_warn = false;
1126           break;
1127         case OPTION_SET_START:
1128           set_start = parse_vma (optarg, "--set-start");
1129           set_start_set = true;
1130           break;
1131         case 0:
1132           break;                /* we've been given a long option */
1133         case 'h':
1134           copy_usage (stdout, 0);
1135         default:
1136           copy_usage (stderr, 1);
1137         }
1138     }
1139
1140   if (show_version)
1141     {
1142       printf ("GNU %s version %s\n", program_name, program_version);
1143       exit (0);
1144     }
1145
1146   if (copy_byte >= interleave)
1147     {
1148       fprintf (stderr, "%s: byte number must be less than interleave\n",
1149                program_name);
1150       exit (1);
1151     }
1152
1153   if (optind == argc || optind + 2 < argc)
1154     copy_usage (stderr, 1);
1155
1156   input_filename = argv[optind];
1157   if (optind + 1 < argc)
1158     output_filename = argv[optind + 1];
1159
1160   /* Default is to strip no symbols.  */
1161   if (strip_symbols == strip_undef && discard_locals == locals_undef)
1162     strip_symbols = strip_none;
1163
1164   if (output_target == (char *) NULL)
1165     output_target = input_target;
1166
1167   /* If there is no destination file then create a temp and rename
1168      the result into the input.  */
1169
1170   if (output_filename == (char *) NULL)
1171     {
1172       char *tmpname = make_tempname (input_filename);
1173       copy_file (input_filename, tmpname, input_target, output_target);
1174       if (status == 0)
1175         smart_rename (tmpname, input_filename);
1176       else
1177         unlink (tmpname);
1178     }
1179   else
1180     {
1181       copy_file (input_filename, output_filename, input_target, output_target);
1182     }
1183
1184   if (adjust_warn)
1185     {
1186       for (p = adjust_sections; p != NULL; p = p->next)
1187         {
1188           if (! p->used)
1189             {
1190               fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x",
1191                        program_name, p->name,
1192                        p->adjust ? '=' : '+');
1193               fprintf_vma (stderr, p->val);
1194               fprintf (stderr, " never used\n");
1195             }
1196         }
1197     }
1198
1199   /* We could issue similar warnings for remove_sections, but I don't
1200      think that would be as useful.  */
1201
1202   return 0;
1203 }
1204
1205 int
1206 main (argc, argv)
1207      int argc;
1208      char *argv[];
1209 {
1210   program_name = argv[0];
1211   xmalloc_set_program_name (program_name);
1212   strip_symbols = strip_undef;
1213   discard_locals = locals_undef;
1214
1215   bfd_init ();
1216
1217   if (is_strip < 0)
1218     {
1219       int i = strlen (program_name);
1220       is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
1221     }
1222
1223   if (is_strip)
1224     strip_main (argc, argv);
1225   else
1226     copy_main (argc, argv);
1227
1228   return status;
1229 }
This page took 0.092934 seconds and 4 git commands to generate.