* binary.c: New file for raw binary output format.
[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"
22#include "bucomm.h"
23#include <getopt.h>
6c7ed084 24#include "libiberty.h"
c0367ba5 25
6c7ed084
ILT
26static bfd_vma parse_vma PARAMS ((const char *, const char *));
27static void setup_section PARAMS ((bfd *, asection *, PTR));
28static void copy_section PARAMS ((bfd *, asection *, PTR));
29static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
c0367ba5 30
46050fe4 31#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
c0367ba5 32
46050fe4
ILT
33static asymbol **isympp = NULL; /* Input symbols */
34static asymbol **osympp = NULL; /* Output symbols that survive stripping */
f7b839f7
DM
35
36/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
37static int copy_byte = -1;
38static int interleave = 4;
39
46050fe4 40static boolean verbose; /* Print file and target names. */
f7b839f7 41static int status = 0; /* Exit status. */
c0367ba5
ILT
42
43enum strip_action
46050fe4
ILT
44 {
45 strip_undef,
46 strip_none, /* don't strip */
47 strip_debug, /* strip all debugger symbols */
48 strip_all /* strip all symbols */
49 };
c0367ba5
ILT
50
51/* Which symbols to remove. */
46050fe4 52static enum strip_action strip_symbols;
c0367ba5
ILT
53
54enum locals_action
46050fe4
ILT
55 {
56 locals_undef,
57 locals_start_L, /* discard locals starting with L */
58 locals_all /* discard all locals */
59 };
60
61/* Which local symbols to remove. Overrides strip_all. */
62static enum locals_action discard_locals;
63
6c7ed084
ILT
64/* Structure used to hold lists of sections and actions to take. */
65
66struct section_list
67{
68 /* Next section to adjust. */
69 struct section_list *next;
70 /* Section name. */
71 const char *name;
72 /* Whether this entry was used. */
73 boolean used;
74 /* Remaining fields only used if not on remove_sections list. */
75 /* Whether to adjust or set VMA. */
76 boolean adjust;
77 /* Amount to adjust by or set to. */
78 bfd_vma val;
79};
80
81/* List of sections to remove. */
82
83static struct section_list *remove_sections;
84
85/* Adjustments to the start address. */
86static bfd_vma adjust_start = 0;
87static boolean set_start_set = false;
88static bfd_vma set_start;
89
90/* Adjustments to section VMA's. */
91static bfd_vma adjust_section_vma = 0;
92static struct section_list *adjust_sections;
93
46050fe4
ILT
94/* Options to handle if running as "strip". */
95
96static struct option strip_options[] =
c0367ba5 97{
46050fe4
ILT
98 {"discard-all", no_argument, 0, 'x'},
99 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 100 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 101 {"help", no_argument, 0, 'h'},
46050fe4 102 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7 103 {"input-target", required_argument, 0, 'I'},
46050fe4 104 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7 105 {"output-target", required_argument, 0, 'O'},
6c7ed084 106 {"remove-section", required_argument, 0, 'R'},
f7b839f7
DM
107 {"strip-all", no_argument, 0, 's'},
108 {"strip-debug", no_argument, 0, 'S'},
46050fe4 109 {"target", required_argument, 0, 'F'},
46050fe4 110 {"verbose", no_argument, 0, 'v'},
f7b839f7 111 {"version", no_argument, 0, 'V'},
46050fe4 112 {0, no_argument, 0, 0}
c0367ba5
ILT
113};
114
46050fe4 115/* Options to handle if running as "objcopy". */
c0367ba5 116
6c7ed084
ILT
117/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
118
119#define OPTION_ADJUST_START 150
120#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1)
121#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1)
122#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1)
123#define OPTION_NO_ADJUST_WARNINGS (OPTION_ADJUST_WARNINGS + 1)
124#define OPTION_SET_START (OPTION_NO_ADJUST_WARNINGS + 1)
125
46050fe4
ILT
126static struct option copy_options[] =
127{
6c7ed084
ILT
128 {"adjust-start", required_argument, 0, OPTION_ADJUST_START},
129 {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA},
130 {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA},
131 {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS},
f7b839f7 132 {"byte", required_argument, 0, 'b'},
46050fe4
ILT
133 {"discard-all", no_argument, 0, 'x'},
134 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 135 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 136 {"help", no_argument, 0, 'h'},
46050fe4 137 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7
DM
138 {"input-target", required_argument, 0, 'I'},
139 {"interleave", required_argument, 0, 'i'},
6c7ed084 140 {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS},
46050fe4 141 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7 142 {"output-target", required_argument, 0, 'O'},
6c7ed084
ILT
143 {"remove-section", required_argument, 0, 'R'},
144 {"set-start", required_argument, 0, OPTION_SET_START},
f7b839f7
DM
145 {"strip-all", no_argument, 0, 'S'},
146 {"strip-debug", no_argument, 0, 'g'},
46050fe4 147 {"target", required_argument, 0, 'F'},
46050fe4 148 {"verbose", no_argument, 0, 'v'},
f7b839f7 149 {"version", no_argument, 0, 'V'},
46050fe4 150 {0, no_argument, 0, 0}
c0367ba5
ILT
151};
152
153/* IMPORTS */
46050fe4
ILT
154extern char *program_name;
155extern char *program_version;
156
157/* This flag distinguishes between strip and objcopy:
158 1 means this is 'strip'; 0 means this is 'objcopy'.
159 -1 means if we should use argv[0] to decide. */
160extern int is_strip;
c0367ba5
ILT
161
162
46050fe4
ILT
163static void
164copy_usage (stream, status)
c0367ba5
ILT
165 FILE *stream;
166 int status;
167{
46050fe4 168 fprintf (stream, "\
f7b839f7 169Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
6c7ed084 170 [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
46050fe4
ILT
171 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
172 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
6c7ed084
ILT
173 [--remove-section=section] [--set-start=val] [--adjust-start=incr]\n\
174 [--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\
175 [--adjust-warnings] [--no-adjust-warnings] [--verbose] [--version]\n\
176 [--help] in-file [out-file]\n",
f7b839f7 177 program_name);
46050fe4 178 exit (status);
c0367ba5
ILT
179}
180
46050fe4
ILT
181static void
182strip_usage (stream, status)
c0367ba5
ILT
183 FILE *stream;
184 int status;
185{
46050fe4 186 fprintf (stream, "\
6c7ed084 187Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
46050fe4
ILT
188 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
189 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
6c7ed084 190 [--remove-section=section] [--verbose] [--version] [--help] file...\n",
46050fe4
ILT
191 program_name);
192 exit (status);
c0367ba5
ILT
193}
194
6c7ed084
ILT
195/* Parse a string into a VMA, with a fatal error if it can't be
196 parsed. */
197
198static bfd_vma
199parse_vma (s, arg)
200 const char *s;
201 const char *arg;
202{
203 bfd_vma ret;
204 const char *end;
205
206 ret = bfd_scan_vma (s, &end, 0);
207 if (*end != '\0')
208 {
209 fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s);
210 exit (1);
211 }
212 return ret;
213}
c0367ba5 214
46050fe4 215/* Return the name of a temporary file in the same directory as FILENAME. */
c0367ba5 216
46050fe4
ILT
217static char *
218make_tempname (filename)
219 char *filename;
c0367ba5 220{
46050fe4
ILT
221 static char template[] = "stXXXXXX";
222 char *tmpname;
223 char *slash = strrchr (filename, '/');
224
225 if (slash != (char *) NULL)
226 {
227 *slash = 0;
228 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
229 strcpy (tmpname, filename);
230 strcat (tmpname, "/");
231 strcat (tmpname, template);
232 mktemp (tmpname);
233 *slash = '/';
234 }
235 else
236 {
237 tmpname = xmalloc (sizeof (template));
238 strcpy (tmpname, template);
239 mktemp (tmpname);
c0367ba5 240 }
46050fe4 241 return tmpname;
c0367ba5
ILT
242}
243
46050fe4 244/* Choose which symbol entries to copy; put the result in OSYMS.
c0367ba5 245 We don't copy in place, because that confuses the relocs.
46050fe4
ILT
246 Return the number of symbols to print. */
247
c0367ba5
ILT
248static unsigned int
249filter_symbols (abfd, osyms, isyms, symcount)
250 bfd *abfd;
251 asymbol **osyms, **isyms;
ae5d2ff5 252 long symcount;
c0367ba5
ILT
253{
254 register asymbol **from = isyms, **to = osyms;
ae5d2ff5 255 long src_count = 0, dst_count = 0;
c0367ba5 256
46050fe4
ILT
257 for (; src_count < symcount; src_count++)
258 {
259 asymbol *sym = from[src_count];
260 flagword flags = sym->flags;
261 int keep;
c0367ba5 262
46050fe4 263 if ((flags & BSF_GLOBAL) /* Keep if external. */
77ccab3c 264 || (flags & BSF_KEEP) /* Keep if used in a relocation. */
6c7ed084 265 || bfd_is_und_section (bfd_get_section (sym))
46050fe4
ILT
266 || bfd_is_com_section (bfd_get_section (sym)))
267 keep = 1;
268 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
269 keep = strip_symbols != strip_debug;
270 else /* Local symbol. */
271 keep = discard_locals != locals_all
272 && (discard_locals != locals_start_L ||
77ccab3c 273 ! bfd_is_local_label (abfd, sym));
46050fe4
ILT
274 if (keep)
275 to[dst_count++] = sym;
c0367ba5 276 }
c0367ba5
ILT
277
278 return dst_count;
279}
280
f7b839f7
DM
281/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
282 Adjust *SIZE. */
283
284void
285filter_bytes (memhunk, size)
5d2f7e30 286 char *memhunk;
f7b839f7
DM
287 bfd_size_type *size;
288{
289 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
290
291 for (; from < end; from += interleave)
292 *to++ = *from;
293 *size /= interleave;
294}
295
46050fe4
ILT
296/* Copy object file IBFD onto OBFD. */
297
c0367ba5 298static void
46050fe4
ILT
299copy_object (ibfd, obfd)
300 bfd *ibfd;
301 bfd *obfd;
c0367ba5 302{
6c7ed084 303 bfd_vma start;
ae5d2ff5 304 long symcount;
c0367ba5 305
46050fe4
ILT
306 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
307 {
308 nonfatal (bfd_get_filename (obfd));
309 }
c0367ba5 310
46050fe4
ILT
311 if (verbose)
312 printf ("copy from %s(%s) to %s(%s)\n",
313 bfd_get_filename(ibfd), bfd_get_target(ibfd),
314 bfd_get_filename(obfd), bfd_get_target(obfd));
c0367ba5 315
6c7ed084
ILT
316 if (set_start_set)
317 start = set_start;
318 else
319 start = bfd_get_start_address (ibfd);
320 start += adjust_start;
321
322 if (!bfd_set_start_address (obfd, start)
46050fe4
ILT
323 || !bfd_set_file_flags (obfd,
324 (bfd_get_file_flags (ibfd)
325 & bfd_applicable_file_flags (obfd))))
326 {
327 nonfatal (bfd_get_filename (ibfd));
328 }
c0367ba5 329
46050fe4
ILT
330 /* Copy architecture of input file to output file */
331 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
332 bfd_get_mach (ibfd)))
333 {
334 fprintf (stderr, "Output file cannot represent architecture %s\n",
335 bfd_printable_arch_mach (bfd_get_arch (ibfd),
336 bfd_get_mach (ibfd)));
337 }
338 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
339 {
340 nonfatal (bfd_get_filename(ibfd));
341 }
c0367ba5 342
46050fe4
ILT
343 if (isympp)
344 free (isympp);
345 if (osympp != isympp)
346 free (osympp);
c0367ba5 347
77ccab3c
JL
348 /* bfd mandates that all output sections be created and sizes set before
349 any output is done. Thus, we traverse all sections multiple times. */
350 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
351
352 /* Symbol filtering must happen after the output sections have
353 been created, but before their contents are set. */
46050fe4
ILT
354 if (strip_symbols == strip_all && discard_locals == locals_undef)
355 {
356 osympp = isympp = NULL;
357 symcount = 0;
c0367ba5 358 }
46050fe4
ILT
359 else
360 {
ae5d2ff5
ILT
361 long symsize;
362
363 symsize = bfd_get_symtab_upper_bound (ibfd);
364 if (symsize < 0)
365 {
366 nonfatal (bfd_get_filename (ibfd));
367 }
368
369 osympp = isympp = (asymbol **) xmalloc (symsize);
46050fe4 370 symcount = bfd_canonicalize_symtab (ibfd, isympp);
ae5d2ff5
ILT
371 if (symcount < 0)
372 {
373 nonfatal (bfd_get_filename (ibfd));
374 }
46050fe4
ILT
375
376 if (strip_symbols == strip_debug || discard_locals != locals_undef)
c0367ba5 377 {
77ccab3c
JL
378 /* Mark symbols used in output relocations so that they
379 are kept, even if they are local labels or static symbols.
380
381 Note we iterate over the input sections examining their
382 relocations since the relocations for the output sections
383 haven't been set yet. mark_symbols_used_in_relocations will
384 ignore input sections which have no corresponding output
385 section. */
386 bfd_map_over_sections (ibfd,
387 mark_symbols_used_in_relocations,
6c7ed084 388 (PTR)isympp);
46050fe4
ILT
389 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
390 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
c0367ba5 391 }
46050fe4
ILT
392 }
393
394 bfd_set_symtab (obfd, osympp, symcount);
c0367ba5 395
77ccab3c 396 /* This has to happen after the symbol table has been set. */
f7b839f7 397 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
6f9077cd
JM
398
399 /* Allow the BFD backend to copy any private data it understands
400 from the input BFD to the output BFD. This is done last to
401 permit the routine to look at the filtered symbol table, which is
402 important for the ECOFF code at least. */
403 if (!bfd_copy_private_bfd_data (ibfd, obfd))
404 {
405 fprintf (stderr, "%s: %s: error copying private BFD data: %s\n",
406 program_name, bfd_get_filename (obfd),
407 bfd_errmsg (bfd_get_error ()));
408 status = 1;
409 return;
410 }
c0367ba5 411}
46050fe4
ILT
412
413static char *
414cat (a, b, c)
415 char *a;
416 char *b;
417 char *c;
c0367ba5 418{
46050fe4
ILT
419 size_t size = strlen (a) + strlen (b) + strlen (c);
420 char *r = xmalloc (size + 1);
421
422 strcpy (r, a);
423 strcat (r, b);
424 strcat (r, c);
425 return r;
c0367ba5
ILT
426}
427
46050fe4
ILT
428/* Read each archive element in turn from IBFD, copy the
429 contents to temp file, and keep the temp file handle. */
430
431static void
432copy_archive (ibfd, obfd, output_target)
433 bfd *ibfd;
434 bfd *obfd;
435 char *output_target;
c0367ba5 436{
46050fe4
ILT
437 bfd **ptr = &obfd->archive_head;
438 bfd *this_element;
90f6517d 439 char *dir = make_tempname (bfd_get_filename (obfd));
46050fe4
ILT
440
441 /* Make a temp directory to hold the contents. */
90f6517d 442 mkdir (dir, 0700);
46050fe4
ILT
443 obfd->has_armap = ibfd->has_armap;
444
445 this_element = bfd_openr_next_archived_file (ibfd, NULL);
446 ibfd->archive_head = this_element;
447 while (this_element != (bfd *) NULL)
448 {
449 /* Create an output file for this member. */
450 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
451 bfd *output_bfd = bfd_openw (output_name, output_target);
452
453 if (output_bfd == (bfd *) NULL)
454 {
455 nonfatal (output_name);
c0367ba5 456 }
46050fe4
ILT
457 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
458 {
459 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
460 }
461
46050fe4
ILT
462 if (bfd_check_format (this_element, bfd_object) == true)
463 {
464 copy_object (this_element, output_bfd);
465 }
c0367ba5 466
46050fe4
ILT
467 bfd_close (output_bfd);
468 /* Open the newly output file and attatch to our list. */
469 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 470
46050fe4
ILT
471 /* Mark it for deletion. */
472 *ptr = output_bfd;
473 ptr = &output_bfd->next;
474 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
475 this_element = this_element->next;
c0367ba5 476 }
46050fe4 477 *ptr = (bfd *) NULL;
c0367ba5 478
46050fe4
ILT
479 if (!bfd_close (obfd))
480 {
481 nonfatal (bfd_get_filename (obfd));
c0367ba5 482 }
c0367ba5 483
46050fe4
ILT
484 /* Delete all the files that we opened.
485 Construct their names again, unfortunately, but
486 we're about to exit anyway. */
487 for (this_element = ibfd->archive_head;
488 this_element != (bfd *) NULL;
489 this_element = this_element->next)
490 {
491 unlink (cat (dir, "/", bfd_get_filename (this_element)));
492 }
493 rmdir (dir);
494 if (!bfd_close (ibfd))
495 {
496 nonfatal (bfd_get_filename (ibfd));
497 }
c0367ba5
ILT
498}
499
46050fe4
ILT
500/* The top-level control. */
501
502static void
503copy_file (input_filename, output_filename, input_target, output_target)
504 char *input_filename;
505 char *output_filename;
506 char *input_target;
507 char *output_target;
c0367ba5 508{
46050fe4 509 bfd *ibfd;
cef35d48 510 char **matching;
c0367ba5
ILT
511
512 /* To allow us to do "strip *" without dying on the first
513 non-object file, failures are nonfatal. */
514
46050fe4 515 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
516 if (ibfd == NULL)
517 {
46050fe4 518 nonfatal (input_filename);
c0367ba5
ILT
519 }
520
cef35d48
DM
521 if (bfd_check_format (ibfd, bfd_archive))
522 {
6c7ed084
ILT
523 bfd *obfd;
524
525 /* bfd_get_target does not return the correct value until
526 bfd_check_format succeeds. */
527 if (output_target == NULL)
528 output_target = bfd_get_target (ibfd);
529
530 obfd = bfd_openw (output_filename, output_target);
cef35d48
DM
531 if (obfd == NULL)
532 {
533 nonfatal (output_filename);
534 }
535 copy_archive (ibfd, obfd, output_target);
536 }
537 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4 538 {
6c7ed084
ILT
539 bfd *obfd;
540
541 /* bfd_get_target does not return the correct value until
542 bfd_check_format succeeds. */
543 if (output_target == NULL)
544 output_target = bfd_get_target (ibfd);
545
546 obfd = bfd_openw (output_filename, output_target);
46050fe4
ILT
547 if (obfd == NULL)
548 {
549 nonfatal (output_filename);
550 }
c0367ba5 551
46050fe4 552 copy_object (ibfd, obfd);
c0367ba5 553
46050fe4
ILT
554 if (!bfd_close (obfd))
555 {
556 nonfatal (output_filename);
557 }
558
559 if (!bfd_close (ibfd))
560 {
561 nonfatal (input_filename);
562 }
563 }
cef35d48 564 else
46050fe4 565 {
cef35d48 566 bfd_nonfatal (input_filename);
c9563567 567 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
46050fe4 568 {
cef35d48
DM
569 list_matching_formats (matching);
570 free (matching);
46050fe4 571 }
cef35d48 572 status = 1;
46050fe4
ILT
573 }
574}
575
576/* Create a section in OBFD with the same name and attributes
577 as ISECTION in IBFD. */
c0367ba5 578
c0367ba5 579static void
6c7ed084 580setup_section (ibfd, isection, obfdarg)
46050fe4
ILT
581 bfd *ibfd;
582 sec_ptr isection;
6c7ed084 583 PTR obfdarg;
c0367ba5 584{
6c7ed084
ILT
585 bfd *obfd = (bfd *) obfdarg;
586 struct section_list *p;
46050fe4 587 sec_ptr osection;
6c7ed084 588 bfd_vma vma;
46050fe4
ILT
589 char *err;
590
591 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
592 && (strip_symbols == strip_debug
593 || strip_symbols == strip_all
594 || discard_locals == locals_all))
595 return;
596
6c7ed084
ILT
597 for (p = remove_sections; p != NULL; p = p->next)
598 {
599 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
600 {
601 p->used = true;
602 return;
603 }
604 }
605
77ccab3c 606 osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
46050fe4
ILT
607 if (osection == NULL)
608 {
77ccab3c
JL
609 err = "making";
610 goto loser;
c0367ba5
ILT
611 }
612
46050fe4
ILT
613 if (!bfd_set_section_size (obfd,
614 osection,
615 bfd_section_size (ibfd, isection)))
616 {
617 err = "size";
618 goto loser;
c0367ba5
ILT
619 }
620
6c7ed084
ILT
621 vma = bfd_section_vma (ibfd, isection);
622 for (p = adjust_sections; p != NULL; p = p->next)
623 {
624 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
625 {
626 if (p->adjust)
627 vma += p->val;
628 else
629 vma = p->val;
630 p->used = true;
631 break;
632 }
633 }
634 if (p == NULL)
635 vma += adjust_section_vma;
636
637 if (! bfd_set_section_vma (obfd, osection, vma))
46050fe4
ILT
638 {
639 err = "vma";
640 goto loser;
641 }
c0367ba5 642
46050fe4
ILT
643 if (bfd_set_section_alignment (obfd,
644 osection,
645 bfd_section_alignment (ibfd, isection))
646 == false)
647 {
648 err = "alignment";
649 goto loser;
650 }
c0367ba5 651
46050fe4
ILT
652 if (!bfd_set_section_flags (obfd, osection,
653 bfd_get_section_flags (ibfd, isection)))
654 {
655 err = "flags";
656 goto loser;
c0367ba5
ILT
657 }
658
c9563567
JL
659 /* This used to be mangle_section; we do here to avoid using
660 bfd_get_section_by_name since some formats allow multiple
661 sections with the same name. */
662 isection->output_section = osection;
663 isection->output_offset = 0;
664
77ccab3c
JL
665 /* Allow the BFD backend to copy any private data it understands
666 from the input section to the output section. */
667 if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
668 {
669 err = "private data";
670 goto loser;
671 }
672
46050fe4
ILT
673 /* All went well */
674 return;
c0367ba5
ILT
675
676loser:
46050fe4
ILT
677 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
678 program_name,
679 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
c9563567 680 err, bfd_errmsg (bfd_get_error ()));
46050fe4
ILT
681 status = 1;
682}
683
684/* Copy the data of input section ISECTION of IBFD
685 to an output section with the same name in OBFD.
686 If stripping then don't copy any relocation info. */
687
c0367ba5 688static void
6c7ed084 689copy_section (ibfd, isection, obfdarg)
46050fe4
ILT
690 bfd *ibfd;
691 sec_ptr isection;
6c7ed084 692 PTR obfdarg;
c0367ba5 693{
6c7ed084
ILT
694 bfd *obfd = (bfd *) obfdarg;
695 struct section_list *p;
46050fe4 696 arelent **relpp;
ae5d2ff5 697 long relcount;
46050fe4
ILT
698 sec_ptr osection;
699 bfd_size_type size;
700
701 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
702 && (strip_symbols == strip_debug
703 || strip_symbols == strip_all
704 || discard_locals == locals_all))
705 {
706 return;
707 }
c0367ba5 708
6c7ed084
ILT
709 for (p = remove_sections; p != NULL; p = p->next)
710 if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0)
711 return;
712
77ccab3c 713 osection = isection->output_section;
46050fe4 714 size = bfd_get_section_size_before_reloc (isection);
c0367ba5 715
77ccab3c 716 if (size == 0 || osection == 0)
c0367ba5
ILT
717 return;
718
ae5d2ff5
ILT
719 if (strip_symbols == strip_all)
720 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
46050fe4 721 else
c0367ba5 722 {
ae5d2ff5
ILT
723 long relsize;
724
725 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
726 if (relsize < 0)
727 {
728 nonfatal (bfd_get_filename (ibfd));
729 }
730 if (relsize == 0)
731 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
732 else
733 {
734 relpp = (arelent **) xmalloc (relsize);
735 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
736 if (relcount < 0)
737 {
738 nonfatal (bfd_get_filename (ibfd));
739 }
740 bfd_set_reloc (obfd, osection, relpp, relcount);
741 }
c0367ba5
ILT
742 }
743
744 isection->_cooked_size = isection->_raw_size;
46050fe4 745 isection->reloc_done = true;
c0367ba5 746
46050fe4 747 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 748 {
46050fe4 749 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 750
46050fe4
ILT
751 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
752 size))
753 {
754 nonfatal (bfd_get_filename (ibfd));
755 }
c0367ba5 756
6f9077cd
JM
757 if (copy_byte >= 0)
758 {
759 filter_bytes (memhunk, &size);
760 /* The section has gotten smaller. */
761 if (!bfd_set_section_size (obfd, osection, size))
762 nonfatal (bfd_get_filename (obfd));
763 }
f7b839f7 764
46050fe4
ILT
765 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
766 size))
767 {
768 nonfatal (bfd_get_filename (obfd));
769 }
770 free (memhunk);
c0367ba5 771 }
46050fe4 772}
c0367ba5 773
77ccab3c
JL
774/* Mark all the symbols which will be used in output relocations with
775 the BSF_KEEP flag so that those symbols will not be stripped.
776
777 Ignore relocations which will not appear in the output file. */
778
779static void
6c7ed084 780mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
77ccab3c
JL
781 bfd *ibfd;
782 sec_ptr isection;
6c7ed084 783 PTR symbolsarg;
77ccab3c 784{
6c7ed084 785 asymbol **symbols = (asymbol **) symbolsarg;
ae5d2ff5 786 long relsize;
77ccab3c 787 arelent **relpp;
ae5d2ff5 788 long relcount, i;
77ccab3c
JL
789
790 /* Ignore an input section with no corresponding output section. */
791 if (isection->output_section == NULL)
792 return;
793
ae5d2ff5
ILT
794 relsize = bfd_get_reloc_upper_bound (ibfd, isection);
795 if (relsize < 0)
796 bfd_fatal (bfd_get_filename (ibfd));
797
798 relpp = (arelent **) xmalloc (relsize);
77ccab3c 799 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
ae5d2ff5
ILT
800 if (relcount < 0)
801 bfd_fatal (bfd_get_filename (ibfd));
77ccab3c
JL
802
803 /* Examine each symbol used in a relocation. If it's not one of the
804 special bfd section symbols, then mark it with BSF_KEEP. */
805 for (i = 0; i < relcount; i++)
806 {
6c7ed084
ILT
807 if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
808 && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
809 && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
77ccab3c
JL
810 (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
811 }
812
813 if (relpp != NULL)
814 free (relpp);
815}
816
46050fe4
ILT
817/* The number of bytes to copy at once. */
818#define COPY_BUF 8192
819
820/* Copy file FROM to file TO, performing no translations.
821 Return 0 if ok, -1 if error. */
822
823static int
824simple_copy (from, to)
825 char *from, *to;
c0367ba5 826{
46050fe4
ILT
827 int fromfd, tofd, nread;
828 char buf[COPY_BUF];
829
830 fromfd = open (from, O_RDONLY);
831 if (fromfd < 0)
832 return -1;
833 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
834 if (tofd < 0)
835 {
836 close (fromfd);
837 return -1;
838 }
839 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
840 {
841 if (write (tofd, buf, nread) != nread)
842 {
843 close (fromfd);
844 close (tofd);
845 return -1;
846 }
847 }
848 close (fromfd);
849 close (tofd);
850 if (nread < 0)
851 return -1;
852 return 0;
853}
c0367ba5 854
46050fe4
ILT
855#ifndef S_ISLNK
856#ifdef S_IFLNK
857#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
858#else
859#define S_ISLNK(m) 0
860#define lstat stat
861#endif
862#endif
863
864/* Rename FROM to TO, copying if TO is a link.
865 Assumes that TO already exists, because FROM is a temp file.
866 Return 0 if ok, -1 if error. */
867
868static int
869smart_rename (from, to)
870 char *from, *to;
871{
872 struct stat s;
873 int ret = 0;
c0367ba5 874
46050fe4
ILT
875 if (lstat (to, &s))
876 return -1;
c0367ba5 877
46050fe4
ILT
878 /* Use rename only if TO is not a symbolic link and has
879 only one hard link. */
880 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
881 {
882 ret = rename (from, to);
883 if (ret == 0)
884 {
885 /* Try to preserve the permission bits and ownership of TO. */
886 chmod (to, s.st_mode & 07777);
887 chown (to, s.st_uid, s.st_gid);
888 }
889 }
890 else
891 {
892 ret = simple_copy (from, to);
893 if (ret == 0)
894 unlink (from);
895 }
896 return ret;
897}
898
899static int
900strip_main (argc, argv)
901 int argc;
902 char *argv[];
903{
904 char *input_target = NULL, *output_target = NULL;
905 boolean show_version = false;
906 int c, i;
907
6c7ed084 908 while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVv",
46050fe4
ILT
909 strip_options, (int *) 0)) != EOF)
910 {
911 switch (c)
912 {
913 case 'I':
914 input_target = optarg;
704bbd0d 915 break;
46050fe4
ILT
916 case 'O':
917 output_target = optarg;
918 break;
919 case 'F':
920 input_target = output_target = optarg;
921 break;
6c7ed084
ILT
922 case 'R':
923 {
924 struct section_list *n;
925
926 n = (struct section_list *) xmalloc (sizeof (struct section_list));
927 n->name = optarg;
928 n->used = false;
929 n->next = remove_sections;
930 remove_sections = n;
931 }
932 break;
46050fe4 933 case 's':
c0367ba5 934 strip_symbols = strip_all;
46050fe4
ILT
935 break;
936 case 'S':
937 case 'g':
938 strip_symbols = strip_debug;
939 break;
940 case 'x':
941 discard_locals = locals_all;
942 break;
943 case 'X':
944 discard_locals = locals_start_L;
945 break;
946 case 'v':
947 verbose = true;
948 break;
949 case 'V':
950 show_version = true;
951 break;
952 case 0:
953 break; /* we've been given a long option */
954 case 'h':
955 strip_usage (stdout, 0);
956 default:
957 strip_usage (stderr, 1);
958 }
959 }
960
961 if (show_version)
962 {
963 printf ("GNU %s version %s\n", program_name, program_version);
964 exit (0);
965 }
c0367ba5 966
46050fe4
ILT
967 /* Default is to strip all symbols. */
968 if (strip_symbols == strip_undef && discard_locals == locals_undef)
969 strip_symbols = strip_all;
970
971 if (output_target == (char *) NULL)
972 output_target = input_target;
973
974 i = optind;
975 if (i == argc)
976 strip_usage (stderr, 1);
977
978 for (; i < argc; i++)
979 {
980 int hold_status = status;
c0367ba5 981
46050fe4
ILT
982 char *tmpname = make_tempname (argv[i]);
983 status = 0;
984 copy_file (argv[i], tmpname, input_target, output_target);
985 if (status == 0)
986 {
987 smart_rename (tmpname, argv[i]);
988 status = hold_status;
c0367ba5 989 }
46050fe4
ILT
990 else
991 unlink (tmpname);
992 free (tmpname);
993 }
994
995 return 0;
996}
997
998static int
999copy_main (argc, argv)
1000 int argc;
1001 char *argv[];
1002{
6c7ed084 1003 char *input_filename = NULL, *output_filename = NULL;
46050fe4
ILT
1004 char *input_target = NULL, *output_target = NULL;
1005 boolean show_version = false;
6c7ed084 1006 boolean adjust_warn = true;
46050fe4 1007 int c;
6c7ed084 1008 struct section_list *p;
46050fe4 1009
6c7ed084 1010 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVv",
46050fe4
ILT
1011 copy_options, (int *) 0)) != EOF)
1012 {
1013 switch (c)
1014 {
f7b839f7
DM
1015 case 'b':
1016 copy_byte = atoi(optarg);
1017 if (copy_byte < 0)
1018 {
1019 fprintf (stderr, "%s: byte number must be non-negative\n",
1020 program_name);
1021 exit (1);
1022 }
1023 break;
1024 case 'i':
1025 interleave = atoi(optarg);
1026 if (interleave < 1)
1027 {
1028 fprintf(stderr, "%s: interleave must be positive\n",
1029 program_name);
1030 exit (1);
1031 }
1032 break;
c0367ba5 1033 case 'I':
46050fe4 1034 case 's': /* "source" - 'I' is preferred */
c0367ba5 1035 input_target = optarg;
704bbd0d 1036 break;
c0367ba5 1037 case 'O':
46050fe4 1038 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
1039 output_target = optarg;
1040 break;
1041 case 'F':
c0367ba5
ILT
1042 input_target = output_target = optarg;
1043 break;
6c7ed084
ILT
1044 case 'R':
1045 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1046 p->name = optarg;
1047 p->used = false;
1048 p->next = remove_sections;
1049 remove_sections = p;
1050 break;
c0367ba5
ILT
1051 case 'S':
1052 strip_symbols = strip_all;
1053 break;
1054 case 'g':
1055 strip_symbols = strip_debug;
1056 break;
1057 case 'x':
1058 discard_locals = locals_all;
1059 break;
1060 case 'X':
1061 discard_locals = locals_start_L;
1062 break;
1063 case 'v':
1064 verbose = true;
1065 break;
1066 case 'V':
1067 show_version = true;
1068 break;
6c7ed084
ILT
1069 case OPTION_ADJUST_START:
1070 adjust_start = parse_vma (optarg, "--adjust-start");
1071 break;
1072 case OPTION_ADJUST_SECTION_VMA:
1073 {
1074 const char *s;
1075 int len;
1076 char *name;
1077
1078 p = (struct section_list *) xmalloc (sizeof (struct section_list));
1079 s = strchr (optarg, '=');
1080 if (s != NULL)
1081 {
1082 p->adjust = false;
1083 p->val = parse_vma (s + 1, "--adjust-section-vma");
1084 }
1085 else
1086 {
1087 s = strchr (optarg, '+');
1088 if (s == NULL)
1089 {
1090 s = strchr (optarg, '-');
1091 if (s == NULL)
1092 {
1093 fprintf (stderr,
1094 "%s: bad format for --adjust-section-vma\n",
1095 program_name);
1096 exit (1);
1097 }
1098 }
1099 p->adjust = true;
1100 p->val = parse_vma (s + 1, "--adjust-section-vma");
1101 if (*s == '-')
1102 p->val = - p->val;
1103 }
1104
1105 len = s - optarg;
1106 name = (char *) xmalloc (len + 1);
1107 strncpy (name, optarg, len);
1108 name[len] = '\0';
1109 p->name = name;
1110
1111 p->used = false;
1112
1113 p->next = adjust_sections;
1114 adjust_sections = p;
1115 }
1116 break;
1117 case OPTION_ADJUST_VMA:
1118 adjust_section_vma = parse_vma (optarg, "--adjust-vma");
1119 adjust_start = adjust_section_vma;
1120 break;
1121 case OPTION_ADJUST_WARNINGS:
1122 adjust_warn = true;
1123 break;
1124 case OPTION_NO_ADJUST_WARNINGS:
1125 adjust_warn = false;
1126 break;
1127 case OPTION_SET_START:
1128 set_start = parse_vma (optarg, "--set-start");
1129 set_start_set = true;
1130 break;
46050fe4 1131 case 0:
c0367ba5
ILT
1132 break; /* we've been given a long option */
1133 case 'h':
1134 copy_usage (stdout, 0);
1135 default:
1136 copy_usage (stderr, 1);
46050fe4
ILT
1137 }
1138 }
1139
1140 if (show_version)
1141 {
1142 printf ("GNU %s version %s\n", program_name, program_version);
1143 exit (0);
1144 }
c0367ba5 1145
f7b839f7
DM
1146 if (copy_byte >= interleave)
1147 {
1148 fprintf (stderr, "%s: byte number must be less than interleave\n",
1149 program_name);
1150 exit (1);
1151 }
1152
46050fe4
ILT
1153 if (optind == argc || optind + 2 < argc)
1154 copy_usage (stderr, 1);
c0367ba5
ILT
1155
1156 input_filename = argv[optind];
1157 if (optind + 1 < argc)
46050fe4 1158 output_filename = argv[optind + 1];
c0367ba5
ILT
1159
1160 /* Default is to strip no symbols. */
1161 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 1162 strip_symbols = strip_none;
c0367ba5
ILT
1163
1164 if (output_target == (char *) NULL)
1165 output_target = input_target;
1166
46050fe4
ILT
1167 /* If there is no destination file then create a temp and rename
1168 the result into the input. */
1169
1170 if (output_filename == (char *) NULL)
1171 {
1172 char *tmpname = make_tempname (input_filename);
1173 copy_file (input_filename, tmpname, input_target, output_target);
1174 if (status == 0)
1175 smart_rename (tmpname, input_filename);
1176 else
1177 unlink (tmpname);
1178 }
1179 else
1180 {
1181 copy_file (input_filename, output_filename, input_target, output_target);
1182 }
1183
6c7ed084
ILT
1184 if (adjust_warn)
1185 {
1186 for (p = adjust_sections; p != NULL; p = p->next)
1187 {
1188 if (! p->used)
1189 {
1190 fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x",
1191 program_name, p->name,
1192 p->adjust ? '=' : '+');
1193 fprintf_vma (stderr, p->val);
1194 fprintf (stderr, " never used\n");
1195 }
1196 }
1197 }
1198
1199 /* We could issue similar warnings for remove_sections, but I don't
1200 think that would be as useful. */
1201
c0367ba5
ILT
1202 return 0;
1203}
46050fe4
ILT
1204
1205int
1206main (argc, argv)
1207 int argc;
1208 char *argv[];
1209{
1210 program_name = argv[0];
704bbd0d 1211 xmalloc_set_program_name (program_name);
46050fe4
ILT
1212 strip_symbols = strip_undef;
1213 discard_locals = locals_undef;
1214
1215 bfd_init ();
1216
1217 if (is_strip < 0)
1218 {
1219 int i = strlen (program_name);
1220 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
1221 }
1222
1223 if (is_strip)
1224 strip_main (argc, argv);
1225 else
1226 copy_main (argc, argv);
1227
1228 return status;
1229}
This page took 0.109772 seconds and 4 git commands to generate.