Mention mi0 and mi1 as --interpreter options.
[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;
24e01a36 726 boolean undefined;
252b5132 727
57938635
AM
728 if (redefine_sym_list)
729 {
730 const char *old_name, *new_name;
731
732 old_name = bfd_asymbol_name (sym);
733 new_name = lookup_sym_redefinition (old_name);
734 name = bfd_asymbol_name (sym) = new_name;
735 }
736
252b5132
RH
737 if (change_leading_char
738 && (bfd_get_symbol_leading_char (abfd)
739 != bfd_get_symbol_leading_char (obfd))
740 && (bfd_get_symbol_leading_char (abfd) == '\0'
741 || (name[0] == bfd_get_symbol_leading_char (abfd))))
742 {
743 if (bfd_get_symbol_leading_char (obfd) == '\0')
744 name = bfd_asymbol_name (sym) = name + 1;
745 else
746 {
747 char *n;
748
749 n = xmalloc (strlen (name) + 2);
750 n[0] = bfd_get_symbol_leading_char (obfd);
751 if (bfd_get_symbol_leading_char (abfd) == '\0')
752 strcpy (n + 1, name);
753 else
754 strcpy (n + 1, name + 1);
755 name = bfd_asymbol_name (sym) = n;
756 }
757 }
758
24e01a36
L
759 undefined = bfd_is_und_section (bfd_get_section (sym));
760
252b5132
RH
761 if (remove_leading_char
762 && ((flags & BSF_GLOBAL) != 0
763 || (flags & BSF_WEAK) != 0
24e01a36 764 || undefined
252b5132
RH
765 || bfd_is_com_section (bfd_get_section (sym)))
766 && name[0] == bfd_get_symbol_leading_char (abfd))
767 name = bfd_asymbol_name (sym) = name + 1;
768
769 if (strip_symbols == STRIP_ALL)
770 keep = 0;
771 else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */
772 || ((flags & BSF_SECTION_SYM) != 0
773 && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
774 & BSF_KEEP) != 0))
775 keep = 1;
d8121479
L
776 else if (relocatable /* Relocatable file. */
777 && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
778 keep = 1;
16b2b71c
NC
779 else if (bfd_decode_symclass (sym) == 'I')
780 /* Global symbols in $idata sections need to be retained
781 even if relocatable is false. External users of the
782 library containing the $idata section may reference these
783 symbols. */
af3bdff7 784 keep = 1;
252b5132
RH
785 else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */
786 || (flags & BSF_WEAK) != 0
24e01a36 787 || undefined
252b5132
RH
788 || bfd_is_com_section (bfd_get_section (sym)))
789 keep = strip_symbols != STRIP_UNNEEDED;
790 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
791 keep = (strip_symbols != STRIP_DEBUG
792 && strip_symbols != STRIP_UNNEEDED
793 && ! convert_debugging);
af3bdff7
NC
794 else if (bfd_get_section (sym)->comdat)
795 /* COMDAT sections store special information in local
796 symbols, so we cannot risk stripping any of them. */
797 keep = 1;
252b5132
RH
798 else /* Local symbol. */
799 keep = (strip_symbols != STRIP_UNNEEDED
800 && (discard_locals != LOCALS_ALL
801 && (discard_locals != LOCALS_START_L
802 || ! bfd_is_local_label (abfd, sym))));
803
804 if (keep && is_specified_symbol (name, strip_specific_list))
805 keep = 0;
806 if (!keep && is_specified_symbol (name, keep_specific_list))
807 keep = 1;
808 if (keep && is_strip_section (abfd, bfd_get_section (sym)))
809 keep = 0;
e0c60db2 810
252b5132
RH
811 if (keep && (flags & BSF_GLOBAL) != 0
812 && (weaken || is_specified_symbol (name, weaken_specific_list)))
813 {
814 sym->flags &=~ BSF_GLOBAL;
815 sym->flags |= BSF_WEAK;
816 }
24e01a36 817 if (keep && !undefined && (flags & (BSF_GLOBAL | BSF_WEAK))
16b2b71c
NC
818 && (is_specified_symbol (name, localize_specific_list)
819 || (keepglobal_specific_list != NULL
820 && ! is_specified_symbol (name, keepglobal_specific_list))))
252b5132
RH
821 {
822 sym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
823 sym->flags |= BSF_LOCAL;
824 }
825
826 if (keep)
827 to[dst_count++] = sym;
828 }
829
830 to[dst_count] = NULL;
831
832 return dst_count;
833}
834
57938635
AM
835static const char *
836lookup_sym_redefinition (source)
837 const char *source;
838{
839 const char *result;
840 struct redefine_node *list;
841
842 result = source;
843
844 for (list = redefine_sym_list; list != NULL; list = list->next)
845 {
846 if (strcmp (source, list->source) == 0)
847 {
848 result = list->target;
849 break;
850 }
851 }
852 return result;
853}
854
855/* Add a node to a symbol redefine list */
856
857static void
858redefine_list_append (source, target)
859 const char *source;
860 const char *target;
861{
862 struct redefine_node **p;
863 struct redefine_node *list;
864 struct redefine_node *new_node;
865
866 for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
867 {
868 if (strcmp (source, list->source) == 0)
869 {
870 fatal (_("%s: Multiple redefinition of symbol \"%s\""),
871 "--redefine-sym",
872 source);
873 }
874
875 if (strcmp (target, list->target) == 0)
876 {
877 fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
878 "--redefine-sym",
879 target);
880 }
881 }
882
883 new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
884
885 new_node->source = strdup (source);
886 new_node->target = strdup (target);
887 new_node->next = NULL;
888
889 *p = new_node;
890}
891
892
252b5132
RH
893/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
894 Adjust *SIZE. */
895
896static void
897filter_bytes (memhunk, size)
898 char *memhunk;
899 bfd_size_type *size;
900{
901 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
902
903 for (; from < end; from += interleave)
904 *to++ = *from;
b4c96d0d 905 if (*size % interleave > (bfd_size_type) copy_byte)
252b5132
RH
906 *size = (*size / interleave) + 1;
907 else
908 *size /= interleave;
909}
910
911/* Copy object file IBFD onto OBFD. */
912
913static void
914copy_object (ibfd, obfd)
915 bfd *ibfd;
916 bfd *obfd;
917{
918 bfd_vma start;
919 long symcount;
920 asection **osections = NULL;
921 bfd_size_type *gaps = NULL;
922 bfd_size_type max_gap = 0;
923 long symsize;
924 PTR dhandle;
925
23719f39
NC
926 if (ibfd->xvec->byteorder != obfd->xvec->byteorder
927 && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
928 && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
929 {
930 fatal (_("Unable to change endianness of input file(s)"));
931 return;
932 }
252b5132
RH
933
934 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
935 RETURN_NONFATAL (bfd_get_filename (obfd));
936
937 if (verbose)
938 printf (_("copy from %s(%s) to %s(%s)\n"),
939 bfd_get_filename (ibfd), bfd_get_target (ibfd),
940 bfd_get_filename (obfd), bfd_get_target (obfd));
941
942 if (set_start_set)
943 start = set_start;
944 else
945 start = bfd_get_start_address (ibfd);
946 start += change_start;
947
948 if (!bfd_set_start_address (obfd, start)
949 || !bfd_set_file_flags (obfd,
950 (bfd_get_file_flags (ibfd)
951 & bfd_applicable_file_flags (obfd))))
952 RETURN_NONFATAL (bfd_get_filename (ibfd));
953
954 /* Copy architecture of input file to output file */
955 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
956 bfd_get_mach (ibfd)))
957 non_fatal (_("Warning: Output file cannot represent architecture %s"),
958 bfd_printable_arch_mach (bfd_get_arch (ibfd),
959 bfd_get_mach (ibfd)));
57938635 960
252b5132
RH
961 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
962 RETURN_NONFATAL (bfd_get_filename (ibfd));
963
964 if (isympp)
965 free (isympp);
57938635 966
252b5132
RH
967 if (osympp != isympp)
968 free (osympp);
969
970 /* BFD mandates that all output sections be created and sizes set before
971 any output is done. Thus, we traverse all sections multiple times. */
972 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
973
974 if (add_sections != NULL)
975 {
976 struct section_add *padd;
977 struct section_list *pset;
978
979 for (padd = add_sections; padd != NULL; padd = padd->next)
980 {
981 padd->section = bfd_make_section (obfd, padd->name);
982 if (padd->section == NULL)
983 {
984 non_fatal (_("can't create section `%s': %s"),
985 padd->name, bfd_errmsg (bfd_get_error ()));
986 status = 1;
987 return;
988 }
989 else
990 {
991 flagword flags;
57938635 992
252b5132
RH
993 if (! bfd_set_section_size (obfd, padd->section, padd->size))
994 RETURN_NONFATAL (bfd_get_filename (obfd));
995
996 pset = find_section_list (padd->name, false);
997 if (pset != NULL)
998 pset->used = true;
999
1000 if (pset != NULL && pset->set_flags)
1001 flags = pset->flags | SEC_HAS_CONTENTS;
1002 else
1003 flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
57938635 1004
252b5132
RH
1005 if (! bfd_set_section_flags (obfd, padd->section, flags))
1006 RETURN_NONFATAL (bfd_get_filename (obfd));
1007
1008 if (pset != NULL)
1009 {
1010 if (pset->change_vma != CHANGE_IGNORE)
1011 if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val))
1012 RETURN_NONFATAL (bfd_get_filename (obfd));
57938635 1013
252b5132
RH
1014 if (pset->change_lma != CHANGE_IGNORE)
1015 {
1016 padd->section->lma = pset->lma_val;
57938635 1017
252b5132
RH
1018 if (! bfd_set_section_alignment
1019 (obfd, padd->section,
1020 bfd_section_alignment (obfd, padd->section)))
1021 RETURN_NONFATAL (bfd_get_filename (obfd));
1022 }
1023 }
1024 }
1025 }
1026 }
1027
1028 if (gap_fill_set || pad_to_set)
1029 {
1030 asection **set;
1031 unsigned int c, i;
1032
1033 /* We must fill in gaps between the sections and/or we must pad
1034 the last section to a specified address. We do this by
1035 grabbing a list of the sections, sorting them by VMA, and
1036 increasing the section sizes as required to fill the gaps.
1037 We write out the gap contents below. */
1038
1039 c = bfd_count_sections (obfd);
1040 osections = (asection **) xmalloc (c * sizeof (asection *));
1041 set = osections;
1042 bfd_map_over_sections (obfd, get_sections, (void *) &set);
1043
1044 qsort (osections, c, sizeof (asection *), compare_section_lma);
1045
1046 gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
1047 memset (gaps, 0, c * sizeof (bfd_size_type));
1048
1049 if (gap_fill_set)
1050 {
1051 for (i = 0; i < c - 1; i++)
1052 {
1053 flagword flags;
1054 bfd_size_type size;
1055 bfd_vma gap_start, gap_stop;
1056
1057 flags = bfd_get_section_flags (obfd, osections[i]);
1058 if ((flags & SEC_HAS_CONTENTS) == 0
1059 || (flags & SEC_LOAD) == 0)
1060 continue;
1061
1062 size = bfd_section_size (obfd, osections[i]);
1063 gap_start = bfd_section_lma (obfd, osections[i]) + size;
1064 gap_stop = bfd_section_lma (obfd, osections[i + 1]);
1065 if (gap_start < gap_stop)
1066 {
1067 if (! bfd_set_section_size (obfd, osections[i],
1068 size + (gap_stop - gap_start)))
1069 {
1070 non_fatal (_("Can't fill gap after %s: %s"),
1071 bfd_get_section_name (obfd, osections[i]),
1072 bfd_errmsg (bfd_get_error ()));
1073 status = 1;
1074 break;
1075 }
1076 gaps[i] = gap_stop - gap_start;
1077 if (max_gap < gap_stop - gap_start)
1078 max_gap = gap_stop - gap_start;
1079 }
1080 }
1081 }
1082
1083 if (pad_to_set)
1084 {
1085 bfd_vma lma;
1086 bfd_size_type size;
1087
1088 lma = bfd_section_lma (obfd, osections[c - 1]);
1089 size = bfd_section_size (obfd, osections[c - 1]);
1090 if (lma + size < pad_to)
1091 {
1092 if (! bfd_set_section_size (obfd, osections[c - 1],
1093 pad_to - lma))
1094 {
1095 non_fatal (_("Can't add padding to %s: %s"),
1096 bfd_get_section_name (obfd, osections[c - 1]),
1097 bfd_errmsg (bfd_get_error ()));
1098 status = 1;
1099 }
1100 else
1101 {
1102 gaps[c - 1] = pad_to - (lma + size);
1103 if (max_gap < pad_to - (lma + size))
1104 max_gap = pad_to - (lma + size);
1105 }
1106 }
1107 }
1108 }
1109
1110 /* Symbol filtering must happen after the output sections have
1111 been created, but before their contents are set. */
1112 dhandle = NULL;
1113 symsize = bfd_get_symtab_upper_bound (ibfd);
1114 if (symsize < 0)
1115 RETURN_NONFATAL (bfd_get_filename (ibfd));
57938635 1116
252b5132
RH
1117 osympp = isympp = (asymbol **) xmalloc (symsize);
1118 symcount = bfd_canonicalize_symtab (ibfd, isympp);
1119 if (symcount < 0)
1120 RETURN_NONFATAL (bfd_get_filename (ibfd));
57938635 1121
252b5132
RH
1122 if (convert_debugging)
1123 dhandle = read_debugging_info (ibfd, isympp, symcount);
57938635
AM
1124
1125 if (strip_symbols == STRIP_DEBUG
252b5132
RH
1126 || strip_symbols == STRIP_ALL
1127 || strip_symbols == STRIP_UNNEEDED
1128 || discard_locals != LOCALS_UNDEF
1129 || strip_specific_list != NULL
1130 || keep_specific_list != NULL
1131 || localize_specific_list != NULL
16b2b71c 1132 || keepglobal_specific_list != NULL
252b5132
RH
1133 || weaken_specific_list != NULL
1134 || sections_removed
f91ea849 1135 || sections_copied
252b5132
RH
1136 || convert_debugging
1137 || change_leading_char
1138 || remove_leading_char
57938635 1139 || redefine_sym_list
252b5132
RH
1140 || weaken)
1141 {
1142 /* Mark symbols used in output relocations so that they
1143 are kept, even if they are local labels or static symbols.
57938635 1144
252b5132
RH
1145 Note we iterate over the input sections examining their
1146 relocations since the relocations for the output sections
1147 haven't been set yet. mark_symbols_used_in_relocations will
1148 ignore input sections which have no corresponding output
1149 section. */
1150 if (strip_symbols != STRIP_ALL)
1151 bfd_map_over_sections (ibfd,
1152 mark_symbols_used_in_relocations,
1153 (PTR)isympp);
1154 osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
1155 symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
1156 }
1157
1158 if (convert_debugging && dhandle != NULL)
1159 {
1160 if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
1161 {
1162 status = 1;
1163 return;
1164 }
1165 }
1166
1167 bfd_set_symtab (obfd, osympp, symcount);
1168
1169 /* This has to happen after the symbol table has been set. */
1170 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
1171
1172 if (add_sections != NULL)
1173 {
1174 struct section_add *padd;
1175
1176 for (padd = add_sections; padd != NULL; padd = padd->next)
1177 {
1178 if (! bfd_set_section_contents (obfd, padd->section,
1179 (PTR) padd->contents,
1180 (file_ptr) 0,
1181 (bfd_size_type) padd->size))
1182 RETURN_NONFATAL (bfd_get_filename (obfd));
1183 }
1184 }
1185
1186 if (gap_fill_set || pad_to_set)
1187 {
1188 bfd_byte *buf;
1189 int c, i;
1190
1191 /* Fill in the gaps. */
1192
1193 if (max_gap > 8192)
1194 max_gap = 8192;
1195 buf = (bfd_byte *) xmalloc (max_gap);
1196 memset (buf, gap_fill, (size_t) max_gap);
1197
1198 c = bfd_count_sections (obfd);
1199 for (i = 0; i < c; i++)
1200 {
1201 if (gaps[i] != 0)
1202 {
1203 bfd_size_type left;
1204 file_ptr off;
1205
1206 left = gaps[i];
1207 off = bfd_section_size (obfd, osections[i]) - left;
1208 while (left > 0)
1209 {
1210 bfd_size_type now;
1211
1212 if (left > 8192)
1213 now = 8192;
1214 else
1215 now = left;
1216
1217 if (! bfd_set_section_contents (obfd, osections[i], buf,
1218 off, now))
1219 RETURN_NONFATAL (bfd_get_filename (obfd));
1220
1221 left -= now;
1222 off += now;
1223 }
1224 }
1225 }
1226 }
1227
1228 /* Allow the BFD backend to copy any private data it understands
1229 from the input BFD to the output BFD. This is done last to
1230 permit the routine to look at the filtered symbol table, which is
1231 important for the ECOFF code at least. */
1232 if (!bfd_copy_private_bfd_data (ibfd, obfd))
1233 {
1234 non_fatal (_("%s: error copying private BFD data: %s"),
1235 bfd_get_filename (obfd),
1236 bfd_errmsg (bfd_get_error ()));
1237 status = 1;
1238 return;
1239 }
1240}
1241
1242/* Read each archive element in turn from IBFD, copy the
1243 contents to temp file, and keep the temp file handle. */
1244
1245static void
1246copy_archive (ibfd, obfd, output_target)
1247 bfd *ibfd;
1248 bfd *obfd;
1249 const char *output_target;
1250{
1251 struct name_list
1252 {
1253 struct name_list *next;
1254 char *name;
1255 bfd *obfd;
1256 } *list, *l;
1257 bfd **ptr = &obfd->archive_head;
1258 bfd *this_element;
1259 char *dir = make_tempname (bfd_get_filename (obfd));
1260
1261 /* Make a temp directory to hold the contents. */
1262#if defined (_WIN32) && !defined (__CYGWIN32__)
1263 if (mkdir (dir) != 0)
1264#else
1265 if (mkdir (dir, 0700) != 0)
1266#endif
1267 {
1268 fatal (_("cannot mkdir %s for archive copying (error: %s)"),
1269 dir, strerror (errno));
1270 }
1271 obfd->has_armap = ibfd->has_armap;
1272
1273 list = NULL;
1274
1275 this_element = bfd_openr_next_archived_file (ibfd, NULL);
1276 while (!status && this_element != (bfd *) NULL)
1277 {
1278 /* Create an output file for this member. */
1279 char *output_name = concat (dir, "/", bfd_get_filename (this_element),
1280 (char *) NULL);
1281 bfd *output_bfd = bfd_openw (output_name, output_target);
1282 bfd *last_element;
8066d1a2
AS
1283 struct stat buf;
1284 int stat_status = 0;
1285
1286 if (preserve_dates)
1287 {
1288 stat_status = bfd_stat_arch_elt (this_element, &buf);
1289 if (stat_status != 0)
1290 non_fatal (_("internal stat error on %s"),
1291 bfd_get_filename (this_element));
1292 }
252b5132
RH
1293
1294 l = (struct name_list *) xmalloc (sizeof (struct name_list));
1295 l->name = output_name;
1296 l->next = list;
1297 list = l;
1298
1299 if (output_bfd == (bfd *) NULL)
1300 RETURN_NONFATAL (output_name);
1301
1302 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1303 RETURN_NONFATAL (bfd_get_filename (obfd));
1304
1305 if (bfd_check_format (this_element, bfd_object) == true)
1306 copy_object (this_element, output_bfd);
1307
1308 if (!bfd_close (output_bfd))
1309 {
1310 bfd_nonfatal (bfd_get_filename (output_bfd));
1311 /* Error in new object file. Don't change archive. */
1312 status = 1;
1313 }
1314
8066d1a2
AS
1315 if (preserve_dates && stat_status == 0)
1316 set_times (output_name, &buf);
1317
252b5132
RH
1318 /* Open the newly output file and attach to our list. */
1319 output_bfd = bfd_openr (output_name, output_target);
1320
1321 l->obfd = output_bfd;
1322
1323 *ptr = output_bfd;
1324 ptr = &output_bfd->next;
1325
1326 last_element = this_element;
1327
1328 this_element = bfd_openr_next_archived_file (ibfd, last_element);
1329
1330 bfd_close (last_element);
1331 }
1332 *ptr = (bfd *) NULL;
1333
1334 if (!bfd_close (obfd))
1335 RETURN_NONFATAL (bfd_get_filename (obfd));
1336
1337 if (!bfd_close (ibfd))
1338 RETURN_NONFATAL (bfd_get_filename (ibfd));
1339
1340 /* Delete all the files that we opened. */
1341 for (l = list; l != NULL; l = l->next)
1342 {
1343 bfd_close (l->obfd);
1344 unlink (l->name);
1345 }
1346 rmdir (dir);
1347}
1348
1349/* The top-level control. */
1350
1351static void
1352copy_file (input_filename, output_filename, input_target, output_target)
1353 const char *input_filename;
1354 const char *output_filename;
1355 const char *input_target;
1356 const char *output_target;
1357{
1358 bfd *ibfd;
1359 char **matching;
1360
1361 /* To allow us to do "strip *" without dying on the first
1362 non-object file, failures are nonfatal. */
1363
1364 ibfd = bfd_openr (input_filename, input_target);
1365 if (ibfd == NULL)
1366 RETURN_NONFATAL (input_filename);
1367
1368 if (bfd_check_format (ibfd, bfd_archive))
1369 {
1370 bfd *obfd;
1371
1372 /* bfd_get_target does not return the correct value until
1373 bfd_check_format succeeds. */
1374 if (output_target == NULL)
1375 output_target = bfd_get_target (ibfd);
1376
1377 obfd = bfd_openw (output_filename, output_target);
1378 if (obfd == NULL)
1379 RETURN_NONFATAL (output_filename);
1380
1381 copy_archive (ibfd, obfd, output_target);
1382 }
1383 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
1384 {
1385 bfd *obfd;
1386
1387 /* bfd_get_target does not return the correct value until
1388 bfd_check_format succeeds. */
1389 if (output_target == NULL)
1390 output_target = bfd_get_target (ibfd);
1391
1392 obfd = bfd_openw (output_filename, output_target);
1393 if (obfd == NULL)
1394 RETURN_NONFATAL (output_filename);
1395
1396 copy_object (ibfd, obfd);
1397
1398 if (!bfd_close (obfd))
1399 RETURN_NONFATAL (output_filename);
1400
1401 if (!bfd_close (ibfd))
1402 RETURN_NONFATAL (input_filename);
1403 }
1404 else
1405 {
1406 bfd_nonfatal (input_filename);
57938635 1407
252b5132
RH
1408 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1409 {
1410 list_matching_formats (matching);
1411 free (matching);
1412 }
57938635 1413
252b5132
RH
1414 status = 1;
1415 }
1416}
1417
1418/* Create a section in OBFD with the same name and attributes
1419 as ISECTION in IBFD. */
1420
1421static void
1422setup_section (ibfd, isection, obfdarg)
1423 bfd *ibfd;
1424 sec_ptr isection;
1425 PTR obfdarg;
1426{
1427 bfd *obfd = (bfd *) obfdarg;
1428 struct section_list *p;
1429 sec_ptr osection;
1430 bfd_size_type size;
1431 bfd_vma vma;
1432 bfd_vma lma;
1433 flagword flags;
1a89cc7d 1434 const char *err;
252b5132
RH
1435
1436 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
1437 && (strip_symbols == STRIP_DEBUG
1438 || strip_symbols == STRIP_UNNEEDED
1439 || strip_symbols == STRIP_ALL
1440 || discard_locals == LOCALS_ALL
1441 || convert_debugging))
1442 return;
1443
1444 p = find_section_list (bfd_section_name (ibfd, isection), false);
1445 if (p != NULL)
1446 p->used = true;
1447
f91ea849
ILT
1448 if (sections_removed && p != NULL && p->remove)
1449 return;
1450 if (sections_copied && (p == NULL || ! p->copy))
252b5132
RH
1451 return;
1452
1453 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
57938635 1454
252b5132
RH
1455 if (osection == NULL)
1456 {
1a89cc7d 1457 err = _("making");
252b5132
RH
1458 goto loser;
1459 }
1460
1461 size = bfd_section_size (ibfd, isection);
1462 if (copy_byte >= 0)
1463 size = (size + interleave - 1) / interleave;
1464 if (! bfd_set_section_size (obfd, osection, size))
1465 {
1a89cc7d 1466 err = _("size");
252b5132
RH
1467 goto loser;
1468 }
57938635 1469
252b5132
RH
1470 vma = bfd_section_vma (ibfd, isection);
1471 if (p != NULL && p->change_vma == CHANGE_MODIFY)
1472 vma += p->vma_val;
1473 else if (p != NULL && p->change_vma == CHANGE_SET)
1474 vma = p->vma_val;
1475 else
1476 vma += change_section_address;
57938635 1477
252b5132
RH
1478 if (! bfd_set_section_vma (obfd, osection, vma))
1479 {
1a89cc7d 1480 err = _("vma");
252b5132
RH
1481 goto loser;
1482 }
1483
1484 lma = isection->lma;
1485 if ((p != NULL) && p->change_lma != CHANGE_IGNORE)
1486 {
1487 if (p->change_lma == CHANGE_MODIFY)
1488 lma += p->lma_val;
1489 else if (p->change_lma == CHANGE_SET)
1490 lma = p->lma_val;
1491 else
1492 abort ();
1493 }
1494 else
1495 lma += change_section_address;
57938635 1496
252b5132
RH
1497 osection->lma = lma;
1498
1499 /* FIXME: This is probably not enough. If we change the LMA we
1500 may have to recompute the header for the file as well. */
1501 if (bfd_set_section_alignment (obfd,
1502 osection,
1503 bfd_section_alignment (ibfd, isection))
1504 == false)
1505 {
1a89cc7d 1506 err = _("alignment");
252b5132
RH
1507 goto loser;
1508 }
1509
1510 flags = bfd_get_section_flags (ibfd, isection);
1511 if (p != NULL && p->set_flags)
1512 flags = p->flags | (flags & SEC_HAS_CONTENTS);
1513 if (!bfd_set_section_flags (obfd, osection, flags))
1514 {
1a89cc7d 1515 err = _("flags");
252b5132
RH
1516 goto loser;
1517 }
1518
1519 /* This used to be mangle_section; we do here to avoid using
1520 bfd_get_section_by_name since some formats allow multiple
1521 sections with the same name. */
1522 isection->output_section = osection;
1523 isection->output_offset = 0;
1524
1525 /* Allow the BFD backend to copy any private data it understands
1526 from the input section to the output section. */
1527 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
1528 {
1a89cc7d 1529 err = _("private data");
252b5132
RH
1530 goto loser;
1531 }
1532
1533 /* All went well */
1534 return;
1535
1536loser:
1537 non_fatal (_("%s: section `%s': error in %s: %s"),
1538 bfd_get_filename (ibfd),
1539 bfd_section_name (ibfd, isection),
1540 err, bfd_errmsg (bfd_get_error ()));
1541 status = 1;
1542}
1543
1544/* Copy the data of input section ISECTION of IBFD
1545 to an output section with the same name in OBFD.
1546 If stripping then don't copy any relocation info. */
1547
1548static void
1549copy_section (ibfd, isection, obfdarg)
1550 bfd *ibfd;
1551 sec_ptr isection;
1552 PTR obfdarg;
1553{
1554 bfd *obfd = (bfd *) obfdarg;
1555 struct section_list *p;
1556 arelent **relpp;
1557 long relcount;
1558 sec_ptr osection;
1559 bfd_size_type size;
1560 long relsize;
1561
1562 /* If we have already failed earlier on, do not keep on generating
1563 complaints now. */
1564 if (status != 0)
1565 return;
57938635 1566
252b5132
RH
1567 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
1568 && (strip_symbols == STRIP_DEBUG
1569 || strip_symbols == STRIP_UNNEEDED
1570 || strip_symbols == STRIP_ALL
1571 || discard_locals == LOCALS_ALL
1572 || convert_debugging))
e0c60db2 1573 return;
252b5132
RH
1574
1575 p = find_section_list (bfd_section_name (ibfd, isection), false);
1576
f91ea849
ILT
1577 if (sections_removed && p != NULL && p->remove)
1578 return;
1579 if (sections_copied && (p == NULL || ! p->copy))
252b5132
RH
1580 return;
1581
1582 osection = isection->output_section;
1583 size = bfd_get_section_size_before_reloc (isection);
1584
1585 if (size == 0 || osection == 0)
1586 return;
1587
252b5132
RH
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 }
e0c60db2
NC
1619 else if (sections_removed)
1620 {
1621 /* Remove relocations which are against symbols
1622 in sections that have been removed, unless
1623 the symbols are going to be preserved. */
1624 arelent ** temp_relpp;
1625 asymbol * sym;
1626 long temp_relcount = 0;
1627 long i;
1628
1629 temp_relpp = (arelent **) xmalloc (relsize);
1630 for (i = 0; i < relcount; i++)
1631 {
1632 sym = *relpp [i]->sym_ptr_ptr;
1633
1634 /* FIXME: Should we warn about deleted relocs ? */
1635 if (is_specified_symbol (bfd_asymbol_name (sym),
1636 keep_specific_list)
1637 || bfd_get_output_section (sym) != NULL)
1638 temp_relpp [temp_relcount++] = relpp [i];
1639 }
1640
1641 relcount = temp_relcount;
1642 free (relpp);
1643 relpp = temp_relpp;
1644 }
1645
252b5132
RH
1646 bfd_set_reloc (obfd, osection,
1647 (relcount == 0 ? (arelent **) NULL : relpp), relcount);
1648 }
57938635 1649
252b5132
RH
1650 isection->_cooked_size = isection->_raw_size;
1651 isection->reloc_done = true;
1652
1653 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
1654 {
1655 PTR memhunk = (PTR) xmalloc ((unsigned) size);
1656
1657 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
1658 size))
1659 RETURN_NONFATAL (bfd_get_filename (ibfd));
1660
57938635 1661 if (copy_byte >= 0)
252b5132
RH
1662 filter_bytes (memhunk, &size);
1663
1664 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
1665 size))
1666 RETURN_NONFATAL (bfd_get_filename (obfd));
1667
1668 free (memhunk);
1669 }
1670 else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
1671 {
1672 PTR memhunk = (PTR) xmalloc ((unsigned) size);
1673
1674 /* We don't permit the user to turn off the SEC_HAS_CONTENTS
1675 flag--they can just remove the section entirely and add it
1676 back again. However, we do permit them to turn on the
1677 SEC_HAS_CONTENTS flag, and take it to mean that the section
1678 contents should be zeroed out. */
1679
1680 memset (memhunk, 0, size);
1681 if (! bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
1682 size))
1683 RETURN_NONFATAL (bfd_get_filename (obfd));
1684 free (memhunk);
1685 }
1686}
1687
1688/* Get all the sections. This is used when --gap-fill or --pad-to is
1689 used. */
1690
1691static void
1692get_sections (obfd, osection, secppparg)
b4c96d0d 1693 bfd *obfd ATTRIBUTE_UNUSED;
252b5132
RH
1694 asection *osection;
1695 PTR secppparg;
1696{
1697 asection ***secppp = (asection ***) secppparg;
1698
1699 **secppp = osection;
1700 ++(*secppp);
1701}
1702
1703/* Sort sections by VMA. This is called via qsort, and is used when
1704 --gap-fill or --pad-to is used. We force non loadable or empty
1705 sections to the front, where they are easier to ignore. */
1706
1707static int
1708compare_section_lma (arg1, arg2)
1709 const PTR arg1;
1710 const PTR arg2;
1711{
1712 const asection **sec1 = (const asection **) arg1;
1713 const asection **sec2 = (const asection **) arg2;
1714 flagword flags1, flags2;
1715
1716 /* Sort non loadable sections to the front. */
1717 flags1 = (*sec1)->flags;
1718 flags2 = (*sec2)->flags;
1719 if ((flags1 & SEC_HAS_CONTENTS) == 0
1720 || (flags1 & SEC_LOAD) == 0)
1721 {
1722 if ((flags2 & SEC_HAS_CONTENTS) != 0
1723 && (flags2 & SEC_LOAD) != 0)
1724 return -1;
1725 }
1726 else
1727 {
1728 if ((flags2 & SEC_HAS_CONTENTS) == 0
1729 || (flags2 & SEC_LOAD) == 0)
1730 return 1;
1731 }
1732
1733 /* Sort sections by LMA. */
1734 if ((*sec1)->lma > (*sec2)->lma)
1735 return 1;
1736 else if ((*sec1)->lma < (*sec2)->lma)
1737 return -1;
1738
1739 /* Sort sections with the same LMA by size. */
1740 if ((*sec1)->_raw_size > (*sec2)->_raw_size)
1741 return 1;
1742 else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
1743 return -1;
1744
1745 return 0;
1746}
1747
1748/* Mark all the symbols which will be used in output relocations with
1749 the BSF_KEEP flag so that those symbols will not be stripped.
1750
1751 Ignore relocations which will not appear in the output file. */
1752
1753static void
1754mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
1755 bfd *ibfd;
1756 sec_ptr isection;
1757 PTR symbolsarg;
1758{
1759 asymbol **symbols = (asymbol **) symbolsarg;
1760 long relsize;
1761 arelent **relpp;
1762 long relcount, i;
1763
1764 /* Ignore an input section with no corresponding output section. */
1765 if (isection->output_section == NULL)
1766 return;
1767
1768 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
1769 if (relsize < 0)
1770 bfd_fatal (bfd_get_filename (ibfd));
1771
1772 if (relsize == 0)
1773 return;
1774
1775 relpp = (arelent **) xmalloc (relsize);
1776 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
1777 if (relcount < 0)
1778 bfd_fatal (bfd_get_filename (ibfd));
1779
e0c60db2 1780 /* Examine each symbol used in a relocation. */
252b5132
RH
1781 for (i = 0; i < relcount; i++)
1782 {
e0c60db2
NC
1783 asymbol * sym = * relpp[i]->sym_ptr_ptr;
1784
1785 /* If the symbol's output section does not exist (because it
1786 has been removed with -R) then do not keep the symbol. */
1787 if (bfd_get_output_section (sym) == NULL)
1788 continue;
1789
1790 /* If the symbols is not one of the special bfd
1791 section symbols, then mark it with BSF_KEEP. */
1792 if (sym != bfd_com_section_ptr->symbol
1793 && sym != bfd_abs_section_ptr->symbol
1794 && sym != bfd_und_section_ptr->symbol)
1795 sym->flags |= BSF_KEEP;
252b5132
RH
1796 }
1797
1798 if (relpp != NULL)
1799 free (relpp);
1800}
1801
1802/* Write out debugging information. */
1803
1804static boolean
1805write_debugging_info (obfd, dhandle, symcountp, symppp)
1806 bfd *obfd;
1807 PTR dhandle;
b4c96d0d
ILT
1808 long *symcountp ATTRIBUTE_UNUSED;
1809 asymbol ***symppp ATTRIBUTE_UNUSED;
252b5132
RH
1810{
1811 if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
1812 return write_ieee_debugging_info (obfd, dhandle);
1813
1814 if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
1815 || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
1816 {
1817 bfd_byte *syms, *strings;
1818 bfd_size_type symsize, stringsize;
1819 asection *stabsec, *stabstrsec;
1820
1821 if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
1822 &symsize, &strings,
1823 &stringsize))
1824 return false;
1825
1826 stabsec = bfd_make_section (obfd, ".stab");
1827 stabstrsec = bfd_make_section (obfd, ".stabstr");
1828 if (stabsec == NULL
1829 || stabstrsec == NULL
1830 || ! bfd_set_section_size (obfd, stabsec, symsize)
1831 || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
1832 || ! bfd_set_section_alignment (obfd, stabsec, 2)
1833 || ! bfd_set_section_alignment (obfd, stabstrsec, 0)
1834 || ! bfd_set_section_flags (obfd, stabsec,
1835 (SEC_HAS_CONTENTS
1836 | SEC_READONLY
1837 | SEC_DEBUGGING))
1838 || ! bfd_set_section_flags (obfd, stabstrsec,
1839 (SEC_HAS_CONTENTS
1840 | SEC_READONLY
1841 | SEC_DEBUGGING)))
1842 {
1843 non_fatal (_("%s: can't create debugging section: %s"),
1844 bfd_get_filename (obfd),
1845 bfd_errmsg (bfd_get_error ()));
1846 return false;
1847 }
1848
1849 /* We can get away with setting the section contents now because
1850 the next thing the caller is going to do is copy over the
1851 real sections. We may someday have to split the contents
1852 setting out of this function. */
1853 if (! bfd_set_section_contents (obfd, stabsec, syms, (file_ptr) 0,
1854 symsize)
1855 || ! bfd_set_section_contents (obfd, stabstrsec, strings,
1856 (file_ptr) 0, stringsize))
1857 {
1858 non_fatal (_("%s: can't set debugging section contents: %s"),
1859 bfd_get_filename (obfd),
1860 bfd_errmsg (bfd_get_error ()));
1861 return false;
1862 }
1863
1864 return true;
1865 }
1866
1867 non_fatal (_("%s: don't know how to write debugging information for %s"),
1868 bfd_get_filename (obfd), bfd_get_target (obfd));
1869 return false;
1870}
1871
1872static int
1873strip_main (argc, argv)
1874 int argc;
1875 char *argv[];
1876{
1877 char *input_target = NULL, *output_target = NULL;
1878 boolean show_version = false;
1879 int c, i;
1880 struct section_list *p;
1881 char *output_file = NULL;
1882
6d900bf6 1883 while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXVv",
252b5132
RH
1884 strip_options, (int *) 0)) != EOF)
1885 {
1886 switch (c)
1887 {
1888 case 'I':
1889 input_target = optarg;
1890 break;
1891 case 'O':
1892 output_target = optarg;
1893 break;
1894 case 'F':
1895 input_target = output_target = optarg;
1896 break;
1897 case 'R':
1898 p = find_section_list (optarg, true);
1899 p->remove = true;
1900 sections_removed = true;
1901 break;
1902 case 's':
1903 strip_symbols = STRIP_ALL;
1904 break;
1905 case 'S':
1906 case 'g':
db4f6831 1907 case 'd': /* Historic BSD alias for -g. Used by early NetBSD. */
252b5132
RH
1908 strip_symbols = STRIP_DEBUG;
1909 break;
1910 case OPTION_STRIP_UNNEEDED:
1911 strip_symbols = STRIP_UNNEEDED;
1912 break;
1913 case 'K':
1914 add_specific_symbol (optarg, &keep_specific_list);
1915 break;
1916 case 'N':
1917 add_specific_symbol (optarg, &strip_specific_list);
1918 break;
1919 case 'o':
1920 output_file = optarg;
1921 break;
1922 case 'p':
1923 preserve_dates = true;
1924 break;
1925 case 'x':
1926 discard_locals = LOCALS_ALL;
1927 break;
1928 case 'X':
1929 discard_locals = LOCALS_START_L;
1930 break;
1931 case 'v':
1932 verbose = true;
1933 break;
1934 case 'V':
1935 show_version = true;
1936 break;
1937 case 0:
1938 break; /* we've been given a long option */
1939 case 'h':
1940 strip_usage (stdout, 0);
1941 default:
1942 strip_usage (stderr, 1);
1943 }
1944 }
1945
1946 if (show_version)
1947 print_version ("strip");
1948
1949 /* Default is to strip all symbols. */
1950 if (strip_symbols == STRIP_UNDEF
1951 && discard_locals == LOCALS_UNDEF
1952 && strip_specific_list == NULL)
1953 strip_symbols = STRIP_ALL;
1954
1955 if (output_target == (char *) NULL)
1956 output_target = input_target;
1957
1958 i = optind;
1959 if (i == argc
1960 || (output_file != NULL && (i + 1) < argc))
1961 strip_usage (stderr, 1);
1962
1963 for (; i < argc; i++)
1964 {
1965 int hold_status = status;
1966 struct stat statbuf;
1967 char *tmpname;
1968
1969 if (preserve_dates)
1970 {
1971 if (stat (argv[i], &statbuf) < 0)
1972 {
1973 non_fatal (_("%s: cannot stat: %s"), argv[i], strerror (errno));
1974 continue;
1975 }
1976 }
1977
1978 if (output_file != NULL)
1979 tmpname = output_file;
1980 else
1981 tmpname = make_tempname (argv[i]);
1982 status = 0;
1983
1984 copy_file (argv[i], tmpname, input_target, output_target);
1985 if (status == 0)
1986 {
1987 if (preserve_dates)
1988 set_times (tmpname, &statbuf);
1989 if (output_file == NULL)
1990 smart_rename (tmpname, argv[i], preserve_dates);
1991 status = hold_status;
1992 }
1993 else
1994 unlink (tmpname);
1995 if (output_file == NULL)
1996 free (tmpname);
1997 }
1998
1999 return 0;
2000}
2001
2002static int
2003copy_main (argc, argv)
2004 int argc;
2005 char *argv[];
2006{
43a0748c 2007 char * binary_architecture = NULL;
252b5132
RH
2008 char *input_filename = NULL, *output_filename = NULL;
2009 char *input_target = NULL, *output_target = NULL;
2010 boolean show_version = false;
2011 boolean change_warn = true;
2012 int c;
2013 struct section_list *p;
2014 struct stat statbuf;
2015
6d900bf6 2016 while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXVvW:",
252b5132
RH
2017 copy_options, (int *) 0)) != EOF)
2018 {
2019 switch (c)
2020 {
2021 case 'b':
2022 copy_byte = atoi (optarg);
2023 if (copy_byte < 0)
2024 fatal (_("byte number must be non-negative"));
2025 break;
57938635 2026
43a0748c
NC
2027 case 'B':
2028 binary_architecture = optarg;
2029 break;
2030
252b5132
RH
2031 case 'i':
2032 interleave = atoi (optarg);
2033 if (interleave < 1)
2034 fatal (_("interleave must be positive"));
2035 break;
57938635 2036
252b5132
RH
2037 case 'I':
2038 case 's': /* "source" - 'I' is preferred */
2039 input_target = optarg;
2040 break;
57938635 2041
252b5132
RH
2042 case 'O':
2043 case 'd': /* "destination" - 'O' is preferred */
2044 output_target = optarg;
2045 break;
57938635 2046
252b5132
RH
2047 case 'F':
2048 input_target = output_target = optarg;
2049 break;
57938635 2050
f91ea849
ILT
2051 case 'j':
2052 p = find_section_list (optarg, true);
2053 if (p->remove)
2054 fatal (_("%s both copied and removed"), optarg);
2055 p->copy = true;
2056 sections_copied = true;
2057 break;
57938635 2058
252b5132
RH
2059 case 'R':
2060 p = find_section_list (optarg, true);
f91ea849
ILT
2061 if (p->copy)
2062 fatal (_("%s both copied and removed"), optarg);
252b5132
RH
2063 p->remove = true;
2064 sections_removed = true;
2065 break;
57938635 2066
252b5132
RH
2067 case 'S':
2068 strip_symbols = STRIP_ALL;
2069 break;
57938635 2070
252b5132
RH
2071 case 'g':
2072 strip_symbols = STRIP_DEBUG;
2073 break;
57938635 2074
252b5132
RH
2075 case OPTION_STRIP_UNNEEDED:
2076 strip_symbols = STRIP_UNNEEDED;
2077 break;
57938635 2078
252b5132
RH
2079 case 'K':
2080 add_specific_symbol (optarg, &keep_specific_list);
2081 break;
57938635 2082
252b5132
RH
2083 case 'N':
2084 add_specific_symbol (optarg, &strip_specific_list);
2085 break;
57938635 2086
252b5132
RH
2087 case 'L':
2088 add_specific_symbol (optarg, &localize_specific_list);
2089 break;
57938635 2090
16b2b71c
NC
2091 case 'G':
2092 add_specific_symbol (optarg, &keepglobal_specific_list);
2093 break;
2094
252b5132
RH
2095 case 'W':
2096 add_specific_symbol (optarg, &weaken_specific_list);
2097 break;
57938635 2098
252b5132
RH
2099 case 'p':
2100 preserve_dates = true;
2101 break;
57938635 2102
252b5132
RH
2103 case 'x':
2104 discard_locals = LOCALS_ALL;
2105 break;
57938635 2106
252b5132
RH
2107 case 'X':
2108 discard_locals = LOCALS_START_L;
2109 break;
57938635 2110
252b5132
RH
2111 case 'v':
2112 verbose = true;
2113 break;
57938635 2114
252b5132
RH
2115 case 'V':
2116 show_version = true;
2117 break;
57938635 2118
252b5132
RH
2119 case OPTION_WEAKEN:
2120 weaken = true;
2121 break;
57938635 2122
252b5132
RH
2123 case OPTION_ADD_SECTION:
2124 {
2125 const char *s;
2126 struct stat st;
2127 struct section_add *pa;
2128 int len;
2129 char *name;
2130 FILE *f;
2131
2132 s = strchr (optarg, '=');
57938635 2133
252b5132 2134 if (s == NULL)
57938635 2135 fatal (_("bad format for %s"), "--add-section");
252b5132
RH
2136
2137 if (stat (s + 1, & st) < 0)
2138 fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno));
2139
2140 pa = (struct section_add *) xmalloc (sizeof (struct section_add));
2141
2142 len = s - optarg;
2143 name = (char *) xmalloc (len + 1);
2144 strncpy (name, optarg, len);
2145 name[len] = '\0';
2146 pa->name = name;
2147
2148 pa->filename = s + 1;
2149
2150 pa->size = st.st_size;
2151
2152 pa->contents = (bfd_byte *) xmalloc (pa->size);
2153 f = fopen (pa->filename, FOPEN_RB);
57938635 2154
252b5132
RH
2155 if (f == NULL)
2156 fatal (_("cannot open: %s: %s"), pa->filename, strerror (errno));
57938635 2157
252b5132
RH
2158 if (fread (pa->contents, 1, pa->size, f) == 0
2159 || ferror (f))
2160 fatal (_("%s: fread failed"), pa->filename);
2161
2162 fclose (f);
2163
2164 pa->next = add_sections;
2165 add_sections = pa;
2166 }
2167 break;
57938635 2168
252b5132
RH
2169 case OPTION_CHANGE_START:
2170 change_start = parse_vma (optarg, "--change-start");
2171 break;
57938635 2172
252b5132
RH
2173 case OPTION_CHANGE_SECTION_ADDRESS:
2174 case OPTION_CHANGE_SECTION_LMA:
2175 case OPTION_CHANGE_SECTION_VMA:
2176 {
2177 const char *s;
2178 int len;
2179 char *name;
b4c96d0d 2180 char *option = NULL;
252b5132 2181 bfd_vma val;
b4c96d0d 2182 enum change_action what = CHANGE_IGNORE;
57938635 2183
252b5132
RH
2184 switch (c)
2185 {
b4c96d0d
ILT
2186 case OPTION_CHANGE_SECTION_ADDRESS:
2187 option = "--change-section-address";
2188 break;
2189 case OPTION_CHANGE_SECTION_LMA:
2190 option = "--change-section-lma";
2191 break;
2192 case OPTION_CHANGE_SECTION_VMA:
2193 option = "--change-section-vma";
2194 break;
252b5132 2195 }
57938635 2196
252b5132
RH
2197 s = strchr (optarg, '=');
2198 if (s == NULL)
2199 {
2200 s = strchr (optarg, '+');
2201 if (s == NULL)
2202 {
2203 s = strchr (optarg, '-');
2204 if (s == NULL)
2205 fatal (_("bad format for %s"), option);
2206 }
2207 }
2208
2209 len = s - optarg;
2210 name = (char *) xmalloc (len + 1);
2211 strncpy (name, optarg, len);
2212 name[len] = '\0';
2213
2214 p = find_section_list (name, true);
2215
2216 val = parse_vma (s + 1, option);
2217
2218 switch (*s)
2219 {
2220 case '=': what = CHANGE_SET; break;
2221 case '-': val = - val; /* Drop through. */
2222 case '+': what = CHANGE_MODIFY; break;
2223 }
57938635 2224
252b5132
RH
2225 switch (c)
2226 {
2227 case OPTION_CHANGE_SECTION_ADDRESS:
2228 p->change_vma = what;
2229 p->vma_val = val;
2230 /* Drop through. */
57938635 2231
252b5132
RH
2232 case OPTION_CHANGE_SECTION_LMA:
2233 p->change_lma = what;
2234 p->lma_val = val;
2235 break;
57938635 2236
252b5132
RH
2237 case OPTION_CHANGE_SECTION_VMA:
2238 p->change_vma = what;
2239 p->vma_val = val;
2240 break;
2241 }
2242 }
2243 break;
57938635 2244
252b5132
RH
2245 case OPTION_CHANGE_ADDRESSES:
2246 change_section_address = parse_vma (optarg, "--change-addresses");
2247 change_start = change_section_address;
2248 break;
57938635 2249
252b5132
RH
2250 case OPTION_CHANGE_WARNINGS:
2251 change_warn = true;
2252 break;
57938635 2253
252b5132
RH
2254 case OPTION_CHANGE_LEADING_CHAR:
2255 change_leading_char = true;
2256 break;
57938635 2257
252b5132
RH
2258 case OPTION_DEBUGGING:
2259 convert_debugging = true;
2260 break;
57938635 2261
252b5132
RH
2262 case OPTION_GAP_FILL:
2263 {
2264 bfd_vma gap_fill_vma;
2265
2266 gap_fill_vma = parse_vma (optarg, "--gap-fill");
2267 gap_fill = (bfd_byte) gap_fill_vma;
2268 if ((bfd_vma) gap_fill != gap_fill_vma)
2269 {
2270 char buff[20];
57938635 2271
252b5132 2272 sprintf_vma (buff, gap_fill_vma);
57938635 2273
252b5132
RH
2274 non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
2275 buff, gap_fill);
2276 }
2277 gap_fill_set = true;
2278 }
2279 break;
57938635 2280
252b5132
RH
2281 case OPTION_NO_CHANGE_WARNINGS:
2282 change_warn = false;
2283 break;
57938635 2284
252b5132
RH
2285 case OPTION_PAD_TO:
2286 pad_to = parse_vma (optarg, "--pad-to");
2287 pad_to_set = true;
2288 break;
57938635 2289
252b5132
RH
2290 case OPTION_REMOVE_LEADING_CHAR:
2291 remove_leading_char = true;
2292 break;
57938635
AM
2293
2294 case OPTION_REDEFINE_SYM:
2295 {
2296 /* Push this redefinition onto redefine_symbol_list. */
2297
2298 int len;
2299 const char *s;
2300 const char *nextarg;
2301 char *source, *target;
2302
2303 s = strchr (optarg, '=');
2304 if (s == NULL)
2305 {
2306 fatal (_("bad format for %s"), "--redefine-sym");
2307 }
2308
2309 len = s - optarg;
2310 source = (char *) xmalloc (len + 1);
2311 strncpy (source, optarg, len);
2312 source[len] = '\0';
2313
2314 nextarg = s + 1;
2315 len = strlen (nextarg);
2316 target = (char *) xmalloc (len + 1);
2317 strcpy (target, nextarg);
2318
2319 redefine_list_append (source, target);
2320
2321 free (source);
2322 free (target);
2323 }
2324 break;
2325
252b5132
RH
2326 case OPTION_SET_SECTION_FLAGS:
2327 {
2328 const char *s;
2329 int len;
2330 char *name;
2331
2332 s = strchr (optarg, '=');
2333 if (s == NULL)
57938635 2334 fatal (_("bad format for %s"), "--set-section-flags");
252b5132
RH
2335
2336 len = s - optarg;
2337 name = (char *) xmalloc (len + 1);
2338 strncpy (name, optarg, len);
2339 name[len] = '\0';
2340
2341 p = find_section_list (name, true);
2342
2343 p->set_flags = true;
2344 p->flags = parse_flags (s + 1);
2345 }
2346 break;
57938635 2347
252b5132
RH
2348 case OPTION_SET_START:
2349 set_start = parse_vma (optarg, "--set-start");
2350 set_start_set = true;
2351 break;
57938635 2352
420496c1
NC
2353 case OPTION_SREC_LEN:
2354 Chunk = parse_vma (optarg, "--srec-len");
2355 break;
2356
2357 case OPTION_SREC_FORCES3:
2358 S3Forced = true;
2359 break;
2360
16b2b71c
NC
2361 case OPTION_STRIP_SYMBOLS:
2362 add_specific_symbols (optarg, &strip_specific_list);
2363 break;
2364
2365 case OPTION_KEEP_SYMBOLS:
2366 add_specific_symbols (optarg, &keep_specific_list);
2367 break;
2368
2369 case OPTION_LOCALIZE_SYMBOLS:
2370 add_specific_symbols (optarg, &localize_specific_list);
2371 break;
2372
2373 case OPTION_KEEPGLOBAL_SYMBOLS:
2374 add_specific_symbols (optarg, &keepglobal_specific_list);
2375 break;
2376
2377 case OPTION_WEAKEN_SYMBOLS:
2378 add_specific_symbols (optarg, &weaken_specific_list);
2379 break;
2380
252b5132
RH
2381 case 0:
2382 break; /* we've been given a long option */
57938635 2383
252b5132
RH
2384 case 'h':
2385 copy_usage (stdout, 0);
57938635 2386
252b5132
RH
2387 default:
2388 copy_usage (stderr, 1);
2389 }
2390 }
2391
2392 if (show_version)
2393 print_version ("objcopy");
2394
2395 if (copy_byte >= interleave)
2396 fatal (_("byte number must be less than interleave"));
2397
2398 if (optind == argc || optind + 2 < argc)
2399 copy_usage (stderr, 1);
2400
2401 input_filename = argv[optind];
2402 if (optind + 1 < argc)
2403 output_filename = argv[optind + 1];
2404
2405 /* Default is to strip no symbols. */
2406 if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
2407 strip_symbols = STRIP_NONE;
2408
2409 if (output_target == (char *) NULL)
2410 output_target = input_target;
2411
43a0748c 2412 if (binary_architecture != (char *) NULL)
252b5132 2413 {
43a0748c
NC
2414 if (input_target && strcmp (input_target, "binary") == 0)
2415 {
2416 const bfd_arch_info_type * temp_arch_info;
2417
2418 temp_arch_info = bfd_scan_arch (binary_architecture);
2419
2420 if (temp_arch_info != NULL)
2421 bfd_external_binary_architecture = temp_arch_info->arch;
2422 else
2423 fatal (_("architecture %s unknown"), binary_architecture);
2424 }
2425 else
2426 {
2427 non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
2428 non_fatal (_(" Argument %s ignored"), binary_architecture);
2429 }
252b5132
RH
2430 }
2431
43a0748c
NC
2432 if (preserve_dates)
2433 if (stat (input_filename, & statbuf) < 0)
2434 fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno));
2435
252b5132
RH
2436 /* If there is no destination file then create a temp and rename
2437 the result into the input. */
2438
2439 if (output_filename == (char *) NULL)
2440 {
2441 char *tmpname = make_tempname (input_filename);
2442
2443 copy_file (input_filename, tmpname, input_target, output_target);
2444 if (status == 0)
57938635 2445 {
252b5132
RH
2446 if (preserve_dates)
2447 set_times (tmpname, &statbuf);
2448 smart_rename (tmpname, input_filename, preserve_dates);
2449 }
2450 else
2451 unlink (tmpname);
2452 }
2453 else
2454 {
2455 copy_file (input_filename, output_filename, input_target, output_target);
2456 if (status == 0 && preserve_dates)
2457 set_times (output_filename, &statbuf);
2458 }
2459
2460 if (change_warn)
2461 {
2462 for (p = change_sections; p != NULL; p = p->next)
2463 {
2464 if (! p->used)
2465 {
2466 if (p->change_vma != CHANGE_IGNORE)
2467 {
2468 char buff [20];
2469
2470 sprintf_vma (buff, p->vma_val);
57938635 2471
252b5132 2472 /* xgettext:c-format */
57938635
AM
2473 non_fatal (_("%s %s%c0x%s never used"),
2474 "--change-section-vma",
252b5132
RH
2475 p->name,
2476 p->change_vma == CHANGE_SET ? '=' : '+',
2477 buff);
2478 }
57938635 2479
252b5132
RH
2480 if (p->change_lma != CHANGE_IGNORE)
2481 {
2482 char buff [20];
2483
2484 sprintf_vma (buff, p->lma_val);
57938635 2485
252b5132 2486 /* xgettext:c-format */
57938635
AM
2487 non_fatal (_("%s %s%c0x%s never used"),
2488 "--change-section-lma",
252b5132
RH
2489 p->name,
2490 p->change_lma == CHANGE_SET ? '=' : '+',
2491 buff);
2492 }
2493 }
2494 }
2495 }
2496
2497 return 0;
2498}
2499
2500int
2501main (argc, argv)
2502 int argc;
2503 char *argv[];
2504{
2505#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
2506 setlocale (LC_MESSAGES, "");
2507#endif
2508 bindtextdomain (PACKAGE, LOCALEDIR);
2509 textdomain (PACKAGE);
2510
2511 program_name = argv[0];
2512 xmalloc_set_program_name (program_name);
2513
2514 START_PROGRESS (program_name, 0);
2515
2516 strip_symbols = STRIP_UNDEF;
2517 discard_locals = LOCALS_UNDEF;
2518
2519 bfd_init ();
2520 set_default_bfd_target ();
2521
2522 if (is_strip < 0)
2523 {
2524 int i = strlen (program_name);
5af11cab
AM
2525#ifdef HAVE_DOS_BASED_FILE_SYSTEM
2526 /* Drop the .exe suffix, if any. */
2527 if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0)
2528 {
2529 i -= 4;
2530 program_name[i] = '\0';
2531 }
2532#endif
2533 is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
252b5132
RH
2534 }
2535
2536 if (is_strip)
2537 strip_main (argc, argv);
2538 else
2539 copy_main (argc, argv);
2540
2541 END_PROGRESS (program_name);
2542
2543 return status;
2544}
This page took 0.311331 seconds and 4 git commands to generate.