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