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];
88 strip_symbols = strip_undef; /* default is to strip everything. */
89 discard_locals = locals_undef;
91 while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
96 strip_symbols = strip_all;
100 strip_symbols = strip_debug;
106 discard_locals = locals_all;
109 discard_locals = locals_start_L;
116 /* Default is to strip all symbols: */
117 if (strip_symbols == strip_undef && discard_locals == locals_undef) {
118 strip_symbols = strip_all;
121 /* OK, all options now parsed. If no filename specified, do a.out. */
122 if (optind == argc) return !strip_file ("a.out");
124 /* We were given several filenames to do: */
125 while (optind < argc)
126 if (!strip_file (argv[optind++])) return 1;
133 /* Why does strip need to do this, and anyway, if it does shouldn't this be
136 static int delayed_signal;
138 static int sigint_handled = 0;
139 static int sighup_handled = 0;
140 static int sigterm_handled = 0;
146 delayed_signal = signo;
147 signal (signo, delay_signal);
150 /* Effectively defer handling of asynchronous kill signals. */
152 handle_sigs () /* puff puff */
156 if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
158 signal (SIGINT, delay_signal);
161 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
163 signal (SIGHUP, delay_signal);
166 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
168 signal (SIGTERM, delay_signal);
174 /* Effectively undefer handling. */
176 unhandle_sigs () /* put them down */
178 if (sigint_handled) signal (SIGINT, SIG_DFL);
180 if (sighup_handled) signal (SIGHUP, SIG_DFL);
182 if (sigterm_handled) signal (SIGTERM, SIG_DFL);
184 /* Handle any signal that came in while they were deferred. */
186 kill (getpid (), delayed_signal);
193 strip_file (filetostrip)
196 static char template[] = "stXXXXXX";
202 ibfd = bfd_openr (filetostrip, target);
204 if (ibfd == NULL) bfd_fatal (filetostrip);
206 handle_sigs (); /* light up */
208 if (!bfd_check_format (ibfd, bfd_object)) {
209 fprintf (stderr, "Can't strip %s file %s.\n",
210 bfd_format_string (bfd_get_format (ibfd)), filetostrip);
214 slash = strrchr( filetostrip, '/' );
217 tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
218 strcpy( tmpname, filetostrip );
219 strcat( tmpname, "/" );
220 strcat( tmpname, template );
224 tmpname = xmalloc( sizeof(template) );
225 strcpy( tmpname, template );
229 obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
230 if (obfd == NULL) bfd_fatal (tmpname);
232 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
236 if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
237 (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
238 ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
239 HAS_LOCALS))) == false) ||
240 bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
241 bfd_fatal (bfd_get_filename (ibfd));
243 /* Copy architecture of input file to output file */
244 if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
245 bfd_get_machine (ibfd))) {
246 fprintf(stderr, "Output file cannot represent architecture %s",
247 bfd_printable_arch_mach (bfd_get_architecture(ibfd),
248 bfd_get_machine (ibfd)));
252 /* bfd mandates that all output sections be created and sizes set before
253 any output is done. Thus, we traverse all sections twice. */
254 bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
255 bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
257 if (!bfd_close (obfd)) bfd_fatal (filetostrip);
258 if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
260 rename(tmpname, filetostrip);
268 /** Actually do the work */
270 setup_sections (ibfd, isection, obfd)
278 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
279 if (osection == NULL) {
284 if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
289 if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
294 if (bfd_set_section_alignment (obfd, osection,
295 bfd_section_alignment (ibfd, isection))
299 } /* on error, I presume. */
301 if (!bfd_set_section_flags (obfd, osection,
302 bfd_get_section_flags (ibfd, isection))) {
311 fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
313 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
314 err, bfd_errmsg (bfd_error));
319 copy_sections (ibfd, isection, obfd)
324 static unsigned char *memhunk = NULL;
325 static unsigned memhunksize = 0;
332 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
334 size = bfd_section_size (ibfd, isection);
335 iflg = bfd_get_section_flags (ibfd, isection);
338 we don't need any memory because there's nothing in this section,
339 we had no memory so we got some,
340 we had some memory but not enough so we got more,
341 or we fail to allocat. */
346 if ((iflg & SEC_HAS_CONTENTS) == 0)
349 if (memhunk == NULL) {
350 memhunk = (unsigned char *) xmalloc (size);
354 if (size > memhunksize) {
355 temp = (unsigned char *) xrealloc ((char *) memhunk, size);
360 /* now we have enough memory, just do it: */
361 if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
362 bfd_fatal (bfd_get_filename (ibfd));
364 if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
365 bfd_fatal (bfd_get_filename (obfd));