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. */
22 #include <sys/types.h>
30 strip_all, /* strip all symbols */
31 strip_debug, /* strip all debugger symbols */
34 /* Which symbols to remove. */
35 enum strip_action strip_symbols;
39 locals_start_L, /* discard locals starting with L */
40 locals_all, /* discard all locals */
43 /* Which local symbols to remove. */
44 enum locals_action discard_locals;
46 /* The name this program was run with. */
49 struct option long_options[] = {
50 {"strip-all", 0, 0, 's'},
51 {"strip-debug", 0, 0, 'S'},
52 {"discard-all", 0, 0, 'x'},
53 {"discard-locals", 0, 0, 'X'},
57 static char *target = NULL;
59 static int fatal_error;
61 extern char *malloc();
62 extern char *mktemp();
63 extern char *realloc();
64 extern char *strcpy();
75 static int strip_bfd(bfd *ibfd, bfd *obfd);
76 static int strip_file(char *filetostrip);
77 static void usage(void);
79 static int strip_bfd();
80 static int strip_file();
83 static void copy_sections ();
84 static void setup_sections ();
92 program_name = argv[0];
94 strip_symbols = strip_undef; /* default is to strip everything. */
95 discard_locals = locals_undef;
97 while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
102 strip_symbols = strip_all;
106 strip_symbols = strip_debug;
112 discard_locals = locals_all;
115 discard_locals = locals_start_L;
119 } /* switch on option */
120 } /* for each option */
122 if (strip_symbols == strip_undef && discard_locals == locals_undef) {
123 strip_symbols = strip_all;
124 } /* Default is to strip all symbols. */
127 if (argc == optind) {
128 return(strip_file("a.out"));
132 for ( ; optind < argc; ++optind) {
133 retval &= strip_file(argv[optind]);
134 } /* for each file to strip */
137 } /* if no arguments given */
141 static int delayed_signal;
143 void delay_signal(signo)
146 delayed_signal = signo;
147 signal(signo, delay_signal);
148 } /* delay_signal() */
150 static int sigint_handled = 0;
151 static int sighup_handled = 0;
152 static int sigterm_handled = 0;
155 /* Effectively defer handling of asynchronous kill signals. */
158 if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
160 signal(SIGINT, delay_signal);
161 } /* if not ignored */
163 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
165 signal(SIGHUP, delay_signal);
166 } /* if not ignored */
168 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
170 signal(SIGTERM, delay_signal);
171 } /* if not ignored */
174 } /* handle_sigs() */
176 void unhandle_sigs() {
177 /* Effectively undefer handling. */
179 signal (SIGINT, SIG_DFL);
181 signal (SIGHUP, SIG_DFL);
183 signal (SIGTERM, SIG_DFL);
185 /* Handle any signal that came in while they were deferred. */
187 kill (getpid (), delayed_signal);
190 } /* unhandle_sigs() */
192 static int strip_file(filetostrip)
197 char tmpfilename[] = "stXXXXXX";
199 if ((ibfd = bfd_openr(filetostrip, (char *)NULL)) == NULL) {
200 bfd_perror(filetostrip);
202 } /* on error opening input */
204 obfd = bfd_openw(mktemp(tmpfilename),
205 target? target: bfd_get_target (ibfd));
207 bfd_perror(tmpfilename);
209 if (bfd_close(ibfd) == false) {
210 bfd_perror(bfd_get_filename(ibfd));
211 } /* on close error */
214 } /* on error opening output */
218 if (bfd_check_format(ibfd, bfd_object) != false) {
219 if (bfd_set_format(obfd, bfd_get_format(ibfd)) != false) {
220 if (!strip_bfd(ibfd, obfd)) {
223 if (bfd_close(ibfd) == false) {
224 bfd_perror(bfd_get_filename(ibfd));
225 } /* on close error */
227 if (bfd_close(obfd) == false) {
228 bfd_perror(bfd_get_filename(obfd));
229 } /* on close error */
231 rename(tmpfilename, filetostrip);
234 } /* strip_bfd prints it's own failing messages */
236 bfd_perror(filetostrip);
237 } /* can't set format */
239 /* not an object file */
240 (void) fprintf(stderr, "File %s has format 0x%x that will not be stripped.\n",
241 filetostrip, (unsigned) bfd_get_format(ibfd));
242 } /* if anything fails along the way */
245 if (bfd_close(ibfd) == false) {
246 bfd_perror(bfd_get_filename(ibfd));
247 } /* on close error */
249 if (bfd_close(obfd) == false) {
250 bfd_perror(bfd_get_filename(obfd));
251 } /* on close error */
253 if (unlink(tmpfilename)) {
264 bfd_set_start_address (abfd, new_address)
268 bfd_get_start_address (abfd) = new_address;
275 strip_bfd(ibfd, obfd)
279 if (bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false
280 || bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd) & ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS)) == false
281 || bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) {
282 bfd_perror(bfd_get_filename(ibfd));
284 } /* on error setting file attributes */
286 /* bfd mandates that all output sections be created and sizes set before
287 any output is done. Thus, we traverse all sections twice. */
290 bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
292 bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
297 setup_sections(ibfd, isection, obfd)
307 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
308 if (osection == NULL)
311 if (!bfd_set_section_size(obfd, osection,
312 bfd_section_size(ibfd, isection)))
315 if (!bfd_set_section_vma(obfd, osection,
316 bfd_section_vma(ibfd, isection)))
319 if (!bfd_set_section_alignment(obfd, osection,
320 bfd_section_alignment(ibfd, isection)))
323 if (!bfd_set_section_flags(obfd, osection,
324 bfd_get_section_flags(ibfd, isection)))
329 (void) fprintf(stderr, "file \"%s\", section \"%s\": error in %s: ",
330 bfd_get_filename(ibfd),
331 bfd_section_name(ibfd, isection),
339 copy_sections(ibfd, isection, obfd)
344 static char *memhunk = NULL;
345 static unsigned memhunksize = 0;
352 osection = bfd_get_section_by_name (obfd,
353 bfd_section_name(ibfd, isection));
355 size = bfd_section_size(ibfd, isection);
356 iflg = bfd_get_section_flags(ibfd, isection);
359 we don't need any memory because there's nothing in this section,
360 we had no memory so we got some,
361 we had some memory but not enough so we got more,
362 or we fail to allocat. */
367 if (memhunk == NULL) {
368 memhunk = malloc (size);
372 if (size > memhunksize) {
373 temp = realloc (memhunk, size);
375 if (!temp) /* If realloc failed, blow away our mem */
380 if (memhunk == NULL) {
381 /* failed to allocate or reallocate */
382 /* FIXME, we should just copy in pieces. */
383 (void) fprintf(stderr,
384 "Could not allocate %lu bytes in which to copy section.\n", size);
388 /* now we have enough memory */
390 if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size)) {
391 bfd_perror(bfd_get_filename(ibfd));
395 if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size)) {
396 bfd_perror(bfd_get_filename(obfd));
406 Usage: %s [-gsxSX] [+strip-all] [+strip-debug] [+discard-all]\n\
407 [+discard-locals] file...\n", program_name);