]> Git Repo - binutils.git/blob - binutils/strip.c
* symtab.c (_initialize_symtab): Remove builtin type
[binutils.git] / binutils / strip.c
1 /*** strip.c -- 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 /* BUGS: When there's not enough memory, this should do the copy
19    in pieces rather than just fail as it does now */
20
21 #include "sysdep.h"
22 #include "bfd.h"
23
24 #include "getopt.h"
25
26
27
28 #include <signal.h>
29
30 /* Various program options */
31
32 int show_version = 0;
33
34 /* Which symbols to remove. */
35 enum strip_action {
36   strip_undef,
37   strip_all,                    /* strip all symbols */
38   strip_debug,                  /* strip all debugger symbols */
39 } strip_symbols;
40
41 /* Which local symbols to remove. */
42 enum {
43   locals_undef,
44   locals_start_L,               /* discard locals starting with L */
45   locals_all,                   /* discard all locals */
46 } discard_locals;
47
48 extern char *mktemp();
49
50 /* IMPORTS */
51 extern char *program_version;
52 extern char *program_name;
53 extern char *target;
54 extern char *xmalloc();
55
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));
59 \f
60 /** main, etc */
61
62 static void
63 usage ()
64 {
65   fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
66            program_version, program_name);
67   exit (1);
68 }
69
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'},
74                                 {0, 0, 0, 0}
75                                 };
76
77 int
78 main (argc, argv)
79      char **argv;
80      int argc;
81 {
82   int ind;
83   int c;
84   program_name = argv[0];
85         
86   strip_symbols = strip_undef;  /* default is to strip everything.  */
87   discard_locals = locals_undef;
88         
89   while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
90     switch (c) {
91     case 0:
92       break;
93     case 's':
94       strip_symbols = strip_all;
95       break;
96     case 'g':
97     case 'S':
98       strip_symbols = strip_debug;
99       break;
100     case 'T':
101       target = optarg;
102       break;
103     case 'x':
104       discard_locals = locals_all;
105       break;
106     case 'X':
107       discard_locals = locals_start_L;
108       break;
109     default:
110       usage ();
111     }
112   }
113
114   /* Default is to strip all symbols: */
115   if (strip_symbols == strip_undef && discard_locals == locals_undef) {
116     strip_symbols = strip_all;
117   }
118
119   /* OK, all options now parsed.  If no filename specified, do a.out. */
120   if (optind == argc) return !strip_file ("a.out");
121   
122   /* We were given several filenames to do: */
123   while (optind < argc)
124     if (!strip_file (argv[optind++])) return 1;
125
126   return 0;
127 }
128 \f
129 /** Hack signals */
130
131 /* Why does strip need to do this, and anyway, if it does shouldn't this be
132    handled by bfd? */
133
134 static int delayed_signal;
135
136 static int sigint_handled = 0;
137 static int sighup_handled = 0;
138 static int sigterm_handled = 0;
139
140 void
141 delay_signal (signo)
142      int signo;
143 {
144   delayed_signal = signo;
145   signal (signo, delay_signal);
146 }
147
148 /* Effectively defer handling of asynchronous kill signals.  */
149 void
150 handle_sigs ()                  /* puff puff */
151 {
152   delayed_signal = 0;
153         
154   if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
155     sigint_handled = 1;
156     signal (SIGINT, delay_signal);
157   }
158         
159   if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
160     sighup_handled = 1;
161     signal (SIGHUP, delay_signal);
162   }
163         
164   if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
165     sigterm_handled = 1;
166     signal (SIGTERM, delay_signal);
167   }
168         
169   return;
170 }
171
172 /* Effectively undefer handling.  */
173 void
174 unhandle_sigs ()                /* put them down */
175 {
176   if (sigint_handled) signal (SIGINT, SIG_DFL);
177
178   if (sighup_handled) signal (SIGHUP, SIG_DFL);
179
180   if (sigterm_handled) signal (SIGTERM, SIG_DFL);
181         
182   /* Handle any signal that came in while they were deferred.  */
183   if (delayed_signal)
184     kill (getpid (), delayed_signal);
185         
186   return;
187 }
188 \f
189
190 static boolean
191 strip_file (filetostrip)
192      char *filetostrip;
193 {
194   static char template[] = "stXXXXXX";
195   char *slash;
196   char *tmpname;
197   bfd *ibfd;
198   bfd *obfd;
199
200   ibfd = bfd_openr (filetostrip, target);
201
202   if (ibfd == NULL) bfd_fatal (filetostrip);
203
204   handle_sigs ();               /* light up */
205
206   if (!bfd_check_format (ibfd, bfd_object)) {
207     fprintf (stderr, "Can't strip %s file %s.\n",
208              bfd_format_string (bfd_get_format (ibfd)), filetostrip);
209     exit (1);
210   }
211
212   slash = strrchr( filetostrip, '/' );
213   if ( slash ){
214     *slash = 0;
215     tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
216     strcpy( tmpname, filetostrip );
217     strcat( tmpname, "/" );
218     strcat( tmpname, template );
219     mktemp( tmpname );
220     *slash = '/';
221   } else {
222     tmpname = xmalloc( sizeof(template) );
223     strcpy( tmpname, template );
224     mktemp( tmpname );
225   }
226
227   obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
228   if (obfd == NULL) bfd_fatal (tmpname);
229
230   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
231     bfd_fatal (tmpname);
232
233
234   if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
235       (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
236                                   ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
237                                     HAS_LOCALS))) == false) ||
238       bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
239     bfd_fatal (bfd_get_filename (ibfd));
240
241    /* Copy architecture of input file to output file */
242    if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
243                                bfd_get_machine (ibfd))) {
244      fprintf(stderr, "Output file cannot represent architecture %s",
245         bfd_printable_arch_mach (bfd_get_architecture(ibfd),
246                                  bfd_get_machine (ibfd)));
247    }
248  
249
250   /* bfd mandates that all output sections be created and sizes set before
251      any output is done.  Thus, we traverse all sections twice.  */
252   bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
253   bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
254
255   if (!bfd_close (obfd)) bfd_fatal (filetostrip);
256   if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
257
258   rename(tmpname, filetostrip);
259   free(tmpname);
260
261   unhandle_sigs();
262
263   return true;
264 }
265 \f
266 /** Actually do the work */
267 static void
268 setup_sections (ibfd, isection, obfd)
269      bfd *ibfd;
270      sec_ptr isection;
271      bfd *obfd;
272 {
273   sec_ptr osection;
274   char *err;
275
276   osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
277   if (osection == NULL) {
278       err = "making";
279       goto loser;
280     }
281
282   if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
283      err = "size";
284      goto loser;
285   }
286
287   if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
288      err = "vma";
289      goto loser;
290   }
291
292   if (bfd_set_section_alignment (obfd, osection,
293                              bfd_section_alignment (ibfd, isection))
294       != true) {
295           err = "alignment";
296           goto loser;
297   } /* on error, I presume. */
298
299   if (!bfd_set_section_flags (obfd, osection,
300                               bfd_get_section_flags (ibfd, isection))) {
301      err = "flags";
302      goto loser;
303   }
304
305   /* All went well */
306   return;
307   
308  loser:
309   fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
310            program_name,
311            bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
312            err, bfd_errmsg (bfd_error));
313   exit (1);
314 }
315
316 static void
317 copy_sections (ibfd, isection, obfd)
318      bfd *ibfd;
319      sec_ptr isection;
320      bfd *obfd;
321 {
322   static unsigned char *memhunk = NULL;
323   static unsigned memhunksize = 0;
324
325   sec_ptr osection;
326   unsigned long size;
327   flagword iflg;
328   unsigned char *temp;
329
330   osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
331
332   size = bfd_section_size (ibfd, isection);
333   iflg = bfd_get_section_flags (ibfd, isection);
334
335   /* either:
336      we don't need any memory because there's nothing in this section,
337      we had no memory so we got some,
338      we had some memory but not enough so we got more,
339      or we fail to allocat. */
340
341   if (size == 0)
342      return;
343
344   if ((iflg & SEC_HAS_CONTENTS) == 0)
345       return;
346
347   if (memhunk == NULL) {
348      memhunk = (unsigned char *) xmalloc (size);
349      memhunksize = size;
350   }
351
352   if (size > memhunksize) {
353      temp = (unsigned char *) xrealloc ((char *) memhunk, size);
354      memhunksize = size;
355      memhunk = temp;
356   }
357
358   /* now we have enough memory, just do it: */
359   if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
360      bfd_fatal (bfd_get_filename (ibfd));
361
362   if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
363      bfd_fatal (bfd_get_filename (obfd));
364 }
This page took 0.04007 seconds and 4 git commands to generate.