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 ();
27 static void mangle_section ();
29 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
31 static asymbol
**isympp
= NULL
; /* Input symbols */
32 static asymbol
**osympp
= NULL
; /* Output symbols that survive stripping */
34 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
35 static int copy_byte
= -1;
36 static int interleave
= 4;
38 static boolean verbose
; /* Print file and target names. */
39 static int status
= 0; /* Exit status. */
44 strip_none
, /* don't strip */
45 strip_debug
, /* strip all debugger symbols */
46 strip_all
/* strip all symbols */
49 /* Which symbols to remove. */
50 static enum strip_action strip_symbols
;
55 locals_start_L
, /* discard locals starting with L */
56 locals_all
/* discard all locals */
59 /* Which local symbols to remove. Overrides strip_all. */
60 static enum locals_action discard_locals
;
62 /* Options to handle if running as "strip". */
64 static struct option strip_options
[] =
66 {"discard-all", no_argument
, 0, 'x'},
67 {"discard-locals", no_argument
, 0, 'X'},
68 {"format", required_argument
, 0, 'F'}, /* Obsolete */
69 {"help", no_argument
, 0, 'h'},
70 {"input-format", required_argument
, 0, 'I'}, /* Obsolete */
71 {"input-target", required_argument
, 0, 'I'},
72 {"output-format", required_argument
, 0, 'O'}, /* Obsolete */
73 {"output-target", required_argument
, 0, 'O'},
74 {"strip-all", no_argument
, 0, 's'},
75 {"strip-debug", no_argument
, 0, 'S'},
76 {"target", required_argument
, 0, 'F'},
77 {"verbose", no_argument
, 0, 'v'},
78 {"version", no_argument
, 0, 'V'},
79 {0, no_argument
, 0, 0}
82 /* Options to handle if running as "objcopy". */
84 static struct option copy_options
[] =
86 {"byte", required_argument
, 0, 'b'},
87 {"discard-all", no_argument
, 0, 'x'},
88 {"discard-locals", no_argument
, 0, 'X'},
89 {"format", required_argument
, 0, 'F'}, /* Obsolete */
90 {"help", no_argument
, 0, 'h'},
91 {"input-format", required_argument
, 0, 'I'}, /* Obsolete */
92 {"input-target", required_argument
, 0, 'I'},
93 {"interleave", required_argument
, 0, 'i'},
94 {"output-format", required_argument
, 0, 'O'}, /* Obsolete */
95 {"output-target", required_argument
, 0, 'O'},
96 {"strip-all", no_argument
, 0, 'S'},
97 {"strip-debug", no_argument
, 0, 'g'},
98 {"target", required_argument
, 0, 'F'},
99 {"verbose", no_argument
, 0, 'v'},
100 {"version", no_argument
, 0, 'V'},
101 {0, no_argument
, 0, 0}
105 extern char *program_name
;
106 extern char *program_version
;
108 /* This flag distinguishes between strip and objcopy:
109 1 means this is 'strip'; 0 means this is 'objcopy'.
110 -1 means if we should use argv[0] to decide. */
115 copy_usage (stream
, status
)
120 Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
121 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
122 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
123 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
124 [--verbose] [--version] [--help] in-file [out-file]\n",
130 strip_usage (stream
, status
)
135 Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
136 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
137 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
138 [--verbose] [--version] [--help] file...\n",
144 /* Return the name of a temporary file in the same directory as FILENAME. */
147 make_tempname (filename
)
150 static char template[] = "stXXXXXX";
152 char *slash
= strrchr (filename
, '/');
154 if (slash
!= (char *) NULL
)
157 tmpname
= xmalloc (strlen (filename
) + sizeof (template) + 1);
158 strcpy (tmpname
, filename
);
159 strcat (tmpname
, "/");
160 strcat (tmpname
, template);
166 tmpname
= xmalloc (sizeof (template));
167 strcpy (tmpname
, template);
173 /* Choose which symbol entries to copy; put the result in OSYMS.
174 We don't copy in place, because that confuses the relocs.
175 Return the number of symbols to print. */
178 filter_symbols (abfd
, osyms
, isyms
, symcount
)
180 asymbol
**osyms
, **isyms
;
181 unsigned long symcount
;
183 register asymbol
**from
= isyms
, **to
= osyms
;
184 char locals_prefix
= bfd_get_symbol_leading_char (abfd
) == '_' ? 'L' : '.';
185 unsigned int src_count
= 0, dst_count
= 0;
187 for (; src_count
< symcount
; src_count
++)
189 asymbol
*sym
= from
[src_count
];
190 flagword flags
= sym
->flags
;
193 if ((flags
& BSF_GLOBAL
) /* Keep if external. */
194 || bfd_get_section (sym
) == &bfd_und_section
195 || bfd_is_com_section (bfd_get_section (sym
)))
197 else if ((flags
& BSF_DEBUGGING
) != 0) /* Debugging symbol. */
198 keep
= strip_symbols
!= strip_debug
;
199 else /* Local symbol. */
200 keep
= discard_locals
!= locals_all
201 && (discard_locals
!= locals_start_L
||
202 bfd_asymbol_name (sym
)[0] != locals_prefix
);
204 to
[dst_count
++] = sym
;
210 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
214 filter_bytes (memhunk
, size
)
218 char *from
= memhunk
+ copy_byte
, *to
= memhunk
, *end
= memhunk
+ *size
;
220 for (; from
< end
; from
+= interleave
)
225 /* Copy object file IBFD onto OBFD. */
228 copy_object (ibfd
, obfd
)
232 unsigned int symcount
;
234 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
236 nonfatal (bfd_get_filename (obfd
));
240 printf ("copy from %s(%s) to %s(%s)\n",
241 bfd_get_filename(ibfd
), bfd_get_target(ibfd
),
242 bfd_get_filename(obfd
), bfd_get_target(obfd
));
244 if (!bfd_set_start_address (obfd
, bfd_get_start_address (ibfd
))
245 || !bfd_set_file_flags (obfd
,
246 (bfd_get_file_flags (ibfd
)
247 & bfd_applicable_file_flags (obfd
))))
249 nonfatal (bfd_get_filename (ibfd
));
252 /* Copy architecture of input file to output file */
253 if (!bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
254 bfd_get_mach (ibfd
)))
256 fprintf (stderr
, "Output file cannot represent architecture %s\n",
257 bfd_printable_arch_mach (bfd_get_arch (ibfd
),
258 bfd_get_mach (ibfd
)));
260 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
262 nonfatal (bfd_get_filename(ibfd
));
267 if (osympp
!= isympp
)
270 if (strip_symbols
== strip_all
&& discard_locals
== locals_undef
)
272 osympp
= isympp
= NULL
;
277 osympp
= isympp
= (asymbol
**) xmalloc (get_symtab_upper_bound (ibfd
));
278 symcount
= bfd_canonicalize_symtab (ibfd
, isympp
);
280 if (strip_symbols
== strip_debug
|| discard_locals
!= locals_undef
)
282 osympp
= (asymbol
**) xmalloc (symcount
* sizeof (asymbol
*));
283 symcount
= filter_symbols (ibfd
, osympp
, isympp
, symcount
);
287 bfd_set_symtab (obfd
, osympp
, symcount
);
289 /* bfd mandates that all output sections be created and sizes set before
290 any output is done. Thus, we traverse all sections multiple times. */
291 bfd_map_over_sections (ibfd
, setup_section
, (void *) obfd
);
292 bfd_map_over_sections (ibfd
, copy_section
, (void *) obfd
);
293 bfd_map_over_sections (ibfd
, mangle_section
, (void *) obfd
);
302 size_t size
= strlen (a
) + strlen (b
) + strlen (c
);
303 char *r
= xmalloc (size
+ 1);
311 /* Read each archive element in turn from IBFD, copy the
312 contents to temp file, and keep the temp file handle. */
315 copy_archive (ibfd
, obfd
, output_target
)
320 bfd
**ptr
= &obfd
->archive_head
;
322 char *dir
= cat ("./#", make_tempname (""), "cd");
324 /* Make a temp directory to hold the contents. */
326 obfd
->has_armap
= ibfd
->has_armap
;
328 this_element
= bfd_openr_next_archived_file (ibfd
, NULL
);
329 ibfd
->archive_head
= this_element
;
330 while (this_element
!= (bfd
*) NULL
)
332 /* Create an output file for this member. */
333 char *output_name
= cat (dir
, "/", bfd_get_filename(this_element
));
334 bfd
*output_bfd
= bfd_openw (output_name
, output_target
);
336 if (output_bfd
== (bfd
*) NULL
)
338 nonfatal (output_name
);
340 if (!bfd_set_format (obfd
, bfd_get_format (ibfd
)))
342 nonfatal (bfd_get_filename (obfd
));
345 if (bfd_check_format (this_element
, bfd_object
) == true)
347 copy_object (this_element
, output_bfd
);
350 bfd_close (output_bfd
);
351 /* Open the newly output file and attatch to our list. */
352 output_bfd
= bfd_openr (output_name
, output_target
);
354 /* Mark it for deletion. */
356 ptr
= &output_bfd
->next
;
357 this_element
->next
= bfd_openr_next_archived_file (ibfd
, this_element
);
358 this_element
= this_element
->next
;
362 if (!bfd_close (obfd
))
364 nonfatal (bfd_get_filename (obfd
));
367 /* Delete all the files that we opened.
368 Construct their names again, unfortunately, but
369 we're about to exit anyway. */
370 for (this_element
= ibfd
->archive_head
;
371 this_element
!= (bfd
*) NULL
;
372 this_element
= this_element
->next
)
374 unlink (cat (dir
, "/", bfd_get_filename (this_element
)));
377 if (!bfd_close (ibfd
))
379 nonfatal (bfd_get_filename (ibfd
));
383 /* The top-level control. */
386 copy_file (input_filename
, output_filename
, input_target
, output_target
)
387 char *input_filename
;
388 char *output_filename
;
395 /* To allow us to do "strip *" without dying on the first
396 non-object file, failures are nonfatal. */
398 ibfd
= bfd_openr (input_filename
, input_target
);
401 nonfatal (input_filename
);
404 if (bfd_check_format (ibfd
, bfd_archive
))
406 bfd
*obfd
= bfd_openw (output_filename
, output_target
);
409 nonfatal (output_filename
);
411 copy_archive (ibfd
, obfd
, output_target
);
413 else if (bfd_check_format_matches (ibfd
, bfd_object
, &matching
))
415 bfd
*obfd
= bfd_openw (output_filename
, output_target
);
418 nonfatal (output_filename
);
421 copy_object (ibfd
, obfd
);
423 if (!bfd_close (obfd
))
425 nonfatal (output_filename
);
428 if (!bfd_close (ibfd
))
430 nonfatal (input_filename
);
435 bfd_nonfatal (input_filename
);
436 if (bfd_error
== file_ambiguously_recognized
)
438 list_matching_formats (matching
);
445 /* Create a section in OBFD with the same name and attributes
446 as ISECTION in IBFD. */
449 setup_section (ibfd
, isection
, obfd
)
457 if ((bfd_get_section_flags (ibfd
, isection
) & SEC_DEBUGGING
) != 0
458 && (strip_symbols
== strip_debug
459 || strip_symbols
== strip_all
460 || discard_locals
== locals_all
))
463 osection
= bfd_get_section_by_name (obfd
, bfd_section_name (ibfd
, isection
));
464 if (osection
== NULL
)
466 osection
= bfd_make_section (obfd
, bfd_section_name (ibfd
, isection
));
467 if (osection
== NULL
)
474 if (!bfd_set_section_size (obfd
,
476 bfd_section_size (ibfd
, isection
)))
482 if (bfd_set_section_vma (obfd
,
484 bfd_section_vma (ibfd
, isection
))
491 if (bfd_set_section_alignment (obfd
,
493 bfd_section_alignment (ibfd
, isection
))
500 if (!bfd_set_section_flags (obfd
, osection
,
501 bfd_get_section_flags (ibfd
, isection
)))
511 fprintf (stderr
, "%s: %s: section `%s': error in %s: %s\n",
513 bfd_get_filename (ibfd
), bfd_section_name (ibfd
, isection
),
514 err
, bfd_errmsg (bfd_error
));
518 /* Copy the data of input section ISECTION of IBFD
519 to an output section with the same name in OBFD.
520 If stripping then don't copy any relocation info. */
523 copy_section (ibfd
, isection
, obfd
)
533 if ((bfd_get_section_flags (ibfd
, isection
) & SEC_DEBUGGING
) != 0
534 && (strip_symbols
== strip_debug
535 || strip_symbols
== strip_all
536 || discard_locals
== locals_all
))
541 osection
= bfd_get_section_by_name (obfd
,
542 bfd_section_name (ibfd
, isection
));
544 size
= bfd_get_section_size_before_reloc (isection
);
549 if (strip_symbols
== strip_all
550 || bfd_get_reloc_upper_bound (ibfd
, isection
) == 0)
552 bfd_set_reloc (obfd
, osection
, (arelent
**) NULL
, 0);
556 relpp
= (arelent
**) xmalloc (bfd_get_reloc_upper_bound (ibfd
, isection
));
557 relcount
= bfd_canonicalize_reloc (ibfd
, isection
, relpp
, isympp
);
558 bfd_set_reloc (obfd
, osection
, relpp
, relcount
);
561 isection
->_cooked_size
= isection
->_raw_size
;
562 isection
->reloc_done
= true;
564 if (bfd_get_section_flags (ibfd
, isection
) & SEC_HAS_CONTENTS
)
566 PTR memhunk
= (PTR
) xmalloc ((unsigned) size
);
568 if (!bfd_get_section_contents (ibfd
, isection
, memhunk
, (file_ptr
) 0,
571 nonfatal (bfd_get_filename (ibfd
));
575 filter_bytes (memhunk
, &size
);
577 if (!bfd_set_section_contents (obfd
, osection
, memhunk
, (file_ptr
) 0,
580 nonfatal (bfd_get_filename (obfd
));
586 /* All the symbols have been read in and point to their owning input section.
587 They have been relocated so that they are all relative to the base of
588 their owning section. On the way out, all the symbols will be relocated to
589 their new location in the output file, through some complex sums. */
592 mangle_section (ibfd
, p
, obfd
)
597 p
->output_section
= bfd_get_section_by_name (obfd
, p
->name
);
598 p
->output_offset
= 0;
601 /* The number of bytes to copy at once. */
602 #define COPY_BUF 8192
604 /* Copy file FROM to file TO, performing no translations.
605 Return 0 if ok, -1 if error. */
608 simple_copy (from
, to
)
611 int fromfd
, tofd
, nread
;
614 fromfd
= open (from
, O_RDONLY
);
617 tofd
= open (to
, O_WRONLY
| O_CREAT
| O_TRUNC
);
623 while ((nread
= read (fromfd
, buf
, sizeof buf
)) > 0)
625 if (write (tofd
, buf
, nread
) != nread
)
641 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
648 /* Rename FROM to TO, copying if TO is a link.
649 Assumes that TO already exists, because FROM is a temp file.
650 Return 0 if ok, -1 if error. */
653 smart_rename (from
, to
)
662 /* Use rename only if TO is not a symbolic link and has
663 only one hard link. */
664 if (!S_ISLNK (s
.st_mode
) && s
.st_nlink
== 1)
666 ret
= rename (from
, to
);
669 /* Try to preserve the permission bits and ownership of TO. */
670 chmod (to
, s
.st_mode
& 07777);
671 chown (to
, s
.st_uid
, s
.st_gid
);
676 ret
= simple_copy (from
, to
);
684 strip_main (argc
, argv
)
688 char *input_target
= NULL
, *output_target
= NULL
;
689 boolean show_version
= false;
692 while ((c
= getopt_long (argc
, argv
, "I:O:F:sSgxXVv",
693 strip_options
, (int *) 0)) != EOF
)
698 input_target
= optarg
;
701 output_target
= optarg
;
704 input_target
= output_target
= optarg
;
707 strip_symbols
= strip_all
;
711 strip_symbols
= strip_debug
;
714 discard_locals
= locals_all
;
717 discard_locals
= locals_start_L
;
726 break; /* we've been given a long option */
728 strip_usage (stdout
, 0);
730 strip_usage (stderr
, 1);
736 printf ("GNU %s version %s\n", program_name
, program_version
);
740 /* Default is to strip all symbols. */
741 if (strip_symbols
== strip_undef
&& discard_locals
== locals_undef
)
742 strip_symbols
= strip_all
;
744 if (output_target
== (char *) NULL
)
745 output_target
= input_target
;
749 strip_usage (stderr
, 1);
751 for (; i
< argc
; i
++)
753 int hold_status
= status
;
755 char *tmpname
= make_tempname (argv
[i
]);
757 copy_file (argv
[i
], tmpname
, input_target
, output_target
);
760 smart_rename (tmpname
, argv
[i
]);
761 status
= hold_status
;
772 copy_main (argc
, argv
)
776 char *input_filename
, *output_filename
;
777 char *input_target
= NULL
, *output_target
= NULL
;
778 boolean show_version
= false;
781 while ((c
= getopt_long (argc
, argv
, "b:i:I:s:O:d:F:SgxXVv",
782 copy_options
, (int *) 0)) != EOF
)
787 copy_byte
= atoi(optarg
);
790 fprintf (stderr
, "%s: byte number must be non-negative\n",
796 interleave
= atoi(optarg
);
799 fprintf(stderr
, "%s: interleave must be positive\n",
805 case 's': /* "source" - 'I' is preferred */
806 input_target
= optarg
;
809 case 'd': /* "destination" - 'O' is preferred */
810 output_target
= optarg
;
813 input_target
= output_target
= optarg
;
816 strip_symbols
= strip_all
;
819 strip_symbols
= strip_debug
;
822 discard_locals
= locals_all
;
825 discard_locals
= locals_start_L
;
834 break; /* we've been given a long option */
836 copy_usage (stdout
, 0);
838 copy_usage (stderr
, 1);
844 printf ("GNU %s version %s\n", program_name
, program_version
);
848 if (copy_byte
>= interleave
)
850 fprintf (stderr
, "%s: byte number must be less than interleave\n",
855 if (optind
== argc
|| optind
+ 2 < argc
)
856 copy_usage (stderr
, 1);
858 input_filename
= argv
[optind
];
859 if (optind
+ 1 < argc
)
860 output_filename
= argv
[optind
+ 1];
862 /* Default is to strip no symbols. */
863 if (strip_symbols
== strip_undef
&& discard_locals
== locals_undef
)
864 strip_symbols
= strip_none
;
866 if (output_target
== (char *) NULL
)
867 output_target
= input_target
;
869 /* If there is no destination file then create a temp and rename
870 the result into the input. */
872 if (output_filename
== (char *) NULL
)
874 char *tmpname
= make_tempname (input_filename
);
875 copy_file (input_filename
, tmpname
, input_target
, output_target
);
877 smart_rename (tmpname
, input_filename
);
883 copy_file (input_filename
, output_filename
, input_target
, output_target
);
894 program_name
= argv
[0];
895 xmalloc_set_program_name (program_name
);
896 strip_symbols
= strip_undef
;
897 discard_locals
= locals_undef
;
903 int i
= strlen (program_name
);
904 is_strip
= (i
>= 5 && strcmp (program_name
+ i
- 5, "strip"));
908 strip_main (argc
, argv
);
910 copy_main (argc
, argv
);