* archures.c: Rename `struct bfd_arch_info_struct' to `struct
[deliverable/binutils-gdb.git] / binutils / strip.c
CommitLineData
c074abee
DHW
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
32int show_version = 0;
33
34/* Which symbols to remove. */
35enum 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. */
42enum {
43 locals_undef,
44 locals_start_L, /* discard locals starting with L */
45 locals_all, /* discard all locals */
46} discard_locals;
47
48extern char *mktemp();
49
50/* IMPORTS */
51extern char *program_version;
52extern char *program_name;
53extern char *target;
54extern char *xmalloc();
55
56PROTO(static boolean, strip_file, (char *filetostrip));
57PROTO(static void, copy_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
58PROTO(static void, setup_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
59\f
60/** main, etc */
61
62static void
63usage ()
64{
65 fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
66 program_version, program_name);
67 exit (1);
68}
69
70struct 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
77int
78main (argc, argv)
79 char **argv;
80 int argc;
81{
82 int ind;
83 int c;
84 program_name = argv[0];
85
21214e8e
SC
86 bfd_init();
87
c074abee
DHW
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
136static int delayed_signal;
137
138static int sigint_handled = 0;
139static int sighup_handled = 0;
140static int sigterm_handled = 0;
141
142void
143delay_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. */
151void
152handle_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. */
175void
176unhandle_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
192static boolean
193strip_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 */
269static void
270setup_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
318static void
319copy_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.04241 seconds and 4 git commands to generate.