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