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