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