objcopy.c revision 218822
1/* objcopy.c -- copy object file from input to output, optionally massaging it.
2   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3   2001, 2002, 2003, 2004, 2005, 2006, 2007
4   Free Software Foundation, Inc.
5
6   This file is part of GNU Binutils.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21   02110-1301, USA.  */
22
23#include "sysdep.h"
24#include "bfd.h"
25#include "progress.h"
26#include "getopt.h"
27#include "libiberty.h"
28#include "bucomm.h"
29#include "budbg.h"
30#include "filenames.h"
31#include "fnmatch.h"
32#include "elf-bfd.h"
33#include <sys/stat.h>
34#include "libbfd.h"
35
36/* A list of symbols to explicitly strip out, or to keep.  A linked
37   list is good enough for a small number from the command line, but
38   this will slow things down a lot if many symbols are being
39   deleted.  */
40
41struct symlist
42{
43  const char *name;
44  struct symlist *next;
45};
46
47/* A list to support redefine_sym.  */
48struct redefine_node
49{
50  char *source;
51  char *target;
52  struct redefine_node *next;
53};
54
55typedef struct section_rename
56{
57  const char *            old_name;
58  const char *            new_name;
59  flagword                flags;
60  struct section_rename * next;
61}
62section_rename;
63
64/* List of sections to be renamed.  */
65static section_rename *section_rename_list;
66
67#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
68
69static asymbol **isympp = NULL;	/* Input symbols.  */
70static asymbol **osympp = NULL;	/* Output symbols that survive stripping.  */
71
72/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
73static int copy_byte = -1;
74static int interleave = 4;
75
76static bfd_boolean verbose;		/* Print file and target names.  */
77static bfd_boolean preserve_dates;	/* Preserve input file timestamp.  */
78static int status = 0;		/* Exit status.  */
79
80enum strip_action
81  {
82    STRIP_UNDEF,
83    STRIP_NONE,			/* Don't strip.  */
84    STRIP_DEBUG,		/* Strip all debugger symbols.  */
85    STRIP_UNNEEDED,		/* Strip unnecessary symbols.  */
86    STRIP_NONDEBUG,		/* Strip everything but debug info.  */
87    STRIP_ALL			/* Strip all symbols.  */
88  };
89
90/* Which symbols to remove.  */
91static enum strip_action strip_symbols;
92
93enum locals_action
94  {
95    LOCALS_UNDEF,
96    LOCALS_START_L,		/* Discard locals starting with L.  */
97    LOCALS_ALL			/* Discard all locals.  */
98  };
99
100/* Which local symbols to remove.  Overrides STRIP_ALL.  */
101static enum locals_action discard_locals;
102
103/* What kind of change to perform.  */
104enum change_action
105{
106  CHANGE_IGNORE,
107  CHANGE_MODIFY,
108  CHANGE_SET
109};
110
111/* Structure used to hold lists of sections and actions to take.  */
112struct section_list
113{
114  struct section_list * next;	   /* Next section to change.  */
115  const char *		name;	   /* Section name.  */
116  bfd_boolean		used;	   /* Whether this entry was used.  */
117  bfd_boolean		remove;	   /* Whether to remove this section.  */
118  bfd_boolean		copy;	   /* Whether to copy this section.  */
119  enum change_action	change_vma;/* Whether to change or set VMA.  */
120  bfd_vma		vma_val;   /* Amount to change by or set to.  */
121  enum change_action	change_lma;/* Whether to change or set LMA.  */
122  bfd_vma		lma_val;   /* Amount to change by or set to.  */
123  bfd_boolean		set_flags; /* Whether to set the section flags.	 */
124  flagword		flags;	   /* What to set the section flags to.	 */
125};
126
127static struct section_list *change_sections;
128
129/* TRUE if some sections are to be removed.  */
130static bfd_boolean sections_removed;
131
132/* TRUE if only some sections are to be copied.  */
133static bfd_boolean sections_copied;
134
135/* Changes to the start address.  */
136static bfd_vma change_start = 0;
137static bfd_boolean set_start_set = FALSE;
138static bfd_vma set_start;
139
140/* Changes to section addresses.  */
141static bfd_vma change_section_address = 0;
142
143/* Filling gaps between sections.  */
144static bfd_boolean gap_fill_set = FALSE;
145static bfd_byte gap_fill = 0;
146
147/* Pad to a given address.  */
148static bfd_boolean pad_to_set = FALSE;
149static bfd_vma pad_to;
150
151/* Use alternative machine code?  */
152static unsigned long use_alt_mach_code = 0;
153
154/* Output BFD flags user wants to set or clear */
155static flagword bfd_flags_to_set;
156static flagword bfd_flags_to_clear;
157
158/* List of sections to add.  */
159struct section_add
160{
161  /* Next section to add.  */
162  struct section_add *next;
163  /* Name of section to add.  */
164  const char *name;
165  /* Name of file holding section contents.  */
166  const char *filename;
167  /* Size of file.  */
168  size_t size;
169  /* Contents of file.  */
170  bfd_byte *contents;
171  /* BFD section, after it has been added.  */
172  asection *section;
173};
174
175/* List of sections to add to the output BFD.  */
176static struct section_add *add_sections;
177
178/* If non-NULL the argument to --add-gnu-debuglink.
179   This should be the filename to store in the .gnu_debuglink section.  */
180static const char * gnu_debuglink_filename = NULL;
181
182/* Whether to convert debugging information.  */
183static bfd_boolean convert_debugging = FALSE;
184
185/* Whether to change the leading character in symbol names.  */
186static bfd_boolean change_leading_char = FALSE;
187
188/* Whether to remove the leading character from global symbol names.  */
189static bfd_boolean remove_leading_char = FALSE;
190
191/* Whether to permit wildcard in symbol comparison.  */
192static bfd_boolean wildcard = FALSE;
193
194/* True if --localize-hidden is in effect.  */
195static bfd_boolean localize_hidden = FALSE;
196
197/* List of symbols to strip, keep, localize, keep-global, weaken,
198   or redefine.  */
199static struct symlist *strip_specific_list = NULL;
200static struct symlist *strip_unneeded_list = NULL;
201static struct symlist *keep_specific_list = NULL;
202static struct symlist *localize_specific_list = NULL;
203static struct symlist *globalize_specific_list = NULL;
204static struct symlist *keepglobal_specific_list = NULL;
205static struct symlist *weaken_specific_list = NULL;
206static struct redefine_node *redefine_sym_list = NULL;
207
208/* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
209static bfd_boolean weaken = FALSE;
210
211/* If this is TRUE, we retain BSF_FILE symbols.  */
212static bfd_boolean keep_file_symbols = FALSE;
213
214/* Prefix symbols/sections.  */
215static char *prefix_symbols_string = 0;
216static char *prefix_sections_string = 0;
217static char *prefix_alloc_sections_string = 0;
218
219/* True if --extract-symbol was passed on the command line.  */
220static bfd_boolean extract_symbol = FALSE;
221
222/* If `reverse_bytes' is nonzero, then reverse the order of every chunk
223   of <reverse_bytes> bytes within each output section.  */
224static int reverse_bytes = 0;
225
226
227/* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
228enum command_line_switch
229  {
230    OPTION_ADD_SECTION=150,
231    OPTION_CHANGE_ADDRESSES,
232    OPTION_CHANGE_LEADING_CHAR,
233    OPTION_CHANGE_START,
234    OPTION_CHANGE_SECTION_ADDRESS,
235    OPTION_CHANGE_SECTION_LMA,
236    OPTION_CHANGE_SECTION_VMA,
237    OPTION_CHANGE_WARNINGS,
238    OPTION_DEBUGGING,
239    OPTION_GAP_FILL,
240    OPTION_NO_CHANGE_WARNINGS,
241    OPTION_PAD_TO,
242    OPTION_REMOVE_LEADING_CHAR,
243    OPTION_SET_SECTION_FLAGS,
244    OPTION_SET_START,
245    OPTION_STRIP_UNNEEDED,
246    OPTION_WEAKEN,
247    OPTION_REDEFINE_SYM,
248    OPTION_REDEFINE_SYMS,
249    OPTION_SREC_LEN,
250    OPTION_SREC_FORCES3,
251    OPTION_STRIP_SYMBOLS,
252    OPTION_STRIP_UNNEEDED_SYMBOL,
253    OPTION_STRIP_UNNEEDED_SYMBOLS,
254    OPTION_KEEP_SYMBOLS,
255    OPTION_LOCALIZE_HIDDEN,
256    OPTION_LOCALIZE_SYMBOLS,
257    OPTION_GLOBALIZE_SYMBOL,
258    OPTION_GLOBALIZE_SYMBOLS,
259    OPTION_KEEPGLOBAL_SYMBOLS,
260    OPTION_WEAKEN_SYMBOLS,
261    OPTION_RENAME_SECTION,
262    OPTION_ALT_MACH_CODE,
263    OPTION_PREFIX_SYMBOLS,
264    OPTION_PREFIX_SECTIONS,
265    OPTION_PREFIX_ALLOC_SECTIONS,
266    OPTION_FORMATS_INFO,
267    OPTION_ADD_GNU_DEBUGLINK,
268    OPTION_ONLY_KEEP_DEBUG,
269    OPTION_KEEP_FILE_SYMBOLS,
270    OPTION_READONLY_TEXT,
271    OPTION_WRITABLE_TEXT,
272    OPTION_PURE,
273    OPTION_IMPURE,
274    OPTION_EXTRACT_SYMBOL,
275    OPTION_REVERSE_BYTES
276  };
277
278/* Options to handle if running as "strip".  */
279
280static struct option strip_options[] =
281{
282  {"discard-all", no_argument, 0, 'x'},
283  {"discard-locals", no_argument, 0, 'X'},
284  {"format", required_argument, 0, 'F'}, /* Obsolete */
285  {"help", no_argument, 0, 'h'},
286  {"info", no_argument, 0, OPTION_FORMATS_INFO},
287  {"input-format", required_argument, 0, 'I'}, /* Obsolete */
288  {"input-target", required_argument, 0, 'I'},
289  {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
290  {"keep-symbol", required_argument, 0, 'K'},
291  {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
292  {"output-format", required_argument, 0, 'O'},	/* Obsolete */
293  {"output-target", required_argument, 0, 'O'},
294  {"output-file", required_argument, 0, 'o'},
295  {"preserve-dates", no_argument, 0, 'p'},
296  {"remove-section", required_argument, 0, 'R'},
297  {"strip-all", no_argument, 0, 's'},
298  {"strip-debug", no_argument, 0, 'S'},
299  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
300  {"strip-symbol", required_argument, 0, 'N'},
301  {"target", required_argument, 0, 'F'},
302  {"verbose", no_argument, 0, 'v'},
303  {"version", no_argument, 0, 'V'},
304  {"wildcard", no_argument, 0, 'w'},
305  {0, no_argument, 0, 0}
306};
307
308/* Options to handle if running as "objcopy".  */
309
310static struct option copy_options[] =
311{
312  {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
313  {"add-section", required_argument, 0, OPTION_ADD_SECTION},
314  {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
315  {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
316  {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
317  {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
318  {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
319  {"binary-architecture", required_argument, 0, 'B'},
320  {"byte", required_argument, 0, 'b'},
321  {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
322  {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
323  {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
324  {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
325  {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
326  {"change-start", required_argument, 0, OPTION_CHANGE_START},
327  {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
328  {"debugging", no_argument, 0, OPTION_DEBUGGING},
329  {"discard-all", no_argument, 0, 'x'},
330  {"discard-locals", no_argument, 0, 'X'},
331  {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
332  {"format", required_argument, 0, 'F'}, /* Obsolete */
333  {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
334  {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
335  {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
336  {"help", no_argument, 0, 'h'},
337  {"impure", no_argument, 0, OPTION_IMPURE},
338  {"info", no_argument, 0, OPTION_FORMATS_INFO},
339  {"input-format", required_argument, 0, 'I'}, /* Obsolete */
340  {"input-target", required_argument, 0, 'I'},
341  {"interleave", required_argument, 0, 'i'},
342  {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
343  {"keep-global-symbol", required_argument, 0, 'G'},
344  {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
345  {"keep-symbol", required_argument, 0, 'K'},
346  {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
347  {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
348  {"localize-symbol", required_argument, 0, 'L'},
349  {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
350  {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
351  {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
352  {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
353  {"only-section", required_argument, 0, 'j'},
354  {"output-format", required_argument, 0, 'O'},	/* Obsolete */
355  {"output-target", required_argument, 0, 'O'},
356  {"pad-to", required_argument, 0, OPTION_PAD_TO},
357  {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
358  {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
359  {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
360  {"preserve-dates", no_argument, 0, 'p'},
361  {"pure", no_argument, 0, OPTION_PURE},
362  {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
363  {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
364  {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
365  {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
366  {"remove-section", required_argument, 0, 'R'},
367  {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
368  {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
369  {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
370  {"set-start", required_argument, 0, OPTION_SET_START},
371  {"srec-len", required_argument, 0, OPTION_SREC_LEN},
372  {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
373  {"strip-all", no_argument, 0, 'S'},
374  {"strip-debug", no_argument, 0, 'g'},
375  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
376  {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
377  {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
378  {"strip-symbol", required_argument, 0, 'N'},
379  {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
380  {"target", required_argument, 0, 'F'},
381  {"verbose", no_argument, 0, 'v'},
382  {"version", no_argument, 0, 'V'},
383  {"weaken", no_argument, 0, OPTION_WEAKEN},
384  {"weaken-symbol", required_argument, 0, 'W'},
385  {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
386  {"wildcard", no_argument, 0, 'w'},
387  {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
388  {0, no_argument, 0, 0}
389};
390
391/* IMPORTS */
392extern char *program_name;
393
394/* This flag distinguishes between strip and objcopy:
395   1 means this is 'strip'; 0 means this is 'objcopy'.
396   -1 means if we should use argv[0] to decide.  */
397extern int is_strip;
398
399/* The maximum length of an S record.  This variable is declared in srec.c
400   and can be modified by the --srec-len parameter.  */
401extern unsigned int Chunk;
402
403/* Restrict the generation of Srecords to type S3 only.
404   This variable is declare in bfd/srec.c and can be toggled
405   on by the --srec-forceS3 command line switch.  */
406extern bfd_boolean S3Forced;
407
408/* Defined in bfd/binary.c.  Used to set architecture and machine of input
409   binary files.  */
410extern enum bfd_architecture  bfd_external_binary_architecture;
411extern unsigned long          bfd_external_machine;
412
413/* Forward declarations.  */
414static void setup_section (bfd *, asection *, void *);
415static void setup_bfd_headers (bfd *, bfd *);
416static void copy_section (bfd *, asection *, void *);
417static void get_sections (bfd *, asection *, void *);
418static int compare_section_lma (const void *, const void *);
419static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
420static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
421static const char *lookup_sym_redefinition (const char *);
422
423static void
424copy_usage (FILE *stream, int exit_status)
425{
426  fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
427  fprintf (stream, _(" Copies a binary file, possibly transforming it in the process\n"));
428  fprintf (stream, _(" The options are:\n"));
429  fprintf (stream, _("\
430  -I --input-target <bfdname>      Assume input file is in format <bfdname>\n\
431  -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
432  -B --binary-architecture <arch>  Set arch of output file, when input is binary\n\
433  -F --target <bfdname>            Set both input and output format to <bfdname>\n\
434     --debugging                   Convert debugging information, if possible\n\
435  -p --preserve-dates              Copy modified/access timestamps to the output\n\
436  -j --only-section <name>         Only copy section <name> into the output\n\
437     --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\n\
438  -R --remove-section <name>       Remove section <name> from the output\n\
439  -S --strip-all                   Remove all symbol and relocation information\n\
440  -g --strip-debug                 Remove all debugging symbols & sections\n\
441     --strip-unneeded              Remove all symbols not needed by relocations\n\
442  -N --strip-symbol <name>         Do not copy symbol <name>\n\
443     --strip-unneeded-symbol <name>\n\
444                                   Do not copy symbol <name> unless needed by\n\
445                                     relocations\n\
446     --only-keep-debug             Strip everything but the debug information\n\
447     --extract-symbol              Remove section contents but keep symbols\n\
448  -K --keep-symbol <name>          Do not strip symbol <name>\n\
449     --keep-file-symbols           Do not strip file symbol(s)\n\
450     --localize-hidden             Turn all ELF hidden symbols into locals\n\
451  -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
452     --globalize-symbol <name>     Force symbol <name> to be marked as a global\n\
453  -G --keep-global-symbol <name>   Localize all symbols except <name>\n\
454  -W --weaken-symbol <name>        Force symbol <name> to be marked as a weak\n\
455     --weaken                      Force all global symbols to be marked as weak\n\
456  -w --wildcard                    Permit wildcard in symbol comparison\n\
457  -x --discard-all                 Remove all non-global symbols\n\
458  -X --discard-locals              Remove any compiler-generated symbols\n\
459  -i --interleave <number>         Only copy one out of every <number> bytes\n\
460  -b --byte <num>                  Select byte <num> in every interleaved block\n\
461     --gap-fill <val>              Fill gaps between sections with <val>\n\
462     --pad-to <addr>               Pad the last section up to address <addr>\n\
463     --set-start <addr>            Set the start address to <addr>\n\
464    {--change-start|--adjust-start} <incr>\n\
465                                   Add <incr> to the start address\n\
466    {--change-addresses|--adjust-vma} <incr>\n\
467                                   Add <incr> to LMA, VMA and start addresses\n\
468    {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\
469                                   Change LMA and VMA of section <name> by <val>\n\
470     --change-section-lma <name>{=|+|-}<val>\n\
471                                   Change the LMA of section <name> by <val>\n\
472     --change-section-vma <name>{=|+|-}<val>\n\
473                                   Change the VMA of section <name> by <val>\n\
474    {--[no-]change-warnings|--[no-]adjust-warnings}\n\
475                                   Warn if a named section does not exist\n\
476     --set-section-flags <name>=<flags>\n\
477                                   Set section <name>'s properties to <flags>\n\
478     --add-section <name>=<file>   Add section <name> found in <file> to output\n\
479     --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
480     --change-leading-char         Force output format's leading character style\n\
481     --remove-leading-char         Remove leading character from global symbols\n\
482     --reverse-bytes=<num>         Reverse <num> bytes at a time, in output sections with content\n\
483     --redefine-sym <old>=<new>    Redefine symbol name <old> to <new>\n\
484     --redefine-syms <file>        --redefine-sym for all symbol pairs \n\
485                                     listed in <file>\n\
486     --srec-len <number>           Restrict the length of generated Srecords\n\
487     --srec-forceS3                Restrict the type of generated Srecords to S3\n\
488     --strip-symbols <file>        -N for all symbols listed in <file>\n\
489     --strip-unneeded-symbols <file>\n\
490                                   --strip-unneeded-symbol for all symbols listed\n\
491                                     in <file>\n\
492     --keep-symbols <file>         -K for all symbols listed in <file>\n\
493     --localize-symbols <file>     -L for all symbols listed in <file>\n\
494     --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
495     --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
496     --weaken-symbols <file>       -W for all symbols listed in <file>\n\
497     --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
498     --writable-text               Mark the output text as writable\n\
499     --readonly-text               Make the output text write protected\n\
500     --pure                        Mark the output file as demand paged\n\
501     --impure                      Mark the output file as impure\n\
502     --prefix-symbols <prefix>     Add <prefix> to start of every symbol name\n\
503     --prefix-sections <prefix>    Add <prefix> to start of every section name\n\
504     --prefix-alloc-sections <prefix>\n\
505                                   Add <prefix> to start of every allocatable\n\
506                                     section name\n\
507  -v --verbose                     List all object files modified\n\
508  @<file>                          Read options from <file>\n\
509  -V --version                     Display this program's version number\n\
510  -h --help                        Display this output\n\
511     --info                        List object formats & architectures supported\n\
512"));
513  list_supported_targets (program_name, stream);
514  if (REPORT_BUGS_TO[0] && exit_status == 0)
515    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
516  exit (exit_status);
517}
518
519static void
520strip_usage (FILE *stream, int exit_status)
521{
522  fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name);
523  fprintf (stream, _(" Removes symbols and sections from files\n"));
524  fprintf (stream, _(" The options are:\n"));
525  fprintf (stream, _("\
526  -I --input-target=<bfdname>      Assume input file is in format <bfdname>\n\
527  -O --output-target=<bfdname>     Create an output file in format <bfdname>\n\
528  -F --target=<bfdname>            Set both input and output format to <bfdname>\n\
529  -p --preserve-dates              Copy modified/access timestamps to the output\n\
530  -R --remove-section=<name>       Remove section <name> from the output\n\
531  -s --strip-all                   Remove all symbol and relocation information\n\
532  -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
533     --strip-unneeded              Remove all symbols not needed by relocations\n\
534     --only-keep-debug             Strip everything but the debug information\n\
535  -N --strip-symbol=<name>         Do not copy symbol <name>\n\
536  -K --keep-symbol=<name>          Do not strip symbol <name>\n\
537     --keep-file-symbols           Do not strip file symbol(s)\n\
538  -w --wildcard                    Permit wildcard in symbol comparison\n\
539  -x --discard-all                 Remove all non-global symbols\n\
540  -X --discard-locals              Remove any compiler-generated symbols\n\
541  -v --verbose                     List all object files modified\n\
542  -V --version                     Display this program's version number\n\
543  -h --help                        Display this output\n\
544     --info                        List object formats & architectures supported\n\
545  -o <file>                        Place stripped output into <file>\n\
546"));
547
548  list_supported_targets (program_name, stream);
549  if (REPORT_BUGS_TO[0] && exit_status == 0)
550    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
551  exit (exit_status);
552}
553
554/* Parse section flags into a flagword, with a fatal error if the
555   string can't be parsed.  */
556
557static flagword
558parse_flags (const char *s)
559{
560  flagword ret;
561  const char *snext;
562  int len;
563
564  ret = SEC_NO_FLAGS;
565
566  do
567    {
568      snext = strchr (s, ',');
569      if (snext == NULL)
570	len = strlen (s);
571      else
572	{
573	  len = snext - s;
574	  ++snext;
575	}
576
577      if (0) ;
578#define PARSE_FLAG(fname,fval) \
579  else if (strncasecmp (fname, s, len) == 0) ret |= fval
580      PARSE_FLAG ("alloc", SEC_ALLOC);
581      PARSE_FLAG ("load", SEC_LOAD);
582      PARSE_FLAG ("noload", SEC_NEVER_LOAD);
583      PARSE_FLAG ("readonly", SEC_READONLY);
584      PARSE_FLAG ("debug", SEC_DEBUGGING);
585      PARSE_FLAG ("code", SEC_CODE);
586      PARSE_FLAG ("data", SEC_DATA);
587      PARSE_FLAG ("rom", SEC_ROM);
588      PARSE_FLAG ("share", SEC_COFF_SHARED);
589      PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
590#undef PARSE_FLAG
591      else
592	{
593	  char *copy;
594
595	  copy = xmalloc (len + 1);
596	  strncpy (copy, s, len);
597	  copy[len] = '\0';
598	  non_fatal (_("unrecognized section flag `%s'"), copy);
599	  fatal (_("supported flags: %s"),
600		 "alloc, load, noload, readonly, debug, code, data, rom, share, contents");
601	}
602
603      s = snext;
604    }
605  while (s != NULL);
606
607  return ret;
608}
609
610/* Find and optionally add an entry in the change_sections list.  */
611
612static struct section_list *
613find_section_list (const char *name, bfd_boolean add)
614{
615  struct section_list *p;
616
617  for (p = change_sections; p != NULL; p = p->next)
618    if (strcmp (p->name, name) == 0)
619      return p;
620
621  if (! add)
622    return NULL;
623
624  p = xmalloc (sizeof (struct section_list));
625  p->name = name;
626  p->used = FALSE;
627  p->remove = FALSE;
628  p->copy = FALSE;
629  p->change_vma = CHANGE_IGNORE;
630  p->change_lma = CHANGE_IGNORE;
631  p->vma_val = 0;
632  p->lma_val = 0;
633  p->set_flags = FALSE;
634  p->flags = 0;
635
636  p->next = change_sections;
637  change_sections = p;
638
639  return p;
640}
641
642/* Add a symbol to strip_specific_list.  */
643
644static void
645add_specific_symbol (const char *name, struct symlist **list)
646{
647  struct symlist *tmp_list;
648
649  tmp_list = xmalloc (sizeof (struct symlist));
650  tmp_list->name = name;
651  tmp_list->next = *list;
652  *list = tmp_list;
653}
654
655/* Add symbols listed in `filename' to strip_specific_list.  */
656
657#define IS_WHITESPACE(c)      ((c) == ' ' || (c) == '\t')
658#define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
659
660static void
661add_specific_symbols (const char *filename, struct symlist **list)
662{
663  off_t  size;
664  FILE * f;
665  char * line;
666  char * buffer;
667  unsigned int line_count;
668
669  size = get_file_size (filename);
670  if (size == 0)
671    {
672      status = 1;
673      return;
674    }
675
676  buffer = xmalloc (size + 2);
677  f = fopen (filename, FOPEN_RT);
678  if (f == NULL)
679    fatal (_("cannot open '%s': %s"), filename, strerror (errno));
680
681  if (fread (buffer, 1, size, f) == 0 || ferror (f))
682    fatal (_("%s: fread failed"), filename);
683
684  fclose (f);
685  buffer [size] = '\n';
686  buffer [size + 1] = '\0';
687
688  line_count = 1;
689
690  for (line = buffer; * line != '\0'; line ++)
691    {
692      char * eol;
693      char * name;
694      char * name_end;
695      int finished = FALSE;
696
697      for (eol = line;; eol ++)
698	{
699	  switch (* eol)
700	    {
701	    case '\n':
702	      * eol = '\0';
703	      /* Cope with \n\r.  */
704	      if (eol[1] == '\r')
705		++ eol;
706	      finished = TRUE;
707	      break;
708
709	    case '\r':
710	      * eol = '\0';
711	      /* Cope with \r\n.  */
712	      if (eol[1] == '\n')
713		++ eol;
714	      finished = TRUE;
715	      break;
716
717	    case 0:
718	      finished = TRUE;
719	      break;
720
721	    case '#':
722	      /* Line comment, Terminate the line here, in case a
723		 name is present and then allow the rest of the
724		 loop to find the real end of the line.  */
725	      * eol = '\0';
726	      break;
727
728	    default:
729	      break;
730	    }
731
732	  if (finished)
733	    break;
734	}
735
736      /* A name may now exist somewhere between 'line' and 'eol'.
737	 Strip off leading whitespace and trailing whitespace,
738	 then add it to the list.  */
739      for (name = line; IS_WHITESPACE (* name); name ++)
740	;
741      for (name_end = name;
742	   (! IS_WHITESPACE (* name_end))
743	   && (! IS_LINE_TERMINATOR (* name_end));
744	   name_end ++)
745	;
746
747      if (! IS_LINE_TERMINATOR (* name_end))
748	{
749	  char * extra;
750
751	  for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++)
752	    ;
753
754	  if (! IS_LINE_TERMINATOR (* extra))
755	    non_fatal (_("%s:%d: Ignoring rubbish found on this line"),
756		       filename, line_count);
757	}
758
759      * name_end = '\0';
760
761      if (name_end > name)
762	add_specific_symbol (name, list);
763
764      /* Advance line pointer to end of line.  The 'eol ++' in the for
765	 loop above will then advance us to the start of the next line.  */
766      line = eol;
767      line_count ++;
768    }
769}
770
771/* See whether a symbol should be stripped or kept based on
772   strip_specific_list and keep_symbols.  */
773
774static bfd_boolean
775is_specified_symbol (const char *name, struct symlist *list)
776{
777  struct symlist *tmp_list;
778
779  if (wildcard)
780    {
781      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
782	if (*(tmp_list->name) != '!')
783	  {
784	    if (!fnmatch (tmp_list->name, name, 0))
785	      return TRUE;
786	  }
787	else
788	  {
789	    if (fnmatch (tmp_list->name + 1, name, 0))
790	      return TRUE;
791	  }
792    }
793  else
794    {
795      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
796	if (strcmp (name, tmp_list->name) == 0)
797	  return TRUE;
798    }
799
800  return FALSE;
801}
802
803/* Return a pointer to the symbol used as a signature for GROUP.  */
804
805static asymbol *
806group_signature (asection *group)
807{
808  bfd *abfd = group->owner;
809  Elf_Internal_Shdr *ghdr;
810
811  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
812    return NULL;
813
814  ghdr = &elf_section_data (group)->this_hdr;
815  if (ghdr->sh_link < elf_numsections (abfd))
816    {
817      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
818      Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
819
820      if (symhdr->sh_type == SHT_SYMTAB
821	  && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
822	return isympp[ghdr->sh_info - 1];
823    }
824  return NULL;
825}
826
827/* See if a section is being removed.  */
828
829static bfd_boolean
830is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
831{
832  if (sections_removed || sections_copied)
833    {
834      struct section_list *p;
835
836      p = find_section_list (bfd_get_section_name (abfd, sec), FALSE);
837
838      if (sections_removed && p != NULL && p->remove)
839	return TRUE;
840      if (sections_copied && (p == NULL || ! p->copy))
841	return TRUE;
842    }
843
844  if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0)
845    {
846      if (strip_symbols == STRIP_DEBUG
847	  || strip_symbols == STRIP_UNNEEDED
848	  || strip_symbols == STRIP_ALL
849	  || discard_locals == LOCALS_ALL
850	  || convert_debugging)
851	return TRUE;
852
853      if (strip_symbols == STRIP_NONDEBUG)
854	return FALSE;
855    }
856
857  if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
858    {
859      asymbol *gsym;
860      const char *gname;
861
862      /* PR binutils/3166
863	 Group sections look like debugging sections but they are not.
864	 (They have a non-zero size but they are not ALLOCated).  */
865      if (strip_symbols == STRIP_NONDEBUG)
866	return TRUE;
867
868      /* PR binutils/3181
869	 If we are going to strip the group signature symbol, then
870	 strip the group section too.  */
871      gsym = group_signature (sec);
872      if (gsym != NULL)
873	gname = gsym->name;
874      else
875	gname = sec->name;
876      if ((strip_symbols == STRIP_ALL
877	   && !is_specified_symbol (gname, keep_specific_list))
878	  || is_specified_symbol (gname, strip_specific_list))
879	return TRUE;
880    }
881
882  return FALSE;
883}
884
885/* Return true if SYM is a hidden symbol.  */
886
887static bfd_boolean
888is_hidden_symbol (asymbol *sym)
889{
890  elf_symbol_type *elf_sym;
891
892  elf_sym = elf_symbol_from (sym->the_bfd, sym);
893  if (elf_sym != NULL)
894    switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
895      {
896      case STV_HIDDEN:
897      case STV_INTERNAL:
898	return TRUE;
899      }
900  return FALSE;
901}
902
903/* Choose which symbol entries to copy; put the result in OSYMS.
904   We don't copy in place, because that confuses the relocs.
905   Return the number of symbols to print.  */
906
907static unsigned int
908filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
909		asymbol **isyms, long symcount)
910{
911  asymbol **from = isyms, **to = osyms;
912  long src_count = 0, dst_count = 0;
913  int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
914
915  for (; src_count < symcount; src_count++)
916    {
917      asymbol *sym = from[src_count];
918      flagword flags = sym->flags;
919      char *name = (char *) bfd_asymbol_name (sym);
920      bfd_boolean keep;
921      bfd_boolean used_in_reloc = FALSE;
922      bfd_boolean undefined;
923      bfd_boolean rem_leading_char;
924      bfd_boolean add_leading_char;
925
926      undefined = bfd_is_und_section (bfd_get_section (sym));
927
928      if (redefine_sym_list)
929	{
930	  char *old_name, *new_name;
931
932	  old_name = (char *) bfd_asymbol_name (sym);
933	  new_name = (char *) lookup_sym_redefinition (old_name);
934	  bfd_asymbol_name (sym) = new_name;
935	  name = new_name;
936	}
937
938      /* Check if we will remove the current leading character.  */
939      rem_leading_char =
940	(name[0] == bfd_get_symbol_leading_char (abfd))
941	&& (change_leading_char
942	    || (remove_leading_char
943		&& ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
944		    || undefined
945		    || bfd_is_com_section (bfd_get_section (sym)))));
946
947      /* Check if we will add a new leading character.  */
948      add_leading_char =
949	change_leading_char
950	&& (bfd_get_symbol_leading_char (obfd) != '\0')
951	&& (bfd_get_symbol_leading_char (abfd) == '\0'
952	    || (name[0] == bfd_get_symbol_leading_char (abfd)));
953
954      /* Short circuit for change_leading_char if we can do it in-place.  */
955      if (rem_leading_char && add_leading_char && !prefix_symbols_string)
956        {
957	  name[0] = bfd_get_symbol_leading_char (obfd);
958	  bfd_asymbol_name (sym) = name;
959	  rem_leading_char = FALSE;
960	  add_leading_char = FALSE;
961        }
962
963      /* Remove leading char.  */
964      if (rem_leading_char)
965	bfd_asymbol_name (sym) = ++name;
966
967      /* Add new leading char and/or prefix.  */
968      if (add_leading_char || prefix_symbols_string)
969        {
970          char *n, *ptr;
971
972          ptr = n = xmalloc (1 + strlen (prefix_symbols_string)
973			     + strlen (name) + 1);
974          if (add_leading_char)
975	    *ptr++ = bfd_get_symbol_leading_char (obfd);
976
977          if (prefix_symbols_string)
978            {
979              strcpy (ptr, prefix_symbols_string);
980              ptr += strlen (prefix_symbols_string);
981           }
982
983          strcpy (ptr, name);
984          bfd_asymbol_name (sym) = n;
985          name = n;
986	}
987
988      if (strip_symbols == STRIP_ALL)
989	keep = FALSE;
990      else if ((flags & BSF_KEEP) != 0		/* Used in relocation.  */
991	       || ((flags & BSF_SECTION_SYM) != 0
992		   && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
993		       & BSF_KEEP) != 0))
994	{
995	  keep = TRUE;
996	  used_in_reloc = TRUE;
997	}
998      else if (relocatable			/* Relocatable file.  */
999	       && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
1000	keep = TRUE;
1001      else if (bfd_decode_symclass (sym) == 'I')
1002	/* Global symbols in $idata sections need to be retained
1003	   even if relocatable is FALSE.  External users of the
1004	   library containing the $idata section may reference these
1005	   symbols.  */
1006	keep = TRUE;
1007      else if ((flags & BSF_GLOBAL) != 0	/* Global symbol.  */
1008	       || (flags & BSF_WEAK) != 0
1009	       || undefined
1010	       || bfd_is_com_section (bfd_get_section (sym)))
1011	keep = strip_symbols != STRIP_UNNEEDED;
1012      else if ((flags & BSF_DEBUGGING) != 0)	/* Debugging symbol.  */
1013	keep = (strip_symbols != STRIP_DEBUG
1014		&& strip_symbols != STRIP_UNNEEDED
1015		&& ! convert_debugging);
1016      else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
1017	/* COMDAT sections store special information in local
1018	   symbols, so we cannot risk stripping any of them.  */
1019	keep = TRUE;
1020      else			/* Local symbol.  */
1021	keep = (strip_symbols != STRIP_UNNEEDED
1022		&& (discard_locals != LOCALS_ALL
1023		    && (discard_locals != LOCALS_START_L
1024			|| ! bfd_is_local_label (abfd, sym))));
1025
1026      if (keep && is_specified_symbol (name, strip_specific_list))
1027	{
1028	  /* There are multiple ways to set 'keep' above, but if it
1029	     was the relocatable symbol case, then that's an error.  */
1030	  if (used_in_reloc)
1031	    {
1032	      non_fatal (_("not stripping symbol `%s' because it is named in a relocation"), name);
1033	      status = 1;
1034	    }
1035	  else
1036	    keep = FALSE;
1037	}
1038
1039      if (keep
1040	  && !(flags & BSF_KEEP)
1041	  && is_specified_symbol (name, strip_unneeded_list))
1042	keep = FALSE;
1043
1044      if (!keep
1045	  && ((keep_file_symbols && (flags & BSF_FILE))
1046	      || is_specified_symbol (name, keep_specific_list)))
1047	keep = TRUE;
1048
1049      if (keep && is_strip_section (abfd, bfd_get_section (sym)))
1050	keep = FALSE;
1051
1052      if (keep)
1053	{
1054	  if ((flags & BSF_GLOBAL) != 0
1055	      && (weaken || is_specified_symbol (name, weaken_specific_list)))
1056	    {
1057	      sym->flags &= ~ BSF_GLOBAL;
1058	      sym->flags |= BSF_WEAK;
1059	    }
1060
1061	  if (!undefined
1062	      && (flags & (BSF_GLOBAL | BSF_WEAK))
1063	      && (is_specified_symbol (name, localize_specific_list)
1064		  || (keepglobal_specific_list != NULL
1065		      && ! is_specified_symbol (name, keepglobal_specific_list))
1066		  || (localize_hidden && is_hidden_symbol (sym))))
1067	    {
1068	      sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
1069	      sym->flags |= BSF_LOCAL;
1070	    }
1071
1072	  if (!undefined
1073	      && (flags & BSF_LOCAL)
1074	      && is_specified_symbol (name, globalize_specific_list))
1075	    {
1076	      sym->flags &= ~ BSF_LOCAL;
1077	      sym->flags |= BSF_GLOBAL;
1078	    }
1079
1080	  to[dst_count++] = sym;
1081	}
1082    }
1083
1084  to[dst_count] = NULL;
1085
1086  return dst_count;
1087}
1088
1089/* Find the redefined name of symbol SOURCE.  */
1090
1091static const char *
1092lookup_sym_redefinition (const char *source)
1093{
1094  struct redefine_node *list;
1095
1096  for (list = redefine_sym_list; list != NULL; list = list->next)
1097    if (strcmp (source, list->source) == 0)
1098      return list->target;
1099
1100  return source;
1101}
1102
1103/* Add a node to a symbol redefine list.  */
1104
1105static void
1106redefine_list_append (const char *cause, const char *source, const char *target)
1107{
1108  struct redefine_node **p;
1109  struct redefine_node *list;
1110  struct redefine_node *new_node;
1111
1112  for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
1113    {
1114      if (strcmp (source, list->source) == 0)
1115	fatal (_("%s: Multiple redefinition of symbol \"%s\""),
1116	       cause, source);
1117
1118      if (strcmp (target, list->target) == 0)
1119	fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
1120	       cause, target);
1121    }
1122
1123  new_node = xmalloc (sizeof (struct redefine_node));
1124
1125  new_node->source = strdup (source);
1126  new_node->target = strdup (target);
1127  new_node->next = NULL;
1128
1129  *p = new_node;
1130}
1131
1132/* Handle the --redefine-syms option.  Read lines containing "old new"
1133   from the file, and add them to the symbol redefine list.  */
1134
1135static void
1136add_redefine_syms_file (const char *filename)
1137{
1138  FILE *file;
1139  char *buf;
1140  size_t bufsize;
1141  size_t len;
1142  size_t outsym_off;
1143  int c, lineno;
1144
1145  file = fopen (filename, "r");
1146  if (file == NULL)
1147    fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
1148	   filename, strerror (errno));
1149
1150  bufsize = 100;
1151  buf = xmalloc (bufsize);
1152
1153  lineno = 1;
1154  c = getc (file);
1155  len = 0;
1156  outsym_off = 0;
1157  while (c != EOF)
1158    {
1159      /* Collect the input symbol name.  */
1160      while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
1161	{
1162	  if (c == '#')
1163	    goto comment;
1164	  buf[len++] = c;
1165	  if (len >= bufsize)
1166	    {
1167	      bufsize *= 2;
1168	      buf = xrealloc (buf, bufsize);
1169	    }
1170	  c = getc (file);
1171	}
1172      buf[len++] = '\0';
1173      if (c == EOF)
1174	break;
1175
1176      /* Eat white space between the symbol names.  */
1177      while (IS_WHITESPACE (c))
1178	c = getc (file);
1179      if (c == '#' || IS_LINE_TERMINATOR (c))
1180	goto comment;
1181      if (c == EOF)
1182	break;
1183
1184      /* Collect the output symbol name.  */
1185      outsym_off = len;
1186      while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
1187	{
1188	  if (c == '#')
1189	    goto comment;
1190	  buf[len++] = c;
1191	  if (len >= bufsize)
1192	    {
1193	      bufsize *= 2;
1194	      buf = xrealloc (buf, bufsize);
1195	    }
1196	  c = getc (file);
1197	}
1198      buf[len++] = '\0';
1199      if (c == EOF)
1200	break;
1201
1202      /* Eat white space at end of line.  */
1203      while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c))
1204	c = getc (file);
1205      if (c == '#')
1206	goto comment;
1207      /* Handle \r\n.  */
1208      if ((c == '\r' && (c = getc (file)) == '\n')
1209	  || c == '\n' || c == EOF)
1210	{
1211 end_of_line:
1212	  /* Append the redefinition to the list.  */
1213	  if (buf[0] != '\0')
1214	    redefine_list_append (filename, &buf[0], &buf[outsym_off]);
1215
1216	  lineno++;
1217	  len = 0;
1218	  outsym_off = 0;
1219	  if (c == EOF)
1220	    break;
1221	  c = getc (file);
1222	  continue;
1223	}
1224      else
1225	fatal (_("%s:%d: garbage found at end of line"), filename, lineno);
1226 comment:
1227      if (len != 0 && (outsym_off == 0 || outsym_off == len))
1228	fatal (_("%s:%d: missing new symbol name"), filename, lineno);
1229      buf[len++] = '\0';
1230
1231      /* Eat the rest of the line and finish it.  */
1232      while (c != '\n' && c != EOF)
1233	c = getc (file);
1234      goto end_of_line;
1235    }
1236
1237  if (len != 0)
1238    fatal (_("%s:%d: premature end of file"), filename, lineno);
1239
1240  free (buf);
1241}
1242
1243/* Copy unkown object file IBFD onto OBFD.
1244   Returns TRUE upon success, FALSE otherwise.  */
1245
1246static bfd_boolean
1247copy_unknown_object (bfd *ibfd, bfd *obfd)
1248{
1249  char *cbuf;
1250  int tocopy;
1251  long ncopied;
1252  long size;
1253  struct stat buf;
1254
1255  if (bfd_stat_arch_elt (ibfd, &buf) != 0)
1256    {
1257      bfd_nonfatal (bfd_get_archive_filename (ibfd));
1258      return FALSE;
1259    }
1260
1261  size = buf.st_size;
1262  if (size < 0)
1263    {
1264      non_fatal (_("stat returns negative size for `%s'"),
1265		 bfd_get_archive_filename (ibfd));
1266      return FALSE;
1267    }
1268
1269  if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0)
1270    {
1271      bfd_nonfatal (bfd_get_archive_filename (ibfd));
1272      return FALSE;
1273    }
1274
1275  if (verbose)
1276    printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
1277	    bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
1278
1279  cbuf = xmalloc (BUFSIZE);
1280  ncopied = 0;
1281  while (ncopied < size)
1282    {
1283      tocopy = size - ncopied;
1284      if (tocopy > BUFSIZE)
1285	tocopy = BUFSIZE;
1286
1287      if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
1288	  != (bfd_size_type) tocopy)
1289	{
1290	  bfd_nonfatal (bfd_get_archive_filename (ibfd));
1291	  free (cbuf);
1292	  return FALSE;
1293	}
1294
1295      if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
1296	  != (bfd_size_type) tocopy)
1297	{
1298	  bfd_nonfatal (bfd_get_filename (obfd));
1299	  free (cbuf);
1300	  return FALSE;
1301	}
1302
1303      ncopied += tocopy;
1304    }
1305
1306  chmod (bfd_get_filename (obfd), buf.st_mode);
1307  free (cbuf);
1308  return TRUE;
1309}
1310
1311/* Copy object file IBFD onto OBFD.
1312   Returns TRUE upon success, FALSE otherwise.  */
1313
1314static bfd_boolean
1315copy_object (bfd *ibfd, bfd *obfd)
1316{
1317  bfd_vma start;
1318  long symcount;
1319  asection **osections = NULL;
1320  asection *gnu_debuglink_section = NULL;
1321  bfd_size_type *gaps = NULL;
1322  bfd_size_type max_gap = 0;
1323  long symsize;
1324  void *dhandle;
1325  enum bfd_architecture iarch;
1326  unsigned int imach;
1327
1328  if (ibfd->xvec->byteorder != obfd->xvec->byteorder
1329      && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
1330      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
1331    fatal (_("Unable to change endianness of input file(s)"));
1332
1333  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1334    {
1335      bfd_nonfatal (bfd_get_filename (obfd));
1336      return FALSE;
1337    }
1338
1339  if (verbose)
1340    printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
1341	    bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
1342	    bfd_get_filename (obfd), bfd_get_target (obfd));
1343
1344  if (extract_symbol)
1345    start = 0;
1346  else
1347    {
1348      if (set_start_set)
1349	start = set_start;
1350      else
1351	start = bfd_get_start_address (ibfd);
1352      start += change_start;
1353    }
1354
1355  /* Neither the start address nor the flags
1356     need to be set for a core file.  */
1357  if (bfd_get_format (obfd) != bfd_core)
1358    {
1359      flagword flags;
1360
1361      flags = bfd_get_file_flags (ibfd);
1362      flags |= bfd_flags_to_set;
1363      flags &= ~bfd_flags_to_clear;
1364      flags &= bfd_applicable_file_flags (obfd);
1365
1366      if (!bfd_set_start_address (obfd, start)
1367	  || !bfd_set_file_flags (obfd, flags))
1368	{
1369	  bfd_nonfatal (bfd_get_archive_filename (ibfd));
1370	  return FALSE;
1371	}
1372    }
1373
1374  /* Copy architecture of input file to output file.  */
1375  iarch = bfd_get_arch (ibfd);
1376  imach = bfd_get_mach (ibfd);
1377  if (!bfd_set_arch_mach (obfd, iarch, imach)
1378      && (ibfd->target_defaulted
1379	  || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
1380    {
1381      if (bfd_get_arch (ibfd) == bfd_arch_unknown)
1382	non_fatal (_("Unable to recognise the format of the input file `%s'"),
1383		   bfd_get_archive_filename (ibfd));
1384      else
1385	non_fatal (_("Warning: Output file cannot represent architecture `%s'"),
1386		   bfd_printable_arch_mach (bfd_get_arch (ibfd),
1387					    bfd_get_mach (ibfd)));
1388      return FALSE;
1389    }
1390
1391  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1392    {
1393      bfd_nonfatal (bfd_get_archive_filename (ibfd));
1394      return FALSE;
1395    }
1396
1397  if (isympp)
1398    free (isympp);
1399
1400  if (osympp != isympp)
1401    free (osympp);
1402
1403  isympp = NULL;
1404  osympp = NULL;
1405
1406  symsize = bfd_get_symtab_upper_bound (ibfd);
1407  if (symsize < 0)
1408    {
1409      bfd_nonfatal (bfd_get_archive_filename (ibfd));
1410      return FALSE;
1411    }
1412
1413  osympp = isympp = xmalloc (symsize);
1414  symcount = bfd_canonicalize_symtab (ibfd, isympp);
1415  if (symcount < 0)
1416    {
1417      bfd_nonfatal (bfd_get_filename (ibfd));
1418      return FALSE;
1419    }
1420
1421  /* BFD mandates that all output sections be created and sizes set before
1422     any output is done.  Thus, we traverse all sections multiple times.  */
1423  bfd_map_over_sections (ibfd, setup_section, obfd);
1424
1425  setup_bfd_headers (ibfd, obfd);
1426
1427  if (add_sections != NULL)
1428    {
1429      struct section_add *padd;
1430      struct section_list *pset;
1431
1432      for (padd = add_sections; padd != NULL; padd = padd->next)
1433	{
1434	  flagword flags;
1435
1436	  pset = find_section_list (padd->name, FALSE);
1437	  if (pset != NULL)
1438	    pset->used = TRUE;
1439
1440	  flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
1441	  if (pset != NULL && pset->set_flags)
1442	    flags = pset->flags | SEC_HAS_CONTENTS;
1443
1444	  /* bfd_make_section_with_flags() does not return very helpful
1445	     error codes, so check for the most likely user error first.  */
1446	  if (bfd_get_section_by_name (obfd, padd->name))
1447	    {
1448	      non_fatal (_("can't add section '%s' - it already exists!"), padd->name);
1449	      return FALSE;
1450	    }
1451	  else
1452	    {
1453	      padd->section = bfd_make_section_with_flags (obfd, padd->name, flags);
1454	      if (padd->section == NULL)
1455		{
1456		  non_fatal (_("can't create section `%s': %s"),
1457			     padd->name, bfd_errmsg (bfd_get_error ()));
1458		  return FALSE;
1459		}
1460	    }
1461
1462	  if (! bfd_set_section_size (obfd, padd->section, padd->size))
1463	    {
1464	      bfd_nonfatal (bfd_get_filename (obfd));
1465	      return FALSE;
1466	    }
1467
1468	  if (pset != NULL)
1469	    {
1470	      if (pset->change_vma != CHANGE_IGNORE)
1471		if (! bfd_set_section_vma (obfd, padd->section,
1472					   pset->vma_val))
1473		  {
1474		    bfd_nonfatal (bfd_get_filename (obfd));
1475		    return FALSE;
1476		  }
1477
1478	      if (pset->change_lma != CHANGE_IGNORE)
1479		{
1480		  padd->section->lma = pset->lma_val;
1481
1482		  if (! bfd_set_section_alignment
1483		      (obfd, padd->section,
1484		       bfd_section_alignment (obfd, padd->section)))
1485		    {
1486		      bfd_nonfatal (bfd_get_filename (obfd));
1487		      return FALSE;
1488		    }
1489		}
1490	    }
1491	}
1492    }
1493
1494  if (gnu_debuglink_filename != NULL)
1495    {
1496      gnu_debuglink_section = bfd_create_gnu_debuglink_section
1497	(obfd, gnu_debuglink_filename);
1498
1499      if (gnu_debuglink_section == NULL)
1500	{
1501	  bfd_nonfatal (gnu_debuglink_filename);
1502	  return FALSE;
1503	}
1504
1505      /* Special processing for PE format files.  We
1506	 have no way to distinguish PE from COFF here.  */
1507      if (bfd_get_flavour (obfd) == bfd_target_coff_flavour)
1508	{
1509	  bfd_vma debuglink_vma;
1510	  asection * highest_section;
1511	  asection * sec;
1512
1513	  /* The PE spec requires that all sections be adjacent and sorted
1514	     in ascending order of VMA.  It also specifies that debug
1515	     sections should be last.  This is despite the fact that debug
1516	     sections are not loaded into memory and so in theory have no
1517	     use for a VMA.
1518
1519	     This means that the debuglink section must be given a non-zero
1520	     VMA which makes it contiguous with other debug sections.  So
1521	     walk the current section list, find the section with the
1522	     highest VMA and start the debuglink section after that one.  */
1523	  for (sec = obfd->sections, highest_section = NULL;
1524	       sec != NULL;
1525	       sec = sec->next)
1526	    if (sec->vma > 0
1527		&& (highest_section == NULL
1528		    || sec->vma > highest_section->vma))
1529	      highest_section = sec;
1530
1531	  if (highest_section)
1532	    debuglink_vma = BFD_ALIGN (highest_section->vma
1533				       + highest_section->size,
1534				       /* FIXME: We ought to be using
1535					  COFF_PAGE_SIZE here or maybe
1536					  bfd_get_section_alignment() (if it
1537					  was set) but since this is for PE
1538					  and we know the required alignment
1539					  it is easier just to hard code it.  */
1540				       0x1000);
1541	  else
1542	    /* Umm, not sure what to do in this case.  */
1543	    debuglink_vma = 0x1000;
1544
1545	  bfd_set_section_vma (obfd, gnu_debuglink_section, debuglink_vma);
1546	}
1547    }
1548
1549  if (bfd_count_sections (obfd) != 0
1550      && (gap_fill_set || pad_to_set))
1551    {
1552      asection **set;
1553      unsigned int c, i;
1554
1555      /* We must fill in gaps between the sections and/or we must pad
1556	 the last section to a specified address.  We do this by
1557	 grabbing a list of the sections, sorting them by VMA, and
1558	 increasing the section sizes as required to fill the gaps.
1559	 We write out the gap contents below.  */
1560
1561      c = bfd_count_sections (obfd);
1562      osections = xmalloc (c * sizeof (asection *));
1563      set = osections;
1564      bfd_map_over_sections (obfd, get_sections, &set);
1565
1566      qsort (osections, c, sizeof (asection *), compare_section_lma);
1567
1568      gaps = xmalloc (c * sizeof (bfd_size_type));
1569      memset (gaps, 0, c * sizeof (bfd_size_type));
1570
1571      if (gap_fill_set)
1572	{
1573	  for (i = 0; i < c - 1; i++)
1574	    {
1575	      flagword flags;
1576	      bfd_size_type size;
1577	      bfd_vma gap_start, gap_stop;
1578
1579	      flags = bfd_get_section_flags (obfd, osections[i]);
1580	      if ((flags & SEC_HAS_CONTENTS) == 0
1581		  || (flags & SEC_LOAD) == 0)
1582		continue;
1583
1584	      size = bfd_section_size (obfd, osections[i]);
1585	      gap_start = bfd_section_lma (obfd, osections[i]) + size;
1586	      gap_stop = bfd_section_lma (obfd, osections[i + 1]);
1587	      if (gap_start < gap_stop)
1588		{
1589		  if (! bfd_set_section_size (obfd, osections[i],
1590					      size + (gap_stop - gap_start)))
1591		    {
1592		      non_fatal (_("Can't fill gap after %s: %s"),
1593				 bfd_get_section_name (obfd, osections[i]),
1594				 bfd_errmsg (bfd_get_error ()));
1595		      status = 1;
1596		      break;
1597		    }
1598		  gaps[i] = gap_stop - gap_start;
1599		  if (max_gap < gap_stop - gap_start)
1600		    max_gap = gap_stop - gap_start;
1601		}
1602	    }
1603	}
1604
1605      if (pad_to_set)
1606	{
1607	  bfd_vma lma;
1608	  bfd_size_type size;
1609
1610	  lma = bfd_section_lma (obfd, osections[c - 1]);
1611	  size = bfd_section_size (obfd, osections[c - 1]);
1612	  if (lma + size < pad_to)
1613	    {
1614	      if (! bfd_set_section_size (obfd, osections[c - 1],
1615					  pad_to - lma))
1616		{
1617		  non_fatal (_("Can't add padding to %s: %s"),
1618			     bfd_get_section_name (obfd, osections[c - 1]),
1619			     bfd_errmsg (bfd_get_error ()));
1620		  status = 1;
1621		}
1622	      else
1623		{
1624		  gaps[c - 1] = pad_to - (lma + size);
1625		  if (max_gap < pad_to - (lma + size))
1626		    max_gap = pad_to - (lma + size);
1627		}
1628	    }
1629	}
1630    }
1631
1632  /* Symbol filtering must happen after the output sections
1633     have been created, but before their contents are set.  */
1634  dhandle = NULL;
1635  if (convert_debugging)
1636    dhandle = read_debugging_info (ibfd, isympp, symcount);
1637
1638  if (strip_symbols == STRIP_DEBUG
1639      || strip_symbols == STRIP_ALL
1640      || strip_symbols == STRIP_UNNEEDED
1641      || strip_symbols == STRIP_NONDEBUG
1642      || discard_locals != LOCALS_UNDEF
1643      || localize_hidden
1644      || strip_specific_list != NULL
1645      || keep_specific_list != NULL
1646      || localize_specific_list != NULL
1647      || globalize_specific_list != NULL
1648      || keepglobal_specific_list != NULL
1649      || weaken_specific_list != NULL
1650      || prefix_symbols_string
1651      || sections_removed
1652      || sections_copied
1653      || convert_debugging
1654      || change_leading_char
1655      || remove_leading_char
1656      || redefine_sym_list
1657      || weaken)
1658    {
1659      /* Mark symbols used in output relocations so that they
1660	 are kept, even if they are local labels or static symbols.
1661
1662	 Note we iterate over the input sections examining their
1663	 relocations since the relocations for the output sections
1664	 haven't been set yet.  mark_symbols_used_in_relocations will
1665	 ignore input sections which have no corresponding output
1666	 section.  */
1667      if (strip_symbols != STRIP_ALL)
1668	bfd_map_over_sections (ibfd,
1669			       mark_symbols_used_in_relocations,
1670			       isympp);
1671      osympp = xmalloc ((symcount + 1) * sizeof (asymbol *));
1672      symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
1673    }
1674
1675  if (convert_debugging && dhandle != NULL)
1676    {
1677      if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
1678	{
1679	  status = 1;
1680	  return FALSE;
1681	}
1682    }
1683
1684  bfd_set_symtab (obfd, osympp, symcount);
1685
1686  /* This has to happen after the symbol table has been set.  */
1687  bfd_map_over_sections (ibfd, copy_section, obfd);
1688
1689  if (add_sections != NULL)
1690    {
1691      struct section_add *padd;
1692
1693      for (padd = add_sections; padd != NULL; padd = padd->next)
1694	{
1695	  if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
1696					  0, padd->size))
1697	    {
1698	      bfd_nonfatal (bfd_get_filename (obfd));
1699	      return FALSE;
1700	    }
1701	}
1702    }
1703
1704  if (gnu_debuglink_filename != NULL)
1705    {
1706      if (! bfd_fill_in_gnu_debuglink_section
1707	  (obfd, gnu_debuglink_section, gnu_debuglink_filename))
1708	{
1709	  bfd_nonfatal (gnu_debuglink_filename);
1710	  return FALSE;
1711	}
1712    }
1713
1714  if (gap_fill_set || pad_to_set)
1715    {
1716      bfd_byte *buf;
1717      int c, i;
1718
1719      /* Fill in the gaps.  */
1720      if (max_gap > 8192)
1721	max_gap = 8192;
1722      buf = xmalloc (max_gap);
1723      memset (buf, gap_fill, max_gap);
1724
1725      c = bfd_count_sections (obfd);
1726      for (i = 0; i < c; i++)
1727	{
1728	  if (gaps[i] != 0)
1729	    {
1730	      bfd_size_type left;
1731	      file_ptr off;
1732
1733	      left = gaps[i];
1734	      off = bfd_section_size (obfd, osections[i]) - left;
1735
1736	      while (left > 0)
1737		{
1738		  bfd_size_type now;
1739
1740		  if (left > 8192)
1741		    now = 8192;
1742		  else
1743		    now = left;
1744
1745		  if (! bfd_set_section_contents (obfd, osections[i], buf,
1746						  off, now))
1747		    {
1748		      bfd_nonfatal (bfd_get_filename (obfd));
1749		      return FALSE;
1750		    }
1751
1752		  left -= now;
1753		  off += now;
1754		}
1755	    }
1756	}
1757    }
1758
1759  /* Do not copy backend data if --extract-symbol is passed; anything
1760     that needs to look at the section contents will fail.  */
1761  if (extract_symbol)
1762    return TRUE;
1763
1764  /* Allow the BFD backend to copy any private data it understands
1765     from the input BFD to the output BFD.  This is done last to
1766     permit the routine to look at the filtered symbol table, which is
1767     important for the ECOFF code at least.  */
1768  if (! bfd_copy_private_bfd_data (ibfd, obfd))
1769    {
1770      non_fatal (_("%s: error copying private BFD data: %s"),
1771		 bfd_get_filename (obfd),
1772		 bfd_errmsg (bfd_get_error ()));
1773      return FALSE;
1774    }
1775
1776  /* Switch to the alternate machine code.  We have to do this at the
1777     very end, because we only initialize the header when we create
1778     the first section.  */
1779  if (use_alt_mach_code != 0)
1780    {
1781      if (! bfd_alt_mach_code (obfd, use_alt_mach_code))
1782	{
1783	  non_fatal (_("this target does not support %lu alternative machine codes"),
1784		     use_alt_mach_code);
1785	  if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
1786	    {
1787	      non_fatal (_("treating that number as an absolute e_machine value instead"));
1788	      elf_elfheader (obfd)->e_machine = use_alt_mach_code;
1789	    }
1790	  else
1791	    non_fatal (_("ignoring the alternative value"));
1792	}
1793    }
1794
1795  return TRUE;
1796}
1797
1798/* Read each archive element in turn from IBFD, copy the
1799   contents to temp file, and keep the temp file handle.
1800   If 'force_output_target' is TRUE then make sure that
1801   all elements in the new archive are of the type
1802   'output_target'.  */
1803
1804static void
1805copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
1806	      bfd_boolean force_output_target)
1807{
1808  struct name_list
1809    {
1810      struct name_list *next;
1811      const char *name;
1812      bfd *obfd;
1813    } *list, *l;
1814  bfd **ptr = &obfd->archive_head;
1815  bfd *this_element;
1816  char * dir;
1817
1818  /* Make a temp directory to hold the contents.  */
1819  dir = make_tempdir (bfd_get_filename (obfd));
1820  if (dir == NULL)
1821      fatal (_("cannot create tempdir for archive copying (error: %s)"),
1822	   strerror (errno));
1823
1824  obfd->has_armap = ibfd->has_armap;
1825
1826  list = NULL;
1827
1828  this_element = bfd_openr_next_archived_file (ibfd, NULL);
1829
1830  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1831    RETURN_NONFATAL (bfd_get_filename (obfd));
1832
1833  while (!status && this_element != NULL)
1834    {
1835      char *output_name;
1836      bfd *output_bfd;
1837      bfd *last_element;
1838      struct stat buf;
1839      int stat_status = 0;
1840      bfd_boolean delete = TRUE;
1841
1842      /* Create an output file for this member.  */
1843      output_name = concat (dir, "/",
1844			    bfd_get_filename (this_element), (char *) 0);
1845
1846      /* If the file already exists, make another temp dir.  */
1847      if (stat (output_name, &buf) >= 0)
1848	{
1849	  output_name = make_tempdir (output_name);
1850	  if (output_name == NULL)
1851	    fatal (_("cannot create tempdir for archive copying (error: %s)"),
1852		   strerror (errno));
1853
1854	  l = xmalloc (sizeof (struct name_list));
1855	  l->name = output_name;
1856	  l->next = list;
1857	  l->obfd = NULL;
1858	  list = l;
1859	  output_name = concat (output_name, "/",
1860				bfd_get_filename (this_element), (char *) 0);
1861	}
1862
1863      if (preserve_dates)
1864	{
1865	  stat_status = bfd_stat_arch_elt (this_element, &buf);
1866
1867	  if (stat_status != 0)
1868	    non_fatal (_("internal stat error on %s"),
1869		       bfd_get_filename (this_element));
1870	}
1871
1872      l = xmalloc (sizeof (struct name_list));
1873      l->name = output_name;
1874      l->next = list;
1875      l->obfd = NULL;
1876      list = l;
1877
1878      if (bfd_check_format (this_element, bfd_object))
1879	{
1880	  /* PR binutils/3110: Cope with archives
1881	     containing multiple target types.  */
1882	  if (force_output_target)
1883	    output_bfd = bfd_openw (output_name, output_target);
1884	  else
1885	    output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
1886
1887	  if (output_bfd == NULL)
1888	    RETURN_NONFATAL (output_name);
1889
1890	  delete = ! copy_object (this_element, output_bfd);
1891
1892	  if (! delete
1893	      || bfd_get_arch (this_element) != bfd_arch_unknown)
1894	    {
1895	      if (!bfd_close (output_bfd))
1896		{
1897		  bfd_nonfatal (bfd_get_filename (output_bfd));
1898		  /* Error in new object file. Don't change archive.  */
1899		  status = 1;
1900		}
1901	    }
1902	  else
1903	    goto copy_unknown_element;
1904	}
1905      else
1906	{
1907	  non_fatal (_("Unable to recognise the format of the input file `%s'"),
1908		     bfd_get_archive_filename (this_element));
1909
1910	  output_bfd = bfd_openw (output_name, output_target);
1911copy_unknown_element:
1912	  delete = !copy_unknown_object (this_element, output_bfd);
1913	  if (!bfd_close_all_done (output_bfd))
1914	    {
1915	      bfd_nonfatal (bfd_get_filename (output_bfd));
1916	      /* Error in new object file. Don't change archive.  */
1917	      status = 1;
1918	    }
1919	}
1920
1921      if (delete)
1922	{
1923	  unlink (output_name);
1924	  status = 1;
1925	}
1926      else
1927	{
1928	  if (preserve_dates && stat_status == 0)
1929	    set_times (output_name, &buf);
1930
1931	  /* Open the newly output file and attach to our list.  */
1932	  output_bfd = bfd_openr (output_name, output_target);
1933
1934	  l->obfd = output_bfd;
1935
1936	  *ptr = output_bfd;
1937	  ptr = &output_bfd->archive_next;
1938
1939	  last_element = this_element;
1940
1941	  this_element = bfd_openr_next_archived_file (ibfd, last_element);
1942
1943	  bfd_close (last_element);
1944	}
1945    }
1946  *ptr = NULL;
1947
1948  if (!bfd_close (obfd))
1949    RETURN_NONFATAL (bfd_get_filename (obfd));
1950
1951  if (!bfd_close (ibfd))
1952    RETURN_NONFATAL (bfd_get_filename (ibfd));
1953
1954  /* Delete all the files that we opened.  */
1955  for (l = list; l != NULL; l = l->next)
1956    {
1957      if (l->obfd == NULL)
1958	rmdir (l->name);
1959      else
1960	{
1961	  bfd_close (l->obfd);
1962	  unlink (l->name);
1963	}
1964    }
1965  rmdir (dir);
1966}
1967
1968/* The top-level control.  */
1969
1970static void
1971copy_file (const char *input_filename, const char *output_filename,
1972	   const char *input_target,   const char *output_target)
1973{
1974  bfd *ibfd;
1975  char **obj_matching;
1976  char **core_matching;
1977
1978  if (get_file_size (input_filename) < 1)
1979    {
1980      status = 1;
1981      return;
1982    }
1983
1984  /* To allow us to do "strip *" without dying on the first
1985     non-object file, failures are nonfatal.  */
1986  ibfd = bfd_openr (input_filename, input_target);
1987  if (ibfd == NULL)
1988    RETURN_NONFATAL (input_filename);
1989
1990  if (bfd_check_format (ibfd, bfd_archive))
1991    {
1992      bfd_boolean force_output_target;
1993      bfd *obfd;
1994
1995      /* bfd_get_target does not return the correct value until
1996         bfd_check_format succeeds.  */
1997      if (output_target == NULL)
1998	{
1999	  output_target = bfd_get_target (ibfd);
2000	  force_output_target = FALSE;
2001	}
2002      else
2003	force_output_target = TRUE;
2004
2005      obfd = bfd_openw (output_filename, output_target);
2006      if (obfd == NULL)
2007	RETURN_NONFATAL (output_filename);
2008
2009      copy_archive (ibfd, obfd, output_target, force_output_target);
2010    }
2011  else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
2012    {
2013      bfd *obfd;
2014    do_copy:
2015
2016      /* bfd_get_target does not return the correct value until
2017         bfd_check_format succeeds.  */
2018      if (output_target == NULL)
2019	output_target = bfd_get_target (ibfd);
2020
2021      obfd = bfd_openw (output_filename, output_target);
2022      if (obfd == NULL)
2023	RETURN_NONFATAL (output_filename);
2024
2025      if (! copy_object (ibfd, obfd))
2026	status = 1;
2027
2028      if (!bfd_close (obfd))
2029	RETURN_NONFATAL (output_filename);
2030
2031      if (!bfd_close (ibfd))
2032	RETURN_NONFATAL (input_filename);
2033
2034    }
2035  else
2036    {
2037      bfd_error_type obj_error = bfd_get_error ();
2038      bfd_error_type core_error;
2039
2040      if (bfd_check_format_matches (ibfd, bfd_core, &core_matching))
2041	{
2042	  /* This probably can't happen..  */
2043	  if (obj_error == bfd_error_file_ambiguously_recognized)
2044	    free (obj_matching);
2045	  goto do_copy;
2046	}
2047
2048      core_error = bfd_get_error ();
2049      /* Report the object error in preference to the core error.  */
2050      if (obj_error != core_error)
2051	bfd_set_error (obj_error);
2052
2053      bfd_nonfatal (input_filename);
2054
2055      if (obj_error == bfd_error_file_ambiguously_recognized)
2056	{
2057	  list_matching_formats (obj_matching);
2058	  free (obj_matching);
2059	}
2060      if (core_error == bfd_error_file_ambiguously_recognized)
2061	{
2062	  list_matching_formats (core_matching);
2063	  free (core_matching);
2064	}
2065
2066      status = 1;
2067    }
2068}
2069
2070/* Add a name to the section renaming list.  */
2071
2072static void
2073add_section_rename (const char * old_name, const char * new_name,
2074		    flagword flags)
2075{
2076  section_rename * rename;
2077
2078  /* Check for conflicts first.  */
2079  for (rename = section_rename_list; rename != NULL; rename = rename->next)
2080    if (strcmp (rename->old_name, old_name) == 0)
2081      {
2082	/* Silently ignore duplicate definitions.  */
2083	if (strcmp (rename->new_name, new_name) == 0
2084	    && rename->flags == flags)
2085	  return;
2086
2087	fatal (_("Multiple renames of section %s"), old_name);
2088      }
2089
2090  rename = xmalloc (sizeof (* rename));
2091
2092  rename->old_name = old_name;
2093  rename->new_name = new_name;
2094  rename->flags    = flags;
2095  rename->next     = section_rename_list;
2096
2097  section_rename_list = rename;
2098}
2099
2100/* Check the section rename list for a new name of the input section
2101   ISECTION.  Return the new name if one is found.
2102   Also set RETURNED_FLAGS to the flags to be used for this section.  */
2103
2104static const char *
2105find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
2106		     flagword * returned_flags)
2107{
2108  const char * old_name = bfd_section_name (ibfd, isection);
2109  section_rename * rename;
2110
2111  /* Default to using the flags of the input section.  */
2112  * returned_flags = bfd_get_section_flags (ibfd, isection);
2113
2114  for (rename = section_rename_list; rename != NULL; rename = rename->next)
2115    if (strcmp (rename->old_name, old_name) == 0)
2116      {
2117	if (rename->flags != (flagword) -1)
2118	  * returned_flags = rename->flags;
2119
2120	return rename->new_name;
2121      }
2122
2123  return old_name;
2124}
2125
2126/* Once each of the sections is copied, we may still need to do some
2127   finalization work for private section headers.  Do that here.  */
2128
2129static void
2130setup_bfd_headers (bfd *ibfd, bfd *obfd)
2131{
2132  const char *err;
2133
2134  /* Allow the BFD backend to copy any private data it understands
2135     from the input section to the output section.  */
2136  if (! bfd_copy_private_header_data (ibfd, obfd))
2137    {
2138      err = _("private header data");
2139      goto loser;
2140    }
2141
2142  /* All went well.  */
2143  return;
2144
2145loser:
2146  non_fatal (_("%s: error in %s: %s"),
2147	     bfd_get_filename (ibfd),
2148	     err, bfd_errmsg (bfd_get_error ()));
2149  status = 1;
2150}
2151
2152/* Create a section in OBFD with the same
2153   name and attributes as ISECTION in IBFD.  */
2154
2155static void
2156setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
2157{
2158  bfd *obfd = obfdarg;
2159  struct section_list *p;
2160  sec_ptr osection;
2161  bfd_size_type size;
2162  bfd_vma vma;
2163  bfd_vma lma;
2164  flagword flags;
2165  const char *err;
2166  const char * name;
2167  char *prefix = NULL;
2168
2169  if (is_strip_section (ibfd, isection))
2170    return;
2171
2172  p = find_section_list (bfd_section_name (ibfd, isection), FALSE);
2173  if (p != NULL)
2174    p->used = TRUE;
2175
2176  /* Get the, possibly new, name of the output section.  */
2177  name = find_section_rename (ibfd, isection, & flags);
2178
2179  /* Prefix sections.  */
2180  if ((prefix_alloc_sections_string)
2181      && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
2182    prefix = prefix_alloc_sections_string;
2183  else if (prefix_sections_string)
2184    prefix = prefix_sections_string;
2185
2186  if (prefix)
2187    {
2188      char *n;
2189
2190      n = xmalloc (strlen (prefix) + strlen (name) + 1);
2191      strcpy (n, prefix);
2192      strcat (n, name);
2193      name = n;
2194    }
2195
2196  if (p != NULL && p->set_flags)
2197    flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
2198  else if (strip_symbols == STRIP_NONDEBUG
2199	   && obfd->xvec->flavour != bfd_target_elf_flavour
2200	   && (flags & SEC_ALLOC) != 0)
2201    flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
2202
2203  osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
2204
2205  if (osection == NULL)
2206    {
2207      err = _("making");
2208      goto loser;
2209    }
2210
2211  if (strip_symbols == STRIP_NONDEBUG
2212      && obfd->xvec->flavour == bfd_target_elf_flavour
2213      && (flags & SEC_ALLOC) != 0
2214      && elf_section_type (osection) != SHT_NOTE
2215      && (ibfd->xvec->flavour != bfd_target_elf_flavour
2216	  || elf_section_type (isection) != SHT_NOTE)
2217      && (p == NULL || !p->set_flags))
2218    elf_section_type (osection) = SHT_NOBITS;
2219
2220  size = bfd_section_size (ibfd, isection);
2221  if (copy_byte >= 0)
2222    size = (size + interleave - 1) / interleave;
2223  else if (extract_symbol)
2224    size = 0;
2225  if (! bfd_set_section_size (obfd, osection, size))
2226    {
2227      err = _("size");
2228      goto loser;
2229    }
2230
2231  vma = bfd_section_vma (ibfd, isection);
2232  if (p != NULL && p->change_vma == CHANGE_MODIFY)
2233    vma += p->vma_val;
2234  else if (p != NULL && p->change_vma == CHANGE_SET)
2235    vma = p->vma_val;
2236  else
2237    vma += change_section_address;
2238
2239  if (! bfd_set_section_vma (obfd, osection, extract_symbol ? 0 : vma))
2240    {
2241      err = _("vma");
2242      goto loser;
2243    }
2244
2245  lma = isection->lma;
2246  if ((p != NULL) && p->change_lma != CHANGE_IGNORE)
2247    {
2248      if (p->change_lma == CHANGE_MODIFY)
2249	lma += p->lma_val;
2250      else if (p->change_lma == CHANGE_SET)
2251	lma = p->lma_val;
2252      else
2253	abort ();
2254    }
2255  else
2256    lma += change_section_address;
2257
2258  osection->lma = extract_symbol ? 0 : lma;
2259
2260  /* FIXME: This is probably not enough.  If we change the LMA we
2261     may have to recompute the header for the file as well.  */
2262  if (!bfd_set_section_alignment (obfd,
2263				  osection,
2264				  bfd_section_alignment (ibfd, isection)))
2265    {
2266      err = _("alignment");
2267      goto loser;
2268    }
2269
2270  /* Copy merge entity size.  */
2271  osection->entsize = isection->entsize;
2272
2273  /* This used to be mangle_section; we do here to avoid using
2274     bfd_get_section_by_name since some formats allow multiple
2275     sections with the same name.  */
2276  isection->output_section = osection;
2277  isection->output_offset = extract_symbol ? vma : 0;
2278
2279  /* Do not copy backend data if --extract-symbol is passed; anything
2280     that needs to look at the section contents will fail.  */
2281  if (extract_symbol)
2282    return;
2283
2284  /* Allow the BFD backend to copy any private data it understands
2285     from the input section to the output section.  */
2286  if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
2287    {
2288      err = _("private data");
2289      goto loser;
2290    }
2291  else if ((isection->flags & SEC_GROUP) != 0)
2292    {
2293      asymbol *gsym = group_signature (isection);
2294
2295      if (gsym != NULL)
2296	gsym->flags |= BSF_KEEP;
2297    }
2298
2299  /* All went well.  */
2300  return;
2301
2302loser:
2303  non_fatal (_("%s: section `%s': error in %s: %s"),
2304	     bfd_get_filename (ibfd),
2305	     bfd_section_name (ibfd, isection),
2306	     err, bfd_errmsg (bfd_get_error ()));
2307  status = 1;
2308}
2309
2310/* Copy the data of input section ISECTION of IBFD
2311   to an output section with the same name in OBFD.
2312   If stripping then don't copy any relocation info.  */
2313
2314static void
2315copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
2316{
2317  bfd *obfd = obfdarg;
2318  struct section_list *p;
2319  arelent **relpp;
2320  long relcount;
2321  sec_ptr osection;
2322  bfd_size_type size;
2323  long relsize;
2324  flagword flags;
2325
2326  /* If we have already failed earlier on,
2327     do not keep on generating complaints now.  */
2328  if (status != 0)
2329    return;
2330
2331  if (is_strip_section (ibfd, isection))
2332    return;
2333
2334  flags = bfd_get_section_flags (ibfd, isection);
2335  if ((flags & SEC_GROUP) != 0)
2336    return;
2337
2338  osection = isection->output_section;
2339  size = bfd_get_section_size (isection);
2340
2341  if (size == 0 || osection == 0)
2342    return;
2343
2344  p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
2345
2346  /* Core files do not need to be relocated.  */
2347  if (bfd_get_format (obfd) == bfd_core)
2348    relsize = 0;
2349  else
2350    {
2351      relsize = bfd_get_reloc_upper_bound (ibfd, isection);
2352
2353      if (relsize < 0)
2354	{
2355	  /* Do not complain if the target does not support relocations.  */
2356	  if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
2357	    relsize = 0;
2358	  else
2359	    RETURN_NONFATAL (bfd_get_filename (ibfd));
2360	}
2361    }
2362
2363  if (relsize == 0)
2364    bfd_set_reloc (obfd, osection, NULL, 0);
2365  else
2366    {
2367      relpp = xmalloc (relsize);
2368      relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
2369      if (relcount < 0)
2370	RETURN_NONFATAL (bfd_get_filename (ibfd));
2371
2372      if (strip_symbols == STRIP_ALL)
2373	{
2374	  /* Remove relocations which are not in
2375	     keep_strip_specific_list.  */
2376	  arelent **temp_relpp;
2377	  long temp_relcount = 0;
2378	  long i;
2379
2380	  temp_relpp = xmalloc (relsize);
2381	  for (i = 0; i < relcount; i++)
2382	    if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
2383				     keep_specific_list))
2384	      temp_relpp [temp_relcount++] = relpp [i];
2385	  relcount = temp_relcount;
2386	  free (relpp);
2387	  relpp = temp_relpp;
2388	}
2389
2390      bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
2391      if (relcount == 0)
2392	free (relpp);
2393    }
2394
2395  if (extract_symbol)
2396    return;
2397
2398  if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
2399      && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
2400    {
2401      void *memhunk = xmalloc (size);
2402
2403      if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
2404	RETURN_NONFATAL (bfd_get_filename (ibfd));
2405
2406      if (reverse_bytes)
2407	{
2408	  /* We don't handle leftover bytes (too many possible behaviors,
2409	     and we don't know what the user wants).  The section length
2410	     must be a multiple of the number of bytes to swap.  */
2411	  if ((size % reverse_bytes) == 0)
2412	    {
2413	      unsigned long i, j;
2414	      bfd_byte b;
2415
2416	      for (i = 0; i < size; i += reverse_bytes)
2417		for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++)
2418		  {
2419		    bfd_byte *m = (bfd_byte *) memhunk;
2420
2421		    b = m[i + j];
2422		    m[i + j] = m[(i + reverse_bytes) - (j + 1)];
2423		    m[(i + reverse_bytes) - (j + 1)] = b;
2424		  }
2425	    }
2426	  else
2427	    /* User must pad the section up in order to do this.  */
2428	    fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"),
2429		   bfd_section_name (ibfd, isection), reverse_bytes);
2430	}
2431
2432      if (copy_byte >= 0)
2433	{
2434	  /* Keep only every `copy_byte'th byte in MEMHUNK.  */
2435	  char *from = (char *) memhunk + copy_byte;
2436	  char *to = memhunk;
2437	  char *end = (char *) memhunk + size;
2438
2439	  for (; from < end; from += interleave)
2440	    *to++ = *from;
2441
2442	  size = (size + interleave - 1 - copy_byte) / interleave;
2443	  osection->lma /= interleave;
2444	}
2445
2446      if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
2447	RETURN_NONFATAL (bfd_get_filename (obfd));
2448
2449      free (memhunk);
2450    }
2451  else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
2452    {
2453      void *memhunk = xmalloc (size);
2454
2455      /* We don't permit the user to turn off the SEC_HAS_CONTENTS
2456	 flag--they can just remove the section entirely and add it
2457	 back again.  However, we do permit them to turn on the
2458	 SEC_HAS_CONTENTS flag, and take it to mean that the section
2459	 contents should be zeroed out.  */
2460
2461      memset (memhunk, 0, size);
2462      if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
2463	RETURN_NONFATAL (bfd_get_filename (obfd));
2464      free (memhunk);
2465    }
2466}
2467
2468/* Get all the sections.  This is used when --gap-fill or --pad-to is
2469   used.  */
2470
2471static void
2472get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
2473{
2474  asection ***secppp = secppparg;
2475
2476  **secppp = osection;
2477  ++(*secppp);
2478}
2479
2480/* Sort sections by VMA.  This is called via qsort, and is used when
2481   --gap-fill or --pad-to is used.  We force non loadable or empty
2482   sections to the front, where they are easier to ignore.  */
2483
2484static int
2485compare_section_lma (const void *arg1, const void *arg2)
2486{
2487  const asection *const *sec1 = arg1;
2488  const asection *const *sec2 = arg2;
2489  flagword flags1, flags2;
2490
2491  /* Sort non loadable sections to the front.  */
2492  flags1 = (*sec1)->flags;
2493  flags2 = (*sec2)->flags;
2494  if ((flags1 & SEC_HAS_CONTENTS) == 0
2495      || (flags1 & SEC_LOAD) == 0)
2496    {
2497      if ((flags2 & SEC_HAS_CONTENTS) != 0
2498	  && (flags2 & SEC_LOAD) != 0)
2499	return -1;
2500    }
2501  else
2502    {
2503      if ((flags2 & SEC_HAS_CONTENTS) == 0
2504	  || (flags2 & SEC_LOAD) == 0)
2505	return 1;
2506    }
2507
2508  /* Sort sections by LMA.  */
2509  if ((*sec1)->lma > (*sec2)->lma)
2510    return 1;
2511  else if ((*sec1)->lma < (*sec2)->lma)
2512    return -1;
2513
2514  /* Sort sections with the same LMA by size.  */
2515  if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2))
2516    return 1;
2517  else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2))
2518    return -1;
2519
2520  return 0;
2521}
2522
2523/* Mark all the symbols which will be used in output relocations with
2524   the BSF_KEEP flag so that those symbols will not be stripped.
2525
2526   Ignore relocations which will not appear in the output file.  */
2527
2528static void
2529mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
2530{
2531  asymbol **symbols = symbolsarg;
2532  long relsize;
2533  arelent **relpp;
2534  long relcount, i;
2535
2536  /* Ignore an input section with no corresponding output section.  */
2537  if (isection->output_section == NULL)
2538    return;
2539
2540  relsize = bfd_get_reloc_upper_bound (ibfd, isection);
2541  if (relsize < 0)
2542    {
2543      /* Do not complain if the target does not support relocations.  */
2544      if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
2545	return;
2546      bfd_fatal (bfd_get_filename (ibfd));
2547    }
2548
2549  if (relsize == 0)
2550    return;
2551
2552  relpp = xmalloc (relsize);
2553  relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
2554  if (relcount < 0)
2555    bfd_fatal (bfd_get_filename (ibfd));
2556
2557  /* Examine each symbol used in a relocation.  If it's not one of the
2558     special bfd section symbols, then mark it with BSF_KEEP.  */
2559  for (i = 0; i < relcount; i++)
2560    {
2561      if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
2562	  && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
2563	  && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
2564	(*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
2565    }
2566
2567  if (relpp != NULL)
2568    free (relpp);
2569}
2570
2571/* Write out debugging information.  */
2572
2573static bfd_boolean
2574write_debugging_info (bfd *obfd, void *dhandle,
2575		      long *symcountp ATTRIBUTE_UNUSED,
2576		      asymbol ***symppp ATTRIBUTE_UNUSED)
2577{
2578  if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
2579    return write_ieee_debugging_info (obfd, dhandle);
2580
2581  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
2582      || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
2583    {
2584      bfd_byte *syms, *strings;
2585      bfd_size_type symsize, stringsize;
2586      asection *stabsec, *stabstrsec;
2587      flagword flags;
2588
2589      if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
2590						    &symsize, &strings,
2591						    &stringsize))
2592	return FALSE;
2593
2594      flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
2595      stabsec = bfd_make_section_with_flags (obfd, ".stab", flags);
2596      stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags);
2597      if (stabsec == NULL
2598	  || stabstrsec == NULL
2599	  || ! bfd_set_section_size (obfd, stabsec, symsize)
2600	  || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
2601	  || ! bfd_set_section_alignment (obfd, stabsec, 2)
2602	  || ! bfd_set_section_alignment (obfd, stabstrsec, 0))
2603	{
2604	  non_fatal (_("%s: can't create debugging section: %s"),
2605		     bfd_get_filename (obfd),
2606		     bfd_errmsg (bfd_get_error ()));
2607	  return FALSE;
2608	}
2609
2610      /* We can get away with setting the section contents now because
2611         the next thing the caller is going to do is copy over the
2612         real sections.  We may someday have to split the contents
2613         setting out of this function.  */
2614      if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
2615	  || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
2616					 stringsize))
2617	{
2618	  non_fatal (_("%s: can't set debugging section contents: %s"),
2619		     bfd_get_filename (obfd),
2620		     bfd_errmsg (bfd_get_error ()));
2621	  return FALSE;
2622	}
2623
2624      return TRUE;
2625    }
2626
2627  non_fatal (_("%s: don't know how to write debugging information for %s"),
2628	     bfd_get_filename (obfd), bfd_get_target (obfd));
2629  return FALSE;
2630}
2631
2632static int
2633strip_main (int argc, char *argv[])
2634{
2635  char *input_target = NULL;
2636  char *output_target = NULL;
2637  bfd_boolean show_version = FALSE;
2638  bfd_boolean formats_info = FALSE;
2639  int c;
2640  int i;
2641  struct section_list *p;
2642  char *output_file = NULL;
2643
2644  while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw",
2645			   strip_options, (int *) 0)) != EOF)
2646    {
2647      switch (c)
2648	{
2649	case 'I':
2650	  input_target = optarg;
2651	  break;
2652	case 'O':
2653	  output_target = optarg;
2654	  break;
2655	case 'F':
2656	  input_target = output_target = optarg;
2657	  break;
2658	case 'R':
2659	  p = find_section_list (optarg, TRUE);
2660	  p->remove = TRUE;
2661	  sections_removed = TRUE;
2662	  break;
2663	case 's':
2664	  strip_symbols = STRIP_ALL;
2665	  break;
2666	case 'S':
2667	case 'g':
2668	case 'd':	/* Historic BSD alias for -g.  Used by early NetBSD.  */
2669	  strip_symbols = STRIP_DEBUG;
2670	  break;
2671	case OPTION_STRIP_UNNEEDED:
2672	  strip_symbols = STRIP_UNNEEDED;
2673	  break;
2674	case 'K':
2675	  add_specific_symbol (optarg, &keep_specific_list);
2676	  break;
2677	case 'N':
2678	  add_specific_symbol (optarg, &strip_specific_list);
2679	  break;
2680	case 'o':
2681	  output_file = optarg;
2682	  break;
2683	case 'p':
2684	  preserve_dates = TRUE;
2685	  break;
2686	case 'x':
2687	  discard_locals = LOCALS_ALL;
2688	  break;
2689	case 'X':
2690	  discard_locals = LOCALS_START_L;
2691	  break;
2692	case 'v':
2693	  verbose = TRUE;
2694	  break;
2695	case 'V':
2696	  show_version = TRUE;
2697	  break;
2698	case OPTION_FORMATS_INFO:
2699	  formats_info = TRUE;
2700	  break;
2701	case OPTION_ONLY_KEEP_DEBUG:
2702	  strip_symbols = STRIP_NONDEBUG;
2703	  break;
2704	case OPTION_KEEP_FILE_SYMBOLS:
2705	  keep_file_symbols = 1;
2706	  break;
2707	case 0:
2708	  /* We've been given a long option.  */
2709	  break;
2710	case 'w':
2711	  wildcard = TRUE;
2712	  break;
2713	case 'H':
2714	case 'h':
2715	  strip_usage (stdout, 0);
2716	default:
2717	  strip_usage (stderr, 1);
2718	}
2719    }
2720
2721  if (formats_info)
2722    {
2723      display_info ();
2724      return 0;
2725    }
2726
2727  if (show_version)
2728    print_version ("strip");
2729
2730  /* Default is to strip all symbols.  */
2731  if (strip_symbols == STRIP_UNDEF
2732      && discard_locals == LOCALS_UNDEF
2733      && strip_specific_list == NULL)
2734    strip_symbols = STRIP_ALL;
2735
2736  if (output_target == NULL)
2737    output_target = input_target;
2738
2739  i = optind;
2740  if (i == argc
2741      || (output_file != NULL && (i + 1) < argc))
2742    strip_usage (stderr, 1);
2743
2744  for (; i < argc; i++)
2745    {
2746      int hold_status = status;
2747      struct stat statbuf;
2748      char *tmpname;
2749
2750      if (get_file_size (argv[i]) < 1)
2751	{
2752	  status = 1;
2753	  continue;
2754	}
2755
2756      if (preserve_dates)
2757	/* No need to check the return value of stat().
2758	   It has already been checked in get_file_size().  */
2759	stat (argv[i], &statbuf);
2760
2761      if (output_file == NULL || strcmp (argv[i], output_file) == 0)
2762	tmpname = make_tempname (argv[i]);
2763      else
2764	tmpname = output_file;
2765
2766      if (tmpname == NULL)
2767	{
2768	  non_fatal (_("could not create temporary file to hold stripped copy of '%s'"),
2769		     argv[i]);
2770	  status = 1;
2771	  continue;
2772	}
2773
2774      status = 0;
2775      copy_file (argv[i], tmpname, input_target, output_target);
2776      if (status == 0)
2777	{
2778	  if (preserve_dates)
2779	    set_times (tmpname, &statbuf);
2780	  if (output_file != tmpname)
2781	    smart_rename (tmpname, output_file ? output_file : argv[i],
2782			  preserve_dates);
2783	  status = hold_status;
2784	}
2785      else
2786	unlink_if_ordinary (tmpname);
2787      if (output_file != tmpname)
2788	free (tmpname);
2789    }
2790
2791  return status;
2792}
2793
2794static int
2795copy_main (int argc, char *argv[])
2796{
2797  char * binary_architecture = NULL;
2798  char *input_filename = NULL;
2799  char *output_filename = NULL;
2800  char *tmpname;
2801  char *input_target = NULL;
2802  char *output_target = NULL;
2803  bfd_boolean show_version = FALSE;
2804  bfd_boolean change_warn = TRUE;
2805  bfd_boolean formats_info = FALSE;
2806  int c;
2807  struct section_list *p;
2808  struct stat statbuf;
2809
2810  while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w",
2811			   copy_options, (int *) 0)) != EOF)
2812    {
2813      switch (c)
2814	{
2815	case 'b':
2816	  copy_byte = atoi (optarg);
2817	  if (copy_byte < 0)
2818	    fatal (_("byte number must be non-negative"));
2819	  break;
2820
2821	case 'B':
2822	  binary_architecture = optarg;
2823	  break;
2824
2825	case 'i':
2826	  interleave = atoi (optarg);
2827	  if (interleave < 1)
2828	    fatal (_("interleave must be positive"));
2829	  break;
2830
2831	case 'I':
2832	case 's':		/* "source" - 'I' is preferred */
2833	  input_target = optarg;
2834	  break;
2835
2836	case 'O':
2837	case 'd':		/* "destination" - 'O' is preferred */
2838	  output_target = optarg;
2839	  break;
2840
2841	case 'F':
2842	  input_target = output_target = optarg;
2843	  break;
2844
2845	case 'j':
2846	  p = find_section_list (optarg, TRUE);
2847	  if (p->remove)
2848	    fatal (_("%s both copied and removed"), optarg);
2849	  p->copy = TRUE;
2850	  sections_copied = TRUE;
2851	  break;
2852
2853	case 'R':
2854	  p = find_section_list (optarg, TRUE);
2855	  if (p->copy)
2856	    fatal (_("%s both copied and removed"), optarg);
2857	  p->remove = TRUE;
2858	  sections_removed = TRUE;
2859	  break;
2860
2861	case 'S':
2862	  strip_symbols = STRIP_ALL;
2863	  break;
2864
2865	case 'g':
2866	  strip_symbols = STRIP_DEBUG;
2867	  break;
2868
2869	case OPTION_STRIP_UNNEEDED:
2870	  strip_symbols = STRIP_UNNEEDED;
2871	  break;
2872
2873	case OPTION_ONLY_KEEP_DEBUG:
2874	  strip_symbols = STRIP_NONDEBUG;
2875	  break;
2876
2877	case OPTION_KEEP_FILE_SYMBOLS:
2878	  keep_file_symbols = 1;
2879	  break;
2880
2881	case OPTION_ADD_GNU_DEBUGLINK:
2882	  gnu_debuglink_filename = optarg;
2883	  break;
2884
2885	case 'K':
2886	  add_specific_symbol (optarg, &keep_specific_list);
2887	  break;
2888
2889	case 'N':
2890	  add_specific_symbol (optarg, &strip_specific_list);
2891	  break;
2892
2893	case OPTION_STRIP_UNNEEDED_SYMBOL:
2894	  add_specific_symbol (optarg, &strip_unneeded_list);
2895	  break;
2896
2897	case 'L':
2898	  add_specific_symbol (optarg, &localize_specific_list);
2899	  break;
2900
2901	case OPTION_GLOBALIZE_SYMBOL:
2902	  add_specific_symbol (optarg, &globalize_specific_list);
2903	  break;
2904
2905	case 'G':
2906	  add_specific_symbol (optarg, &keepglobal_specific_list);
2907	  break;
2908
2909	case 'W':
2910	  add_specific_symbol (optarg, &weaken_specific_list);
2911	  break;
2912
2913	case 'p':
2914	  preserve_dates = TRUE;
2915	  break;
2916
2917	case 'w':
2918	  wildcard = TRUE;
2919	  break;
2920
2921	case 'x':
2922	  discard_locals = LOCALS_ALL;
2923	  break;
2924
2925	case 'X':
2926	  discard_locals = LOCALS_START_L;
2927	  break;
2928
2929	case 'v':
2930	  verbose = TRUE;
2931	  break;
2932
2933	case 'V':
2934	  show_version = TRUE;
2935	  break;
2936
2937	case OPTION_FORMATS_INFO:
2938	  formats_info = TRUE;
2939	  break;
2940
2941	case OPTION_WEAKEN:
2942	  weaken = TRUE;
2943	  break;
2944
2945	case OPTION_ADD_SECTION:
2946	  {
2947	    const char *s;
2948	    off_t size;
2949	    struct section_add *pa;
2950	    int len;
2951	    char *name;
2952	    FILE *f;
2953
2954	    s = strchr (optarg, '=');
2955
2956	    if (s == NULL)
2957	      fatal (_("bad format for %s"), "--add-section");
2958
2959	    size = get_file_size (s + 1);
2960	    if (size < 1)
2961	      {
2962		status = 1;
2963		break;
2964	      }
2965
2966	    pa = xmalloc (sizeof (struct section_add));
2967
2968	    len = s - optarg;
2969	    name = xmalloc (len + 1);
2970	    strncpy (name, optarg, len);
2971	    name[len] = '\0';
2972	    pa->name = name;
2973
2974	    pa->filename = s + 1;
2975	    pa->size = size;
2976	    pa->contents = xmalloc (size);
2977
2978	    f = fopen (pa->filename, FOPEN_RB);
2979
2980	    if (f == NULL)
2981	      fatal (_("cannot open: %s: %s"),
2982		     pa->filename, strerror (errno));
2983
2984	    if (fread (pa->contents, 1, pa->size, f) == 0
2985		|| ferror (f))
2986	      fatal (_("%s: fread failed"), pa->filename);
2987
2988	    fclose (f);
2989
2990	    pa->next = add_sections;
2991	    add_sections = pa;
2992	  }
2993	  break;
2994
2995	case OPTION_CHANGE_START:
2996	  change_start = parse_vma (optarg, "--change-start");
2997	  break;
2998
2999	case OPTION_CHANGE_SECTION_ADDRESS:
3000	case OPTION_CHANGE_SECTION_LMA:
3001	case OPTION_CHANGE_SECTION_VMA:
3002	  {
3003	    const char *s;
3004	    int len;
3005	    char *name;
3006	    char *option = NULL;
3007	    bfd_vma val;
3008	    enum change_action what = CHANGE_IGNORE;
3009
3010	    switch (c)
3011	      {
3012	      case OPTION_CHANGE_SECTION_ADDRESS:
3013		option = "--change-section-address";
3014		break;
3015	      case OPTION_CHANGE_SECTION_LMA:
3016		option = "--change-section-lma";
3017		break;
3018	      case OPTION_CHANGE_SECTION_VMA:
3019		option = "--change-section-vma";
3020		break;
3021	      }
3022
3023	    s = strchr (optarg, '=');
3024	    if (s == NULL)
3025	      {
3026		s = strchr (optarg, '+');
3027		if (s == NULL)
3028		  {
3029		    s = strchr (optarg, '-');
3030		    if (s == NULL)
3031		      fatal (_("bad format for %s"), option);
3032		  }
3033	      }
3034
3035	    len = s - optarg;
3036	    name = xmalloc (len + 1);
3037	    strncpy (name, optarg, len);
3038	    name[len] = '\0';
3039
3040	    p = find_section_list (name, TRUE);
3041
3042	    val = parse_vma (s + 1, option);
3043
3044	    switch (*s)
3045	      {
3046	      case '=': what = CHANGE_SET; break;
3047	      case '-': val  = - val; /* Drop through.  */
3048	      case '+': what = CHANGE_MODIFY; break;
3049	      }
3050
3051	    switch (c)
3052	      {
3053	      case OPTION_CHANGE_SECTION_ADDRESS:
3054		p->change_vma = what;
3055		p->vma_val    = val;
3056		/* Drop through.  */
3057
3058	      case OPTION_CHANGE_SECTION_LMA:
3059		p->change_lma = what;
3060		p->lma_val    = val;
3061		break;
3062
3063	      case OPTION_CHANGE_SECTION_VMA:
3064		p->change_vma = what;
3065		p->vma_val    = val;
3066		break;
3067	      }
3068	  }
3069	  break;
3070
3071	case OPTION_CHANGE_ADDRESSES:
3072	  change_section_address = parse_vma (optarg, "--change-addresses");
3073	  change_start = change_section_address;
3074	  break;
3075
3076	case OPTION_CHANGE_WARNINGS:
3077	  change_warn = TRUE;
3078	  break;
3079
3080	case OPTION_CHANGE_LEADING_CHAR:
3081	  change_leading_char = TRUE;
3082	  break;
3083
3084	case OPTION_DEBUGGING:
3085	  convert_debugging = TRUE;
3086	  break;
3087
3088	case OPTION_GAP_FILL:
3089	  {
3090	    bfd_vma gap_fill_vma;
3091
3092	    gap_fill_vma = parse_vma (optarg, "--gap-fill");
3093	    gap_fill = (bfd_byte) gap_fill_vma;
3094	    if ((bfd_vma) gap_fill != gap_fill_vma)
3095	      {
3096		char buff[20];
3097
3098		sprintf_vma (buff, gap_fill_vma);
3099
3100		non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
3101			   buff, gap_fill);
3102	      }
3103	    gap_fill_set = TRUE;
3104	  }
3105	  break;
3106
3107	case OPTION_NO_CHANGE_WARNINGS:
3108	  change_warn = FALSE;
3109	  break;
3110
3111	case OPTION_PAD_TO:
3112	  pad_to = parse_vma (optarg, "--pad-to");
3113	  pad_to_set = TRUE;
3114	  break;
3115
3116	case OPTION_REMOVE_LEADING_CHAR:
3117	  remove_leading_char = TRUE;
3118	  break;
3119
3120	case OPTION_REDEFINE_SYM:
3121	  {
3122	    /* Push this redefinition onto redefine_symbol_list.  */
3123
3124	    int len;
3125	    const char *s;
3126	    const char *nextarg;
3127	    char *source, *target;
3128
3129	    s = strchr (optarg, '=');
3130	    if (s == NULL)
3131	      fatal (_("bad format for %s"), "--redefine-sym");
3132
3133	    len = s - optarg;
3134	    source = xmalloc (len + 1);
3135	    strncpy (source, optarg, len);
3136	    source[len] = '\0';
3137
3138	    nextarg = s + 1;
3139	    len = strlen (nextarg);
3140	    target = xmalloc (len + 1);
3141	    strcpy (target, nextarg);
3142
3143	    redefine_list_append ("--redefine-sym", source, target);
3144
3145	    free (source);
3146	    free (target);
3147	  }
3148	  break;
3149
3150	case OPTION_REDEFINE_SYMS:
3151	  add_redefine_syms_file (optarg);
3152	  break;
3153
3154	case OPTION_SET_SECTION_FLAGS:
3155	  {
3156	    const char *s;
3157	    int len;
3158	    char *name;
3159
3160	    s = strchr (optarg, '=');
3161	    if (s == NULL)
3162	      fatal (_("bad format for %s"), "--set-section-flags");
3163
3164	    len = s - optarg;
3165	    name = xmalloc (len + 1);
3166	    strncpy (name, optarg, len);
3167	    name[len] = '\0';
3168
3169	    p = find_section_list (name, TRUE);
3170
3171	    p->set_flags = TRUE;
3172	    p->flags = parse_flags (s + 1);
3173	  }
3174	  break;
3175
3176	case OPTION_RENAME_SECTION:
3177	  {
3178	    flagword flags;
3179	    const char *eq, *fl;
3180	    char *old_name;
3181	    char *new_name;
3182	    unsigned int len;
3183
3184	    eq = strchr (optarg, '=');
3185	    if (eq == NULL)
3186	      fatal (_("bad format for %s"), "--rename-section");
3187
3188	    len = eq - optarg;
3189	    if (len == 0)
3190	      fatal (_("bad format for %s"), "--rename-section");
3191
3192	    old_name = xmalloc (len + 1);
3193	    strncpy (old_name, optarg, len);
3194	    old_name[len] = 0;
3195
3196	    eq++;
3197	    fl = strchr (eq, ',');
3198	    if (fl)
3199	      {
3200		flags = parse_flags (fl + 1);
3201		len = fl - eq;
3202	      }
3203	    else
3204	      {
3205		flags = -1;
3206		len = strlen (eq);
3207	      }
3208
3209	    if (len == 0)
3210	      fatal (_("bad format for %s"), "--rename-section");
3211
3212	    new_name = xmalloc (len + 1);
3213	    strncpy (new_name, eq, len);
3214	    new_name[len] = 0;
3215
3216	    add_section_rename (old_name, new_name, flags);
3217	  }
3218	  break;
3219
3220	case OPTION_SET_START:
3221	  set_start = parse_vma (optarg, "--set-start");
3222	  set_start_set = TRUE;
3223	  break;
3224
3225	case OPTION_SREC_LEN:
3226	  Chunk = parse_vma (optarg, "--srec-len");
3227	  break;
3228
3229	case OPTION_SREC_FORCES3:
3230	  S3Forced = TRUE;
3231	  break;
3232
3233	case OPTION_STRIP_SYMBOLS:
3234	  add_specific_symbols (optarg, &strip_specific_list);
3235	  break;
3236
3237	case OPTION_STRIP_UNNEEDED_SYMBOLS:
3238	  add_specific_symbols (optarg, &strip_unneeded_list);
3239	  break;
3240
3241	case OPTION_KEEP_SYMBOLS:
3242	  add_specific_symbols (optarg, &keep_specific_list);
3243	  break;
3244
3245	case OPTION_LOCALIZE_HIDDEN:
3246	  localize_hidden = TRUE;
3247	  break;
3248
3249	case OPTION_LOCALIZE_SYMBOLS:
3250	  add_specific_symbols (optarg, &localize_specific_list);
3251	  break;
3252
3253	case OPTION_GLOBALIZE_SYMBOLS:
3254	  add_specific_symbols (optarg, &globalize_specific_list);
3255	  break;
3256
3257	case OPTION_KEEPGLOBAL_SYMBOLS:
3258	  add_specific_symbols (optarg, &keepglobal_specific_list);
3259	  break;
3260
3261	case OPTION_WEAKEN_SYMBOLS:
3262	  add_specific_symbols (optarg, &weaken_specific_list);
3263	  break;
3264
3265	case OPTION_ALT_MACH_CODE:
3266	  use_alt_mach_code = strtoul (optarg, NULL, 0);
3267	  if (use_alt_mach_code == 0)
3268	    fatal (_("unable to parse alternative machine code"));
3269	  break;
3270
3271	case OPTION_PREFIX_SYMBOLS:
3272	  prefix_symbols_string = optarg;
3273	  break;
3274
3275	case OPTION_PREFIX_SECTIONS:
3276	  prefix_sections_string = optarg;
3277	  break;
3278
3279	case OPTION_PREFIX_ALLOC_SECTIONS:
3280	  prefix_alloc_sections_string = optarg;
3281	  break;
3282
3283	case OPTION_READONLY_TEXT:
3284	  bfd_flags_to_set |= WP_TEXT;
3285	  bfd_flags_to_clear &= ~WP_TEXT;
3286	  break;
3287
3288	case OPTION_WRITABLE_TEXT:
3289	  bfd_flags_to_clear |= WP_TEXT;
3290	  bfd_flags_to_set &= ~WP_TEXT;
3291	  break;
3292
3293	case OPTION_PURE:
3294	  bfd_flags_to_set |= D_PAGED;
3295	  bfd_flags_to_clear &= ~D_PAGED;
3296	  break;
3297
3298	case OPTION_IMPURE:
3299	  bfd_flags_to_clear |= D_PAGED;
3300	  bfd_flags_to_set &= ~D_PAGED;
3301	  break;
3302
3303	case OPTION_EXTRACT_SYMBOL:
3304	  extract_symbol = TRUE;
3305	  break;
3306
3307	case OPTION_REVERSE_BYTES:
3308          {
3309            int prev = reverse_bytes;
3310
3311            reverse_bytes = atoi (optarg);
3312            if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0))
3313              fatal (_("number of bytes to reverse must be positive and even"));
3314
3315            if (prev && prev != reverse_bytes)
3316              non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"),
3317                         prev);
3318            break;
3319          }
3320
3321	case 0:
3322	  /* We've been given a long option.  */
3323	  break;
3324
3325	case 'H':
3326	case 'h':
3327	  copy_usage (stdout, 0);
3328
3329	default:
3330	  copy_usage (stderr, 1);
3331	}
3332    }
3333
3334  if (formats_info)
3335    {
3336      display_info ();
3337      return 0;
3338    }
3339
3340  if (show_version)
3341    print_version ("objcopy");
3342
3343  if (copy_byte >= interleave)
3344    fatal (_("byte number must be less than interleave"));
3345
3346  if (optind == argc || optind + 2 < argc)
3347    copy_usage (stderr, 1);
3348
3349  input_filename = argv[optind];
3350  if (optind + 1 < argc)
3351    output_filename = argv[optind + 1];
3352
3353  /* Default is to strip no symbols.  */
3354  if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
3355    strip_symbols = STRIP_NONE;
3356
3357  if (output_target == NULL)
3358    output_target = input_target;
3359
3360  if (binary_architecture != NULL)
3361    {
3362      if (input_target && strcmp (input_target, "binary") == 0)
3363	{
3364	  const bfd_arch_info_type * temp_arch_info;
3365
3366	  temp_arch_info = bfd_scan_arch (binary_architecture);
3367
3368	  if (temp_arch_info != NULL)
3369	    {
3370	      bfd_external_binary_architecture = temp_arch_info->arch;
3371	      bfd_external_machine             = temp_arch_info->mach;
3372	    }
3373	  else
3374	    fatal (_("architecture %s unknown"), binary_architecture);
3375	}
3376      else
3377	{
3378	  non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
3379	  non_fatal (_(" Argument %s ignored"), binary_architecture);
3380	}
3381    }
3382
3383  if (preserve_dates)
3384    if (stat (input_filename, & statbuf) < 0)
3385      fatal (_("warning: could not locate '%s'.  System error message: %s"),
3386	     input_filename, strerror (errno));
3387
3388  /* If there is no destination file, or the source and destination files
3389     are the same, then create a temp and rename the result into the input.  */
3390  if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
3391    tmpname = make_tempname (input_filename);
3392  else
3393    tmpname = output_filename;
3394
3395  if (tmpname == NULL)
3396    fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
3397	   input_filename, strerror (errno));
3398
3399  copy_file (input_filename, tmpname, input_target, output_target);
3400  if (status == 0)
3401    {
3402      if (preserve_dates)
3403	set_times (tmpname, &statbuf);
3404      if (tmpname != output_filename)
3405	smart_rename (tmpname, input_filename, preserve_dates);
3406    }
3407  else
3408    unlink_if_ordinary (tmpname);
3409
3410  if (change_warn)
3411    {
3412      for (p = change_sections; p != NULL; p = p->next)
3413	{
3414	  if (! p->used)
3415	    {
3416	      if (p->change_vma != CHANGE_IGNORE)
3417		{
3418		  char buff [20];
3419
3420		  sprintf_vma (buff, p->vma_val);
3421
3422		  /* xgettext:c-format */
3423		  non_fatal (_("%s %s%c0x%s never used"),
3424			     "--change-section-vma",
3425			     p->name,
3426			     p->change_vma == CHANGE_SET ? '=' : '+',
3427			     buff);
3428		}
3429
3430	      if (p->change_lma != CHANGE_IGNORE)
3431		{
3432		  char buff [20];
3433
3434		  sprintf_vma (buff, p->lma_val);
3435
3436		  /* xgettext:c-format */
3437		  non_fatal (_("%s %s%c0x%s never used"),
3438			     "--change-section-lma",
3439			     p->name,
3440			     p->change_lma == CHANGE_SET ? '=' : '+',
3441			     buff);
3442		}
3443	    }
3444	}
3445    }
3446
3447  return 0;
3448}
3449
3450int
3451main (int argc, char *argv[])
3452{
3453#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
3454  setlocale (LC_MESSAGES, "");
3455#endif
3456#if defined (HAVE_SETLOCALE)
3457  setlocale (LC_CTYPE, "");
3458#endif
3459  bindtextdomain (PACKAGE, LOCALEDIR);
3460  textdomain (PACKAGE);
3461
3462  program_name = argv[0];
3463  xmalloc_set_program_name (program_name);
3464
3465  START_PROGRESS (program_name, 0);
3466
3467  expandargv (&argc, &argv);
3468
3469  strip_symbols = STRIP_UNDEF;
3470  discard_locals = LOCALS_UNDEF;
3471
3472  bfd_init ();
3473  set_default_bfd_target ();
3474
3475  if (is_strip < 0)
3476    {
3477      int i = strlen (program_name);
3478#ifdef HAVE_DOS_BASED_FILE_SYSTEM
3479      /* Drop the .exe suffix, if any.  */
3480      if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0)
3481	{
3482	  i -= 4;
3483	  program_name[i] = '\0';
3484	}
3485#endif
3486      is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
3487    }
3488
3489  if (is_strip)
3490    strip_main (argc, argv);
3491  else
3492    copy_main (argc, argv);
3493
3494  END_PROGRESS (program_name);
3495
3496  return status;
3497}
3498