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