1 /*** strip.c -- strip certain symbols from a rel file.
2 Copyright (C) 1986, 1990 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 1, 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 */
30 /* Various program options */
34 /* Which symbols to remove. */
37 strip_all, /* strip all symbols */
38 strip_debug, /* strip all debugger symbols */
41 /* Which local symbols to remove. */
44 locals_start_L, /* discard locals starting with L */
45 locals_all, /* discard all locals */
48 extern char *mktemp();
51 extern char *program_version;
52 extern char *program_name;
54 extern char *xmalloc();
56 PROTO(static boolean, strip_file, (char *filetostrip));
57 PROTO(static void, copy_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
58 PROTO(static void, setup_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
65 fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
66 program_version, program_name);
70 struct option long_options[] = {{"strip-all", 0, 0, 's'},
71 {"strip-debug", 0, 0, 'S'},
72 {"discard-all", 0, 0, 'x'},
73 {"discard-locals", 0, 0, 'X'},
84 program_name = argv[0];
86 strip_symbols = strip_undef; /* default is to strip everything. */
87 discard_locals = locals_undef;
89 while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
94 strip_symbols = strip_all;
98 strip_symbols = strip_debug;
104 discard_locals = locals_all;
107 discard_locals = locals_start_L;
114 /* Default is to strip all symbols: */
115 if (strip_symbols == strip_undef && discard_locals == locals_undef) {
116 strip_symbols = strip_all;
119 /* OK, all options now parsed. If no filename specified, do a.out. */
120 if (optind == argc) return !strip_file ("a.out");
122 /* We were given several filenames to do: */
123 while (optind < argc)
124 if (!strip_file (argv[optind++])) return 1;
131 /* Why does strip need to do this, and anyway, if it does shouldn't this be
134 static int delayed_signal;
136 static int sigint_handled = 0;
137 static int sighup_handled = 0;
138 static int sigterm_handled = 0;
144 delayed_signal = signo;
145 signal (signo, delay_signal);
148 /* Effectively defer handling of asynchronous kill signals. */
150 handle_sigs () /* puff puff */
154 if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
156 signal (SIGINT, delay_signal);
159 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
161 signal (SIGHUP, delay_signal);
164 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
166 signal (SIGTERM, delay_signal);
172 /* Effectively undefer handling. */
174 unhandle_sigs () /* put them down */
176 if (sigint_handled) signal (SIGINT, SIG_DFL);
178 if (sighup_handled) signal (SIGHUP, SIG_DFL);
180 if (sigterm_handled) signal (SIGTERM, SIG_DFL);
182 /* Handle any signal that came in while they were deferred. */
184 kill (getpid (), delayed_signal);
191 strip_file (filetostrip)
194 static char template[] = "stXXXXXX";
200 ibfd = bfd_openr (filetostrip, target);
202 if (ibfd == NULL) bfd_fatal (filetostrip);
204 handle_sigs (); /* light up */
206 if (!bfd_check_format (ibfd, bfd_object)) {
207 fprintf (stderr, "Can't strip %s file %s.\n",
208 bfd_format_string (bfd_get_format (ibfd)), filetostrip);
212 slash = strrchr( filetostrip, '/' );
215 tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
216 strcpy( tmpname, filetostrip );
217 strcat( tmpname, "/" );
218 strcat( tmpname, template );
222 tmpname = xmalloc( sizeof(template) );
223 strcpy( tmpname, template );
227 obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
228 if (obfd == NULL) bfd_fatal (tmpname);
230 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
234 if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
235 (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
236 ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
237 HAS_LOCALS))) == false) ||
238 bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
239 bfd_fatal (bfd_get_filename (ibfd));
241 /* Copy architecture of input file to output file */
242 if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
243 bfd_get_machine (ibfd))) {
244 fprintf(stderr, "Output file cannot represent architecture %s",
245 bfd_printable_arch_mach (bfd_get_architecture(ibfd),
246 bfd_get_machine (ibfd)));
250 /* bfd mandates that all output sections be created and sizes set before
251 any output is done. Thus, we traverse all sections twice. */
252 bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
253 bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
255 if (!bfd_close (obfd)) bfd_fatal (filetostrip);
256 if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
258 rename(tmpname, filetostrip);
266 /** Actually do the work */
268 setup_sections (ibfd, isection, obfd)
276 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
277 if (osection == NULL) {
282 if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
287 if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
292 if (bfd_set_section_alignment (obfd, osection,
293 bfd_section_alignment (ibfd, isection))
297 } /* on error, I presume. */
299 if (!bfd_set_section_flags (obfd, osection,
300 bfd_get_section_flags (ibfd, isection))) {
309 fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
311 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
312 err, bfd_errmsg (bfd_error));
317 copy_sections (ibfd, isection, obfd)
322 static unsigned char *memhunk = NULL;
323 static unsigned memhunksize = 0;
330 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
332 size = bfd_section_size (ibfd, isection);
333 iflg = bfd_get_section_flags (ibfd, isection);
336 we don't need any memory because there's nothing in this section,
337 we had no memory so we got some,
338 we had some memory but not enough so we got more,
339 or we fail to allocat. */
344 if ((iflg & SEC_HAS_CONTENTS) == 0)
347 if (memhunk == NULL) {
348 memhunk = (unsigned char *) xmalloc (size);
352 if (size > memhunksize) {
353 temp = (unsigned char *) xrealloc ((char *) memhunk, size);
358 /* now we have enough memory, just do it: */
359 if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
360 bfd_fatal (bfd_get_filename (ibfd));
362 if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
363 bfd_fatal (bfd_get_filename (obfd));