* nlmconv.c (powerpc_mangle_relocs): Don't switch a reloc to use
[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));
587 status = 1;
588 }
589 left -= now;
590 off += now;
591 }
592 }
593 }
594 }
595
6f9077cd
JM
596 /* Allow the BFD backend to copy any private data it understands
597 from the input BFD to the output BFD. This is done last to
598 permit the routine to look at the filtered symbol table, which is
599 important for the ECOFF code at least. */
600 if (!bfd_copy_private_bfd_data (ibfd, obfd))
601 {
602 fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
603 program_name, bfd_get_filename (obfd),
604 bfd_errmsg (bfd_get_error ()));
605 status = 1;
606 return;
607 }
c0367ba5 608}
46050fe4
ILT
609
610static char *
611cat (a, b, c)
612 char *a;
613 char *b;
614 char *c;
c0367ba5 615{
46050fe4
ILT
616 size_t size = strlen (a) + strlen (b) + strlen (c);
617 char *r = xmalloc (size + 1);
618
619 strcpy (r, a);
620 strcat (r, b);
621 strcat (r, c);
622 return r;
c0367ba5
ILT
623}
624
46050fe4
ILT
625/* Read each archive element in turn from IBFD, copy the
626 contents to temp file, and keep the temp file handle. */
627
628static void
629copy_archive (ibfd, obfd, output_target)
630 bfd *ibfd;
631 bfd *obfd;
632 char *output_target;
c0367ba5 633{
87a15686
ILT
634 struct name_list
635 {
636 struct name_list *next;
637 char *name;
638 } *list, *l;
46050fe4
ILT
639 bfd **ptr = &obfd->archive_head;
640 bfd *this_element;
90f6517d 641 char *dir = make_tempname (bfd_get_filename (obfd));
46050fe4
ILT
642
643 /* Make a temp directory to hold the contents. */
90f6517d 644 mkdir (dir, 0700);
46050fe4
ILT
645 obfd->has_armap = ibfd->has_armap;
646
87a15686
ILT
647 list = NULL;
648
46050fe4 649 this_element = bfd_openr_next_archived_file (ibfd, NULL);
46050fe4
ILT
650 while (this_element != (bfd *) NULL)
651 {
652 /* Create an output file for this member. */
653 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
654 bfd *output_bfd = bfd_openw (output_name, output_target);
87a15686
ILT
655 bfd *last_element;
656
657 l = (struct name_list *) xmalloc (sizeof (struct name_list));
658 l->name = output_name;
659 l->next = list;
660 list = l;
46050fe4
ILT
661
662 if (output_bfd == (bfd *) NULL)
663 {
664 nonfatal (output_name);
c0367ba5 665 }
46050fe4
ILT
666 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
667 {
668 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
669 }
670
46050fe4
ILT
671 if (bfd_check_format (this_element, bfd_object) == true)
672 {
673 copy_object (this_element, output_bfd);
674 }
c0367ba5 675
46050fe4 676 bfd_close (output_bfd);
87a15686
ILT
677
678 /* Open the newly output file and attach to our list. */
46050fe4 679 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 680
46050fe4
ILT
681 *ptr = output_bfd;
682 ptr = &output_bfd->next;
87a15686
ILT
683
684 last_element = this_element;
685
686 this_element = bfd_openr_next_archived_file (ibfd, last_element);
687
688 bfd_close (last_element);
c0367ba5 689 }
46050fe4 690 *ptr = (bfd *) NULL;
c0367ba5 691
46050fe4
ILT
692 if (!bfd_close (obfd))
693 {
694 nonfatal (bfd_get_filename (obfd));
c0367ba5 695 }
c0367ba5 696
87a15686
ILT
697 /* Delete all the files that we opened. */
698 for (l = list; l != NULL; l = l->next)
699 unlink (l->name);
46050fe4 700 rmdir (dir);
87a15686 701
46050fe4
ILT
702 if (!bfd_close (ibfd))
703 {
704 nonfatal (bfd_get_filename (ibfd));
705 }
c0367ba5
ILT
706}
707
46050fe4
ILT
708/* The top-level control. */
709
710static void
711copy_file (input_filename, output_filename, input_target, output_target)
712 char *input_filename;
713 char *output_filename;
714 char *input_target;
715 char *output_target;
c0367ba5 716{
46050fe4 717 bfd *ibfd;
cef35d48 718 char **matching;
c0367ba5
ILT
719
720 /* To allow us to do "strip *" without dying on the first
721 non-object file, failures are nonfatal. */
722
46050fe4 723 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
724 if (ibfd == NULL)
725 {
46050fe4 726 nonfatal (input_filename);
c0367ba5
ILT
727 }
728
cef35d48
DM
729 if (bfd_check_format (ibfd, bfd_archive))
730 {
6c7ed084
ILT
731 bfd *obfd;
732
733 /* bfd_get_target does not return the correct value until
734 bfd_check_format succeeds. */
735 if (output_target == NULL)
736 output_target = bfd_get_target (ibfd);
737
738 obfd = bfd_openw (output_filename, output_target);
cef35d48
DM
739 if (obfd == NULL)
740 {
741 nonfatal (output_filename);
742 }
743 copy_archive (ibfd, obfd, output_target);
744 }
745 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4 746 {
6c7ed084
ILT
747 bfd *obfd;
748
749 /* bfd_get_target does not return the correct value until
750 bfd_check_format succeeds. */
751 if (output_target == NULL)
752 output_target = bfd_get_target (ibfd);
753
754 obfd = bfd_openw (output_filename, output_target);
46050fe4
ILT
755 if (obfd == NULL)
756 {
757 nonfatal (output_filename);
758 }
c0367ba5 759
46050fe4 760 copy_object (ibfd, obfd);
c0367ba5 761
46050fe4
ILT
762 if (!bfd_close (obfd))
763 {
764 nonfatal (output_filename);
765 }
766
767 if (!bfd_close (ibfd))
768 {
769 nonfatal (input_filename);
770 }
771 }
cef35d48 772 else
46050fe4 773 {
cef35d48 774 bfd_nonfatal (input_filename);
c9563567 775 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
46050fe4 776 {
cef35d48
DM
777 list_matching_formats (matching);
778 free (matching);
46050fe4 779 }
cef35d48 780 status = 1;
46050fe4
ILT
781 }
782}
783
784/* Create a section in OBFD with the same name and attributes
785 as ISECTION in IBFD. */
c0367ba5 786
c0367ba5 787static void
6c7ed084 788setup_section (ibfd, isection, obfdarg)
46050fe4
ILT
789 bfd *ibfd;
790 sec_ptr isection;
6c7ed084 791 PTR obfdarg;
c0367ba5 792{
6c7ed084
ILT
793 bfd *obfd = (bfd *) obfdarg;
794 struct section_list *p;
46050fe4 795 sec_ptr osection;
6c7ed084 796 bfd_vma vma;
46050fe4
ILT
797 char *err;
798
799 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
800 && (strip_symbols == strip_debug
801 || strip_symbols == strip_all
802 || discard_locals == locals_all))
803 return;
804
6c7ed084
ILT
805 for (p = remove_sections; p != NULL; p = p->next)
806 {
807 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
808 {
809 p->used = true;
810 return;
811 }
812 }
813
77ccab3c 814 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
46050fe4
ILT
815 if (osection == NULL)
816 {
77ccab3c
JL
817 err = "making";
818 goto loser;
c0367ba5
ILT
819 }
820
46050fe4
ILT
821 if (!bfd_set_section_size (obfd,
822 osection,
823 bfd_section_size (ibfd, isection)))
824 {
825 err = "size";
826 goto loser;
c0367ba5
ILT
827 }
828
6c7ed084
ILT
829 vma = bfd_section_vma (ibfd, isection);
830 for (p = adjust_sections; p != NULL; p = p->next)
831 {
832 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
833 {
834 if (p->adjust)
835 vma += p->val;
836 else
837 vma = p->val;
838 p->used = true;
839 break;
840 }
841 }
842 if (p == NULL)
843 vma += adjust_section_vma;
844
845 if (! bfd_set_section_vma (obfd, osection, vma))
46050fe4
ILT
846 {
847 err = "vma";
848 goto loser;
849 }
c0367ba5 850
46050fe4
ILT
851 if (bfd_set_section_alignment (obfd,
852 osection,
853 bfd_section_alignment (ibfd, isection))
854 == false)
855 {
856 err = "alignment";
857 goto loser;
858 }
c0367ba5 859
46050fe4
ILT
860 if (!bfd_set_section_flags (obfd, osection,
861 bfd_get_section_flags (ibfd, isection)))
862 {
863 err = "flags";
864 goto loser;
c0367ba5
ILT
865 }
866
c9563567
JL
867 /* This used to be mangle_section; we do here to avoid using
868 bfd_get_section_by_name since some formats allow multiple
869 sections with the same name. */
870 isection->output_section = osection;
871 isection->output_offset = 0;
872
77ccab3c
JL
873 /* Allow the BFD backend to copy any private data it understands
874 from the input section to the output section. */
875 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
876 {
877 err = "private data";
878 goto loser;
879 }
880
46050fe4
ILT
881 /* All went well */
882 return;
c0367ba5
ILT
883
884loser:
46050fe4
ILT
885 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
886 program_name,
887 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
c9563567 888 err, bfd_errmsg (bfd_get_error ()));
46050fe4
ILT
889 status = 1;
890}
891
892/* Copy the data of input section ISECTION of IBFD
893 to an output section with the same name in OBFD.
894 If stripping then don't copy any relocation info. */
895
c0367ba5 896static void
6c7ed084 897copy_section (ibfd, isection, obfdarg)
46050fe4
ILT
898 bfd *ibfd;
899 sec_ptr isection;
6c7ed084 900 PTR obfdarg;
c0367ba5 901{
6c7ed084
ILT
902 bfd *obfd = (bfd *) obfdarg;
903 struct section_list *p;
46050fe4 904 arelent **relpp;
ae5d2ff5 905 long relcount;
46050fe4
ILT
906 sec_ptr osection;
907 bfd_size_type size;
908
909 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
910 && (strip_symbols == strip_debug
911 || strip_symbols == strip_all
912 || discard_locals == locals_all))
913 {
914 return;
915 }
c0367ba5 916
6c7ed084
ILT
917 for (p = remove_sections; p != NULL; p = p->next)
918 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
919 return;
920
77ccab3c 921 osection = isection->output_section;
46050fe4 922 size = bfd_get_section_size_before_reloc (isection);
c0367ba5 923
77ccab3c 924 if (size == 0 || osection == 0)
c0367ba5
ILT
925 return;
926
ae5d2ff5
ILT
927 if (strip_symbols == strip_all)
928 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
46050fe4 929 else
c0367ba5 930 {
ae5d2ff5
ILT
931 long relsize;
932
933 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
934 if (relsize < 0)
935 {
936 nonfatal (bfd_get_filename (ibfd));
937 }
938 if (relsize == 0)
939 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
940 else
941 {
942 relpp = (arelent **) xmalloc (relsize);
943 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
944 if (relcount < 0)
945 {
946 nonfatal (bfd_get_filename (ibfd));
947 }
948 bfd_set_reloc (obfd, osection, relpp, relcount);
949 }
c0367ba5
ILT
950 }
951
952 isection->_cooked_size = isection->_raw_size;
46050fe4 953 isection->reloc_done = true;
c0367ba5 954
46050fe4 955 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 956 {
46050fe4 957 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 958
46050fe4
ILT
959 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
960 size))
961 {
962 nonfatal (bfd_get_filename (ibfd));
963 }
c0367ba5 964
6f9077cd
JM
965 if (copy_byte >= 0)
966 {
967 filter_bytes (memhunk, &size);
968 /* The section has gotten smaller. */
969 if (!bfd_set_section_size (obfd, osection, size))
970 nonfatal (bfd_get_filename (obfd));
971 }
f7b839f7 972
46050fe4
ILT
973 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
974 size))
975 {
976 nonfatal (bfd_get_filename (obfd));
977 }
978 free (memhunk);
c0367ba5 979 }
46050fe4 980}
c0367ba5 981
87a15686
ILT
982/* Get all the sections. This is used when --gap-fill or --pad-to is
983 used. */
596d99ba
ILT
984
985static void
986get_sections (obfd, osection, secppparg)
987 bfd *obfd;
988 asection *osection;
989 PTR secppparg;
990{
991 asection ***secppp = (asection ***) secppparg;
992
993 **secppp = osection;
994 ++(*secppp);
995}
996
997/* Sort sections by VMA. This is called via qsort, and is used when
87a15686
ILT
998 --gap-fill or --pad-to is used. We force non loadable or empty
999 sections to the front, where they are easier to ignore. */
596d99ba
ILT
1000
1001static int
1002compare_section_vma (arg1, arg2)
1003 const PTR arg1;
1004 const PTR arg2;
1005{
1006 const asection **sec1 = (const asection **) arg1;
1007 const asection **sec2 = (const asection **) arg2;
87a15686
ILT
1008 flagword flags1, flags2;
1009
1010 /* Sort non loadable sections to the front. */
1011 flags1 = (*sec1)->flags;
1012 flags2 = (*sec2)->flags;
1013 if ((flags1 & SEC_HAS_CONTENTS) == 0
1014 || (flags1 & SEC_LOAD) == 0)
1015 {
1016 if ((flags2 & SEC_HAS_CONTENTS) != 0
1017 && (flags2 & SEC_LOAD) != 0)
1018 return -1;
1019 }
1020 else
1021 {
1022 if ((flags2 & SEC_HAS_CONTENTS) == 0
1023 || (flags2 & SEC_LOAD) == 0)
1024 return 1;
1025 }
596d99ba 1026
87a15686 1027 /* Sort sections by VMA. */
596d99ba
ILT
1028 if ((*sec1)->vma > (*sec2)->vma)
1029 return 1;
1030 else if ((*sec1)->vma < (*sec2)->vma)
1031 return -1;
87a15686
ILT
1032
1033 /* Sort sections with the same VMA by size. */
1034 if ((*sec1)->_raw_size > (*sec2)->_raw_size)
1035 return 1;
1036 else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
1037 return -1;
1038
1039 return 0;
596d99ba
ILT
1040}
1041
77ccab3c
JL
1042/* Mark all the symbols which will be used in output relocations with
1043 the BSF_KEEP flag so that those symbols will not be stripped.
1044
1045 Ignore relocations which will not appear in the output file. */
1046
1047static void
6c7ed084 1048mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
77ccab3c
JL
1049 bfd *ibfd;
1050 sec_ptr isection;
6c7ed084 1051 PTR symbolsarg;
77ccab3c 1052{
6c7ed084 1053 asymbol **symbols = (asymbol **) symbolsarg;
ae5d2ff5 1054 long relsize;
77ccab3c 1055 arelent **relpp;
ae5d2ff5 1056 long relcount, i;
77ccab3c
JL
1057
1058 /* Ignore an input section with no corresponding output section. */
1059 if (isection->output_section == NULL)
1060 return;
1061
ae5d2ff5
ILT
1062 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
1063 if (relsize < 0)
1064 bfd_fatal (bfd_get_filename (ibfd));
1065
1066 relpp = (arelent **) xmalloc (relsize);
77ccab3c 1067 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
ae5d2ff5
ILT
1068 if (relcount < 0)
1069 bfd_fatal (bfd_get_filename (ibfd));
77ccab3c
JL
1070
1071 /* Examine each symbol used in a relocation. If it's not one of the
1072 special bfd section symbols, then mark it with BSF_KEEP. */
1073 for (i = 0; i < relcount; i++)
1074 {
6c7ed084
ILT
1075 if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
1076 && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
1077 && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
77ccab3c
JL
1078 (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
1079 }
1080
1081 if (relpp != NULL)
1082 free (relpp);
1083}
1084
46050fe4
ILT
1085/* The number of bytes to copy at once. */
1086#define COPY_BUF 8192
1087
1088/* Copy file FROM to file TO, performing no translations.
1089 Return 0 if ok, -1 if error. */
1090
1091static int
1092simple_copy (from, to)
1093 char *from, *to;
c0367ba5 1094{
46050fe4
ILT
1095 int fromfd, tofd, nread;
1096 char buf[COPY_BUF];
1097
1098 fromfd = open (from, O_RDONLY);
1099 if (fromfd < 0)
1100 return -1;
1101 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
1102 if (tofd < 0)
1103 {
1104 close (fromfd);
1105 return -1;
1106 }
1107 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
1108 {
1109 if (write (tofd, buf, nread) != nread)
1110 {
1111 close (fromfd);
1112 close (tofd);
1113 return -1;
1114 }
1115 }
1116 close (fromfd);
1117 close (tofd);
1118 if (nread < 0)
1119 return -1;
1120 return 0;
1121}
c0367ba5 1122
46050fe4
ILT
1123#ifndef S_ISLNK
1124#ifdef S_IFLNK
1125#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1126#else
1127#define S_ISLNK(m) 0
1128#define lstat stat
1129#endif
1130#endif
1131
1132/* Rename FROM to TO, copying if TO is a link.
1133 Assumes that TO already exists, because FROM is a temp file.
1134 Return 0 if ok, -1 if error. */
1135
1136static int
1137smart_rename (from, to)
1138 char *from, *to;
1139{
1140 struct stat s;
1141 int ret = 0;
c0367ba5 1142
46050fe4
ILT
1143 if (lstat (to, &s))
1144 return -1;
c0367ba5 1145
46050fe4
ILT
1146 /* Use rename only if TO is not a symbolic link and has
1147 only one hard link. */
1148 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
1149 {
1150 ret = rename (from, to);
1151 if (ret == 0)
1152 {
1153 /* Try to preserve the permission bits and ownership of TO. */
1154 chmod (to, s.st_mode & 07777);
1155 chown (to, s.st_uid, s.st_gid);
1156 }
1157 }
1158 else
1159 {
1160 ret = simple_copy (from, to);
1161 if (ret == 0)
1162 unlink (from);
1163 }
1164 return ret;
1165}
1166
1167static int
1168strip_main (argc, argv)
1169 int argc;
1170 char *argv[];
1171{
1172 char *input_target = NULL, *output_target = NULL;
1173 boolean show_version = false;
1174 int c, i;
1175
4af19c61 1176 while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVvN:",
46050fe4
ILT
1177 strip_options, (int *) 0)) != EOF)
1178 {
1179 switch (c)
1180 {
1181 case 'I':
1182 input_target = optarg;
704bbd0d 1183 break;
46050fe4
ILT
1184 case 'O':
1185 output_target = optarg;
1186 break;
1187 case 'F':
1188 input_target = output_target = optarg;
1189 break;
6c7ed084
ILT
1190 case 'R':
1191 {
1192 struct section_list *n;
1193
1194 n = (struct section_list *) xmalloc (sizeof (struct section_list));
1195 n->name = optarg;
1196 n->used = false;
1197 n->next = remove_sections;
1198 remove_sections = n;
1199 }
1200 break;
46050fe4 1201 case 's':
c0367ba5 1202 strip_symbols = strip_all;
46050fe4
ILT
1203 break;
1204 case 'S':
1205 case 'g':
1206 strip_symbols = strip_debug;
1207 break;
4af19c61
KR
1208 case 'N':
1209 add_strip_symbol (optarg);
1210 break;
46050fe4
ILT
1211 case 'x':
1212 discard_locals = locals_all;
1213 break;
1214 case 'X':
1215 discard_locals = locals_start_L;
1216 break;
1217 case 'v':
1218 verbose = true;
1219 break;
1220 case 'V':
1221 show_version = true;
1222 break;
1223 case 0:
1224 break; /* we've been given a long option */
1225 case 'h':
1226 strip_usage (stdout, 0);
1227 default:
1228 strip_usage (stderr, 1);
1229 }
1230 }
1231
1232 if (show_version)
1233 {
1234 printf ("GNU %s version %s\n", program_name, program_version);
1235 exit (0);
1236 }
c0367ba5 1237
46050fe4 1238 /* Default is to strip all symbols. */
4af19c61
KR
1239 if (strip_symbols == strip_undef
1240 && discard_locals == locals_undef
1241 && strip_specific_list == NULL)
46050fe4
ILT
1242 strip_symbols = strip_all;
1243
1244 if (output_target == (char *) NULL)
1245 output_target = input_target;
1246
1247 i = optind;
1248 if (i == argc)
1249 strip_usage (stderr, 1);
1250
1251 for (; i < argc; i++)
1252 {
1253 int hold_status = status;
c0367ba5 1254
46050fe4
ILT
1255 char *tmpname = make_tempname (argv[i]);
1256 status = 0;
1257 copy_file (argv[i], tmpname, input_target, output_target);
1258 if (status == 0)
1259 {
1260 smart_rename (tmpname, argv[i]);
1261 status = hold_status;
c0367ba5 1262 }
46050fe4
ILT
1263 else
1264 unlink (tmpname);
1265 free (tmpname);
1266 }
1267
1268 return 0;
1269}
1270
1271static int
1272copy_main (argc, argv)
1273 int argc;
1274 char *argv[];
1275{
6c7ed084 1276 char *input_filename = NULL, *output_filename = NULL;
46050fe4
ILT
1277 char *input_target = NULL, *output_target = NULL;
1278 boolean show_version = false;
6c7ed084 1279 boolean adjust_warn = true;
46050fe4 1280 int c;
6c7ed084 1281 struct section_list *p;
46050fe4 1282
4af19c61 1283 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVvN:",
46050fe4
ILT
1284 copy_options, (int *) 0)) != EOF)
1285 {
1286 switch (c)
1287 {
f7b839f7
DM
1288 case 'b':
1289 copy_byte = atoi(optarg);
1290 if (copy_byte < 0)
1291 {
1292 fprintf (stderr, "%s: byte number must be non-negative\n",
1293 program_name);
1294 exit (1);
1295 }
1296 break;
1297 case 'i':
1298 interleave = atoi(optarg);
1299 if (interleave < 1)
1300 {
1301 fprintf(stderr, "%s: interleave must be positive\n",
1302 program_name);
1303 exit (1);
1304 }
1305 break;
c0367ba5 1306 case 'I':
46050fe4 1307 case 's': /* "source" - 'I' is preferred */
c0367ba5 1308 input_target = optarg;
704bbd0d 1309 break;
c0367ba5 1310 case 'O':
46050fe4 1311 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
1312 output_target = optarg;
1313 break;
1314 case 'F':
c0367ba5
ILT
1315 input_target = output_target = optarg;
1316 break;
6c7ed084
ILT
1317 case 'R':
1318 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1319 p->name = optarg;
1320 p->used = false;
1321 p->next = remove_sections;
1322 remove_sections = p;
1323 break;
c0367ba5
ILT
1324 case 'S':
1325 strip_symbols = strip_all;
1326 break;
1327 case 'g':
1328 strip_symbols = strip_debug;
1329 break;
4af19c61
KR
1330 case 'N':
1331 add_strip_symbol (optarg);
1332 break;
c0367ba5
ILT
1333 case 'x':
1334 discard_locals = locals_all;
1335 break;
1336 case 'X':
1337 discard_locals = locals_start_L;
1338 break;
1339 case 'v':
1340 verbose = true;
1341 break;
1342 case 'V':
1343 show_version = true;
1344 break;
6c7ed084
ILT
1345 case OPTION_ADJUST_START:
1346 adjust_start = parse_vma (optarg, "--adjust-start");
1347 break;
1348 case OPTION_ADJUST_SECTION_VMA:
1349 {
1350 const char *s;
1351 int len;
1352 char *name;
1353
1354 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1355 s = strchr (optarg, '=');
1356 if (s != NULL)
1357 {
1358 p->adjust = false;
1359 p->val = parse_vma (s + 1, "--adjust-section-vma");
1360 }
1361 else
1362 {
1363 s = strchr (optarg, '+');
1364 if (s == NULL)
1365 {
1366 s = strchr (optarg, '-');
1367 if (s == NULL)
1368 {
1369 fprintf (stderr,
1370 "%s: bad format for --adjust-section-vma\n",
1371 program_name);
1372 exit (1);
1373 }
1374 }
1375 p->adjust = true;
1376 p->val = parse_vma (s + 1, "--adjust-section-vma");
1377 if (*s == '-')
1378 p->val = - p->val;
1379 }
1380
1381 len = s - optarg;
1382 name = (char *) xmalloc (len + 1);
1383 strncpy (name, optarg, len);
1384 name[len] = '\0';
1385 p->name = name;
1386
1387 p->used = false;
1388
1389 p->next = adjust_sections;
1390 adjust_sections = p;
1391 }
1392 break;
1393 case OPTION_ADJUST_VMA:
1394 adjust_section_vma = parse_vma (optarg, "--adjust-vma");
1395 adjust_start = adjust_section_vma;
1396 break;
1397 case OPTION_ADJUST_WARNINGS:
1398 adjust_warn = true;
1399 break;
596d99ba
ILT
1400 case OPTION_GAP_FILL:
1401 {
1402 bfd_vma gap_fill_vma;
1403
1404 gap_fill_vma = parse_vma (optarg, "--gap-fill");
1405 gap_fill = (bfd_byte) gap_fill_vma;
1406 if ((bfd_vma) gap_fill != gap_fill_vma)
1407 {
1408 fprintf (stderr, "%s: warning: truncating gap-fill from 0x",
1409 program_name);
1410 fprintf_vma (stderr, gap_fill_vma);
1411 fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill);
1412 }
1413 gap_fill_set = true;
1414 }
1415 break;
6c7ed084
ILT
1416 case OPTION_NO_ADJUST_WARNINGS:
1417 adjust_warn = false;
1418 break;
87a15686
ILT
1419 case OPTION_PAD_TO:
1420 pad_to = parse_vma (optarg, "--pad-to");
1421 pad_to_set = true;
1422 break;
6c7ed084
ILT
1423 case OPTION_SET_START:
1424 set_start = parse_vma (optarg, "--set-start");
1425 set_start_set = true;
1426 break;
46050fe4 1427 case 0:
c0367ba5
ILT
1428 break; /* we've been given a long option */
1429 case 'h':
1430 copy_usage (stdout, 0);
1431 default:
1432 copy_usage (stderr, 1);
46050fe4
ILT
1433 }
1434 }
1435
1436 if (show_version)
1437 {
1438 printf ("GNU %s version %s\n", program_name, program_version);
1439 exit (0);
1440 }
c0367ba5 1441
f7b839f7
DM
1442 if (copy_byte >= interleave)
1443 {
1444 fprintf (stderr, "%s: byte number must be less than interleave\n",
1445 program_name);
1446 exit (1);
1447 }
1448
46050fe4
ILT
1449 if (optind == argc || optind + 2 < argc)
1450 copy_usage (stderr, 1);
c0367ba5
ILT
1451
1452 input_filename = argv[optind];
1453 if (optind + 1 < argc)
46050fe4 1454 output_filename = argv[optind + 1];
c0367ba5
ILT
1455
1456 /* Default is to strip no symbols. */
1457 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 1458 strip_symbols = strip_none;
c0367ba5
ILT
1459
1460 if (output_target == (char *) NULL)
1461 output_target = input_target;
1462
46050fe4
ILT
1463 /* If there is no destination file then create a temp and rename
1464 the result into the input. */
1465
1466 if (output_filename == (char *) NULL)
1467 {
1468 char *tmpname = make_tempname (input_filename);
1469 copy_file (input_filename, tmpname, input_target, output_target);
1470 if (status == 0)
1471 smart_rename (tmpname, input_filename);
1472 else
1473 unlink (tmpname);
1474 }
1475 else
1476 {
1477 copy_file (input_filename, output_filename, input_target, output_target);
1478 }
1479
6c7ed084
ILT
1480 if (adjust_warn)
1481 {
1482 for (p = adjust_sections; p != NULL; p = p->next)
1483 {
1484 if (! p->used)
1485 {
1486 fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x",
1487 program_name, p->name,
1488 p->adjust ? '=' : '+');
1489 fprintf_vma (stderr, p->val);
1490 fprintf (stderr, " never used\n");
1491 }
1492 }
1493 }
1494
1495 /* We could issue similar warnings for remove_sections, but I don't
1496 think that would be as useful. */
1497
c0367ba5
ILT
1498 return 0;
1499}
46050fe4
ILT
1500
1501int
1502main (argc, argv)
1503 int argc;
1504 char *argv[];
1505{
1506 program_name = argv[0];
704bbd0d 1507 xmalloc_set_program_name (program_name);
46050fe4
ILT
1508 strip_symbols = strip_undef;
1509 discard_locals = locals_undef;
1510
1511 bfd_init ();
1512
1513 if (is_strip < 0)
1514 {
1515 int i = strlen (program_name);
87a15686 1516 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0);
46050fe4
ILT
1517 }
1518
1519 if (is_strip)
1520 strip_main (argc, argv);
1521 else
1522 copy_main (argc, argv);
1523
1524 return status;
1525}
This page took 0.131246 seconds and 4 git commands to generate.