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