]> Git Repo - binutils.git/blob - binutils/ostrip.c
Include bfd.h before sysdep.h, so ansidecl and PROTO() get defined first.
[binutils.git] / binutils / ostrip.c
1 /* strip certain symbols from a rel file.
2    Copyright (C) 1986, 1990 Free Software Foundation, Inc.
3
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)
7    any later version.
8
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.
13
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.  */
17
18 #include "bfd.h"
19 #include "sysdep.h"
20 #include "getopt.h"
21
22 #include <stdio.h>
23 #include <signal.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 enum strip_action {
28   strip_undef,
29   strip_all,                    /* strip all symbols */
30   strip_debug,                  /* strip all debugger symbols */
31 };
32
33 /* Which symbols to remove. */
34 enum strip_action strip_symbols;
35
36 enum locals_action {
37   locals_undef,
38   locals_start_L,               /* discard locals starting with L */
39   locals_all,                   /* discard all locals */
40 };
41
42 /* Which local symbols to remove. */
43 enum locals_action discard_locals;
44
45 /* The name this program was run with. */
46 char *program_name;
47
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'},
53   {0, 0, 0, 0},
54 };
55
56 static char *target = NULL;
57
58 static int fatal_error;
59
60 extern char *malloc();
61 extern char *mktemp();
62 extern char *realloc();
63 extern char *strcpy();
64 extern int exit();
65 extern int fprintf();
66 extern int free();
67 extern int getpid();
68 extern int kill();
69 extern int perror();
70 extern int sprintf();
71 extern int unlink();
72
73 #ifdef __STDC__
74 static int strip_bfd(bfd *ibfd, bfd *obfd);
75 static int strip_file(char *filetostrip);
76 static void usage(void);
77 #else
78 static int strip_bfd();
79 static int strip_file();
80 static void usage();
81 #endif /* __STDC__ */
82 static void copy_sections ();
83 static void setup_sections ();
84
85 int main(argc, argv)
86 char **argv;
87 int argc;
88 {
89         int ind;
90         int c;
91         program_name = argv[0];
92         
93         strip_symbols = strip_undef;    /* default is to strip everything.  */
94         discard_locals = locals_undef;
95         
96         while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
97                 switch (c) {
98                 case 0:
99                         break;
100                 case 's':
101                         strip_symbols = strip_all;
102                         break;
103                 case 'g':
104                 case 'S':
105                         strip_symbols = strip_debug;
106                         break;
107                 case 'T':
108                         target = optarg;
109                         break;
110                 case 'x':
111                         discard_locals = locals_all;
112                         break;
113                 case 'X':
114                         discard_locals = locals_start_L;
115                         break;
116                 default:
117                         usage ();
118                 } /* switch on option */
119         } /* for each option */
120         
121         if (strip_symbols == strip_undef && discard_locals == locals_undef) {
122                 strip_symbols = strip_all;
123         } /* Default is to strip all symbols.  */
124         
125         
126         if (argc == optind) {
127                 return(strip_file("a.out"));
128         } else {
129                 int retval = 0;
130
131                 for ( ; optind < argc; ++optind) {
132                         retval &= strip_file(argv[optind]);
133                 } /* for each file to strip */
134
135                 return(retval);
136         } /* if no arguments given */
137
138 } /* main() */
139
140 static int delayed_signal;
141
142 void delay_signal(signo)
143 int signo;
144 {
145         delayed_signal = signo;
146         signal(signo, delay_signal);
147 } /* delay_signal() */
148
149 static int sigint_handled = 0;
150 static int sighup_handled = 0;
151 static int sigterm_handled = 0;
152
153 void handle_sigs() {
154         /* Effectively defer handling of asynchronous kill signals.  */
155         delayed_signal = 0;
156         
157         if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
158                 sigint_handled = 1;
159                 signal(SIGINT, delay_signal);
160         } /* if not ignored */
161         
162         if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
163                 sighup_handled = 1;
164                 signal(SIGHUP, delay_signal);
165         } /* if not ignored */
166         
167         if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
168                 sigterm_handled = 1;
169                 signal(SIGTERM, delay_signal);
170         } /* if not ignored */
171         
172         return;
173 } /* handle_sigs() */
174
175 void unhandle_sigs() {
176         /* Effectively undefer handling.  */
177         if (sigint_handled)
178             signal (SIGINT, SIG_DFL);
179         if (sighup_handled)
180             signal (SIGHUP, SIG_DFL);
181         if (sigterm_handled)
182             signal (SIGTERM, SIG_DFL);
183         
184         /* Handle any signal that came in while they were deferred.  */
185         if (delayed_signal)
186             kill (getpid (), delayed_signal);
187         
188         return;
189 } /* unhandle_sigs() */
190
191 static int strip_file(filetostrip)
192 char *filetostrip;
193 {
194         bfd *ibfd;
195         bfd *obfd;
196         char tmpfilename[] = "stXXXXXX";
197
198         if ((ibfd = bfd_openr(filetostrip, (char *)NULL)) == NULL) {
199                 bfd_perror(filetostrip);
200                 return(1);
201         } /* on error opening input */
202         
203         obfd = bfd_openw(mktemp(tmpfilename),
204                          target? target: bfd_get_target (ibfd));
205         if (obfd == NULL) {
206                 bfd_perror(tmpfilename);
207
208                 if (bfd_close(ibfd) == false) {
209                         bfd_perror(bfd_get_filename(ibfd));
210                 } /* on close error */
211
212                 return(1);
213         } /* on error opening output */
214
215         handle_sigs();
216
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)) {
220                                 /* success */
221
222                                 if (bfd_close(ibfd) == false) {
223                                         bfd_perror(bfd_get_filename(ibfd));
224                                 } /* on close error */
225
226                                 if (bfd_close(obfd) == false) {
227                                         bfd_perror(bfd_get_filename(obfd));
228                                 } /* on close error */
229
230                                 rename(tmpfilename, filetostrip);
231                                 unhandle_sigs();
232                                 return(0);
233                         } /* strip_bfd prints it's own failing messages */
234                 } else {
235                         bfd_perror(filetostrip);
236                 } /* can't set format */
237         } else {
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 */
242         
243
244         if (bfd_close(ibfd) == false) {
245                 bfd_perror(bfd_get_filename(ibfd));
246         } /* on close error */
247
248         if (bfd_close(obfd) == false) {
249                 bfd_perror(bfd_get_filename(obfd));
250         } /* on close error */
251         
252         if (unlink(tmpfilename)) {
253                 perror(tmpfilename);
254         } /* on error */
255         
256         unhandle_sigs();
257
258         return(1);
259 } /* strip_file() */
260
261
262 boolean
263 bfd_set_start_address (abfd, new_address)
264      bfd *abfd;
265      bfd_vma new_address;
266 {
267   bfd_get_start_address (abfd) = new_address;
268   return true;
269 }
270
271
272
273 static int
274 strip_bfd(ibfd, obfd)
275         bfd *ibfd;
276         bfd *obfd;
277 {
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));
282                 return(1);
283         } /* on error setting file attributes */
284
285       /* bfd mandates that all output sections be created and sizes set before
286          any output is done.  Thus, we traverse all sections twice.  */
287
288         fatal_error = 0;
289         bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
290         if (!fatal_error)
291                 bfd_map_over_sections (ibfd, copy_sections,  (void *)obfd);
292         return fatal_error;
293 }
294
295 static void
296 setup_sections(ibfd, isection, obfd)
297 bfd *ibfd;
298 sec_ptr isection;
299 bfd *obfd;
300 {
301         sec_ptr osection;
302         char *err;
303
304         do {
305             err = "making";
306             osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
307             if (osection == NULL)
308                 break;
309             err = "size";
310             if (!bfd_set_section_size(obfd, osection, 
311                  bfd_section_size(ibfd, isection)))
312                 break;
313             err = "vma";
314             if (!bfd_set_section_vma(obfd, osection,
315                  bfd_section_vma(ibfd, isection)))
316                 break;
317             err = "alignment";
318             if (!bfd_set_section_alignment(obfd, osection,
319                  bfd_section_alignment(ibfd, isection)))
320                 break;
321             err = "flags";
322             if (!bfd_set_section_flags(obfd, osection,
323                  bfd_get_section_flags(ibfd, isection)))
324                 break;
325             return;
326         } while (0);
327
328         (void) fprintf(stderr, "file \"%s\", section \"%s\": error in %s: ",
329                        bfd_get_filename(ibfd),
330                        bfd_section_name(ibfd, isection),
331                        err);
332
333         bfd_perror("");
334         fatal_error = 1;
335 }
336
337 static void
338 copy_sections(ibfd, isection, obfd)
339 bfd *ibfd;
340 sec_ptr isection;
341 bfd *obfd;
342 {
343         static char *memhunk = NULL;
344         static unsigned memhunksize = 0;
345
346         sec_ptr osection;
347         unsigned long size;
348         flagword iflg;
349         char *temp;
350
351         osection = bfd_get_section_by_name (obfd,
352                                             bfd_section_name(ibfd, isection));
353
354         size = bfd_section_size(ibfd, isection);
355         iflg = bfd_get_section_flags(ibfd, isection);
356
357         /* either:
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. */
362
363         if (size == 0)
364                 return;
365
366         if (memhunk == NULL) {
367                 memhunk = malloc (size);
368                 memhunksize = size;
369         }
370
371         if (size > memhunksize) {
372                 temp = realloc (memhunk, size);
373                 memhunksize = size;
374                 if (!temp)      /* If realloc failed, blow away our mem */
375                         free (memhunk);
376                 memhunk = temp;
377         }
378
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);
384                 return;
385         }
386
387         /* now we have enough memory */
388         
389         if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size)) {
390                 bfd_perror(bfd_get_filename(ibfd));
391                 fatal_error = 1;
392                 return;
393         }
394         if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size)) {
395                 bfd_perror(bfd_get_filename(obfd));
396                 fatal_error = 1;
397                 return;
398         }
399 }
400
401 void
402 usage ()
403 {
404   fprintf (stderr, "\
405 Usage: %s [-gsxSX] [+strip-all] [+strip-debug] [+discard-all]\n\
406        [+discard-locals] file...\n", program_name);
407   exit (1);
408 }
409
410 /*
411  * Local Variables:
412  * comment-column: 0
413  * fill-column: 131
414  * End:
415  */
416
417 /* end of strip.c */
This page took 0.049113 seconds and 4 git commands to generate.