1 /* objcopy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991, 92, 93, 94 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 static void setup_section ();
26 static void copy_section ();
28 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
30 static asymbol
**isympp
= NULL
; /* Input symbols */
31 static asymbol
**osympp
= NULL
; /* Output symbols that survive stripping */
33 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
34 static int copy_byte
= -1;
35 static int interleave
= 4;
37 static boolean verbose
; /* Print file and target names. */
38 static int status
= 0; /* Exit status. */
43 strip_none
, /* don't strip */
44 strip_debug
, /* strip all debugger symbols */
45 strip_all
/* strip all symbols */
48 /* Which symbols to remove. */
49 static enum strip_action strip_symbols
;
54 locals_start_L
, /* discard locals starting with L */
55 locals_all
/* discard all locals */
58 /* Which local symbols to remove. Overrides strip_all. */
59 static enum locals_action discard_locals
;
61 /* Options to handle if running as "strip". */
63 static struct option strip_options
[] =
65 {"discard-all", no_argument
, 0, 'x'},
66 {"discard-locals", no_argument
, 0, 'X'},
67 {"format", required_argument
, 0, 'F'}, /* Obsolete */
68 {"help", no_argument
, 0, 'h'},
69 {"input-format", required_argument
, 0, 'I'}, /* Obsolete */
70 {"input-target", required_argument
, 0, 'I'},
71 {"output-format", required_argument
, 0, 'O'}, /* Obsolete */
72 {"output-target", required_argument
, 0, 'O'},
73 {"strip-all", no_argument
, 0, 's'},
74 {"strip-debug", no_argument
, 0, 'S'},
75 {"target", required_argument
, 0, 'F'},
76 {"verbose", no_argument
, 0, 'v'},
77 {"version", no_argument
, 0, 'V'},
78 {0, no_argument
, 0, 0}
81 /* Options to handle if running as "objcopy". */
83 static struct option copy_options
[] =
85 {"byte", required_argument
, 0, 'b'},
86 {"discard-all", no_argument
, 0, 'x'},
87 {"discard-locals", no_argument
, 0, 'X'},
88 {"format", required_argument
, 0, 'F'}, /* Obsolete */
89 {"help", no_argument
, 0, 'h'},
90 {"input-format", required_argument
, 0, 'I'}, /* Obsolete */
91 {"input-target", required_argument
, 0, 'I'},
92 {"interleave", required_argument
, 0, 'i'},
93 {"output-format", required_argument
, 0, 'O'}, /* Obsolete */
94 {"output-target", required_argument
, 0, 'O'},
95 {"strip-all", no_argument
, 0, 'S'},
96 {"strip-debug", no_argument
, 0, 'g'},
97 {"target", required_argument
, 0, 'F'},
98 {"verbose", no_argument
, 0, 'v'},
99 {"version", no_argument
, 0, 'V'},
100 {0, no_argument
, 0, 0}
104 extern char *program_name
;
105 extern char *program_version
;
107 /* This flag distinguishes between strip and objcopy:
108 1 means this is 'strip'; 0 means this is 'objcopy'.
109 -1 means if we should use argv[0] to decide. */
114 copy_usage (stream
, status
)
119 Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
120 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
121 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
122 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
123 [--verbose] [--version] [--help] in-file [out-file]\n",
129 strip_usage (stream
, status
)
134 Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
135 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
136 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
137 [--verbose] [--version] [--help] file...\n",
143 /* Return the name of a temporary file in the same directory as FILENAME. */
146 make_tempname (filename
)
149 static char template[] = "stXXXXXX";
151 char *slash
= strrchr (filename
, '/');
153 if (slash
!= (char *) NULL
)
156 tmpname
= xmalloc (strlen (filename
) + sizeof (template) + 1);
157 strcpy (tmpname
, filename
);
158 strcat (tmpname
, "/");
159 strcat (tmpname
, template);
165 tmpname
= xmalloc (sizeof (template));
166 strcpy (tmpname
, template);
172 /* Choose which symbol entries to copy; put the result in OSYMS.
173 We don't copy in place, because that confuses the relocs.
174 Return the number of symbols to print. */
177 filter_symbols (abfd
, osyms
, isyms
, symcount
)
179 asymbol
**osyms
, **isyms
;
180 unsigned long symcount
;
182 register asymbol
**from
= isyms
, **to
= osyms
;
183 char locals_prefix
= bfd_get_symbol_leading_char (abfd
) == '_' ? 'L' : '.';
184 unsigned int src_count
= 0, dst_count
= 0;
186 for (; src_count
< symcount
; src_count
++)
188 asymbol
*sym
= from
[src_count
];
189 flagword flags
= sym
->flags
;
192 if ((flags
& BSF_GLOBAL
) /* Keep if external. */
193 || bfd_get_section (sym
) == &bfd_und_section
194 || bfd_is_com_section (bfd_get_section (sym
)))
196 else if ((flags
& BSF_DEBUGGING
) != 0) /* Debugging symbol. */
197 keep
= strip_symbols
!= strip_debug
;
198 else /* Local symbol. */
199 keep
= discard_locals
!= locals_all
200 && (discard_locals
!= locals_start_L
||
201 bfd_asymbol_name (sym
)[0] != locals_prefix
);
203 to
[dst_count
++] = sym
;
209 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
213 filter_bytes (memhunk
, size
)
217 char *from
= memhunk
+ copy_byte
, *to
= memhunk
, *end
= memhunk
+ *size
;
219 for (; from
< end
; from
+= interleave
)
224 /* Copy object file IBFD onto OBFD. */
227 copy_object (ibfd
, obfd
)
231 unsigned int symcount
;
233 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
235 nonfatal (bfd_get_filename (obfd
));
239 printf ("copy from %s(%s) to %s(%s)\n",
240 bfd_get_filename(ibfd
), bfd_get_target(ibfd
),
241 bfd_get_filename(obfd
), bfd_get_target(obfd
));
243 if (!bfd_set_start_address (obfd
, bfd_get_start_address (ibfd
))
244 || !bfd_set_file_flags (obfd
,
245 (bfd_get_file_flags (ibfd
)
246 & bfd_applicable_file_flags (obfd
))))
248 nonfatal (bfd_get_filename (ibfd
));
251 /* Copy architecture of input file to output file */
252 if (!bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
253 bfd_get_mach (ibfd
)))
255 fprintf (stderr
, "Output file cannot represent architecture %s\n",
256 bfd_printable_arch_mach (bfd_get_arch (ibfd
),
257 bfd_get_mach (ibfd
)));
259 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
261 nonfatal (bfd_get_filename(ibfd
));
266 if (osympp
!= isympp
)
269 if (strip_symbols
== strip_all
&& discard_locals
== locals_undef
)
271 osympp
= isympp
= NULL
;
276 osympp
= isympp
= (asymbol
**) xmalloc (get_symtab_upper_bound (ibfd
));
277 symcount
= bfd_canonicalize_symtab (ibfd
, isympp
);
279 if (strip_symbols
== strip_debug
|| discard_locals
!= locals_undef
)
281 osympp
= (asymbol
**) xmalloc (symcount
* sizeof (asymbol
*));
282 symcount
= filter_symbols (ibfd
, osympp
, isympp
, symcount
);
286 bfd_set_symtab (obfd
, osympp
, symcount
);
288 /* bfd mandates that all output sections be created and sizes set before
289 any output is done. Thus, we traverse all sections multiple times. */
290 bfd_map_over_sections (ibfd
, setup_section
, (void *) obfd
);
291 bfd_map_over_sections (ibfd
, copy_section
, (void *) obfd
);
300 size_t size
= strlen (a
) + strlen (b
) + strlen (c
);
301 char *r
= xmalloc (size
+ 1);
309 /* Read each archive element in turn from IBFD, copy the
310 contents to temp file, and keep the temp file handle. */
313 copy_archive (ibfd
, obfd
, output_target
)
318 bfd
**ptr
= &obfd
->archive_head
;
320 char *dir
= cat ("./#", make_tempname (""), "cd");
322 /* Make a temp directory to hold the contents. */
324 obfd
->has_armap
= ibfd
->has_armap
;
326 this_element
= bfd_openr_next_archived_file (ibfd
, NULL
);
327 ibfd
->archive_head
= this_element
;
328 while (this_element
!= (bfd
*) NULL
)
330 /* Create an output file for this member. */
331 char *output_name
= cat (dir
, "/", bfd_get_filename(this_element
));
332 bfd
*output_bfd
= bfd_openw (output_name
, output_target
);
334 if (output_bfd
== (bfd
*) NULL
)
336 nonfatal (output_name
);
338 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
340 nonfatal (bfd_get_filename (obfd
));
343 if (bfd_check_format (this_element
, bfd_object
) == true)
345 copy_object (this_element
, output_bfd
);
348 bfd_close (output_bfd
);
349 /* Open the newly output file and attatch to our list. */
350 output_bfd
= bfd_openr (output_name
, output_target
);
352 /* Mark it for deletion. */
354 ptr
= &output_bfd
->next
;
355 this_element
->next
= bfd_openr_next_archived_file (ibfd
, this_element
);
356 this_element
= this_element
->next
;
360 if (!bfd_close (obfd
))
362 nonfatal (bfd_get_filename (obfd
));
365 /* Delete all the files that we opened.
366 Construct their names again, unfortunately, but
367 we're about to exit anyway. */
368 for (this_element
= ibfd
->archive_head
;
369 this_element
!= (bfd
*) NULL
;
370 this_element
= this_element
->next
)
372 unlink (cat (dir
, "/", bfd_get_filename (this_element
)));
375 if (!bfd_close (ibfd
))
377 nonfatal (bfd_get_filename (ibfd
));
381 /* The top-level control. */
384 copy_file (input_filename
, output_filename
, input_target
, output_target
)
385 char *input_filename
;
386 char *output_filename
;
393 /* To allow us to do "strip *" without dying on the first
394 non-object file, failures are nonfatal. */
396 ibfd
= bfd_openr (input_filename
, input_target
);
399 nonfatal (input_filename
);
402 if (bfd_check_format (ibfd
, bfd_archive
))
404 bfd
*obfd
= bfd_openw (output_filename
, output_target
);
407 nonfatal (output_filename
);
409 copy_archive (ibfd
, obfd
, output_target
);
411 else if (bfd_check_format_matches (ibfd
, bfd_object
, &matching
))
413 bfd
*obfd
= bfd_openw (output_filename
, output_target
);
416 nonfatal (output_filename
);
419 copy_object (ibfd
, obfd
);
421 if (!bfd_close (obfd
))
423 nonfatal (output_filename
);
426 if (!bfd_close (ibfd
))
428 nonfatal (input_filename
);
433 bfd_nonfatal (input_filename
);
434 if (bfd_get_error () == bfd_error_file_ambiguously_recognized
)
436 list_matching_formats (matching
);
443 /* Create a section in OBFD with the same name and attributes
444 as ISECTION in IBFD. */
447 setup_section (ibfd
, isection
, obfd
)
455 if ((bfd_get_section_flags (ibfd
, isection
) & SEC_DEBUGGING
) != 0
456 && (strip_symbols
== strip_debug
457 || strip_symbols
== strip_all
458 || discard_locals
== locals_all
))
461 osection
= bfd_get_section_by_name (obfd
, bfd_section_name (ibfd
, isection
));
462 if (osection
== NULL
)
464 osection
= bfd_make_section (obfd
, bfd_section_name (ibfd
, isection
));
465 if (osection
== NULL
)
472 if (!bfd_set_section_size (obfd
,
474 bfd_section_size (ibfd
, isection
)))
480 if (bfd_set_section_vma (obfd
,
482 bfd_section_vma (ibfd
, isection
))
489 if (bfd_set_section_alignment (obfd
,
491 bfd_section_alignment (ibfd
, isection
))
498 if (!bfd_set_section_flags (obfd
, osection
,
499 bfd_get_section_flags (ibfd
, isection
)))
505 /* This used to be mangle_section; we do here to avoid using
506 bfd_get_section_by_name since some formats allow multiple
507 sections with the same name. */
508 isection
->output_section
= osection
;
509 isection
->output_offset
= 0;
515 fprintf (stderr
, "%s: %s: section `%s': error in %s: %s\n",
517 bfd_get_filename (ibfd
), bfd_section_name (ibfd
, isection
),
518 err
, bfd_errmsg (bfd_get_error ()));
522 /* Copy the data of input section ISECTION of IBFD
523 to an output section with the same name in OBFD.
524 If stripping then don't copy any relocation info. */
527 copy_section (ibfd
, isection
, obfd
)
537 if ((bfd_get_section_flags (ibfd
, isection
) & SEC_DEBUGGING
) != 0
538 && (strip_symbols
== strip_debug
539 || strip_symbols
== strip_all
540 || discard_locals
== locals_all
))
545 osection
= bfd_get_section_by_name (obfd
,
546 bfd_section_name (ibfd
, isection
));
548 size
= bfd_get_section_size_before_reloc (isection
);
553 if (strip_symbols
== strip_all
554 || bfd_get_reloc_upper_bound (ibfd
, isection
) == 0)
556 bfd_set_reloc (obfd
, osection
, (arelent
**) NULL
, 0);
560 relpp
= (arelent
**) xmalloc (bfd_get_reloc_upper_bound (ibfd
, isection
));
561 relcount
= bfd_canonicalize_reloc (ibfd
, isection
, relpp
, isympp
);
562 bfd_set_reloc (obfd
, osection
, relpp
, relcount
);
565 isection
->_cooked_size
= isection
->_raw_size
;
566 isection
->reloc_done
= true;
568 if (bfd_get_section_flags (ibfd
, isection
) & SEC_HAS_CONTENTS
)
570 PTR memhunk
= (PTR
) xmalloc ((unsigned) size
);
572 if (!bfd_get_section_contents (ibfd
, isection
, memhunk
, (file_ptr
) 0,
575 nonfatal (bfd_get_filename (ibfd
));
579 filter_bytes (memhunk
, &size
);
581 if (!bfd_set_section_contents (obfd
, osection
, memhunk
, (file_ptr
) 0,
584 nonfatal (bfd_get_filename (obfd
));
590 /* The number of bytes to copy at once. */
591 #define COPY_BUF 8192
593 /* Copy file FROM to file TO, performing no translations.
594 Return 0 if ok, -1 if error. */
597 simple_copy (from
, to
)
600 int fromfd
, tofd
, nread
;
603 fromfd
= open (from
, O_RDONLY
);
606 tofd
= open (to
, O_WRONLY
| O_CREAT
| O_TRUNC
);
612 while ((nread
= read (fromfd
, buf
, sizeof buf
)) > 0)
614 if (write (tofd
, buf
, nread
) != nread
)
630 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
637 /* Rename FROM to TO, copying if TO is a link.
638 Assumes that TO already exists, because FROM is a temp file.
639 Return 0 if ok, -1 if error. */
642 smart_rename (from
, to
)
651 /* Use rename only if TO is not a symbolic link and has
652 only one hard link. */
653 if (!S_ISLNK (s
.st_mode
) && s
.st_nlink
== 1)
655 ret
= rename (from
, to
);
658 /* Try to preserve the permission bits and ownership of TO. */
659 chmod (to
, s
.st_mode
& 07777);
660 chown (to
, s
.st_uid
, s
.st_gid
);
665 ret
= simple_copy (from
, to
);
673 strip_main (argc
, argv
)
677 char *input_target
= NULL
, *output_target
= NULL
;
678 boolean show_version
= false;
681 while ((c
= getopt_long (argc
, argv
, "I:O:F:sSgxXVv",
682 strip_options
, (int *) 0)) != EOF
)
687 input_target
= optarg
;
690 output_target
= optarg
;
693 input_target
= output_target
= optarg
;
696 strip_symbols
= strip_all
;
700 strip_symbols
= strip_debug
;
703 discard_locals
= locals_all
;
706 discard_locals
= locals_start_L
;
715 break; /* we've been given a long option */
717 strip_usage (stdout
, 0);
719 strip_usage (stderr
, 1);
725 printf ("GNU %s version %s\n", program_name
, program_version
);
729 /* Default is to strip all symbols. */
730 if (strip_symbols
== strip_undef
&& discard_locals
== locals_undef
)
731 strip_symbols
= strip_all
;
733 if (output_target
== (char *) NULL
)
734 output_target
= input_target
;
738 strip_usage (stderr
, 1);
740 for (; i
< argc
; i
++)
742 int hold_status
= status
;
744 char *tmpname
= make_tempname (argv
[i
]);
746 copy_file (argv
[i
], tmpname
, input_target
, output_target
);
749 smart_rename (tmpname
, argv
[i
]);
750 status
= hold_status
;
761 copy_main (argc
, argv
)
765 char *input_filename
, *output_filename
;
766 char *input_target
= NULL
, *output_target
= NULL
;
767 boolean show_version
= false;
770 while ((c
= getopt_long (argc
, argv
, "b:i:I:s:O:d:F:SgxXVv",
771 copy_options
, (int *) 0)) != EOF
)
776 copy_byte
= atoi(optarg
);
779 fprintf (stderr
, "%s: byte number must be non-negative\n",
785 interleave
= atoi(optarg
);
788 fprintf(stderr
, "%s: interleave must be positive\n",
794 case 's': /* "source" - 'I' is preferred */
795 input_target
= optarg
;
798 case 'd': /* "destination" - 'O' is preferred */
799 output_target
= optarg
;
802 input_target
= output_target
= optarg
;
805 strip_symbols
= strip_all
;
808 strip_symbols
= strip_debug
;
811 discard_locals
= locals_all
;
814 discard_locals
= locals_start_L
;
823 break; /* we've been given a long option */
825 copy_usage (stdout
, 0);
827 copy_usage (stderr
, 1);
833 printf ("GNU %s version %s\n", program_name
, program_version
);
837 if (copy_byte
>= interleave
)
839 fprintf (stderr
, "%s: byte number must be less than interleave\n",
844 if (optind
== argc
|| optind
+ 2 < argc
)
845 copy_usage (stderr
, 1);
847 input_filename
= argv
[optind
];
848 if (optind
+ 1 < argc
)
849 output_filename
= argv
[optind
+ 1];
851 /* Default is to strip no symbols. */
852 if (strip_symbols
== strip_undef
&& discard_locals
== locals_undef
)
853 strip_symbols
= strip_none
;
855 if (output_target
== (char *) NULL
)
856 output_target
= input_target
;
858 /* If there is no destination file then create a temp and rename
859 the result into the input. */
861 if (output_filename
== (char *) NULL
)
863 char *tmpname
= make_tempname (input_filename
);
864 copy_file (input_filename
, tmpname
, input_target
, output_target
);
866 smart_rename (tmpname
, input_filename
);
872 copy_file (input_filename
, output_filename
, input_target
, output_target
);
883 program_name
= argv
[0];
884 xmalloc_set_program_name (program_name
);
885 strip_symbols
= strip_undef
;
886 discard_locals
= locals_undef
;
892 int i
= strlen (program_name
);
893 is_strip
= (i
>= 5 && strcmp (program_name
+ i
- 5, "strip"));
897 strip_main (argc
, argv
);
899 copy_main (argc
, argv
);