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