1 /* objcopy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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.
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.
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. */
25 asymbol **isympp = NULL; /* Input symbols */
26 asymbol **osympp = NULL; /* Output symbols that survive stripping */
27 char *input_target = NULL;
28 char *output_target = NULL;
29 char *input_filename = NULL;
30 char *output_filename = NULL;
33 static void setup_sections();
34 static void copy_sections();
35 static boolean verbose;
37 /* This flag distinguishes between strip and objcopy:
38 1 means this is 'strip'; 0 means this is 'objcopy'.
39 -1 means if we should use argv[0] to decide. */
47 strip_none, /* don't strip */
48 strip_debug, /* strip all debugger symbols */
49 strip_all /* strip all symbols */
52 /* Which symbols to remove. */
53 enum strip_action strip_symbols;
58 locals_start_L, /* discard locals starting with L */
59 locals_all /* discard all locals */
62 /* Which local symbols to remove. */
63 enum locals_action discard_locals;
65 /* Options to handle if running as "strip". */
67 struct option strip_options[] = {
68 {"strip-all", no_argument, 0, 's'},
69 {"strip-debug", no_argument, 0, 'S'},
70 {"discard-all", no_argument, 0, 'x'},
71 {"discard-locals", no_argument, 0, 'X'},
72 {"help", no_argument, 0, 'h'},
73 {"input-format", required_argument, 0, 'I'},
74 {"output-format", required_argument, 0, 'O'},
75 {"format", required_argument, 0, 'F'},
76 {"target", required_argument, 0, 'F'},
78 {"version", no_argument, 0, 'V'},
79 {"verbose", no_argument, 0, 'v'},
80 {0, no_argument, 0, 0}
83 /* Options to handle if running as "objcopy". */
85 struct option copy_options[] = {
86 {"strip-all", no_argument, 0, 'S'},
87 {"strip-debug", no_argument, 0, 'g'},
88 {"discard-all", no_argument, 0, 'x'},
89 {"discard-locals", no_argument, 0, 'X'},
90 {"help", no_argument, 0, 'h'},
91 {"input-format", required_argument, 0, 'I'},
92 {"output-format", required_argument, 0, 'O'},
93 {"format", required_argument, 0, 'F'},
94 {"target", required_argument, 0, 'F'},
96 {"version", no_argument, 0, 'V'},
97 {"verbose", no_argument, 0, 'v'},
98 {0, no_argument, 0, 0}
102 extern char *program_name;
103 extern char *program_version;
108 copy_usage(stream, status)
113 Usage: %s [-vVSgxX] [-I format] [-O format] [-F format]\n\
114 [--format=format] [--target=format] [--input-format=format]\n\
115 [--output-format=format] [--strip-all] [--strip-debug]\n\
116 [--discard-all] [--discard-locals] [--verbose] [--version]\n\
117 [--help] in-file [out-file]\n", program_name);
123 strip_usage(stream, status)
128 Usage: %s [-vVsSgxX] [-I format] [-O format] [-F format]\n\
129 [--format=format] [--target=format] [--input-format=format]\n\
130 [--output-format=format] [--strip-all] [--strip-debug] [--discard-all]\n\
131 [--discard-locals] [--verbose] [--version] [--help] file...\n",
137 /* Create a temp file in the same directory as supplied */
140 make_tempname(filename)
143 static char template[] = "stXXXXXX";
145 char * slash = strrchr( filename, '/' );
146 if (slash != (char *)NULL){
148 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
149 strcpy(tmpname, filename);
150 strcat(tmpname, "/" );
151 strcat(tmpname, template);
155 tmpname = xmalloc(sizeof(template));
156 strcpy(tmpname, template);
163 All the symbols have been read in and point to their owning input section.
164 They have been relocated to that they are all relative to the base of
165 their owning section. On the way out, all the symbols will be relocated to
166 their new location in the output file, through some complex sums.
170 mangle_sections(ibfd, obfd)
174 asection *current = ibfd->sections;
175 for (; current != NULL; current = current->next) {
176 current->output_section = bfd_get_section_by_name(obfd, current->name);
177 current->output_offset = 0;
181 /* Choose which symbol entries to copy; put the result in osyms.
182 We don't copy in place, because that confuses the relocs.
183 Return the number of symbols to be printed. */
185 filter_symbols (abfd, osyms, isyms, symcount)
187 asymbol **osyms, **isyms;
188 unsigned long symcount;
190 register asymbol **from = isyms, **to = osyms;
191 unsigned int dst_count = 0;
193 char locals_prefix = bfd_get_symbol_leading_char(abfd) == '_' ? 'L' : '.';
195 unsigned int src_count = 0;
196 for (; src_count <symcount; src_count++) {
199 flagword flags = (from[src_count])->flags;
200 sym = from[src_count];
201 if ((flags & BSF_GLOBAL) /* Keep if external */
202 || (sym->section == &bfd_und_section)
203 || (bfd_is_com_section (sym->section)))
205 else if ((flags & BSF_DEBUGGING) != 0) /* debugging symbol */
206 keep = strip_symbols != strip_debug;
207 else /* local symbol */
208 keep = (discard_locals != locals_all)
209 && !(discard_locals == locals_start_L &&
210 sym->name[0] == locals_prefix);
214 to[dst_count++] = from[src_count];
222 copy_object(ibfd, obfd)
227 unsigned int symcount;
230 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
231 bfd_fatal(output_filename);
235 printf("copy from %s(%s) to %s(%s)\n",
236 ibfd->filename, ibfd->xvec->name,
237 obfd->filename, obfd->xvec->name);
239 if (! bfd_set_start_address (obfd, bfd_get_start_address (ibfd))
240 || ! bfd_set_file_flags (obfd,
241 (bfd_get_file_flags (ibfd)
242 & bfd_applicable_file_flags (obfd))))
243 bfd_fatal (bfd_get_filename (ibfd));
245 /* Copy architecture of input file to output file */
246 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
247 bfd_get_mach(ibfd))) {
248 fprintf(stderr, "Output file cannot represent architecture %s\n",
249 bfd_printable_arch_mach(bfd_get_arch(ibfd),
250 bfd_get_mach(ibfd)));
252 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
254 bfd_fatal(ibfd->filename);
259 if (osympp != isympp)
262 if (strip_symbols == strip_all && discard_locals == locals_undef)
264 osympp = isympp = NULL;
269 osympp = isympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
270 symcount = bfd_canonicalize_symtab(ibfd, isympp);
272 if (strip_symbols == strip_debug || discard_locals != locals_undef)
274 osympp = (asymbol **) xmalloc(symcount * sizeof(asymbol*));
275 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
279 bfd_set_symtab(obfd, osympp, symcount);
282 bfd mandates that all output sections be created and sizes set before
283 any output is done. Thus, we traverse all sections twice.
285 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
286 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
287 mangle_sections(ibfd, obfd);
296 int size = strlen(a) + strlen(b) + strlen(c);
297 char *r = xmalloc(size+1);
305 copy_archive(ibfd, obfd)
309 bfd **ptr = &obfd->archive_head;
311 /* Read each archive element in turn from the input, copy the
312 contents to a temp file, and keep the temp file handle */
313 char *dir = cat("./#",make_tempname(""),"cd");
315 /* Make a temp directory to hold the contents */
317 obfd->has_armap = ibfd->has_armap;
318 this_element = bfd_openr_next_archived_file(ibfd, NULL);
319 ibfd->archive_head = this_element;
320 while (this_element != (bfd *)NULL) {
322 /* Create an output file for this member */
323 char *output_name = cat(dir, "/",this_element->filename);
324 bfd *output_bfd = bfd_openw(output_name, output_target);
326 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
327 bfd_fatal(output_filename);
329 if (output_bfd == (bfd *)NULL) {
330 bfd_fatal(output_name);
332 if (bfd_check_format(this_element, bfd_object) == true) {
333 copy_object(this_element, output_bfd);
336 bfd_close(output_bfd);
337 /* Now open the newly output file and attatch to our list */
338 output_bfd = bfd_openr(output_name, output_target);
339 /* Mark it for deletion */
343 ptr = &output_bfd->next;
344 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
345 this_element = this_element->next;
350 if (!bfd_close(obfd))
351 bfd_fatal(output_filename);
353 /* Now delete all the files that we opened.
354 Construct their names again, unfortunately, but so what;
355 we're about to exit anyway. */
356 for (this_element = ibfd->archive_head;
357 this_element != (bfd *)NULL;
358 this_element = this_element->next)
360 unlink(cat(dir,"/",this_element->filename));
363 if (!bfd_close(ibfd))
364 bfd_fatal(input_filename);
370 copy_file(input_filename, output_filename)
371 char *input_filename;
372 char *output_filename;
376 /* To allow us to do "strip *" without dying on the first
377 non-object file, failures are nonfatal. */
379 ibfd = bfd_openr(input_filename, input_target);
382 bfd_perror(input_filename);
386 if (bfd_check_format(ibfd, bfd_object)) {
387 bfd * obfd = bfd_openw(output_filename, output_target);
390 bfd_perror(output_filename);
394 copy_object(ibfd, obfd);
396 if (!bfd_close(obfd))
398 bfd_perror(output_filename);
402 if (!bfd_close(ibfd))
404 bfd_perror(input_filename);
408 else if (bfd_check_format(ibfd, bfd_archive)) {
409 bfd * obfd = bfd_openw(output_filename, output_target);
412 bfd_perror(output_filename);
415 copy_archive(ibfd, obfd);
418 /* Get the right error message. */
419 (void) bfd_check_format (ibfd, bfd_object);
420 bfd_perror (input_filename);
426 /** Actually do the work */
428 setup_sections(ibfd, isection, obfd)
436 osection = bfd_get_section_by_name(obfd, bfd_section_name(ibfd, isection));
437 if (osection == NULL) {
438 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
439 if (osection == NULL) {
445 if (!bfd_set_section_size(obfd,
447 bfd_section_size(ibfd, isection))) {
452 if (bfd_set_section_vma(obfd,
454 bfd_section_vma(ibfd, isection))
460 if (bfd_set_section_alignment(obfd,
462 bfd_section_alignment(ibfd, isection))
468 if (!bfd_set_section_flags(obfd, osection,
469 bfd_get_section_flags(ibfd, isection))) {
478 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
480 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
481 err, bfd_errmsg(bfd_error));
483 } /* setup_sections() */
486 Copy all the section related data from an input section
489 If stripping then don't copy any relocation info
492 copy_sections(ibfd, isection, obfd)
502 osection = bfd_get_section_by_name(obfd,
503 bfd_section_name(ibfd, isection));
505 size = bfd_get_section_size_before_reloc(isection);
510 if (strip_symbols == strip_all
511 || bfd_get_reloc_upper_bound(ibfd, isection) == 0)
513 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
517 relpp = (arelent **) xmalloc(bfd_get_reloc_upper_bound(ibfd, isection));
518 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, isympp);
519 bfd_set_reloc(obfd, osection, relpp, relcount);
522 isection->_cooked_size = isection->_raw_size;
523 isection->reloc_done =true;
526 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
528 PTR memhunk = (PTR) xmalloc((unsigned)size);
530 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
531 bfd_fatal(bfd_get_filename(ibfd));
533 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
534 bfd_fatal(bfd_get_filename(obfd));
546 int c; /* sez which option char */
548 program_name = argv[0];
550 strip_symbols = strip_undef; /* default is to strip everything. */
551 discard_locals = locals_undef;
556 i = strlen (program_name);
557 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
562 while ((c = getopt_long(argc, argv, "I:O:F:sSgxXVv",
563 strip_options, (int *) 0))
567 input_target = optarg;
569 output_target = optarg;
572 input_target = output_target = optarg;
576 strip_symbols = strip_all;
580 strip_symbols = strip_debug;
583 discard_locals = locals_all;
586 discard_locals = locals_start_L;
595 break; /* we've been given a long option */
597 strip_usage (stdout, 0);
599 strip_usage (stderr, 1);
605 /* Default is to strip all symbols. */
606 if (strip_symbols == strip_undef && discard_locals == locals_undef)
607 strip_symbols = strip_all;
609 if (output_target == (char *) NULL)
610 output_target = input_target;
613 printf ("GNU %s version %s\n", program_name, program_version);
617 strip_usage(stderr, 1);
618 for ( ; i < argc; i++) {
619 char *tmpname = make_tempname(argv[i]);
620 copy_file(argv[i], tmpname);
621 rename(tmpname, argv[i]);
626 /* Invoked as "objcopy", not "strip" */
628 while ((c = getopt_long(argc, argv, "I:s:O:d:F:b:SgxXVv",
629 strip_options, (int *) 0))
633 case 's': /* "source" - 'I' is preferred */
634 input_target = optarg;
636 case 'd': /* "destination" - 'O' is preferred */
637 output_target = optarg;
640 case 'b': /* "both" - 'F' is preferred */
641 input_target = output_target = optarg;
645 strip_symbols = strip_all;
648 strip_symbols = strip_debug;
651 discard_locals = locals_all;
654 discard_locals = locals_start_L;
663 break; /* we've been given a long option */
665 copy_usage (stdout, 0);
667 copy_usage (stderr, 1);
672 printf ("GNU %s version %s\n", program_name, program_version);
677 copy_usage(stderr, 1);
679 input_filename = argv[optind];
680 if (optind + 1 < argc)
681 output_filename = argv[optind+1];
683 /* Default is to strip no symbols. */
684 if (strip_symbols == strip_undef && discard_locals == locals_undef)
685 strip_symbols = strip_none;
687 if (input_filename == (char *) NULL)
688 copy_usage(stderr, 1);
690 if (output_target == (char *) NULL)
691 output_target = input_target;
693 /* If there is no destination file then create a temp and rename
694 the result into the input */
696 if (output_filename == (char *)NULL) {
697 char * tmpname = make_tempname(input_filename);
698 copy_file(input_filename, tmpname);
699 output_filename = input_filename;
700 rename(tmpname, input_filename);
703 copy_file(input_filename, output_filename);