1 /* strip.c -- strip certain symbols from a rel file.
2 Copyright (C) 1986, 1990, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* BUGS: When there's not enough memory, this should do the copy
19 in pieces rather than just fail as it does now */
26 /* Various program options */
30 /* Which symbols to remove. */
33 strip_all, /* strip all symbols */
34 strip_debug, /* strip all debugger symbols */
37 /* Which local symbols to remove. */
40 locals_start_L, /* discard locals starting with L */
41 locals_all, /* discard all locals */
44 extern char *mktemp();
47 extern char *program_version;
48 extern char *program_name;
50 extern char *xmalloc();
52 PROTO(static boolean, strip_file, (char *filetostrip));
53 PROTO(static void, copy_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
54 PROTO(static void, setup_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
61 fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
62 program_version, program_name);
66 struct option long_options[] = {{"strip-all", 0, 0, 's'},
67 {"strip-debug", 0, 0, 'S'},
68 {"discard-all", 0, 0, 'x'},
69 {"discard-locals", 0, 0, 'X'},
80 program_name = argv[0];
84 strip_symbols = strip_undef; /* default is to strip everything. */
85 discard_locals = locals_undef;
87 while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
92 strip_symbols = strip_all;
96 strip_symbols = strip_debug;
102 discard_locals = locals_all;
105 discard_locals = locals_start_L;
112 /* Default is to strip all symbols: */
113 if (strip_symbols == strip_undef && discard_locals == locals_undef) {
114 strip_symbols = strip_all;
117 /* OK, all options now parsed. If no filename specified, do a.out. */
118 if (optind == argc) return !strip_file ("a.out");
120 /* We were given several filenames to do: */
121 while (optind < argc)
122 if (!strip_file (argv[optind++])) return 1;
129 /* Why does strip need to do this, and anyway, if it does shouldn't this be
132 static int delayed_signal;
134 static int sigint_handled = 0;
135 static int sighup_handled = 0;
136 static int sigterm_handled = 0;
142 delayed_signal = signo;
143 signal (signo, delay_signal);
146 /* Effectively defer handling of asynchronous kill signals. */
148 handle_sigs () /* puff puff */
152 if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
154 signal (SIGINT, delay_signal);
157 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
159 signal (SIGHUP, delay_signal);
162 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
164 signal (SIGTERM, delay_signal);
170 /* Effectively undefer handling. */
172 unhandle_sigs () /* put them down */
174 if (sigint_handled) signal (SIGINT, SIG_DFL);
176 if (sighup_handled) signal (SIGHUP, SIG_DFL);
178 if (sigterm_handled) signal (SIGTERM, SIG_DFL);
180 /* Handle any signal that came in while they were deferred. */
182 kill (getpid (), delayed_signal);
189 strip_file (filetostrip)
192 static char template[] = "stXXXXXX";
198 ibfd = bfd_openr (filetostrip, target);
200 if (ibfd == NULL) bfd_fatal (filetostrip);
202 handle_sigs (); /* light up */
204 if (!bfd_check_format (ibfd, bfd_object)) {
205 fprintf (stderr, "Can't strip %s file %s.\n",
206 bfd_format_string (bfd_get_format (ibfd)), filetostrip);
210 slash = strrchr( filetostrip, '/' );
213 tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
214 strcpy( tmpname, filetostrip );
215 strcat( tmpname, "/" );
216 strcat( tmpname, template );
220 tmpname = xmalloc( sizeof(template) );
221 strcpy( tmpname, template );
225 obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
226 if (obfd == NULL) bfd_fatal (tmpname);
228 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
232 if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
233 (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
234 ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
235 HAS_LOCALS))) == false) ||
236 bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
237 bfd_fatal (bfd_get_filename (ibfd));
239 /* Copy architecture of input file to output file */
240 if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
241 bfd_get_machine (ibfd))) {
242 fprintf(stderr, "Output file cannot represent architecture %s",
243 bfd_printable_arch_mach (bfd_get_architecture(ibfd),
244 bfd_get_machine (ibfd)));
248 /* bfd mandates that all output sections be created and sizes set before
249 any output is done. Thus, we traverse all sections twice. */
250 bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
251 bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
253 if (!bfd_close (obfd)) bfd_fatal (filetostrip);
254 if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
256 rename(tmpname, filetostrip);
264 /** Actually do the work */
266 setup_sections (ibfd, isection, obfd)
274 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
275 if (osection == NULL) {
280 if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
285 if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
290 if (bfd_set_section_alignment (obfd, osection,
291 bfd_section_alignment (ibfd, isection))
295 } /* on error, I presume. */
297 if (!bfd_set_section_flags (obfd, osection,
298 bfd_get_section_flags (ibfd, isection))) {
307 fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
309 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
310 err, bfd_errmsg (bfd_error));
315 copy_sections (ibfd, isection, obfd)
320 static unsigned char *memhunk = NULL;
321 static unsigned memhunksize = 0;
328 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
330 size = bfd_section_size (ibfd, isection);
331 iflg = bfd_get_section_flags (ibfd, isection);
334 we don't need any memory because there's nothing in this section,
335 we had no memory so we got some,
336 we had some memory but not enough so we got more,
337 or we fail to allocat. */
342 if ((iflg & SEC_HAS_CONTENTS) == 0)
345 if (memhunk == NULL) {
346 memhunk = (unsigned char *) xmalloc (size);
350 if (size > memhunksize) {
351 temp = (unsigned char *) xrealloc ((char *) memhunk, size);
356 /* now we have enough memory, just do it: */
357 if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
358 bfd_fatal (bfd_get_filename (ibfd));
360 if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
361 bfd_fatal (bfd_get_filename (obfd));