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