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