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