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