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