Add hyphens in usage messages.
[deliverable/binutils-gdb.git] / binutils / copy.c
CommitLineData
d8474a9b
PB
1/* copy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991 Free Software Foundation, Inc.
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
c074abee 20#include "bfd.h"
2a5f387b 21#include "sysdep.h"
5a77e916 22#include "bucomm.h"
cc8787ef 23#include <getopt.h>
fc5d6074 24
c074abee
DHW
25asymbol **sympp;
26char *input_target = NULL;
27char *output_target = NULL;
28char *input_filename = NULL;
29char *output_filename = NULL;
30
31
32static void setup_sections();
33static void copy_sections();
c074abee
DHW
34static boolean verbose;
35
782d7963
PB
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. */
39extern int is_strip;
40
cc8787ef
PB
41int show_version = 0;
42
43enum 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. */
52enum strip_action strip_symbols;
53
54enum 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. */
62enum locals_action discard_locals;
63
64/* Options to handle if running as "strip". */
65
66struct 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'},
75
76 {"version", no_argument, 0, 'V'},
77 {"verbose", no_argument, 0, 'v'},
78 {0, no_argument, 0, 0}
79};
80
81/* Options to handle if running as "copy". */
82
83struct 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'},
92
93 {"version", no_argument, 0, 'V'},
94 {"verbose", no_argument, 0, 'v'},
95 {0, no_argument, 0, 0}
96};
97
c074abee
DHW
98/* IMPORTS */
99extern char *program_name;
5c670bc1 100extern char *program_version;
5a77e916 101
c074abee
DHW
102
103static
104void
cc8787ef 105copy_usage()
c074abee 106{
d2442698
DM
107 fprintf(stderr, "copy %s\n\
108Usage: %s [-vVSgxX] [-I format] [-O format] [-F format]\n\
109 [--format=format] [--target=format] [--input-format=format]\n\
110 [--output-format=format] [--strip-all] [--strip-debug]\n\
111 [--discard-all] [--discard-locals] [--verbose] [--version]\n\
3602ba81 112 in-file [out-file]\n",
d2442698 113 program_version, program_name);
c074abee
DHW
114 exit(1);
115}
116
a51d4b41
PB
117static
118void
119strip_usage()
120{
d2442698
DM
121 fprintf(stderr, "strip %s\n\
122Usage: %s [-vVsSgxX] [-I format] [-O format] [-F format]\n\
123 [--format=format] [--target=format] [--input-format=format]\n\
124 [--output-format=format] [--strip-all] [--strip-debug]\n\
125 [--discard-all] [--discard-locals] [--verbose] [--version] file...\n",
126 program_version, program_name);
a51d4b41
PB
127 exit(1);
128}
129
c074abee
DHW
130
131/* Create a temp file in the same directory as supplied */
132static
133char *
134make_tempname(filename)
135char *filename;
136{
137 static char template[] = "stXXXXXX";
138 char *tmpname;
139 char * slash = strrchr( filename, '/' );
140 if (slash != (char *)NULL){
141 *slash = 0;
142 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
143 strcpy(tmpname, filename);
144 strcat(tmpname, "/" );
145 strcat(tmpname, template);
146 mktemp(tmpname );
147 *slash = '/';
148 } else {
149 tmpname = xmalloc(sizeof(template));
150 strcpy(tmpname, template);
151 mktemp(tmpname);
152 }
153 return tmpname;
154}
155
156/*
157 All the symbols have been read in and point to their owning input section.
158 They have been relocated to that they are all relative to the base of
159 their owning section. On the way out, all the symbols will be relocated to
160 their new location in the output file, through some complex sums.
161
162*/
163static void
164mangle_sections(ibfd, obfd)
165 bfd *ibfd;
166 bfd *obfd;
167{
168 asection *current = ibfd->sections;
169 for (; current != NULL; current = current->next) {
170 current->output_section = bfd_get_section_by_name(obfd, current->name);
171 current->output_offset = 0;
172 }
173}
174
cc8787ef
PB
175/* Choose which symbol entries to copy;
176 compact them downward to get rid of the rest.
177 Return the number of symbols to be printed. */
178static unsigned int
179filter_symbols (abfd, syms, symcount)
180 bfd *abfd;
181 asymbol **syms;
182 unsigned long symcount;
183{
184 asymbol **from, **to;
185 unsigned int dst_count = 0;
186 asymbol *sym;
187 char locals_prefix = bfd_get_symbol_leading_char(abfd) == '_' ? 'L' : '.';
188
189 unsigned int src_count;
190 for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
191 int keep = 0;
192
193 flagword flags = (from[src_count])->flags;
194 sym = from[src_count];
195 if ((flags & BSF_GLOBAL) /* Keep if external */
196 || (sym->section == &bfd_und_section)
a625bbb1 197 || (bfd_is_com_section (sym->section)))
cc8787ef
PB
198 keep = 1;
199 else if ((flags & BSF_DEBUGGING) != 0) /* debugging symbol */
200 keep = strip_symbols != strip_debug;
201 else /* local symbol */
202 keep = (discard_locals != locals_all)
203 && !(discard_locals == locals_start_L &&
204 sym->name[0] == locals_prefix);
205
206
207 if (keep) {
208 to[dst_count++] = from[src_count];
209 }
210 }
211
212 return dst_count;
213}
214
c074abee
DHW
215static
216void
217copy_object(ibfd, obfd)
218bfd *ibfd;
219bfd *obfd;
220{
221
222 unsigned int symcount;
223
224
225 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
226 bfd_fatal(output_filename);
227
228
229 if (verbose)
230 printf("copy from %s(%s) to %s(%s)\n",
231 ibfd->filename, ibfd->xvec->name,
232 obfd->filename, obfd->xvec->name);
233
23565c68
SC
234 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
235 ||
c074abee 236 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
23565c68
SC
237 (HAS_LINENO | HAS_DEBUG |
238 HAS_RELOC | HAS_SYMS | D_PAGED |
239 HAS_LOCALS))) == false)) {
240 bfd_fatal(bfd_get_filename(ibfd));
241 }
c074abee
DHW
242
243 /* Copy architecture of input file to output file */
21214e8e
SC
244 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
245 bfd_get_mach(ibfd))) {
c074abee 246 fprintf(stderr, "Output file cannot represent architecture %s\n",
21214e8e
SC
247 bfd_printable_arch_mach(bfd_get_arch(ibfd),
248 bfd_get_mach(ibfd)));
c074abee
DHW
249 }
250 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
251 {
252 bfd_fatal(ibfd->filename);
253 }
254
255 sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
256 symcount = bfd_canonicalize_symtab(ibfd, sympp);
257
cc8787ef
PB
258 if (strip_symbols == strip_debug || discard_locals != locals_undef)
259 symcount = filter_symbols (ibfd, sympp, symcount);
260
261
262 bfd_set_symtab(obfd, sympp,
263 strip_symbols == strip_all ? 0 : symcount);
c074abee
DHW
264
265 /*
266 bfd mandates that all output sections be created and sizes set before
267 any output is done. Thus, we traverse all sections twice.
268 */
269 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
270 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
271 mangle_sections(ibfd, obfd);
272}
273static
274char *
275cat(a,b,c)
276char *a;
277char *b;
278char *c;
279{
280 int size = strlen(a) + strlen(b) + strlen(c);
281 char *r = xmalloc(size+1);
282 strcpy(r,a);
283 strcat(r,b);
284 strcat(r,c);
285 return r;
286}
287
288static void
289copy_archive(ibfd, obfd)
290bfd *ibfd;
291bfd *obfd;
292{
1417a2cd 293 bfd **ptr = &obfd->archive_head;
c074abee
DHW
294 bfd *this_element;
295 /* Read each archive element in turn from the input, copy the
296 contents to a temp file, and keep the temp file handle */
ad19c0a2 297 char *dir = cat("./#",make_tempname(""),"cd");
c074abee
DHW
298
299 /* Make a temp directory to hold the contents */
300 mkdir(dir,0777);
301 obfd->has_armap = ibfd->has_armap;
302 this_element = bfd_openr_next_archived_file(ibfd, NULL);
ad19c0a2 303 ibfd->archive_head = this_element;
c074abee
DHW
304 while (this_element != (bfd *)NULL) {
305
306 /* Create an output file for this member */
307 char *output_name = cat(dir, "/",this_element->filename);
308 bfd *output_bfd = bfd_openw(output_name, output_target);
ad19c0a2 309
c074abee
DHW
310 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
311 bfd_fatal(output_filename);
312
313 if (output_bfd == (bfd *)NULL) {
314 bfd_fatal(output_name);
315 }
316 if (bfd_check_format(this_element, bfd_object) == true) {
317 copy_object(this_element, output_bfd);
318 }
319
320 bfd_close(output_bfd);
321 /* Now open the newly output file and attatch to our list */
322 output_bfd = bfd_openr(output_name, output_target);
323 /* Mark it for deletion */
324
325 *ptr = output_bfd;
326
1417a2cd 327 ptr = &output_bfd->next;
ad19c0a2
DHW
328 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
329 this_element = this_element->next;
c074abee
DHW
330
331 }
332 *ptr = (bfd *)NULL;
333
334 if (!bfd_close(obfd))
335 bfd_fatal(output_filename);
336
ad19c0a2
DHW
337 /* Now delete all the files that we opened.
338 Construct their names again, unfortunately, but so what;
339 we're about to exit anyway. */
c074abee
DHW
340 for (this_element = ibfd->archive_head;
341 this_element != (bfd *)NULL;
342 this_element = this_element->next)
343 {
344 unlink(cat(dir,"/",this_element->filename));
345 }
ad19c0a2 346 rmdir(dir);
c074abee
DHW
347 if (!bfd_close(ibfd))
348 bfd_fatal(input_filename);
349
350}
351
352static
617cd571 353void
c074abee
DHW
354copy_file(input_filename, output_filename)
355 char *input_filename;
356 char *output_filename;
357{
617cd571 358 bfd *ibfd;
c074abee 359
617cd571
SC
360 ibfd = bfd_openr(input_filename, input_target);
361 if (ibfd == NULL)
362 bfd_fatal(input_filename);
c074abee 363
617cd571
SC
364 if (bfd_check_format(ibfd, bfd_object)) {
365 bfd * obfd = bfd_openw(output_filename, output_target);
366 if (obfd == NULL)
367 bfd_fatal(output_filename);
c074abee 368
617cd571 369 copy_object(ibfd, obfd);
c074abee 370
782d7963
PB
371 if (ibfd->flags & EXEC_P)
372 obfd->flags |= EXEC_P;
617cd571
SC
373 if (!bfd_close(obfd))
374 bfd_fatal(output_filename);
c074abee 375
617cd571
SC
376 if (!bfd_close(ibfd))
377 bfd_fatal(input_filename);
378 }
379 else if (bfd_check_format(ibfd, bfd_archive)) {
380 bfd * obfd = bfd_openw(output_filename, output_target);
381 if (obfd == NULL)
382 bfd_fatal(output_filename);
383 copy_archive(ibfd, obfd);
384 }
c074abee
DHW
385}
386
387
388
389/** Actually do the work */
390static void
391setup_sections(ibfd, isection, obfd)
392 bfd *ibfd;
393 sec_ptr isection;
394 bfd *obfd;
395{
396 sec_ptr osection;
397 char *err;
782d7963
PB
398
399 osection = bfd_get_section_by_name(obfd, bfd_section_name(ibfd, isection));
c074abee 400 if (osection == NULL) {
782d7963
PB
401 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
402 if (osection == NULL) {
403 err = "making";
404 goto loser;
405 }
c074abee
DHW
406 }
407
408 if (!bfd_set_section_size(obfd,
409 osection,
410 bfd_section_size(ibfd, isection))) {
411 err = "size";
412 goto loser;
413 }
414
415 if (bfd_set_section_vma(obfd,
416 osection,
417 bfd_section_vma(ibfd, isection))
418 == false) {
419 err = "vma";
420 goto loser;
421 } /* on error */
422
423 if (bfd_set_section_alignment(obfd,
424 osection,
425 bfd_section_alignment(ibfd, isection))
426 == false) {
427 err = "alignment";
428 goto loser;
429 } /* on error */
430
431 if (!bfd_set_section_flags(obfd, osection,
432 bfd_get_section_flags(ibfd, isection))) {
433 err = "flags";
434 goto loser;
435 }
436
437 /* All went well */
438 return;
439
440loser:
441 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
442 program_name,
443 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
444 err, bfd_errmsg(bfd_error));
445 exit(1);
446} /* setup_sections() */
447
b473cf19
SC
448/*
449Copy all the section related data from an input section
450to an output section
451
452If stripping then don't copy any relocation info
453*/
c074abee
DHW
454static void
455copy_sections(ibfd, isection, obfd)
456 bfd *ibfd;
457 sec_ptr isection;
458 bfd *obfd;
459{
c074abee 460
b473cf19
SC
461 arelent **relpp;
462 int relcount;
463 sec_ptr osection;
fc5d6074 464 bfd_size_type size;
b473cf19
SC
465 osection = bfd_get_section_by_name(obfd,
466 bfd_section_name(ibfd, isection));
467
d20f480f 468 size = bfd_get_section_size_before_reloc(isection);
b473cf19
SC
469
470 if (size == 0)
471 return;
472
cc8787ef
PB
473 if (strip_symbols == strip_all
474 || bfd_get_reloc_upper_bound(ibfd, isection) == 0)
b473cf19
SC
475 {
476 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
477 }
478 else
479 {
5a77e916 480 relpp = (arelent **) xmalloc(bfd_get_reloc_upper_bound(ibfd, isection));
b473cf19
SC
481 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
482 bfd_set_reloc(obfd, osection, relpp, relcount);
483 }
c074abee 484
d20f480f
SC
485 isection->_cooked_size = isection->_raw_size;
486 isection->reloc_done =true;
487
c074abee 488
b473cf19
SC
489 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
490 {
fc5d6074 491 PTR memhunk = (PTR) xmalloc((unsigned)size);
c074abee 492
fc5d6074 493 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
b473cf19 494 bfd_fatal(bfd_get_filename(ibfd));
c074abee 495
fc5d6074 496 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
b473cf19
SC
497 bfd_fatal(bfd_get_filename(obfd));
498 free(memhunk);
c074abee 499 }
b473cf19
SC
500
501
c074abee
DHW
502}
503int
504main(argc, argv)
505 int argc;
506 char *argv[];
507{
617cd571 508 int i;
cc8787ef 509 int c; /* sez which option char */
cc8787ef 510
617cd571
SC
511 program_name = argv[0];
512
cc8787ef
PB
513 strip_symbols = strip_undef; /* default is to strip everything. */
514 discard_locals = locals_undef;
515
21214e8e
SC
516 bfd_init();
517
782d7963
PB
518 if (is_strip < 0) {
519 i = strlen (program_name);
520 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
617cd571
SC
521 }
522
cc8787ef
PB
523 if (is_strip) {
524
525 while ((c = getopt_long(argc, argv, "I:O:F:sSgxXVv",
d2442698 526 strip_options, (int *) 0))
cc8787ef
PB
527 != EOF) {
528 switch (c) {
529 case 'I':
530 input_target = optarg;
531 case 'O':
532 output_target = optarg;
533 break;
534 case 'F':
535 input_target = output_target = optarg;
536 break;
537
538 case 's':
539 strip_symbols = strip_all;
540 break;
541 case 'S':
542 case 'g':
543 strip_symbols = strip_debug;
544 break;
545 case 'x':
546 discard_locals = locals_all;
547 break;
548 case 'X':
549 discard_locals = locals_start_L;
a51d4b41
PB
550 break;
551 case 'v':
552 verbose = true;
553 show_version = true;
554 break;
cc8787ef
PB
555 case 'V':
556 show_version = true;
7c926404 557 break;
cc8787ef
PB
558 case 0:
559 break; /* we've been given a long option */
a51d4b41 560 default:
cc8787ef 561 strip_usage ();
a51d4b41 562 }
cc8787ef
PB
563 }
564
565 i = optind;
566
567 /* Default is to strip all symbols. */
568 if (strip_symbols == strip_undef && discard_locals == locals_undef)
569 strip_symbols = strip_all;
570
571 if (output_target == (char *) NULL)
572 output_target = input_target;
573
a51d4b41 574 if (show_version)
cc8787ef
PB
575 printf ("%s version %s\n", program_name, program_version);
576 else if (i == argc)
577 strip_usage();
a51d4b41
PB
578 for ( ; i < argc; i++) {
579 char *tmpname = make_tempname(argv[i]);
580 copy_file(argv[i], tmpname);
581 rename(tmpname, argv[i]);
582 }
583 return 0;
584 }
585
cc8787ef
PB
586 /* Invoked as "copy", not "strip" */
587
588 while ((c = getopt_long(argc, argv, "I:s:O:d:F:b:SgxXVv",
d2442698 589 strip_options, (int *) 0))
cc8787ef
PB
590 != EOF) {
591 switch (c) {
592 case 'I':
593 case 's': /* "source" - 'I' is preferred */
594 input_target = optarg;
595 case 'O':
596 case 'd': /* "destination" - 'O' is preferred */
597 output_target = optarg;
5c670bc1 598 break;
cc8787ef
PB
599 case 'F':
600 case 'b': /* "both" - 'F' is preferred */
601 input_target = output_target = optarg;
617cd571 602 break;
cc8787ef 603
617cd571 604 case 'S':
cc8787ef
PB
605 strip_symbols = strip_all;
606 break;
607 case 'g':
608 strip_symbols = strip_debug;
617cd571 609 break;
cc8787ef
PB
610 case 'x':
611 discard_locals = locals_all;
612 break;
613 case 'X':
614 discard_locals = locals_start_L;
615 break;
616 case 'v':
617 verbose = true;
618 show_version = true;
617cd571 619 break;
cc8787ef
PB
620 case 'V':
621 show_version = true;
617cd571 622 break;
cc8787ef
PB
623 case 0:
624 break; /* we've been given a long option */
617cd571 625 default:
cc8787ef 626 copy_usage ();
617cd571 627 }
cc8787ef
PB
628 }
629
5c670bc1
RS
630 if (show_version)
631 printf ("%s version %s\n", program_name, program_version);
632
cc8787ef
PB
633 if (optind == argc)
634 if (show_version)
635 exit(0);
636 else
637 copy_usage();
638
639 input_filename = argv[optind];
640 if (optind + 1 < argc)
641 output_filename = argv[optind+1];
642
643 /* Default is to strip no symbols. */
644 if (strip_symbols == strip_undef && discard_locals == locals_undef)
645 strip_symbols = strip_none;
646
617cd571 647 if (input_filename == (char *) NULL)
cc8787ef 648 copy_usage();
617cd571
SC
649
650 if (output_target == (char *) NULL)
651 output_target = input_target;
c074abee 652
617cd571
SC
653 /* If there is no destination file then create a temp and rename
654 the result into the input */
c074abee 655
617cd571
SC
656 if (output_filename == (char *)NULL) {
657 char * tmpname = make_tempname(input_filename);
658 copy_file(input_filename, tmpname);
659 output_filename = input_filename;
660 rename(tmpname, input_filename);
661 }
662 else {
663 copy_file(input_filename, output_filename);
664 }
782d7963 665 return 0;
c074abee 666}
This page took 0.088452 seconds and 4 git commands to generate.