* hosts/sysv4.h: Include <unistd.h>, <stdlib.h>, and <time.h>.
[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>
6c7ed084 24#include "libiberty.h"
c0367ba5 25
6c7ed084
ILT
26static bfd_vma parse_vma PARAMS ((const char *, const char *));
27static void setup_section PARAMS ((bfd *, asection *, PTR));
28static void copy_section PARAMS ((bfd *, asection *, PTR));
596d99ba
ILT
29static void get_sections PARAMS ((bfd *, asection *, PTR));
30static int compare_section_vma PARAMS ((const PTR, const PTR));
4af19c61
KR
31static void add_strip_symbol PARAMS ((const char *));
32static int is_strip_symbol PARAMS ((const char *));
33static unsigned int filter_symbols
34 PARAMS ((bfd *, asymbol **, asymbol **, long));
6c7ed084 35static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
c0367ba5 36
46050fe4 37#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
c0367ba5 38
46050fe4
ILT
39static asymbol **isympp = NULL; /* Input symbols */
40static asymbol **osympp = NULL; /* Output symbols that survive stripping */
f7b839f7
DM
41
42/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
43static int copy_byte = -1;
44static int interleave = 4;
45
46050fe4 46static boolean verbose; /* Print file and target names. */
f7b839f7 47static int status = 0; /* Exit status. */
c0367ba5
ILT
48
49enum strip_action
46050fe4
ILT
50 {
51 strip_undef,
52 strip_none, /* don't strip */
53 strip_debug, /* strip all debugger symbols */
54 strip_all /* strip all symbols */
55 };
c0367ba5
ILT
56
57/* Which symbols to remove. */
46050fe4 58static enum strip_action strip_symbols;
c0367ba5
ILT
59
60enum locals_action
46050fe4
ILT
61 {
62 locals_undef,
63 locals_start_L, /* discard locals starting with L */
64 locals_all /* discard all locals */
65 };
66
67/* Which local symbols to remove. Overrides strip_all. */
68static enum locals_action discard_locals;
69
6c7ed084
ILT
70/* Structure used to hold lists of sections and actions to take. */
71
72struct section_list
73{
74 /* Next section to adjust. */
75 struct section_list *next;
76 /* Section name. */
77 const char *name;
78 /* Whether this entry was used. */
79 boolean used;
80 /* Remaining fields only used if not on remove_sections list. */
81 /* Whether to adjust or set VMA. */
82 boolean adjust;
83 /* Amount to adjust by or set to. */
84 bfd_vma val;
85};
86
87/* List of sections to remove. */
88
89static struct section_list *remove_sections;
90
91/* Adjustments to the start address. */
92static bfd_vma adjust_start = 0;
93static boolean set_start_set = false;
94static bfd_vma set_start;
95
96/* Adjustments to section VMA's. */
97static bfd_vma adjust_section_vma = 0;
98static struct section_list *adjust_sections;
99
596d99ba
ILT
100/* Filling gaps between sections. */
101static boolean gap_fill_set = false;
87a15686
ILT
102static bfd_byte gap_fill = 0;
103
104/* Pad to a given address. */
105static boolean pad_to_set = false;
106static bfd_vma pad_to;
596d99ba 107
46050fe4
ILT
108/* Options to handle if running as "strip". */
109
110static struct option strip_options[] =
c0367ba5 111{
46050fe4
ILT
112 {"discard-all", no_argument, 0, 'x'},
113 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 114 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 115 {"help", no_argument, 0, 'h'},
46050fe4 116 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7 117 {"input-target", required_argument, 0, 'I'},
46050fe4 118 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7 119 {"output-target", required_argument, 0, 'O'},
6c7ed084 120 {"remove-section", required_argument, 0, 'R'},
f7b839f7
DM
121 {"strip-all", no_argument, 0, 's'},
122 {"strip-debug", no_argument, 0, 'S'},
4af19c61 123 {"strip-symbol", required_argument, 0, 'N'},
46050fe4 124 {"target", required_argument, 0, 'F'},
46050fe4 125 {"verbose", no_argument, 0, 'v'},
f7b839f7 126 {"version", no_argument, 0, 'V'},
46050fe4 127 {0, no_argument, 0, 0}
c0367ba5
ILT
128};
129
46050fe4 130/* Options to handle if running as "objcopy". */
c0367ba5 131
6c7ed084
ILT
132/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
133
134#define OPTION_ADJUST_START 150
135#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1)
136#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1)
137#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1)
596d99ba
ILT
138#define OPTION_GAP_FILL (OPTION_ADJUST_WARNINGS + 1)
139#define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1)
87a15686
ILT
140#define OPTION_PAD_TO (OPTION_NO_ADJUST_WARNINGS + 1)
141#define OPTION_SET_START (OPTION_PAD_TO + 1)
6c7ed084 142
46050fe4
ILT
143static struct option copy_options[] =
144{
6c7ed084
ILT
145 {"adjust-start", required_argument, 0, OPTION_ADJUST_START},
146 {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA},
147 {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA},
148 {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS},
f7b839f7 149 {"byte", required_argument, 0, 'b'},
46050fe4
ILT
150 {"discard-all", no_argument, 0, 'x'},
151 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 152 {"format", required_argument, 0, 'F'}, /* Obsolete */
596d99ba 153 {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
46050fe4 154 {"help", no_argument, 0, 'h'},
46050fe4 155 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7
DM
156 {"input-target", required_argument, 0, 'I'},
157 {"interleave", required_argument, 0, 'i'},
6c7ed084 158 {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS},
46050fe4 159 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7 160 {"output-target", required_argument, 0, 'O'},
87a15686 161 {"pad-to", required_argument, 0, OPTION_PAD_TO},
6c7ed084
ILT
162 {"remove-section", required_argument, 0, 'R'},
163 {"set-start", required_argument, 0, OPTION_SET_START},
f7b839f7
DM
164 {"strip-all", no_argument, 0, 'S'},
165 {"strip-debug", no_argument, 0, 'g'},
4af19c61 166 {"strip-symbol", required_argument, 0, 'N'},
46050fe4 167 {"target", required_argument, 0, 'F'},
46050fe4 168 {"verbose", no_argument, 0, 'v'},
f7b839f7 169 {"version", no_argument, 0, 'V'},
46050fe4 170 {0, no_argument, 0, 0}
c0367ba5
ILT
171};
172
173/* IMPORTS */
46050fe4
ILT
174extern char *program_name;
175extern char *program_version;
176
177/* This flag distinguishes between strip and objcopy:
178 1 means this is 'strip'; 0 means this is 'objcopy'.
179 -1 means if we should use argv[0] to decide. */
180extern int is_strip;
c0367ba5
ILT
181
182
46050fe4
ILT
183static void
184copy_usage (stream, status)
c0367ba5
ILT
185 FILE *stream;
186 int status;
187{
46050fe4 188 fprintf (stream, "\
f7b839f7 189Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
6c7ed084 190 [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
46050fe4
ILT
191 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
192 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
87a15686
ILT
193 [--remove-section=section] [--gap-fill=val] [--pad-to=address]\n\
194 [--set-start=val] [--adjust-start=incr] [--adjust-vma=incr]\n\
596d99ba
ILT
195 [--adjust-section-vma=section{=,+,-}val] [--adjust-warnings]\n\
196 [--no-adjust-warnings] [--verbose] [--version] [--help]\n\
4af19c61 197 [--strip-symbol symbol] [-N symbol]\n\
596d99ba 198 in-file [out-file]\n",
f7b839f7 199 program_name);
46050fe4 200 exit (status);
c0367ba5
ILT
201}
202
46050fe4
ILT
203static void
204strip_usage (stream, status)
c0367ba5
ILT
205 FILE *stream;
206 int status;
207{
46050fe4 208 fprintf (stream, "\
6c7ed084 209Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
46050fe4
ILT
210 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
211 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
4af19c61 212 [--strip-symbol symbol] [-N symbol]\n\
6c7ed084 213 [--remove-section=section] [--verbose] [--version] [--help] file...\n",
46050fe4
ILT
214 program_name);
215 exit (status);
c0367ba5
ILT
216}
217
6c7ed084
ILT
218/* Parse a string into a VMA, with a fatal error if it can't be
219 parsed. */
220
221static bfd_vma
222parse_vma (s, arg)
223 const char *s;
224 const char *arg;
225{
226 bfd_vma ret;
227 const char *end;
228
229 ret = bfd_scan_vma (s, &end, 0);
230 if (*end != '\0')
231 {
232 fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s);
233 exit (1);
234 }
235 return ret;
236}
c0367ba5 237
46050fe4 238/* Return the name of a temporary file in the same directory as FILENAME. */
c0367ba5 239
46050fe4
ILT
240static char *
241make_tempname (filename)
242 char *filename;
c0367ba5 243{
46050fe4
ILT
244 static char template[] = "stXXXXXX";
245 char *tmpname;
246 char *slash = strrchr (filename, '/');
247
248 if (slash != (char *) NULL)
249 {
250 *slash = 0;
251 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
252 strcpy (tmpname, filename);
253 strcat (tmpname, "/");
254 strcat (tmpname, template);
255 mktemp (tmpname);
256 *slash = '/';
257 }
258 else
259 {
260 tmpname = xmalloc (sizeof (template));
261 strcpy (tmpname, template);
262 mktemp (tmpname);
c0367ba5 263 }
46050fe4 264 return tmpname;
c0367ba5
ILT
265}
266
4af19c61
KR
267/* Make a list of symbols to explicitly strip out. A linked list is
268 good enough for a small number from the command line, but this will
269 slow things down a lot if many symbols are being deleted. */
270
271struct symlist
272{
273 const char *name;
274 struct symlist *next;
275};
276
277static struct symlist *strip_specific_list = NULL;
278
279static void
280add_strip_symbol (name)
281 const char *name;
282{
283 struct symlist *tmp_list;
284
285 tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist));
286 tmp_list->name = name;
287 tmp_list->next = strip_specific_list;
288 strip_specific_list = tmp_list;
289}
290
291static int
292is_strip_symbol (name)
293 const char *name;
294{
295 struct symlist *tmp_list;
296
297 for (tmp_list = strip_specific_list; tmp_list; tmp_list = tmp_list->next)
298 {
299 if (strcmp (name, tmp_list->name) == 0)
300 return 1;
301 }
302 return 0;
303}
304
46050fe4 305/* Choose which symbol entries to copy; put the result in OSYMS.
c0367ba5 306 We don't copy in place, because that confuses the relocs.
46050fe4
ILT
307 Return the number of symbols to print. */
308
c0367ba5
ILT
309static unsigned int
310filter_symbols (abfd, osyms, isyms, symcount)
311 bfd *abfd;
312 asymbol **osyms, **isyms;
ae5d2ff5 313 long symcount;
c0367ba5
ILT
314{
315 register asymbol **from = isyms, **to = osyms;
ae5d2ff5 316 long src_count = 0, dst_count = 0;
c0367ba5 317
46050fe4
ILT
318 for (; src_count < symcount; src_count++)
319 {
320 asymbol *sym = from[src_count];
321 flagword flags = sym->flags;
322 int keep;
c0367ba5 323
46050fe4 324 if ((flags & BSF_GLOBAL) /* Keep if external. */
77ccab3c 325 || (flags & BSF_KEEP) /* Keep if used in a relocation. */
6c7ed084 326 || bfd_is_und_section (bfd_get_section (sym))
46050fe4
ILT
327 || bfd_is_com_section (bfd_get_section (sym)))
328 keep = 1;
329 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
330 keep = strip_symbols != strip_debug;
331 else /* Local symbol. */
332 keep = discard_locals != locals_all
333 && (discard_locals != locals_start_L ||
77ccab3c 334 ! bfd_is_local_label (abfd, sym));
4af19c61
KR
335
336 if (keep && is_strip_symbol (bfd_asymbol_name (sym)))
337 keep = 0;
338
46050fe4
ILT
339 if (keep)
340 to[dst_count++] = sym;
c0367ba5 341 }
c0367ba5
ILT
342
343 return dst_count;
344}
345
f7b839f7
DM
346/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
347 Adjust *SIZE. */
348
349void
350filter_bytes (memhunk, size)
5d2f7e30 351 char *memhunk;
f7b839f7
DM
352 bfd_size_type *size;
353{
354 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
355
356 for (; from < end; from += interleave)
357 *to++ = *from;
358 *size /= interleave;
359}
360
46050fe4
ILT
361/* Copy object file IBFD onto OBFD. */
362
c0367ba5 363static void
46050fe4
ILT
364copy_object (ibfd, obfd)
365 bfd *ibfd;
366 bfd *obfd;
c0367ba5 367{
6c7ed084 368 bfd_vma start;
ae5d2ff5 369 long symcount;
596d99ba
ILT
370 asection **osections = NULL;
371 bfd_size_type *gaps = NULL;
372 bfd_size_type max_gap = 0;
c0367ba5 373
46050fe4
ILT
374 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
375 {
376 nonfatal (bfd_get_filename (obfd));
377 }
c0367ba5 378
46050fe4
ILT
379 if (verbose)
380 printf ("copy from %s(%s) to %s(%s)\n",
381 bfd_get_filename(ibfd), bfd_get_target(ibfd),
382 bfd_get_filename(obfd), bfd_get_target(obfd));
c0367ba5 383
6c7ed084
ILT
384 if (set_start_set)
385 start = set_start;
386 else
a6afc090 387 start = bfd_get_start_address (ibfd);
6c7ed084
ILT
388 start += adjust_start;
389
390 if (!bfd_set_start_address (obfd, start)
46050fe4
ILT
391 || !bfd_set_file_flags (obfd,
392 (bfd_get_file_flags (ibfd)
393 & bfd_applicable_file_flags (obfd))))
394 {
395 nonfatal (bfd_get_filename (ibfd));
396 }
c0367ba5 397
46050fe4
ILT
398 /* Copy architecture of input file to output file */
399 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
400 bfd_get_mach (ibfd)))
401 {
402 fprintf (stderr, "Output file cannot represent architecture %s\n",
403 bfd_printable_arch_mach (bfd_get_arch (ibfd),
404 bfd_get_mach (ibfd)));
405 }
406 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
407 {
408 nonfatal (bfd_get_filename(ibfd));
409 }
c0367ba5 410
46050fe4
ILT
411 if (isympp)
412 free (isympp);
413 if (osympp != isympp)
414 free (osympp);
c0367ba5 415
77ccab3c
JL
416 /* bfd mandates that all output sections be created and sizes set before
417 any output is done. Thus, we traverse all sections multiple times. */
418 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
419
87a15686 420 if (gap_fill_set || pad_to_set)
596d99ba
ILT
421 {
422 asection **set;
423 unsigned int c, i;
424
87a15686
ILT
425 /* We must fill in gaps between the sections and/or we must pad
426 the last section to a specified address. We do this by
596d99ba 427 grabbing a list of the sections, sorting them by VMA, and
87a15686
ILT
428 increasing the section sizes as required to fill the gaps.
429 We write out the gap contents below. */
596d99ba
ILT
430
431 c = bfd_count_sections (obfd);
432 osections = (asection **) xmalloc (c * sizeof (asection *));
433 set = osections;
434 bfd_map_over_sections (obfd, get_sections, (void *) &set);
435
436 qsort (osections, c, sizeof (asection *), compare_section_vma);
437
438 gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
87a15686
ILT
439 memset (gaps, 0, c * sizeof (bfd_size_type));
440
441 if (gap_fill_set)
442 {
443 for (i = 0; i < c - 1; i++)
444 {
445 flagword flags;
446 bfd_size_type size;
447 bfd_vma gap_start, gap_stop;
448
449 flags = bfd_get_section_flags (obfd, osections[i]);
450 if ((flags & SEC_HAS_CONTENTS) == 0
451 || (flags & SEC_LOAD) == 0)
452 continue;
453
454 size = bfd_section_size (obfd, osections[i]);
455 gap_start = bfd_section_vma (obfd, osections[i]) + size;
456 gap_stop = bfd_section_vma (obfd, osections[i + 1]);
457 if (gap_start < gap_stop)
458 {
459 if (! bfd_set_section_size (obfd, osections[i],
460 size + (gap_stop - gap_start)))
461 {
462 fprintf (stderr, "%s: Can't fill gap after %s: %s\n",
463 program_name,
464 bfd_get_section_name (obfd, osections[i]),
465 bfd_errmsg (bfd_get_error()));
466 status = 1;
467 break;
468 }
469 gaps[i] = gap_stop - gap_start;
470 if (max_gap < gap_stop - gap_start)
471 max_gap = gap_stop - gap_start;
472 }
473 }
474 }
475
476 if (pad_to_set)
596d99ba 477 {
87a15686 478 bfd_vma vma;
596d99ba 479 bfd_size_type size;
87a15686
ILT
480
481 vma = bfd_section_vma (obfd, osections[c - 1]);
482 size = bfd_section_size (obfd, osections[c - 1]);
483 if (vma + size < pad_to)
596d99ba 484 {
87a15686
ILT
485 if (! bfd_set_section_size (obfd, osections[c - 1],
486 pad_to - vma))
596d99ba 487 {
87a15686 488 fprintf (stderr, "%s: Can't add padding to %s: %s\n",
596d99ba 489 program_name,
87a15686
ILT
490 bfd_get_section_name (obfd, osections[c - 1]),
491 bfd_errmsg (bfd_get_error ()));
596d99ba 492 status = 1;
596d99ba 493 }
87a15686
ILT
494 else
495 {
496 gaps[c - 1] = pad_to - (vma + size);
497 if (max_gap < pad_to - (vma + size))
498 max_gap = pad_to - (vma + size);
499 }
596d99ba 500 }
87a15686 501 }
596d99ba
ILT
502 }
503
77ccab3c
JL
504 /* Symbol filtering must happen after the output sections have
505 been created, but before their contents are set. */
46050fe4
ILT
506 if (strip_symbols == strip_all && discard_locals == locals_undef)
507 {
508 osympp = isympp = NULL;
509 symcount = 0;
c0367ba5 510 }
46050fe4
ILT
511 else
512 {
ae5d2ff5
ILT
513 long symsize;
514
515 symsize = bfd_get_symtab_upper_bound (ibfd);
516 if (symsize < 0)
517 {
518 nonfatal (bfd_get_filename (ibfd));
519 }
520
521 osympp = isympp = (asymbol **) xmalloc (symsize);
46050fe4 522 symcount = bfd_canonicalize_symtab (ibfd, isympp);
ae5d2ff5
ILT
523 if (symcount < 0)
524 {
525 nonfatal (bfd_get_filename (ibfd));
526 }
46050fe4 527
4af19c61
KR
528 if (strip_symbols == strip_debug
529 || discard_locals != locals_undef
530 || strip_specific_list)
c0367ba5 531 {
77ccab3c
JL
532 /* Mark symbols used in output relocations so that they
533 are kept, even if they are local labels or static symbols.
534
535 Note we iterate over the input sections examining their
536 relocations since the relocations for the output sections
537 haven't been set yet. mark_symbols_used_in_relocations will
538 ignore input sections which have no corresponding output
539 section. */
540 bfd_map_over_sections (ibfd,
541 mark_symbols_used_in_relocations,
6c7ed084 542 (PTR)isympp);
46050fe4
ILT
543 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
544 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
c0367ba5 545 }
46050fe4
ILT
546 }
547
548 bfd_set_symtab (obfd, osympp, symcount);
c0367ba5 549
77ccab3c 550 /* This has to happen after the symbol table has been set. */
f7b839f7 551 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
6f9077cd 552
87a15686 553 if (gap_fill_set || pad_to_set)
596d99ba
ILT
554 {
555 bfd_byte *buf;
556 int c, i;
557
558 /* Fill in the gaps. */
559
560 if (max_gap > 8192)
561 max_gap = 8192;
562 buf = (bfd_byte *) xmalloc (max_gap);
563 memset (buf, gap_fill, max_gap);
564
565 c = bfd_count_sections (obfd);
87a15686 566 for (i = 0; i < c; i++)
596d99ba
ILT
567 {
568 if (gaps[i] != 0)
569 {
570 bfd_size_type left;
571 file_ptr off;
572
573 left = gaps[i];
574 off = bfd_section_size (obfd, osections[i]) - left;
575 while (left > 0)
576 {
577 bfd_size_type now;
578
579 if (left > 8192)
580 now = 8192;
581 else
582 now = left;
583 if (! bfd_set_section_contents (obfd, osections[i], buf,
584 off, now))
585 {
586 nonfatal (bfd_get_filename (obfd));
596d99ba
ILT
587 }
588 left -= now;
589 off += now;
590 }
591 }
592 }
593 }
594
6f9077cd
JM
595 /* Allow the BFD backend to copy any private data it understands
596 from the input BFD to the output BFD. This is done last to
597 permit the routine to look at the filtered symbol table, which is
598 important for the ECOFF code at least. */
599 if (!bfd_copy_private_bfd_data (ibfd, obfd))
600 {
601 fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
602 program_name, bfd_get_filename (obfd),
603 bfd_errmsg (bfd_get_error ()));
604 status = 1;
605 return;
606 }
c0367ba5 607}
46050fe4
ILT
608
609static char *
610cat (a, b, c)
611 char *a;
612 char *b;
613 char *c;
c0367ba5 614{
46050fe4
ILT
615 size_t size = strlen (a) + strlen (b) + strlen (c);
616 char *r = xmalloc (size + 1);
617
618 strcpy (r, a);
619 strcat (r, b);
620 strcat (r, c);
621 return r;
c0367ba5
ILT
622}
623
46050fe4
ILT
624/* Read each archive element in turn from IBFD, copy the
625 contents to temp file, and keep the temp file handle. */
626
627static void
628copy_archive (ibfd, obfd, output_target)
629 bfd *ibfd;
630 bfd *obfd;
631 char *output_target;
c0367ba5 632{
87a15686
ILT
633 struct name_list
634 {
635 struct name_list *next;
636 char *name;
637 } *list, *l;
46050fe4
ILT
638 bfd **ptr = &obfd->archive_head;
639 bfd *this_element;
90f6517d 640 char *dir = make_tempname (bfd_get_filename (obfd));
46050fe4
ILT
641
642 /* Make a temp directory to hold the contents. */
90f6517d 643 mkdir (dir, 0700);
46050fe4
ILT
644 obfd->has_armap = ibfd->has_armap;
645
87a15686
ILT
646 list = NULL;
647
46050fe4 648 this_element = bfd_openr_next_archived_file (ibfd, NULL);
46050fe4
ILT
649 while (this_element != (bfd *) NULL)
650 {
651 /* Create an output file for this member. */
652 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
653 bfd *output_bfd = bfd_openw (output_name, output_target);
87a15686
ILT
654 bfd *last_element;
655
656 l = (struct name_list *) xmalloc (sizeof (struct name_list));
657 l->name = output_name;
658 l->next = list;
659 list = l;
46050fe4
ILT
660
661 if (output_bfd == (bfd *) NULL)
662 {
663 nonfatal (output_name);
c0367ba5 664 }
46050fe4
ILT
665 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
666 {
667 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
668 }
669
46050fe4
ILT
670 if (bfd_check_format (this_element, bfd_object) == true)
671 {
672 copy_object (this_element, output_bfd);
673 }
c0367ba5 674
46050fe4 675 bfd_close (output_bfd);
87a15686
ILT
676
677 /* Open the newly output file and attach to our list. */
46050fe4 678 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 679
46050fe4
ILT
680 *ptr = output_bfd;
681 ptr = &output_bfd->next;
87a15686
ILT
682
683 last_element = this_element;
684
685 this_element = bfd_openr_next_archived_file (ibfd, last_element);
686
687 bfd_close (last_element);
c0367ba5 688 }
46050fe4 689 *ptr = (bfd *) NULL;
c0367ba5 690
46050fe4
ILT
691 if (!bfd_close (obfd))
692 {
693 nonfatal (bfd_get_filename (obfd));
c0367ba5 694 }
c0367ba5 695
87a15686
ILT
696 /* Delete all the files that we opened. */
697 for (l = list; l != NULL; l = l->next)
698 unlink (l->name);
46050fe4 699 rmdir (dir);
87a15686 700
46050fe4
ILT
701 if (!bfd_close (ibfd))
702 {
703 nonfatal (bfd_get_filename (ibfd));
704 }
c0367ba5
ILT
705}
706
46050fe4
ILT
707/* The top-level control. */
708
709static void
710copy_file (input_filename, output_filename, input_target, output_target)
711 char *input_filename;
712 char *output_filename;
713 char *input_target;
714 char *output_target;
c0367ba5 715{
46050fe4 716 bfd *ibfd;
cef35d48 717 char **matching;
c0367ba5
ILT
718
719 /* To allow us to do "strip *" without dying on the first
720 non-object file, failures are nonfatal. */
721
46050fe4 722 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
723 if (ibfd == NULL)
724 {
46050fe4 725 nonfatal (input_filename);
c0367ba5
ILT
726 }
727
cef35d48
DM
728 if (bfd_check_format (ibfd, bfd_archive))
729 {
6c7ed084
ILT
730 bfd *obfd;
731
732 /* bfd_get_target does not return the correct value until
733 bfd_check_format succeeds. */
734 if (output_target == NULL)
735 output_target = bfd_get_target (ibfd);
736
737 obfd = bfd_openw (output_filename, output_target);
cef35d48
DM
738 if (obfd == NULL)
739 {
740 nonfatal (output_filename);
741 }
742 copy_archive (ibfd, obfd, output_target);
743 }
744 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4 745 {
6c7ed084
ILT
746 bfd *obfd;
747
748 /* bfd_get_target does not return the correct value until
749 bfd_check_format succeeds. */
750 if (output_target == NULL)
751 output_target = bfd_get_target (ibfd);
752
753 obfd = bfd_openw (output_filename, output_target);
46050fe4
ILT
754 if (obfd == NULL)
755 {
756 nonfatal (output_filename);
757 }
c0367ba5 758
46050fe4 759 copy_object (ibfd, obfd);
c0367ba5 760
46050fe4
ILT
761 if (!bfd_close (obfd))
762 {
763 nonfatal (output_filename);
764 }
765
766 if (!bfd_close (ibfd))
767 {
768 nonfatal (input_filename);
769 }
770 }
cef35d48 771 else
46050fe4 772 {
cef35d48 773 bfd_nonfatal (input_filename);
c9563567 774 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
46050fe4 775 {
cef35d48
DM
776 list_matching_formats (matching);
777 free (matching);
46050fe4 778 }
cef35d48 779 status = 1;
46050fe4
ILT
780 }
781}
782
783/* Create a section in OBFD with the same name and attributes
784 as ISECTION in IBFD. */
c0367ba5 785
c0367ba5 786static void
6c7ed084 787setup_section (ibfd, isection, obfdarg)
46050fe4
ILT
788 bfd *ibfd;
789 sec_ptr isection;
6c7ed084 790 PTR obfdarg;
c0367ba5 791{
6c7ed084
ILT
792 bfd *obfd = (bfd *) obfdarg;
793 struct section_list *p;
46050fe4 794 sec_ptr osection;
6c7ed084 795 bfd_vma vma;
46050fe4
ILT
796 char *err;
797
798 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
799 && (strip_symbols == strip_debug
800 || strip_symbols == strip_all
801 || discard_locals == locals_all))
802 return;
803
6c7ed084
ILT
804 for (p = remove_sections; p != NULL; p = p->next)
805 {
806 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
807 {
808 p->used = true;
809 return;
810 }
811 }
812
77ccab3c 813 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
46050fe4
ILT
814 if (osection == NULL)
815 {
77ccab3c
JL
816 err = "making";
817 goto loser;
c0367ba5
ILT
818 }
819
46050fe4
ILT
820 if (!bfd_set_section_size (obfd,
821 osection,
822 bfd_section_size (ibfd, isection)))
823 {
824 err = "size";
825 goto loser;
c0367ba5
ILT
826 }
827
6c7ed084
ILT
828 vma = bfd_section_vma (ibfd, isection);
829 for (p = adjust_sections; p != NULL; p = p->next)
830 {
831 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
832 {
833 if (p->adjust)
834 vma += p->val;
835 else
836 vma = p->val;
837 p->used = true;
838 break;
839 }
840 }
841 if (p == NULL)
842 vma += adjust_section_vma;
843
844 if (! bfd_set_section_vma (obfd, osection, vma))
46050fe4
ILT
845 {
846 err = "vma";
847 goto loser;
848 }
c0367ba5 849
46050fe4
ILT
850 if (bfd_set_section_alignment (obfd,
851 osection,
852 bfd_section_alignment (ibfd, isection))
853 == false)
854 {
855 err = "alignment";
856 goto loser;
857 }
c0367ba5 858
46050fe4
ILT
859 if (!bfd_set_section_flags (obfd, osection,
860 bfd_get_section_flags (ibfd, isection)))
861 {
862 err = "flags";
863 goto loser;
c0367ba5
ILT
864 }
865
c9563567
JL
866 /* This used to be mangle_section; we do here to avoid using
867 bfd_get_section_by_name since some formats allow multiple
868 sections with the same name. */
869 isection->output_section = osection;
870 isection->output_offset = 0;
871
77ccab3c
JL
872 /* Allow the BFD backend to copy any private data it understands
873 from the input section to the output section. */
874 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
875 {
876 err = "private data";
877 goto loser;
878 }
879
46050fe4
ILT
880 /* All went well */
881 return;
c0367ba5
ILT
882
883loser:
46050fe4
ILT
884 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
885 program_name,
886 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
c9563567 887 err, bfd_errmsg (bfd_get_error ()));
46050fe4
ILT
888 status = 1;
889}
890
891/* Copy the data of input section ISECTION of IBFD
892 to an output section with the same name in OBFD.
893 If stripping then don't copy any relocation info. */
894
c0367ba5 895static void
6c7ed084 896copy_section (ibfd, isection, obfdarg)
46050fe4
ILT
897 bfd *ibfd;
898 sec_ptr isection;
6c7ed084 899 PTR obfdarg;
c0367ba5 900{
6c7ed084
ILT
901 bfd *obfd = (bfd *) obfdarg;
902 struct section_list *p;
46050fe4 903 arelent **relpp;
ae5d2ff5 904 long relcount;
46050fe4
ILT
905 sec_ptr osection;
906 bfd_size_type size;
907
908 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
909 && (strip_symbols == strip_debug
910 || strip_symbols == strip_all
911 || discard_locals == locals_all))
912 {
913 return;
914 }
c0367ba5 915
6c7ed084
ILT
916 for (p = remove_sections; p != NULL; p = p->next)
917 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
918 return;
919
77ccab3c 920 osection = isection->output_section;
46050fe4 921 size = bfd_get_section_size_before_reloc (isection);
c0367ba5 922
77ccab3c 923 if (size == 0 || osection == 0)
c0367ba5
ILT
924 return;
925
ae5d2ff5
ILT
926 if (strip_symbols == strip_all)
927 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
46050fe4 928 else
c0367ba5 929 {
ae5d2ff5
ILT
930 long relsize;
931
932 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
933 if (relsize < 0)
934 {
935 nonfatal (bfd_get_filename (ibfd));
936 }
937 if (relsize == 0)
938 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
939 else
940 {
941 relpp = (arelent **) xmalloc (relsize);
942 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
943 if (relcount < 0)
944 {
945 nonfatal (bfd_get_filename (ibfd));
946 }
947 bfd_set_reloc (obfd, osection, relpp, relcount);
948 }
c0367ba5
ILT
949 }
950
951 isection->_cooked_size = isection->_raw_size;
46050fe4 952 isection->reloc_done = true;
c0367ba5 953
46050fe4 954 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 955 {
46050fe4 956 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 957
46050fe4
ILT
958 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
959 size))
960 {
961 nonfatal (bfd_get_filename (ibfd));
962 }
c0367ba5 963
6f9077cd
JM
964 if (copy_byte >= 0)
965 {
966 filter_bytes (memhunk, &size);
967 /* The section has gotten smaller. */
968 if (!bfd_set_section_size (obfd, osection, size))
969 nonfatal (bfd_get_filename (obfd));
970 }
f7b839f7 971
46050fe4
ILT
972 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
973 size))
974 {
975 nonfatal (bfd_get_filename (obfd));
976 }
977 free (memhunk);
c0367ba5 978 }
46050fe4 979}
c0367ba5 980
87a15686
ILT
981/* Get all the sections. This is used when --gap-fill or --pad-to is
982 used. */
596d99ba
ILT
983
984static void
985get_sections (obfd, osection, secppparg)
986 bfd *obfd;
987 asection *osection;
988 PTR secppparg;
989{
990 asection ***secppp = (asection ***) secppparg;
991
992 **secppp = osection;
993 ++(*secppp);
994}
995
996/* Sort sections by VMA. This is called via qsort, and is used when
87a15686
ILT
997 --gap-fill or --pad-to is used. We force non loadable or empty
998 sections to the front, where they are easier to ignore. */
596d99ba
ILT
999
1000static int
1001compare_section_vma (arg1, arg2)
1002 const PTR arg1;
1003 const PTR arg2;
1004{
1005 const asection **sec1 = (const asection **) arg1;
1006 const asection **sec2 = (const asection **) arg2;
87a15686
ILT
1007 flagword flags1, flags2;
1008
1009 /* Sort non loadable sections to the front. */
1010 flags1 = (*sec1)->flags;
1011 flags2 = (*sec2)->flags;
1012 if ((flags1 & SEC_HAS_CONTENTS) == 0
1013 || (flags1 & SEC_LOAD) == 0)
1014 {
1015 if ((flags2 & SEC_HAS_CONTENTS) != 0
1016 && (flags2 & SEC_LOAD) != 0)
1017 return -1;
1018 }
1019 else
1020 {
1021 if ((flags2 & SEC_HAS_CONTENTS) == 0
1022 || (flags2 & SEC_LOAD) == 0)
1023 return 1;
1024 }
596d99ba 1025
87a15686 1026 /* Sort sections by VMA. */
596d99ba
ILT
1027 if ((*sec1)->vma > (*sec2)->vma)
1028 return 1;
1029 else if ((*sec1)->vma < (*sec2)->vma)
1030 return -1;
87a15686
ILT
1031
1032 /* Sort sections with the same VMA by size. */
1033 if ((*sec1)->_raw_size > (*sec2)->_raw_size)
1034 return 1;
1035 else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
1036 return -1;
1037
1038 return 0;
596d99ba
ILT
1039}
1040
77ccab3c
JL
1041/* Mark all the symbols which will be used in output relocations with
1042 the BSF_KEEP flag so that those symbols will not be stripped.
1043
1044 Ignore relocations which will not appear in the output file. */
1045
1046static void
6c7ed084 1047mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
77ccab3c
JL
1048 bfd *ibfd;
1049 sec_ptr isection;
6c7ed084 1050 PTR symbolsarg;
77ccab3c 1051{
6c7ed084 1052 asymbol **symbols = (asymbol **) symbolsarg;
ae5d2ff5 1053 long relsize;
77ccab3c 1054 arelent **relpp;
ae5d2ff5 1055 long relcount, i;
77ccab3c
JL
1056
1057 /* Ignore an input section with no corresponding output section. */
1058 if (isection->output_section == NULL)
1059 return;
1060
ae5d2ff5
ILT
1061 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
1062 if (relsize < 0)
1063 bfd_fatal (bfd_get_filename (ibfd));
1064
1065 relpp = (arelent **) xmalloc (relsize);
77ccab3c 1066 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
ae5d2ff5
ILT
1067 if (relcount < 0)
1068 bfd_fatal (bfd_get_filename (ibfd));
77ccab3c
JL
1069
1070 /* Examine each symbol used in a relocation. If it's not one of the
1071 special bfd section symbols, then mark it with BSF_KEEP. */
1072 for (i = 0; i < relcount; i++)
1073 {
6c7ed084
ILT
1074 if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
1075 && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
1076 && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
77ccab3c
JL
1077 (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
1078 }
1079
1080 if (relpp != NULL)
1081 free (relpp);
1082}
1083
46050fe4
ILT
1084/* The number of bytes to copy at once. */
1085#define COPY_BUF 8192
1086
1087/* Copy file FROM to file TO, performing no translations.
1088 Return 0 if ok, -1 if error. */
1089
1090static int
1091simple_copy (from, to)
1092 char *from, *to;
c0367ba5 1093{
46050fe4
ILT
1094 int fromfd, tofd, nread;
1095 char buf[COPY_BUF];
1096
1097 fromfd = open (from, O_RDONLY);
1098 if (fromfd < 0)
1099 return -1;
1100 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
1101 if (tofd < 0)
1102 {
1103 close (fromfd);
1104 return -1;
1105 }
1106 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
1107 {
1108 if (write (tofd, buf, nread) != nread)
1109 {
1110 close (fromfd);
1111 close (tofd);
1112 return -1;
1113 }
1114 }
1115 close (fromfd);
1116 close (tofd);
1117 if (nread < 0)
1118 return -1;
1119 return 0;
1120}
c0367ba5 1121
46050fe4
ILT
1122#ifndef S_ISLNK
1123#ifdef S_IFLNK
1124#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1125#else
1126#define S_ISLNK(m) 0
1127#define lstat stat
1128#endif
1129#endif
1130
1131/* Rename FROM to TO, copying if TO is a link.
1132 Assumes that TO already exists, because FROM is a temp file.
1133 Return 0 if ok, -1 if error. */
1134
1135static int
1136smart_rename (from, to)
1137 char *from, *to;
1138{
1139 struct stat s;
1140 int ret = 0;
c0367ba5 1141
46050fe4
ILT
1142 if (lstat (to, &s))
1143 return -1;
c0367ba5 1144
46050fe4
ILT
1145 /* Use rename only if TO is not a symbolic link and has
1146 only one hard link. */
1147 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
1148 {
1149 ret = rename (from, to);
1150 if (ret == 0)
1151 {
1152 /* Try to preserve the permission bits and ownership of TO. */
1153 chmod (to, s.st_mode & 07777);
1154 chown (to, s.st_uid, s.st_gid);
1155 }
1156 }
1157 else
1158 {
1159 ret = simple_copy (from, to);
1160 if (ret == 0)
1161 unlink (from);
1162 }
1163 return ret;
1164}
1165
1166static int
1167strip_main (argc, argv)
1168 int argc;
1169 char *argv[];
1170{
1171 char *input_target = NULL, *output_target = NULL;
1172 boolean show_version = false;
1173 int c, i;
1174
4af19c61 1175 while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVvN:",
46050fe4
ILT
1176 strip_options, (int *) 0)) != EOF)
1177 {
1178 switch (c)
1179 {
1180 case 'I':
1181 input_target = optarg;
704bbd0d 1182 break;
46050fe4
ILT
1183 case 'O':
1184 output_target = optarg;
1185 break;
1186 case 'F':
1187 input_target = output_target = optarg;
1188 break;
6c7ed084
ILT
1189 case 'R':
1190 {
1191 struct section_list *n;
1192
1193 n = (struct section_list *) xmalloc (sizeof (struct section_list));
1194 n->name = optarg;
1195 n->used = false;
1196 n->next = remove_sections;
1197 remove_sections = n;
1198 }
1199 break;
46050fe4 1200 case 's':
c0367ba5 1201 strip_symbols = strip_all;
46050fe4
ILT
1202 break;
1203 case 'S':
1204 case 'g':
1205 strip_symbols = strip_debug;
1206 break;
4af19c61
KR
1207 case 'N':
1208 add_strip_symbol (optarg);
1209 break;
46050fe4
ILT
1210 case 'x':
1211 discard_locals = locals_all;
1212 break;
1213 case 'X':
1214 discard_locals = locals_start_L;
1215 break;
1216 case 'v':
1217 verbose = true;
1218 break;
1219 case 'V':
1220 show_version = true;
1221 break;
1222 case 0:
1223 break; /* we've been given a long option */
1224 case 'h':
1225 strip_usage (stdout, 0);
1226 default:
1227 strip_usage (stderr, 1);
1228 }
1229 }
1230
1231 if (show_version)
1232 {
1233 printf ("GNU %s version %s\n", program_name, program_version);
1234 exit (0);
1235 }
c0367ba5 1236
46050fe4 1237 /* Default is to strip all symbols. */
4af19c61
KR
1238 if (strip_symbols == strip_undef
1239 && discard_locals == locals_undef
1240 && strip_specific_list == NULL)
46050fe4
ILT
1241 strip_symbols = strip_all;
1242
1243 if (output_target == (char *) NULL)
1244 output_target = input_target;
1245
1246 i = optind;
1247 if (i == argc)
1248 strip_usage (stderr, 1);
1249
1250 for (; i < argc; i++)
1251 {
1252 int hold_status = status;
c0367ba5 1253
46050fe4
ILT
1254 char *tmpname = make_tempname (argv[i]);
1255 status = 0;
1256 copy_file (argv[i], tmpname, input_target, output_target);
1257 if (status == 0)
1258 {
1259 smart_rename (tmpname, argv[i]);
1260 status = hold_status;
c0367ba5 1261 }
46050fe4
ILT
1262 else
1263 unlink (tmpname);
1264 free (tmpname);
1265 }
1266
1267 return 0;
1268}
1269
1270static int
1271copy_main (argc, argv)
1272 int argc;
1273 char *argv[];
1274{
6c7ed084 1275 char *input_filename = NULL, *output_filename = NULL;
46050fe4
ILT
1276 char *input_target = NULL, *output_target = NULL;
1277 boolean show_version = false;
6c7ed084 1278 boolean adjust_warn = true;
46050fe4 1279 int c;
6c7ed084 1280 struct section_list *p;
46050fe4 1281
4af19c61 1282 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVvN:",
46050fe4
ILT
1283 copy_options, (int *) 0)) != EOF)
1284 {
1285 switch (c)
1286 {
f7b839f7
DM
1287 case 'b':
1288 copy_byte = atoi(optarg);
1289 if (copy_byte < 0)
1290 {
1291 fprintf (stderr, "%s: byte number must be non-negative\n",
1292 program_name);
1293 exit (1);
1294 }
1295 break;
1296 case 'i':
1297 interleave = atoi(optarg);
1298 if (interleave < 1)
1299 {
1300 fprintf(stderr, "%s: interleave must be positive\n",
1301 program_name);
1302 exit (1);
1303 }
1304 break;
c0367ba5 1305 case 'I':
46050fe4 1306 case 's': /* "source" - 'I' is preferred */
c0367ba5 1307 input_target = optarg;
704bbd0d 1308 break;
c0367ba5 1309 case 'O':
46050fe4 1310 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
1311 output_target = optarg;
1312 break;
1313 case 'F':
c0367ba5
ILT
1314 input_target = output_target = optarg;
1315 break;
6c7ed084
ILT
1316 case 'R':
1317 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1318 p->name = optarg;
1319 p->used = false;
1320 p->next = remove_sections;
1321 remove_sections = p;
1322 break;
c0367ba5
ILT
1323 case 'S':
1324 strip_symbols = strip_all;
1325 break;
1326 case 'g':
1327 strip_symbols = strip_debug;
1328 break;
4af19c61
KR
1329 case 'N':
1330 add_strip_symbol (optarg);
1331 break;
c0367ba5
ILT
1332 case 'x':
1333 discard_locals = locals_all;
1334 break;
1335 case 'X':
1336 discard_locals = locals_start_L;
1337 break;
1338 case 'v':
1339 verbose = true;
1340 break;
1341 case 'V':
1342 show_version = true;
1343 break;
6c7ed084
ILT
1344 case OPTION_ADJUST_START:
1345 adjust_start = parse_vma (optarg, "--adjust-start");
1346 break;
1347 case OPTION_ADJUST_SECTION_VMA:
1348 {
1349 const char *s;
1350 int len;
1351 char *name;
1352
1353 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1354 s = strchr (optarg, '=');
1355 if (s != NULL)
1356 {
1357 p->adjust = false;
1358 p->val = parse_vma (s + 1, "--adjust-section-vma");
1359 }
1360 else
1361 {
1362 s = strchr (optarg, '+');
1363 if (s == NULL)
1364 {
1365 s = strchr (optarg, '-');
1366 if (s == NULL)
1367 {
1368 fprintf (stderr,
1369 "%s: bad format for --adjust-section-vma\n",
1370 program_name);
1371 exit (1);
1372 }
1373 }
1374 p->adjust = true;
1375 p->val = parse_vma (s + 1, "--adjust-section-vma");
1376 if (*s == '-')
1377 p->val = - p->val;
1378 }
1379
1380 len = s - optarg;
1381 name = (char *) xmalloc (len + 1);
1382 strncpy (name, optarg, len);
1383 name[len] = '\0';
1384 p->name = name;
1385
1386 p->used = false;
1387
1388 p->next = adjust_sections;
1389 adjust_sections = p;
1390 }
1391 break;
1392 case OPTION_ADJUST_VMA:
1393 adjust_section_vma = parse_vma (optarg, "--adjust-vma");
1394 adjust_start = adjust_section_vma;
1395 break;
1396 case OPTION_ADJUST_WARNINGS:
1397 adjust_warn = true;
1398 break;
596d99ba
ILT
1399 case OPTION_GAP_FILL:
1400 {
1401 bfd_vma gap_fill_vma;
1402
1403 gap_fill_vma = parse_vma (optarg, "--gap-fill");
1404 gap_fill = (bfd_byte) gap_fill_vma;
1405 if ((bfd_vma) gap_fill != gap_fill_vma)
1406 {
1407 fprintf (stderr, "%s: warning: truncating gap-fill from 0x",
1408 program_name);
1409 fprintf_vma (stderr, gap_fill_vma);
1410 fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill);
1411 }
1412 gap_fill_set = true;
1413 }
1414 break;
6c7ed084
ILT
1415 case OPTION_NO_ADJUST_WARNINGS:
1416 adjust_warn = false;
1417 break;
87a15686
ILT
1418 case OPTION_PAD_TO:
1419 pad_to = parse_vma (optarg, "--pad-to");
1420 pad_to_set = true;
1421 break;
6c7ed084
ILT
1422 case OPTION_SET_START:
1423 set_start = parse_vma (optarg, "--set-start");
1424 set_start_set = true;
1425 break;
46050fe4 1426 case 0:
c0367ba5
ILT
1427 break; /* we've been given a long option */
1428 case 'h':
1429 copy_usage (stdout, 0);
1430 default:
1431 copy_usage (stderr, 1);
46050fe4
ILT
1432 }
1433 }
1434
1435 if (show_version)
1436 {
1437 printf ("GNU %s version %s\n", program_name, program_version);
1438 exit (0);
1439 }
c0367ba5 1440
f7b839f7
DM
1441 if (copy_byte >= interleave)
1442 {
1443 fprintf (stderr, "%s: byte number must be less than interleave\n",
1444 program_name);
1445 exit (1);
1446 }
1447
46050fe4
ILT
1448 if (optind == argc || optind + 2 < argc)
1449 copy_usage (stderr, 1);
c0367ba5
ILT
1450
1451 input_filename = argv[optind];
1452 if (optind + 1 < argc)
46050fe4 1453 output_filename = argv[optind + 1];
c0367ba5
ILT
1454
1455 /* Default is to strip no symbols. */
1456 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 1457 strip_symbols = strip_none;
c0367ba5
ILT
1458
1459 if (output_target == (char *) NULL)
1460 output_target = input_target;
1461
46050fe4
ILT
1462 /* If there is no destination file then create a temp and rename
1463 the result into the input. */
1464
1465 if (output_filename == (char *) NULL)
1466 {
1467 char *tmpname = make_tempname (input_filename);
1468 copy_file (input_filename, tmpname, input_target, output_target);
1469 if (status == 0)
1470 smart_rename (tmpname, input_filename);
1471 else
1472 unlink (tmpname);
1473 }
1474 else
1475 {
1476 copy_file (input_filename, output_filename, input_target, output_target);
1477 }
1478
6c7ed084
ILT
1479 if (adjust_warn)
1480 {
1481 for (p = adjust_sections; p != NULL; p = p->next)
1482 {
1483 if (! p->used)
1484 {
1485 fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x",
1486 program_name, p->name,
1487 p->adjust ? '=' : '+');
1488 fprintf_vma (stderr, p->val);
1489 fprintf (stderr, " never used\n");
1490 }
1491 }
1492 }
1493
1494 /* We could issue similar warnings for remove_sections, but I don't
1495 think that would be as useful. */
1496
c0367ba5
ILT
1497 return 0;
1498}
46050fe4
ILT
1499
1500int
1501main (argc, argv)
1502 int argc;
1503 char *argv[];
1504{
1505 program_name = argv[0];
704bbd0d 1506 xmalloc_set_program_name (program_name);
46050fe4
ILT
1507 strip_symbols = strip_undef;
1508 discard_locals = locals_undef;
1509
1510 bfd_init ();
1511
1512 if (is_strip < 0)
1513 {
1514 int i = strlen (program_name);
87a15686 1515 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0);
46050fe4
ILT
1516 }
1517
1518 if (is_strip)
1519 strip_main (argc, argv);
1520 else
1521 copy_main (argc, argv);
1522
1523 return status;
1524}
This page took 0.224365 seconds and 4 git commands to generate.