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