1 /* 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. */
24 #include <sys/types.h>
29 strip_all, /* strip all symbols */
30 strip_debug, /* strip all debugger symbols */
33 /* Which symbols to remove. */
34 enum strip_action strip_symbols;
38 locals_start_L, /* discard locals starting with L */
39 locals_all, /* discard all locals */
42 /* Which local symbols to remove. */
43 enum locals_action discard_locals;
45 /* The name this program was run with. */
48 struct option long_options[] = {
49 {"strip-all", 0, 0, 's'},
50 {"strip-debug", 0, 0, 'S'},
51 {"discard-all", 0, 0, 'x'},
52 {"discard-locals", 0, 0, 'X'},
56 static char *target = NULL;
58 static int fatal_error;
60 extern char *malloc();
61 extern char *mktemp();
62 extern char *realloc();
63 extern char *strcpy();
74 static int strip_bfd(bfd *ibfd, bfd *obfd);
75 static int strip_file(char *filetostrip);
76 static void usage(void);
78 static int strip_bfd();
79 static int strip_file();
82 static void copy_sections ();
83 static void setup_sections ();
91 program_name = argv[0];
93 strip_symbols = strip_undef; /* default is to strip everything. */
94 discard_locals = locals_undef;
96 while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
101 strip_symbols = strip_all;
105 strip_symbols = strip_debug;
111 discard_locals = locals_all;
114 discard_locals = locals_start_L;
118 } /* switch on option */
119 } /* for each option */
121 if (strip_symbols == strip_undef && discard_locals == locals_undef) {
122 strip_symbols = strip_all;
123 } /* Default is to strip all symbols. */
126 if (argc == optind) {
127 return(strip_file("a.out"));
131 for ( ; optind < argc; ++optind) {
132 retval &= strip_file(argv[optind]);
133 } /* for each file to strip */
136 } /* if no arguments given */
140 static int delayed_signal;
142 void delay_signal(signo)
145 delayed_signal = signo;
146 signal(signo, delay_signal);
147 } /* delay_signal() */
149 static int sigint_handled = 0;
150 static int sighup_handled = 0;
151 static int sigterm_handled = 0;
154 /* Effectively defer handling of asynchronous kill signals. */
157 if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
159 signal(SIGINT, delay_signal);
160 } /* if not ignored */
162 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
164 signal(SIGHUP, delay_signal);
165 } /* if not ignored */
167 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
169 signal(SIGTERM, delay_signal);
170 } /* if not ignored */
173 } /* handle_sigs() */
175 void unhandle_sigs() {
176 /* Effectively undefer handling. */
178 signal (SIGINT, SIG_DFL);
180 signal (SIGHUP, SIG_DFL);
182 signal (SIGTERM, SIG_DFL);
184 /* Handle any signal that came in while they were deferred. */
186 kill (getpid (), delayed_signal);
189 } /* unhandle_sigs() */
191 static int strip_file(filetostrip)
196 char tmpfilename[] = "stXXXXXX";
198 if ((ibfd = bfd_openr(filetostrip, (char *)NULL)) == NULL) {
199 bfd_perror(filetostrip);
201 } /* on error opening input */
203 obfd = bfd_openw(mktemp(tmpfilename),
204 target? target: bfd_get_target (ibfd));
206 bfd_perror(tmpfilename);
208 if (bfd_close(ibfd) == false) {
209 bfd_perror(bfd_get_filename(ibfd));
210 } /* on close error */
213 } /* on error opening output */
217 if (bfd_check_format(ibfd, bfd_object) != false) {
218 if (bfd_set_format(obfd, bfd_get_format(ibfd)) != false) {
219 if (!strip_bfd(ibfd, obfd)) {
222 if (bfd_close(ibfd) == false) {
223 bfd_perror(bfd_get_filename(ibfd));
224 } /* on close error */
226 if (bfd_close(obfd) == false) {
227 bfd_perror(bfd_get_filename(obfd));
228 } /* on close error */
230 rename(tmpfilename, filetostrip);
233 } /* strip_bfd prints it's own failing messages */
235 bfd_perror(filetostrip);
236 } /* can't set format */
238 /* not an object file */
239 (void) fprintf(stderr, "File %s has format 0x%x that will not be stripped.\n",
240 filetostrip, (unsigned) bfd_get_format(ibfd));
241 } /* if anything fails along the way */
244 if (bfd_close(ibfd) == false) {
245 bfd_perror(bfd_get_filename(ibfd));
246 } /* on close error */
248 if (bfd_close(obfd) == false) {
249 bfd_perror(bfd_get_filename(obfd));
250 } /* on close error */
252 if (unlink(tmpfilename)) {
263 bfd_set_start_address (abfd, new_address)
267 bfd_get_start_address (abfd) = new_address;
274 strip_bfd(ibfd, obfd)
278 if (bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false
279 || bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd) & ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS)) == false
280 || bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) {
281 bfd_perror(bfd_get_filename(ibfd));
283 } /* on error setting file attributes */
285 /* bfd mandates that all output sections be created and sizes set before
286 any output is done. Thus, we traverse all sections twice. */
289 bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
291 bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
296 setup_sections(ibfd, isection, obfd)
306 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
307 if (osection == NULL)
310 if (!bfd_set_section_size(obfd, osection,
311 bfd_section_size(ibfd, isection)))
314 if (!bfd_set_section_vma(obfd, osection,
315 bfd_section_vma(ibfd, isection)))
318 if (!bfd_set_section_alignment(obfd, osection,
319 bfd_section_alignment(ibfd, isection)))
322 if (!bfd_set_section_flags(obfd, osection,
323 bfd_get_section_flags(ibfd, isection)))
328 (void) fprintf(stderr, "file \"%s\", section \"%s\": error in %s: ",
329 bfd_get_filename(ibfd),
330 bfd_section_name(ibfd, isection),
338 copy_sections(ibfd, isection, obfd)
343 static char *memhunk = NULL;
344 static unsigned memhunksize = 0;
351 osection = bfd_get_section_by_name (obfd,
352 bfd_section_name(ibfd, isection));
354 size = bfd_section_size(ibfd, isection);
355 iflg = bfd_get_section_flags(ibfd, isection);
358 we don't need any memory because there's nothing in this section,
359 we had no memory so we got some,
360 we had some memory but not enough so we got more,
361 or we fail to allocat. */
366 if (memhunk == NULL) {
367 memhunk = malloc (size);
371 if (size > memhunksize) {
372 temp = realloc (memhunk, size);
374 if (!temp) /* If realloc failed, blow away our mem */
379 if (memhunk == NULL) {
380 /* failed to allocate or reallocate */
381 /* FIXME, we should just copy in pieces. */
382 (void) fprintf(stderr,
383 "Could not allocate %lu bytes in which to copy section.\n", size);
387 /* now we have enough memory */
389 if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size)) {
390 bfd_perror(bfd_get_filename(ibfd));
394 if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size)) {
395 bfd_perror(bfd_get_filename(obfd));
405 Usage: %s [-gsxSX] [+strip-all] [+strip-debug] [+discard-all]\n\
406 [+discard-locals] file...\n", program_name);