]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/objcopy.c
* objcopy.c (copy_object): Revert yesterday's change.
[thirdparty/binutils-gdb.git] / binutils / objcopy.c
1 /* objcopy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 \f
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "bucomm.h"
23 #include <getopt.h>
24 #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 }