1 /* copy.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. */
26 char *input_target = NULL;
27 char *output_target = NULL;
28 char *input_filename = NULL;
29 char *output_filename = NULL;
32 static void setup_sections();
33 static void copy_sections();
34 static boolean verbose;
36 /* This flag distinguishes between strip and copy:
37 1 means this is 'strip'; 0 means this is 'copy'.
38 -1 means if we should use argv[0] to decide. */
46 strip_none, /* don't strip */
47 strip_debug, /* strip all debugger symbols */
48 strip_all /* strip all symbols */
51 /* Which symbols to remove. */
52 enum strip_action strip_symbols;
57 locals_start_L, /* discard locals starting with L */
58 locals_all /* discard all locals */
61 /* Which local symbols to remove. */
62 enum locals_action discard_locals;
64 /* Options to handle if running as "strip". */
66 struct option strip_options[] = {
67 {"strip-all", no_argument, 0, 's'},
68 {"strip-debug", no_argument, 0, 'S'},
69 {"discard-all", no_argument, 0, 'x'},
70 {"discard-locals", no_argument, 0, 'X'},
71 {"input-format", required_argument, 0, 'I'},
72 {"output-format", required_argument, 0, 'O'},
73 {"format", required_argument, 0, 'F'},
74 {"target", required_argument, 0, 'F'},
76 {"version", no_argument, 0, 'V'},
77 {"verbose", no_argument, 0, 'v'},
78 {0, no_argument, 0, 0}
81 /* Options to handle if running as "copy". */
83 struct option copy_options[] = {
84 {"strip-all", no_argument, 0, 'S'},
85 {"strip-debug", no_argument, 0, 'g'},
86 {"discard-all", no_argument, 0, 'x'},
87 {"discard-locals", no_argument, 0, 'X'},
88 {"input-format", required_argument, 0, 'I'},
89 {"output-format", required_argument, 0, 'O'},
90 {"format", required_argument, 0, 'F'},
91 {"target", required_argument, 0, 'F'},
93 {"version", no_argument, 0, 'V'},
94 {"verbose", no_argument, 0, 'v'},
95 {0, no_argument, 0, 0}
99 extern char *program_name;
100 extern char *program_version;
108 "Usage %s [-vVSgxX] [-I informat] [-O outformat] infile [outfile]\n",
117 fprintf(stderr, "Usage %s [-vVsSgxX] [-I informat] [-O outformat] filename ...\n", program_name);
122 /* Create a temp file in the same directory as supplied */
125 make_tempname(filename)
128 static char template[] = "stXXXXXX";
130 char * slash = strrchr( filename, '/' );
131 if (slash != (char *)NULL){
133 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
134 strcpy(tmpname, filename);
135 strcat(tmpname, "/" );
136 strcat(tmpname, template);
140 tmpname = xmalloc(sizeof(template));
141 strcpy(tmpname, template);
148 All the symbols have been read in and point to their owning input section.
149 They have been relocated to that they are all relative to the base of
150 their owning section. On the way out, all the symbols will be relocated to
151 their new location in the output file, through some complex sums.
155 mangle_sections(ibfd, obfd)
159 asection *current = ibfd->sections;
160 for (; current != NULL; current = current->next) {
161 current->output_section = bfd_get_section_by_name(obfd, current->name);
162 current->output_offset = 0;
166 /* Choose which symbol entries to copy;
167 compact them downward to get rid of the rest.
168 Return the number of symbols to be printed. */
170 filter_symbols (abfd, syms, symcount)
173 unsigned long symcount;
175 asymbol **from, **to;
176 unsigned int dst_count = 0;
178 char locals_prefix = bfd_get_symbol_leading_char(abfd) == '_' ? 'L' : '.';
180 unsigned int src_count;
181 for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
184 flagword flags = (from[src_count])->flags;
185 sym = from[src_count];
186 if ((flags & BSF_GLOBAL) /* Keep if external */
187 || (sym->section == &bfd_und_section)
188 || (bfd_is_com_section (sym->section)))
190 else if ((flags & BSF_DEBUGGING) != 0) /* debugging symbol */
191 keep = strip_symbols != strip_debug;
192 else /* local symbol */
193 keep = (discard_locals != locals_all)
194 && !(discard_locals == locals_start_L &&
195 sym->name[0] == locals_prefix);
199 to[dst_count++] = from[src_count];
208 copy_object(ibfd, obfd)
213 unsigned int symcount;
216 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
217 bfd_fatal(output_filename);
221 printf("copy from %s(%s) to %s(%s)\n",
222 ibfd->filename, ibfd->xvec->name,
223 obfd->filename, obfd->xvec->name);
225 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
227 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
228 (HAS_LINENO | HAS_DEBUG |
229 HAS_RELOC | HAS_SYMS | D_PAGED |
230 HAS_LOCALS))) == false)) {
231 bfd_fatal(bfd_get_filename(ibfd));
234 /* Copy architecture of input file to output file */
235 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
236 bfd_get_mach(ibfd))) {
237 fprintf(stderr, "Output file cannot represent architecture %s\n",
238 bfd_printable_arch_mach(bfd_get_arch(ibfd),
239 bfd_get_mach(ibfd)));
241 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
243 bfd_fatal(ibfd->filename);
246 sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
247 symcount = bfd_canonicalize_symtab(ibfd, sympp);
249 if (strip_symbols == strip_debug || discard_locals != locals_undef)
250 symcount = filter_symbols (ibfd, sympp, symcount);
253 bfd_set_symtab(obfd, sympp,
254 strip_symbols == strip_all ? 0 : symcount);
257 bfd mandates that all output sections be created and sizes set before
258 any output is done. Thus, we traverse all sections twice.
260 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
261 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
262 mangle_sections(ibfd, obfd);
271 int size = strlen(a) + strlen(b) + strlen(c);
272 char *r = xmalloc(size+1);
280 copy_archive(ibfd, obfd)
284 bfd **ptr = &obfd->archive_head;
286 /* Read each archive element in turn from the input, copy the
287 contents to a temp file, and keep the temp file handle */
288 char *dir = cat("./#",make_tempname(""),"cd");
290 /* Make a temp directory to hold the contents */
292 obfd->has_armap = ibfd->has_armap;
293 this_element = bfd_openr_next_archived_file(ibfd, NULL);
294 ibfd->archive_head = this_element;
295 while (this_element != (bfd *)NULL) {
297 /* Create an output file for this member */
298 char *output_name = cat(dir, "/",this_element->filename);
299 bfd *output_bfd = bfd_openw(output_name, output_target);
301 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
302 bfd_fatal(output_filename);
304 if (output_bfd == (bfd *)NULL) {
305 bfd_fatal(output_name);
307 if (bfd_check_format(this_element, bfd_object) == true) {
308 copy_object(this_element, output_bfd);
311 bfd_close(output_bfd);
312 /* Now open the newly output file and attatch to our list */
313 output_bfd = bfd_openr(output_name, output_target);
314 /* Mark it for deletion */
318 ptr = &output_bfd->next;
319 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
320 this_element = this_element->next;
325 if (!bfd_close(obfd))
326 bfd_fatal(output_filename);
328 /* Now delete all the files that we opened.
329 Construct their names again, unfortunately, but so what;
330 we're about to exit anyway. */
331 for (this_element = ibfd->archive_head;
332 this_element != (bfd *)NULL;
333 this_element = this_element->next)
335 unlink(cat(dir,"/",this_element->filename));
338 if (!bfd_close(ibfd))
339 bfd_fatal(input_filename);
345 copy_file(input_filename, output_filename)
346 char *input_filename;
347 char *output_filename;
351 ibfd = bfd_openr(input_filename, input_target);
353 bfd_fatal(input_filename);
355 if (bfd_check_format(ibfd, bfd_object)) {
356 bfd * obfd = bfd_openw(output_filename, output_target);
358 bfd_fatal(output_filename);
360 copy_object(ibfd, obfd);
362 if (ibfd->flags & EXEC_P)
363 obfd->flags |= EXEC_P;
364 if (!bfd_close(obfd))
365 bfd_fatal(output_filename);
367 if (!bfd_close(ibfd))
368 bfd_fatal(input_filename);
370 else if (bfd_check_format(ibfd, bfd_archive)) {
371 bfd * obfd = bfd_openw(output_filename, output_target);
373 bfd_fatal(output_filename);
374 copy_archive(ibfd, obfd);
380 /** Actually do the work */
382 setup_sections(ibfd, isection, obfd)
390 osection = bfd_get_section_by_name(obfd, bfd_section_name(ibfd, isection));
391 if (osection == NULL) {
392 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
393 if (osection == NULL) {
399 if (!bfd_set_section_size(obfd,
401 bfd_section_size(ibfd, isection))) {
406 if (bfd_set_section_vma(obfd,
408 bfd_section_vma(ibfd, isection))
414 if (bfd_set_section_alignment(obfd,
416 bfd_section_alignment(ibfd, isection))
422 if (!bfd_set_section_flags(obfd, osection,
423 bfd_get_section_flags(ibfd, isection))) {
432 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
434 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
435 err, bfd_errmsg(bfd_error));
437 } /* setup_sections() */
440 Copy all the section related data from an input section
443 If stripping then don't copy any relocation info
446 copy_sections(ibfd, isection, obfd)
456 osection = bfd_get_section_by_name(obfd,
457 bfd_section_name(ibfd, isection));
459 size = bfd_get_section_size_before_reloc(isection);
464 if (strip_symbols == strip_all
465 || bfd_get_reloc_upper_bound(ibfd, isection) == 0)
467 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
471 relpp = (arelent **) xmalloc(bfd_get_reloc_upper_bound(ibfd, isection));
472 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
473 bfd_set_reloc(obfd, osection, relpp, relcount);
476 isection->_cooked_size = isection->_raw_size;
477 isection->reloc_done =true;
480 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
482 PTR memhunk = (PTR) xmalloc((unsigned)size);
484 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
485 bfd_fatal(bfd_get_filename(ibfd));
487 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
488 bfd_fatal(bfd_get_filename(obfd));
500 int c; /* sez which option char */
501 int option_index = 0; /* used by getopt and ignored by us */
503 program_name = argv[0];
505 strip_symbols = strip_undef; /* default is to strip everything. */
506 discard_locals = locals_undef;
511 i = strlen (program_name);
512 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
517 while ((c = getopt_long(argc, argv, "I:O:F:sSgxXVv",
518 strip_options, &option_index))
522 input_target = optarg;
524 output_target = optarg;
527 input_target = output_target = optarg;
531 strip_symbols = strip_all;
535 strip_symbols = strip_debug;
538 discard_locals = locals_all;
541 discard_locals = locals_start_L;
551 break; /* we've been given a long option */
559 /* Default is to strip all symbols. */
560 if (strip_symbols == strip_undef && discard_locals == locals_undef)
561 strip_symbols = strip_all;
563 if (output_target == (char *) NULL)
564 output_target = input_target;
567 printf ("%s version %s\n", program_name, program_version);
570 for ( ; i < argc; i++) {
571 char *tmpname = make_tempname(argv[i]);
572 copy_file(argv[i], tmpname);
573 rename(tmpname, argv[i]);
578 /* Invoked as "copy", not "strip" */
580 while ((c = getopt_long(argc, argv, "I:s:O:d:F:b:SgxXVv",
581 strip_options, &option_index))
585 case 's': /* "source" - 'I' is preferred */
586 input_target = optarg;
588 case 'd': /* "destination" - 'O' is preferred */
589 output_target = optarg;
592 case 'b': /* "both" - 'F' is preferred */
593 input_target = output_target = optarg;
597 strip_symbols = strip_all;
600 strip_symbols = strip_debug;
603 discard_locals = locals_all;
606 discard_locals = locals_start_L;
616 break; /* we've been given a long option */
623 printf ("%s version %s\n", program_name, program_version);
631 input_filename = argv[optind];
632 if (optind + 1 < argc)
633 output_filename = argv[optind+1];
635 /* Default is to strip no symbols. */
636 if (strip_symbols == strip_undef && discard_locals == locals_undef)
637 strip_symbols = strip_none;
639 if (input_filename == (char *) NULL)
642 if (output_target == (char *) NULL)
643 output_target = input_target;
645 /* If there is no destination file then create a temp and rename
646 the result into the input */
648 if (output_filename == (char *)NULL) {
649 char * tmpname = make_tempname(input_filename);
650 copy_file(input_filename, tmpname);
651 output_filename = input_filename;
652 rename(tmpname, input_filename);
655 copy_file(input_filename, output_filename);