* objdump.c (dump_section_header): Print the SEC_NEVER_LOAD flag.
[deliverable/binutils-gdb.git] / binutils / objcopy.c
CommitLineData
c0367ba5 1/* objcopy.c -- copy object file from input to output, optionally massaging it.
f7b839f7 2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
c0367ba5 3
46050fe4
ILT
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19\f
c0367ba5
ILT
20#include "bfd.h"
21#include "sysdep.h"
22#include "bucomm.h"
23#include <getopt.h>
24
f7b839f7
DM
25static void setup_section ();
26static void copy_section ();
77ccab3c 27static void mark_symbols_used_in_relocations ();
c0367ba5 28
46050fe4 29#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
c0367ba5 30
46050fe4
ILT
31static asymbol **isympp = NULL; /* Input symbols */
32static asymbol **osympp = NULL; /* Output symbols that survive stripping */
f7b839f7
DM
33
34/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
35static int copy_byte = -1;
36static int interleave = 4;
37
46050fe4 38static boolean verbose; /* Print file and target names. */
f7b839f7 39static int status = 0; /* Exit status. */
c0367ba5
ILT
40
41enum strip_action
46050fe4
ILT
42 {
43 strip_undef,
44 strip_none, /* don't strip */
45 strip_debug, /* strip all debugger symbols */
46 strip_all /* strip all symbols */
47 };
c0367ba5
ILT
48
49/* Which symbols to remove. */
46050fe4 50static enum strip_action strip_symbols;
c0367ba5
ILT
51
52enum locals_action
46050fe4
ILT
53 {
54 locals_undef,
55 locals_start_L, /* discard locals starting with L */
56 locals_all /* discard all locals */
57 };
58
59/* Which local symbols to remove. Overrides strip_all. */
60static enum locals_action discard_locals;
61
62/* Options to handle if running as "strip". */
63
64static struct option strip_options[] =
c0367ba5 65{
46050fe4
ILT
66 {"discard-all", no_argument, 0, 'x'},
67 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 68 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 69 {"help", no_argument, 0, 'h'},
46050fe4 70 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7 71 {"input-target", required_argument, 0, 'I'},
46050fe4 72 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
73 {"output-target", required_argument, 0, 'O'},
74 {"strip-all", no_argument, 0, 's'},
75 {"strip-debug", no_argument, 0, 'S'},
46050fe4 76 {"target", required_argument, 0, 'F'},
46050fe4 77 {"verbose", no_argument, 0, 'v'},
f7b839f7 78 {"version", no_argument, 0, 'V'},
46050fe4 79 {0, no_argument, 0, 0}
c0367ba5
ILT
80};
81
46050fe4 82/* Options to handle if running as "objcopy". */
c0367ba5 83
46050fe4
ILT
84static struct option copy_options[] =
85{
f7b839f7 86 {"byte", required_argument, 0, 'b'},
46050fe4
ILT
87 {"discard-all", no_argument, 0, 'x'},
88 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 89 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 90 {"help", no_argument, 0, 'h'},
46050fe4 91 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7
DM
92 {"input-target", required_argument, 0, 'I'},
93 {"interleave", required_argument, 0, 'i'},
46050fe4 94 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
95 {"output-target", required_argument, 0, 'O'},
96 {"strip-all", no_argument, 0, 'S'},
97 {"strip-debug", no_argument, 0, 'g'},
46050fe4 98 {"target", required_argument, 0, 'F'},
46050fe4 99 {"verbose", no_argument, 0, 'v'},
f7b839f7 100 {"version", no_argument, 0, 'V'},
46050fe4 101 {0, no_argument, 0, 0}
c0367ba5
ILT
102};
103
104/* IMPORTS */
46050fe4
ILT
105extern char *program_name;
106extern char *program_version;
107
108/* This flag distinguishes between strip and objcopy:
109 1 means this is 'strip'; 0 means this is 'objcopy'.
110 -1 means if we should use argv[0] to decide. */
111extern int is_strip;
c0367ba5
ILT
112
113
46050fe4
ILT
114static void
115copy_usage (stream, status)
c0367ba5
ILT
116 FILE *stream;
117 int status;
118{
46050fe4 119 fprintf (stream, "\
f7b839f7
DM
120Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
121 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
46050fe4
ILT
122 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
123 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
f7b839f7
DM
124 [--verbose] [--version] [--help] in-file [out-file]\n",
125 program_name);
46050fe4 126 exit (status);
c0367ba5
ILT
127}
128
46050fe4
ILT
129static void
130strip_usage (stream, status)
c0367ba5
ILT
131 FILE *stream;
132 int status;
133{
46050fe4
ILT
134 fprintf (stream, "\
135Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
136 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
137 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
138 [--verbose] [--version] [--help] file...\n",
139 program_name);
140 exit (status);
c0367ba5
ILT
141}
142
143
46050fe4 144/* Return the name of a temporary file in the same directory as FILENAME. */
c0367ba5 145
46050fe4
ILT
146static char *
147make_tempname (filename)
148 char *filename;
c0367ba5 149{
46050fe4
ILT
150 static char template[] = "stXXXXXX";
151 char *tmpname;
152 char *slash = strrchr (filename, '/');
153
154 if (slash != (char *) NULL)
155 {
156 *slash = 0;
157 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
158 strcpy (tmpname, filename);
159 strcat (tmpname, "/");
160 strcat (tmpname, template);
161 mktemp (tmpname);
162 *slash = '/';
163 }
164 else
165 {
166 tmpname = xmalloc (sizeof (template));
167 strcpy (tmpname, template);
168 mktemp (tmpname);
c0367ba5 169 }
46050fe4 170 return tmpname;
c0367ba5
ILT
171}
172
46050fe4 173/* Choose which symbol entries to copy; put the result in OSYMS.
c0367ba5 174 We don't copy in place, because that confuses the relocs.
46050fe4
ILT
175 Return the number of symbols to print. */
176
c0367ba5
ILT
177static unsigned int
178filter_symbols (abfd, osyms, isyms, symcount)
179 bfd *abfd;
180 asymbol **osyms, **isyms;
ae5d2ff5 181 long symcount;
c0367ba5
ILT
182{
183 register asymbol **from = isyms, **to = osyms;
ae5d2ff5 184 long src_count = 0, dst_count = 0;
c0367ba5 185
46050fe4
ILT
186 for (; src_count < symcount; src_count++)
187 {
188 asymbol *sym = from[src_count];
189 flagword flags = sym->flags;
190 int keep;
c0367ba5 191
46050fe4 192 if ((flags & BSF_GLOBAL) /* Keep if external. */
77ccab3c 193 || (flags & BSF_KEEP) /* Keep if used in a relocation. */
46050fe4
ILT
194 || bfd_get_section (sym) == &bfd_und_section
195 || bfd_is_com_section (bfd_get_section (sym)))
196 keep = 1;
197 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
198 keep = strip_symbols != strip_debug;
199 else /* Local symbol. */
200 keep = discard_locals != locals_all
201 && (discard_locals != locals_start_L ||
77ccab3c 202 ! bfd_is_local_label (abfd, sym));
46050fe4
ILT
203 if (keep)
204 to[dst_count++] = sym;
c0367ba5 205 }
c0367ba5
ILT
206
207 return dst_count;
208}
209
f7b839f7
DM
210/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
211 Adjust *SIZE. */
212
213void
214filter_bytes (memhunk, size)
5d2f7e30 215 char *memhunk;
f7b839f7
DM
216 bfd_size_type *size;
217{
218 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
219
220 for (; from < end; from += interleave)
221 *to++ = *from;
222 *size /= interleave;
223}
224
46050fe4
ILT
225/* Copy object file IBFD onto OBFD. */
226
c0367ba5 227static void
46050fe4
ILT
228copy_object (ibfd, obfd)
229 bfd *ibfd;
230 bfd *obfd;
c0367ba5 231{
ae5d2ff5 232 long symcount;
c0367ba5 233
46050fe4
ILT
234 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
235 {
236 nonfatal (bfd_get_filename (obfd));
237 }
c0367ba5 238
46050fe4
ILT
239 if (verbose)
240 printf ("copy from %s(%s) to %s(%s)\n",
241 bfd_get_filename(ibfd), bfd_get_target(ibfd),
242 bfd_get_filename(obfd), bfd_get_target(obfd));
c0367ba5 243
46050fe4
ILT
244 if (!bfd_set_start_address (obfd, bfd_get_start_address (ibfd))
245 || !bfd_set_file_flags (obfd,
246 (bfd_get_file_flags (ibfd)
247 & bfd_applicable_file_flags (obfd))))
248 {
249 nonfatal (bfd_get_filename (ibfd));
250 }
c0367ba5 251
46050fe4
ILT
252 /* Copy architecture of input file to output file */
253 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
254 bfd_get_mach (ibfd)))
255 {
256 fprintf (stderr, "Output file cannot represent architecture %s\n",
257 bfd_printable_arch_mach (bfd_get_arch (ibfd),
258 bfd_get_mach (ibfd)));
259 }
260 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
261 {
262 nonfatal (bfd_get_filename(ibfd));
263 }
c0367ba5 264
46050fe4
ILT
265 if (isympp)
266 free (isympp);
267 if (osympp != isympp)
268 free (osympp);
c0367ba5 269
77ccab3c
JL
270 /* bfd mandates that all output sections be created and sizes set before
271 any output is done. Thus, we traverse all sections multiple times. */
272 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
273
274 /* Symbol filtering must happen after the output sections have
275 been created, but before their contents are set. */
46050fe4
ILT
276 if (strip_symbols == strip_all && discard_locals == locals_undef)
277 {
278 osympp = isympp = NULL;
279 symcount = 0;
c0367ba5 280 }
46050fe4
ILT
281 else
282 {
ae5d2ff5
ILT
283 long symsize;
284
285 symsize = bfd_get_symtab_upper_bound (ibfd);
286 if (symsize < 0)
287 {
288 nonfatal (bfd_get_filename (ibfd));
289 }
290
291 osympp = isympp = (asymbol **) xmalloc (symsize);
46050fe4 292 symcount = bfd_canonicalize_symtab (ibfd, isympp);
ae5d2ff5
ILT
293 if (symcount < 0)
294 {
295 nonfatal (bfd_get_filename (ibfd));
296 }
46050fe4
ILT
297
298 if (strip_symbols == strip_debug || discard_locals != locals_undef)
c0367ba5 299 {
77ccab3c
JL
300 /* Mark symbols used in output relocations so that they
301 are kept, even if they are local labels or static symbols.
302
303 Note we iterate over the input sections examining their
304 relocations since the relocations for the output sections
305 haven't been set yet. mark_symbols_used_in_relocations will
306 ignore input sections which have no corresponding output
307 section. */
308 bfd_map_over_sections (ibfd,
309 mark_symbols_used_in_relocations,
310 (void *)isympp);
46050fe4
ILT
311 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
312 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
c0367ba5 313 }
46050fe4
ILT
314 }
315
316 bfd_set_symtab (obfd, osympp, symcount);
c0367ba5 317
77ccab3c 318 /* This has to happen after the symbol table has been set. */
f7b839f7 319 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
6f9077cd
JM
320
321 /* Allow the BFD backend to copy any private data it understands
322 from the input BFD to the output BFD. This is done last to
323 permit the routine to look at the filtered symbol table, which is
324 important for the ECOFF code at least. */
325 if (!bfd_copy_private_bfd_data (ibfd, obfd))
326 {
327 fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
328 program_name, bfd_get_filename (obfd),
329 bfd_errmsg (bfd_get_error ()));
330 status = 1;
331 return;
332 }
c0367ba5 333}
46050fe4
ILT
334
335static char *
336cat (a, b, c)
337 char *a;
338 char *b;
339 char *c;
c0367ba5 340{
46050fe4
ILT
341 size_t size = strlen (a) + strlen (b) + strlen (c);
342 char *r = xmalloc (size + 1);
343
344 strcpy (r, a);
345 strcat (r, b);
346 strcat (r, c);
347 return r;
c0367ba5
ILT
348}
349
46050fe4
ILT
350/* Read each archive element in turn from IBFD, copy the
351 contents to temp file, and keep the temp file handle. */
352
353static void
354copy_archive (ibfd, obfd, output_target)
355 bfd *ibfd;
356 bfd *obfd;
357 char *output_target;
c0367ba5 358{
46050fe4
ILT
359 bfd **ptr = &obfd->archive_head;
360 bfd *this_element;
90f6517d 361 char *dir = make_tempname (bfd_get_filename (obfd));
46050fe4
ILT
362
363 /* Make a temp directory to hold the contents. */
90f6517d 364 mkdir (dir, 0700);
46050fe4
ILT
365 obfd->has_armap = ibfd->has_armap;
366
367 this_element = bfd_openr_next_archived_file (ibfd, NULL);
368 ibfd->archive_head = this_element;
369 while (this_element != (bfd *) NULL)
370 {
371 /* Create an output file for this member. */
372 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
373 bfd *output_bfd = bfd_openw (output_name, output_target);
374
375 if (output_bfd == (bfd *) NULL)
376 {
377 nonfatal (output_name);
c0367ba5 378 }
46050fe4
ILT
379 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
380 {
381 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
382 }
383
46050fe4
ILT
384 if (bfd_check_format (this_element, bfd_object) == true)
385 {
386 copy_object (this_element, output_bfd);
387 }
c0367ba5 388
46050fe4
ILT
389 bfd_close (output_bfd);
390 /* Open the newly output file and attatch to our list. */
391 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 392
46050fe4
ILT
393 /* Mark it for deletion. */
394 *ptr = output_bfd;
395 ptr = &output_bfd->next;
396 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
397 this_element = this_element->next;
c0367ba5 398 }
46050fe4 399 *ptr = (bfd *) NULL;
c0367ba5 400
46050fe4
ILT
401 if (!bfd_close (obfd))
402 {
403 nonfatal (bfd_get_filename (obfd));
c0367ba5 404 }
c0367ba5 405
46050fe4
ILT
406 /* Delete all the files that we opened.
407 Construct their names again, unfortunately, but
408 we're about to exit anyway. */
409 for (this_element = ibfd->archive_head;
410 this_element != (bfd *) NULL;
411 this_element = this_element->next)
412 {
413 unlink (cat (dir, "/", bfd_get_filename (this_element)));
414 }
415 rmdir (dir);
416 if (!bfd_close (ibfd))
417 {
418 nonfatal (bfd_get_filename (ibfd));
419 }
c0367ba5
ILT
420}
421
46050fe4
ILT
422/* The top-level control. */
423
424static void
425copy_file (input_filename, output_filename, input_target, output_target)
426 char *input_filename;
427 char *output_filename;
428 char *input_target;
429 char *output_target;
c0367ba5 430{
46050fe4 431 bfd *ibfd;
cef35d48 432 char **matching;
c0367ba5
ILT
433
434 /* To allow us to do "strip *" without dying on the first
435 non-object file, failures are nonfatal. */
436
46050fe4 437 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
438 if (ibfd == NULL)
439 {
46050fe4 440 nonfatal (input_filename);
c0367ba5
ILT
441 }
442
cef35d48
DM
443 if (bfd_check_format (ibfd, bfd_archive))
444 {
445 bfd *obfd = bfd_openw (output_filename, output_target);
446 if (obfd == NULL)
447 {
448 nonfatal (output_filename);
449 }
450 copy_archive (ibfd, obfd, output_target);
451 }
452 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4
ILT
453 {
454 bfd *obfd = bfd_openw (output_filename, output_target);
455 if (obfd == NULL)
456 {
457 nonfatal (output_filename);
458 }
c0367ba5 459
46050fe4 460 copy_object (ibfd, obfd);
c0367ba5 461
46050fe4
ILT
462 if (!bfd_close (obfd))
463 {
464 nonfatal (output_filename);
465 }
466
467 if (!bfd_close (ibfd))
468 {
469 nonfatal (input_filename);
470 }
471 }
cef35d48 472 else
46050fe4 473 {
cef35d48 474 bfd_nonfatal (input_filename);
c9563567 475 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
46050fe4 476 {
cef35d48
DM
477 list_matching_formats (matching);
478 free (matching);
46050fe4 479 }
cef35d48 480 status = 1;
46050fe4
ILT
481 }
482}
483
484/* Create a section in OBFD with the same name and attributes
485 as ISECTION in IBFD. */
c0367ba5 486
c0367ba5 487static void
f7b839f7 488setup_section (ibfd, isection, obfd)
46050fe4
ILT
489 bfd *ibfd;
490 sec_ptr isection;
491 bfd *obfd;
c0367ba5 492{
46050fe4
ILT
493 sec_ptr osection;
494 char *err;
495
496 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
497 && (strip_symbols == strip_debug
498 || strip_symbols == strip_all
499 || discard_locals == locals_all))
500 return;
501
77ccab3c 502 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
46050fe4
ILT
503 if (osection == NULL)
504 {
77ccab3c
JL
505 err = "making";
506 goto loser;
c0367ba5
ILT
507 }
508
46050fe4
ILT
509 if (!bfd_set_section_size (obfd,
510 osection,
511 bfd_section_size (ibfd, isection)))
512 {
513 err = "size";
514 goto loser;
c0367ba5
ILT
515 }
516
46050fe4
ILT
517 if (bfd_set_section_vma (obfd,
518 osection,
519 bfd_section_vma (ibfd, isection))
520 == false)
521 {
522 err = "vma";
523 goto loser;
524 }
c0367ba5 525
46050fe4
ILT
526 if (bfd_set_section_alignment (obfd,
527 osection,
528 bfd_section_alignment (ibfd, isection))
529 == false)
530 {
531 err = "alignment";
532 goto loser;
533 }
c0367ba5 534
46050fe4
ILT
535 if (!bfd_set_section_flags (obfd, osection,
536 bfd_get_section_flags (ibfd, isection)))
537 {
538 err = "flags";
539 goto loser;
c0367ba5
ILT
540 }
541
c9563567
JL
542 /* This used to be mangle_section; we do here to avoid using
543 bfd_get_section_by_name since some formats allow multiple
544 sections with the same name. */
545 isection->output_section = osection;
546 isection->output_offset = 0;
547
77ccab3c
JL
548 /* Allow the BFD backend to copy any private data it understands
549 from the input section to the output section. */
550 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
551 {
552 err = "private data";
553 goto loser;
554 }
555
46050fe4
ILT
556 /* All went well */
557 return;
c0367ba5
ILT
558
559loser:
46050fe4
ILT
560 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
561 program_name,
562 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
c9563567 563 err, bfd_errmsg (bfd_get_error ()));
46050fe4
ILT
564 status = 1;
565}
566
567/* Copy the data of input section ISECTION of IBFD
568 to an output section with the same name in OBFD.
569 If stripping then don't copy any relocation info. */
570
c0367ba5 571static void
f7b839f7 572copy_section (ibfd, isection, obfd)
46050fe4
ILT
573 bfd *ibfd;
574 sec_ptr isection;
575 bfd *obfd;
c0367ba5 576{
46050fe4 577 arelent **relpp;
ae5d2ff5 578 long relcount;
46050fe4
ILT
579 sec_ptr osection;
580 bfd_size_type size;
581
582 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
583 && (strip_symbols == strip_debug
584 || strip_symbols == strip_all
585 || discard_locals == locals_all))
586 {
587 return;
588 }
c0367ba5 589
77ccab3c 590 osection = isection->output_section;
46050fe4 591 size = bfd_get_section_size_before_reloc (isection);
c0367ba5 592
77ccab3c 593 if (size == 0 || osection == 0)
c0367ba5
ILT
594 return;
595
ae5d2ff5
ILT
596 if (strip_symbols == strip_all)
597 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
46050fe4 598 else
c0367ba5 599 {
ae5d2ff5
ILT
600 long relsize;
601
602 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
603 if (relsize < 0)
604 {
605 nonfatal (bfd_get_filename (ibfd));
606 }
607 if (relsize == 0)
608 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
609 else
610 {
611 relpp = (arelent **) xmalloc (relsize);
612 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
613 if (relcount < 0)
614 {
615 nonfatal (bfd_get_filename (ibfd));
616 }
617 bfd_set_reloc (obfd, osection, relpp, relcount);
618 }
c0367ba5
ILT
619 }
620
621 isection->_cooked_size = isection->_raw_size;
46050fe4 622 isection->reloc_done = true;
c0367ba5 623
46050fe4 624 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 625 {
46050fe4 626 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 627
46050fe4
ILT
628 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
629 size))
630 {
631 nonfatal (bfd_get_filename (ibfd));
632 }
c0367ba5 633
6f9077cd
JM
634 if (copy_byte >= 0)
635 {
636 filter_bytes (memhunk, &size);
637 /* The section has gotten smaller. */
638 if (!bfd_set_section_size (obfd, osection, size))
639 nonfatal (bfd_get_filename (obfd));
640 }
f7b839f7 641
46050fe4
ILT
642 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
643 size))
644 {
645 nonfatal (bfd_get_filename (obfd));
646 }
647 free (memhunk);
c0367ba5 648 }
46050fe4 649}
c0367ba5 650
77ccab3c
JL
651/* Mark all the symbols which will be used in output relocations with
652 the BSF_KEEP flag so that those symbols will not be stripped.
653
654 Ignore relocations which will not appear in the output file. */
655
656static void
657mark_symbols_used_in_relocations (ibfd, isection, symbols)
658 bfd *ibfd;
659 sec_ptr isection;
660 asymbol **symbols;
661{
ae5d2ff5 662 long relsize;
77ccab3c 663 arelent **relpp;
ae5d2ff5 664 long relcount, i;
77ccab3c
JL
665
666 /* Ignore an input section with no corresponding output section. */
667 if (isection->output_section == NULL)
668 return;
669
ae5d2ff5
ILT
670 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
671 if (relsize < 0)
672 bfd_fatal (bfd_get_filename (ibfd));
673
674 relpp = (arelent **) xmalloc (relsize);
77ccab3c 675 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
ae5d2ff5
ILT
676 if (relcount < 0)
677 bfd_fatal (bfd_get_filename (ibfd));
77ccab3c
JL
678
679 /* Examine each symbol used in a relocation. If it's not one of the
680 special bfd section symbols, then mark it with BSF_KEEP. */
681 for (i = 0; i < relcount; i++)
682 {
683 if (*relpp[i]->sym_ptr_ptr != bfd_com_section.symbol
684 && *relpp[i]->sym_ptr_ptr != bfd_abs_section.symbol
685 && *relpp[i]->sym_ptr_ptr != bfd_und_section.symbol)
686 (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
687 }
688
689 if (relpp != NULL)
690 free (relpp);
691}
692
46050fe4
ILT
693/* The number of bytes to copy at once. */
694#define COPY_BUF 8192
695
696/* Copy file FROM to file TO, performing no translations.
697 Return 0 if ok, -1 if error. */
698
699static int
700simple_copy (from, to)
701 char *from, *to;
c0367ba5 702{
46050fe4
ILT
703 int fromfd, tofd, nread;
704 char buf[COPY_BUF];
705
706 fromfd = open (from, O_RDONLY);
707 if (fromfd < 0)
708 return -1;
709 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
710 if (tofd < 0)
711 {
712 close (fromfd);
713 return -1;
714 }
715 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
716 {
717 if (write (tofd, buf, nread) != nread)
718 {
719 close (fromfd);
720 close (tofd);
721 return -1;
722 }
723 }
724 close (fromfd);
725 close (tofd);
726 if (nread < 0)
727 return -1;
728 return 0;
729}
c0367ba5 730
46050fe4
ILT
731#ifndef S_ISLNK
732#ifdef S_IFLNK
733#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
734#else
735#define S_ISLNK(m) 0
736#define lstat stat
737#endif
738#endif
739
740/* Rename FROM to TO, copying if TO is a link.
741 Assumes that TO already exists, because FROM is a temp file.
742 Return 0 if ok, -1 if error. */
743
744static int
745smart_rename (from, to)
746 char *from, *to;
747{
748 struct stat s;
749 int ret = 0;
c0367ba5 750
46050fe4
ILT
751 if (lstat (to, &s))
752 return -1;
c0367ba5 753
46050fe4
ILT
754 /* Use rename only if TO is not a symbolic link and has
755 only one hard link. */
756 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
757 {
758 ret = rename (from, to);
759 if (ret == 0)
760 {
761 /* Try to preserve the permission bits and ownership of TO. */
762 chmod (to, s.st_mode & 07777);
763 chown (to, s.st_uid, s.st_gid);
764 }
765 }
766 else
767 {
768 ret = simple_copy (from, to);
769 if (ret == 0)
770 unlink (from);
771 }
772 return ret;
773}
774
775static int
776strip_main (argc, argv)
777 int argc;
778 char *argv[];
779{
780 char *input_target = NULL, *output_target = NULL;
781 boolean show_version = false;
782 int c, i;
783
784 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
785 strip_options, (int *) 0)) != EOF)
786 {
787 switch (c)
788 {
789 case 'I':
790 input_target = optarg;
704bbd0d 791 break;
46050fe4
ILT
792 case 'O':
793 output_target = optarg;
794 break;
795 case 'F':
796 input_target = output_target = optarg;
797 break;
798 case 's':
c0367ba5 799 strip_symbols = strip_all;
46050fe4
ILT
800 break;
801 case 'S':
802 case 'g':
803 strip_symbols = strip_debug;
804 break;
805 case 'x':
806 discard_locals = locals_all;
807 break;
808 case 'X':
809 discard_locals = locals_start_L;
810 break;
811 case 'v':
812 verbose = true;
813 break;
814 case 'V':
815 show_version = true;
816 break;
817 case 0:
818 break; /* we've been given a long option */
819 case 'h':
820 strip_usage (stdout, 0);
821 default:
822 strip_usage (stderr, 1);
823 }
824 }
825
826 if (show_version)
827 {
828 printf ("GNU %s version %s\n", program_name, program_version);
829 exit (0);
830 }
c0367ba5 831
46050fe4
ILT
832 /* Default is to strip all symbols. */
833 if (strip_symbols == strip_undef && discard_locals == locals_undef)
834 strip_symbols = strip_all;
835
836 if (output_target == (char *) NULL)
837 output_target = input_target;
838
839 i = optind;
840 if (i == argc)
841 strip_usage (stderr, 1);
842
843 for (; i < argc; i++)
844 {
845 int hold_status = status;
c0367ba5 846
46050fe4
ILT
847 char *tmpname = make_tempname (argv[i]);
848 status = 0;
849 copy_file (argv[i], tmpname, input_target, output_target);
850 if (status == 0)
851 {
852 smart_rename (tmpname, argv[i]);
853 status = hold_status;
c0367ba5 854 }
46050fe4
ILT
855 else
856 unlink (tmpname);
857 free (tmpname);
858 }
859
860 return 0;
861}
862
863static int
864copy_main (argc, argv)
865 int argc;
866 char *argv[];
867{
868 char *input_filename, *output_filename;
869 char *input_target = NULL, *output_target = NULL;
870 boolean show_version = false;
871 int c;
872
f7b839f7 873 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
46050fe4
ILT
874 copy_options, (int *) 0)) != EOF)
875 {
876 switch (c)
877 {
f7b839f7
DM
878 case 'b':
879 copy_byte = atoi(optarg);
880 if (copy_byte < 0)
881 {
882 fprintf (stderr, "%s: byte number must be non-negative\n",
883 program_name);
884 exit (1);
885 }
886 break;
887 case 'i':
888 interleave = atoi(optarg);
889 if (interleave < 1)
890 {
891 fprintf(stderr, "%s: interleave must be positive\n",
892 program_name);
893 exit (1);
894 }
895 break;
c0367ba5 896 case 'I':
46050fe4 897 case 's': /* "source" - 'I' is preferred */
c0367ba5 898 input_target = optarg;
704bbd0d 899 break;
c0367ba5 900 case 'O':
46050fe4 901 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
902 output_target = optarg;
903 break;
904 case 'F':
c0367ba5
ILT
905 input_target = output_target = optarg;
906 break;
c0367ba5
ILT
907 case 'S':
908 strip_symbols = strip_all;
909 break;
910 case 'g':
911 strip_symbols = strip_debug;
912 break;
913 case 'x':
914 discard_locals = locals_all;
915 break;
916 case 'X':
917 discard_locals = locals_start_L;
918 break;
919 case 'v':
920 verbose = true;
921 break;
922 case 'V':
923 show_version = true;
924 break;
46050fe4 925 case 0:
c0367ba5
ILT
926 break; /* we've been given a long option */
927 case 'h':
928 copy_usage (stdout, 0);
929 default:
930 copy_usage (stderr, 1);
46050fe4
ILT
931 }
932 }
933
934 if (show_version)
935 {
936 printf ("GNU %s version %s\n", program_name, program_version);
937 exit (0);
938 }
c0367ba5 939
f7b839f7
DM
940 if (copy_byte >= interleave)
941 {
942 fprintf (stderr, "%s: byte number must be less than interleave\n",
943 program_name);
944 exit (1);
945 }
946
46050fe4
ILT
947 if (optind == argc || optind + 2 < argc)
948 copy_usage (stderr, 1);
c0367ba5
ILT
949
950 input_filename = argv[optind];
951 if (optind + 1 < argc)
46050fe4 952 output_filename = argv[optind + 1];
c0367ba5
ILT
953
954 /* Default is to strip no symbols. */
955 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 956 strip_symbols = strip_none;
c0367ba5
ILT
957
958 if (output_target == (char *) NULL)
959 output_target = input_target;
960
46050fe4
ILT
961 /* If there is no destination file then create a temp and rename
962 the result into the input. */
963
964 if (output_filename == (char *) NULL)
965 {
966 char *tmpname = make_tempname (input_filename);
967 copy_file (input_filename, tmpname, input_target, output_target);
968 if (status == 0)
969 smart_rename (tmpname, input_filename);
970 else
971 unlink (tmpname);
972 }
973 else
974 {
975 copy_file (input_filename, output_filename, input_target, output_target);
976 }
977
c0367ba5
ILT
978 return 0;
979}
46050fe4
ILT
980
981int
982main (argc, argv)
983 int argc;
984 char *argv[];
985{
986 program_name = argv[0];
704bbd0d 987 xmalloc_set_program_name (program_name);
46050fe4
ILT
988 strip_symbols = strip_undef;
989 discard_locals = locals_undef;
990
991 bfd_init ();
992
993 if (is_strip < 0)
994 {
995 int i = strlen (program_name);
996 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
997 }
998
999 if (is_strip)
1000 strip_main (argc, argv);
1001 else
1002 copy_main (argc, argv);
1003
1004 return status;
1005}
This page took 0.200112 seconds and 4 git commands to generate.