X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=abcf6a3aad97af66a75fe8ee3d4d0b1a4decf5eb;hb=43a0748c7811bf542e8a9f020292a991db0bfa1a;hp=f2455baf650f562f9fb1639f76dae937acda459c;hpb=3994e2c66d792e3ea0f48d1cf039a022a62960bb;p=binutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index f2455baf650..abcf6a3aad9 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1,5 +1,5 @@ /* objcopy.c -- copy object file from input to output, optionally massaging it. - Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -25,6 +25,7 @@ #include "getopt.h" #include "libiberty.h" #include "budbg.h" +#include "filenames.h" #include /* A list of symbols to explicitly strip out, or to keep. A linked @@ -38,6 +39,14 @@ struct symlist struct symlist *next; }; +/* A list to support redefine_sym. */ +struct redefine_node +{ + char *source; + char *target; + struct redefine_node *next; +}; + static void copy_usage PARAMS ((FILE *, int)); static void strip_usage PARAMS ((FILE *, int)); static flagword parse_flags PARAMS ((const char *)); @@ -60,6 +69,8 @@ static void copy_file PARAMS ((const char *, const char *, const char *, const char *)); static int strip_main PARAMS ((int, char **)); static int copy_main PARAMS ((int, char **)); +static const char *lookup_sym_redefinition PARAMS((const char *)); +static void redefine_list_append PARAMS ((const char *, const char *)); #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;} @@ -172,12 +183,13 @@ static boolean change_leading_char = false; static boolean remove_leading_char = false; -/* List of symbols to strip, keep, localize, and weaken. */ +/* List of symbols to strip, keep, localize, weaken, or redefine. */ static struct symlist *strip_specific_list = NULL; static struct symlist *keep_specific_list = NULL; static struct symlist *localize_specific_list = NULL; static struct symlist *weaken_specific_list = NULL; +static struct redefine_node *redefine_sym_list = NULL; /* If this is true, we weaken global symbols (set BSF_WEAK). */ @@ -202,6 +214,9 @@ static boolean weaken = false; #define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1) #define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1) #define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1) +#define OPTION_REDEFINE_SYM (OPTION_WEAKEN + 1) +#define OPTION_SREC_LEN (OPTION_REDEFINE_SYM + 1) +#define OPTION_SREC_FORCES3 (OPTION_SREC_LEN + 1) /* Options to handle if running as "strip". */ @@ -237,6 +252,7 @@ static struct option copy_options[] = {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES}, {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS}, {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS}, + {"binary-architecture", required_argument, 0, 'B'}, {"byte", required_argument, 0, 'b'}, {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES}, {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR}, @@ -276,6 +292,9 @@ static struct option copy_options[] = {"version", no_argument, 0, 'V'}, {"weaken", no_argument, 0, OPTION_WEAKEN}, {"weaken-symbol", required_argument, 0, 'W'}, + {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM}, + {"srec-len", required_argument, 0, OPTION_SREC_LEN}, + {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3}, {0, no_argument, 0, 0} }; @@ -287,40 +306,76 @@ extern char *program_name; -1 means if we should use argv[0] to decide. */ extern int is_strip; +/* The maximum length of an S record. This variable is declared in srec.c + and can be modified by the --srec-len parameter. */ +extern unsigned int Chunk; + +/* Restrict the generation of Srecords to type S3 only. + This variable is declare in bfd/srec.c and can be toggled + on by the --srec-forceS3 command line switch. */ +extern boolean S3Forced; + +/* Defined in bfd/binary.c. Used to set architecture of input binary files. */ +extern enum bfd_architecture bfd_external_binary_architecture; static void copy_usage (stream, exit_status) FILE *stream; int exit_status; { + fprintf (stream, _("Usage: %s in-file [out-file]\n"), program_name); + fprintf (stream, _(" The switches are:\n")); fprintf (stream, _("\ -Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\ - [-j section] [-R section]\n\ - [-i interleave] [--interleave=interleave] [--byte=byte]\n\ - [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ - [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ - [--discard-locals] [--debugging]\n\ - [--only-section=section] [--remove-section=section]\n"), - program_name); - fprintf (stream, _("\ - [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n\ - [--set-start=val] \n\ - [--change-start=incr] [--change-addresses=incr] \n\ - (--adjust-start and --adjust-vma are aliases for these two) \n\ - [--change-section-address=section{=,+,-}val]\n\ - (--adjust-section-vma is an alias for --change-section-address)\n\ - [--change-section-lma=section{=,+,-}val]\n\ - [--change-section-vma=section{=,+,-}val]\n\ - [--adjust-warnings] [--no-adjust-warnings]\n\ - [--change-warnings] [--no-change-warnings]\n\ - [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\ - [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\ - [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n\ - [-W symbol] [--change-leading-char] [--remove-leading-char] [--weaken]\n\ - [--verbose] [--version] [--help] in-file [out-file]\n")); + -I --input-target Assume input file is in format \n\ + -O --output-target Create an output file in format \n\ + -B --binary-architecture Set arch of output file, when input is binary\n\ + -F --target Set both input and output format to \n\ + --debugging Convert debugging information, if possible\n\ + -p --preserve-dates Copy modified/access timestamps to the output\n\ + -j --only-section Only copy section into the output\n\ + -R --remove-section Remove section from the output\n\ + -S --strip-all Remove all symbol and relocation information\n\ + -g --strip-debug Remove all debugging symbols\n\ + --strip-unneeded Remove all symbols not needed by relocations\n\ + -N --strip-symbol Do not copy symbol \n\ + -K --keep-symbol Only copy symbol \n\ + -L --localize-symbol Force symbol to be marked as a local\n\ + -W --weaken-symbol Force symbol to be marked as a weak\n\ + --weaken Force all global symbols to be marked as weak\n\ + -x --discard-all Remove all non-global symbols\n\ + -X --discard-locals Remove any compiler-generated symbols\n\ + -i --interleave Only copy one out of every bytes\n\ + -b --byte Select byte in every interleaved block\n\ + --gap-fill Fill gaps between sections with \n\ + --pad-to Pad the last section up to address \n\ + --set-start Set the start address to \n\ + {--change-start|--adjust-start} \n\ + Add to the start address\n\ + {--change-addresses|--adjust-vma} \n\ + Add to LMA, VMA and start addresses\n\ + {--change-section-address|--adjust-section-vma} {=|+|-}\n\ + Change LMA and VMA of section by \n\ + --change-section-lma {=|+|-}\n\ + Change the LMA of section by \n\ + --change-section-vma {=|+|-}\n\ + Change the VMA of section by \n\ + {--[no-]change-warnings|--[no-]adjust-warnings}\n\ + Warn if a named section does not exist\n\ + --set-section-flags =\n\ + Set section 's properties to \n\ + --add-section = Add section found in to output\n\ + --change-leading-char Force output format's leading character style\n\ + --remove-leading-char Remove leading character from global symbols\n\ + --redefine-sym = Redefine symbol name to \n\ + --srec-len Restrict the length of generated Srecords\n\ + --srec-forceS3 Restrict the type of generated Srecords to S3\n\ + -v --verbose List all object files modified\n\ + -V --version Display this program's version number\n\ + -h --help Display this output\n\ +")); list_supported_targets (program_name, stream); if (exit_status == 0) - fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (exit_status); } @@ -329,17 +384,30 @@ strip_usage (stream, exit_status) FILE *stream; int exit_status; { + fprintf (stream, _("Usage: %s in-file(s)\n"), program_name); + fprintf (stream, _(" The switches are:\n")); fprintf (stream, _("\ -Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\ - [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ - [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ - [--discard-locals] [--keep-symbol symbol] [-K symbol]\n\ - [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\ - [-o file] [--preserve-dates] [--verbose] [--version] [--help] file...\n"), - program_name); + -I --input-target Assume input file is in format \n\ + -O --output-target Create an output file in format \n\ + -F --target Set both input and output format to \n\ + -p --preserve-dates Copy modified/access timestamps to the output\n\ + -R --remove-section Remove section from the output\n\ + -s --strip-all Remove all symbol and relocation information\n\ + -g -S --strip-debug Remove all debugging symbols\n\ + --strip-unneeded Remove all symbols not needed by relocations\n\ + -N --strip-symbol Do not copy symbol \n\ + -K --keep-symbol Only copy symbol \n\ + -x --discard-all Remove all non-global symbols\n\ + -X --discard-locals Remove any compiler-generated symbols\n\ + -v --verbose List all object files modified\n\ + -V --version Display this program's version number\n\ + -h --help Display this output\n\ + -o Place stripped output into \n\ +")); + list_supported_targets (program_name, stream); if (exit_status == 0) - fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (exit_status); } @@ -389,7 +457,8 @@ parse_flags (s) strncpy (copy, s, len); copy[len] = '\0'; non_fatal (_("unrecognized section flag `%s'"), copy); - fatal (_("supported flags: alloc, load, noload, readonly, debug, code, data, rom, share, contents")); + fatal (_("supported flags: %s"), + "alloc, load, noload, readonly, debug, code, data, rom, share, contents"); } s = snext; @@ -435,7 +504,7 @@ find_section_list (name, add) /* Add a symbol to strip_specific_list. */ -static void +static void add_specific_symbol (name, list) const char *name; struct symlist **list; @@ -507,6 +576,8 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) { register asymbol **from = isyms, **to = osyms; long src_count = 0, dst_count = 0; + int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) + == HAS_RELOC; for (; src_count < symcount; src_count++) { @@ -515,6 +586,15 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) const char *name = bfd_asymbol_name (sym); int keep; + if (redefine_sym_list) + { + const char *old_name, *new_name; + + old_name = bfd_asymbol_name (sym); + new_name = lookup_sym_redefinition (old_name); + name = bfd_asymbol_name (sym) = new_name; + } + if (change_leading_char && (bfd_get_symbol_leading_char (abfd) != bfd_get_symbol_leading_char (obfd)) @@ -552,6 +632,9 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags & BSF_KEEP) != 0)) keep = 1; + else if (relocatable /* Relocatable file. */ + && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0) + keep = 1; else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ || (flags & BSF_WEAK) != 0 || bfd_is_und_section (bfd_get_section (sym)) @@ -596,6 +679,64 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) return dst_count; } +static const char * +lookup_sym_redefinition (source) + const char *source; +{ + const char *result; + struct redefine_node *list; + + result = source; + + for (list = redefine_sym_list; list != NULL; list = list->next) + { + if (strcmp (source, list->source) == 0) + { + result = list->target; + break; + } + } + return result; +} + +/* Add a node to a symbol redefine list */ + +static void +redefine_list_append (source, target) + const char *source; + const char *target; +{ + struct redefine_node **p; + struct redefine_node *list; + struct redefine_node *new_node; + + for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next) + { + if (strcmp (source, list->source) == 0) + { + fatal (_("%s: Multiple redefinition of symbol \"%s\""), + "--redefine-sym", + source); + } + + if (strcmp (target, list->target) == 0) + { + fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"), + "--redefine-sym", + target); + } + } + + new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node)); + + new_node->source = strdup (source); + new_node->target = strdup (target); + new_node->next = NULL; + + *p = new_node; +} + + /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long. Adjust *SIZE. */ @@ -629,6 +770,13 @@ copy_object (ibfd, obfd) long symsize; PTR dhandle; + if (ibfd->xvec->byteorder != obfd->xvec->byteorder + && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN + && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) + { + fatal (_("Unable to change endianness of input file(s)")); + return; + } if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (obfd)); @@ -656,13 +804,13 @@ copy_object (ibfd, obfd) non_fatal (_("Warning: Output file cannot represent architecture %s"), bfd_printable_arch_mach (bfd_get_arch (ibfd), bfd_get_mach (ibfd))); - + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (ibfd)); if (isympp) free (isympp); - + if (osympp != isympp) free (osympp); @@ -688,7 +836,7 @@ copy_object (ibfd, obfd) else { flagword flags; - + if (! bfd_set_section_size (obfd, padd->section, padd->size)) RETURN_NONFATAL (bfd_get_filename (obfd)); @@ -700,7 +848,7 @@ copy_object (ibfd, obfd) flags = pset->flags | SEC_HAS_CONTENTS; else flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; - + if (! bfd_set_section_flags (obfd, padd->section, flags)) RETURN_NONFATAL (bfd_get_filename (obfd)); @@ -709,11 +857,11 @@ copy_object (ibfd, obfd) if (pset->change_vma != CHANGE_IGNORE) if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val)) RETURN_NONFATAL (bfd_get_filename (obfd)); - + if (pset->change_lma != CHANGE_IGNORE) { padd->section->lma = pset->lma_val; - + if (! bfd_set_section_alignment (obfd, padd->section, bfd_section_alignment (obfd, padd->section))) @@ -812,16 +960,16 @@ copy_object (ibfd, obfd) symsize = bfd_get_symtab_upper_bound (ibfd); if (symsize < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + osympp = isympp = (asymbol **) xmalloc (symsize); symcount = bfd_canonicalize_symtab (ibfd, isympp); if (symcount < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (convert_debugging) dhandle = read_debugging_info (ibfd, isympp, symcount); - - if (strip_symbols == STRIP_DEBUG + + if (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_ALL || strip_symbols == STRIP_UNNEEDED || discard_locals != LOCALS_UNDEF @@ -834,11 +982,12 @@ copy_object (ibfd, obfd) || convert_debugging || change_leading_char || remove_leading_char + || redefine_sym_list || weaken) { /* Mark symbols used in output relocations so that they are kept, even if they are local labels or static symbols. - + Note we iterate over the input sections examining their relocations since the relocations for the output sections haven't been set yet. mark_symbols_used_in_relocations will @@ -1101,13 +1250,13 @@ copy_file (input_filename, output_filename, input_target, output_target) else { bfd_nonfatal (input_filename); - + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } - + status = 1; } } @@ -1128,7 +1277,7 @@ setup_section (ibfd, isection, obfdarg) bfd_vma vma; bfd_vma lma; flagword flags; - char *err; + const char *err; if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 && (strip_symbols == STRIP_DEBUG @@ -1148,10 +1297,10 @@ setup_section (ibfd, isection, obfdarg) return; osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection)); - + if (osection == NULL) { - err = "making"; + err = _("making"); goto loser; } @@ -1160,10 +1309,10 @@ setup_section (ibfd, isection, obfdarg) size = (size + interleave - 1) / interleave; if (! bfd_set_section_size (obfd, osection, size)) { - err = "size"; + err = _("size"); goto loser; } - + vma = bfd_section_vma (ibfd, isection); if (p != NULL && p->change_vma == CHANGE_MODIFY) vma += p->vma_val; @@ -1171,10 +1320,10 @@ setup_section (ibfd, isection, obfdarg) vma = p->vma_val; else vma += change_section_address; - + if (! bfd_set_section_vma (obfd, osection, vma)) { - err = "vma"; + err = _("vma"); goto loser; } @@ -1190,7 +1339,7 @@ setup_section (ibfd, isection, obfdarg) } else lma += change_section_address; - + osection->lma = lma; /* FIXME: This is probably not enough. If we change the LMA we @@ -1200,7 +1349,7 @@ setup_section (ibfd, isection, obfdarg) bfd_section_alignment (ibfd, isection)) == false) { - err = "alignment"; + err = _("alignment"); goto loser; } @@ -1209,7 +1358,7 @@ setup_section (ibfd, isection, obfdarg) flags = p->flags | (flags & SEC_HAS_CONTENTS); if (!bfd_set_section_flags (obfd, osection, flags)) { - err = "flags"; + err = _("flags"); goto loser; } @@ -1223,7 +1372,7 @@ setup_section (ibfd, isection, obfdarg) from the input section to the output section. */ if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) { - err = "private data"; + err = _("private data"); goto loser; } @@ -1260,7 +1409,7 @@ copy_section (ibfd, isection, obfdarg) complaints now. */ if (status != 0) return; - + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 && (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_UNNEEDED @@ -1288,7 +1437,7 @@ copy_section (ibfd, isection, obfdarg) relsize = bfd_get_reloc_upper_bound (ibfd, isection); if (relsize < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (relsize == 0) bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); else @@ -1297,7 +1446,7 @@ copy_section (ibfd, isection, obfdarg) relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp); if (relcount < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (strip_symbols == STRIP_ALL) { /* Remove relocations which are not in @@ -1305,7 +1454,7 @@ copy_section (ibfd, isection, obfdarg) arelent **temp_relpp; long temp_relcount = 0; long i; - + temp_relpp = (arelent **) xmalloc (relsize); for (i = 0; i < relcount; i++) if (is_specified_symbol @@ -1319,7 +1468,7 @@ copy_section (ibfd, isection, obfdarg) bfd_set_reloc (obfd, osection, (relcount == 0 ? (arelent **) NULL : relpp), relcount); } - + isection->_cooked_size = isection->_raw_size; isection->reloc_done = true; @@ -1331,7 +1480,7 @@ copy_section (ibfd, isection, obfdarg) size)) RETURN_NONFATAL (bfd_get_filename (ibfd)); - if (copy_byte >= 0) + if (copy_byte >= 0) filter_bytes (memhunk, &size); if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, @@ -1545,7 +1694,7 @@ strip_main (argc, argv) struct section_list *p; char *output_file = NULL; - while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpgxXVv", + while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXVv", strip_options, (int *) 0)) != EOF) { switch (c) @@ -1569,6 +1718,7 @@ strip_main (argc, argv) break; case 'S': case 'g': + case 'd': /* Historic BSD alias for -g. Used by early NetBSD. */ strip_symbols = STRIP_DEBUG; break; case OPTION_STRIP_UNNEEDED: @@ -1668,6 +1818,7 @@ copy_main (argc, argv) int argc; char *argv[]; { + char * binary_architecture = NULL; char *input_filename = NULL, *output_filename = NULL; char *input_target = NULL, *output_target = NULL; boolean show_version = false; @@ -1676,7 +1827,7 @@ copy_main (argc, argv) struct section_list *p; struct stat statbuf; - while ((c = getopt_long (argc, argv, "b:i:I:j:K:N:s:O:d:F:L:R:SpgxXVvW:", + while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:R:SpgxXVvW:", copy_options, (int *) 0)) != EOF) { switch (c) @@ -1686,22 +1837,31 @@ copy_main (argc, argv) if (copy_byte < 0) fatal (_("byte number must be non-negative")); break; + + case 'B': + binary_architecture = optarg; + break; + case 'i': interleave = atoi (optarg); if (interleave < 1) fatal (_("interleave must be positive")); break; + case 'I': case 's': /* "source" - 'I' is preferred */ input_target = optarg; break; + case 'O': case 'd': /* "destination" - 'O' is preferred */ output_target = optarg; break; + case 'F': input_target = output_target = optarg; break; + case 'j': p = find_section_list (optarg, true); if (p->remove) @@ -1709,6 +1869,7 @@ copy_main (argc, argv) p->copy = true; sections_copied = true; break; + case 'R': p = find_section_list (optarg, true); if (p->copy) @@ -1716,45 +1877,59 @@ copy_main (argc, argv) p->remove = true; sections_removed = true; break; + case 'S': strip_symbols = STRIP_ALL; break; + case 'g': strip_symbols = STRIP_DEBUG; break; + case OPTION_STRIP_UNNEEDED: strip_symbols = STRIP_UNNEEDED; break; + case 'K': add_specific_symbol (optarg, &keep_specific_list); break; + case 'N': add_specific_symbol (optarg, &strip_specific_list); break; + case 'L': add_specific_symbol (optarg, &localize_specific_list); break; + case 'W': add_specific_symbol (optarg, &weaken_specific_list); break; + case 'p': preserve_dates = true; break; + case 'x': discard_locals = LOCALS_ALL; break; + case 'X': discard_locals = LOCALS_START_L; break; + case 'v': verbose = true; break; + case 'V': show_version = true; break; + case OPTION_WEAKEN: weaken = true; break; + case OPTION_ADD_SECTION: { const char *s; @@ -1765,9 +1940,9 @@ copy_main (argc, argv) FILE *f; s = strchr (optarg, '='); - + if (s == NULL) - fatal (_("bad format for --add-section NAME=FILENAME")); + fatal (_("bad format for %s"), "--add-section"); if (stat (s + 1, & st) < 0) fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno)); @@ -1786,10 +1961,10 @@ copy_main (argc, argv) pa->contents = (bfd_byte *) xmalloc (pa->size); f = fopen (pa->filename, FOPEN_RB); - + if (f == NULL) fatal (_("cannot open: %s: %s"), pa->filename, strerror (errno)); - + if (fread (pa->contents, 1, pa->size, f) == 0 || ferror (f)) fatal (_("%s: fread failed"), pa->filename); @@ -1800,9 +1975,11 @@ copy_main (argc, argv) add_sections = pa; } break; + case OPTION_CHANGE_START: change_start = parse_vma (optarg, "--change-start"); break; + case OPTION_CHANGE_SECTION_ADDRESS: case OPTION_CHANGE_SECTION_LMA: case OPTION_CHANGE_SECTION_VMA: @@ -1813,7 +1990,7 @@ copy_main (argc, argv) char *option = NULL; bfd_vma val; enum change_action what = CHANGE_IGNORE; - + switch (c) { case OPTION_CHANGE_SECTION_ADDRESS: @@ -1826,7 +2003,7 @@ copy_main (argc, argv) option = "--change-section-vma"; break; } - + s = strchr (optarg, '='); if (s == NULL) { @@ -1854,19 +2031,19 @@ copy_main (argc, argv) case '-': val = - val; /* Drop through. */ case '+': what = CHANGE_MODIFY; break; } - + switch (c) { case OPTION_CHANGE_SECTION_ADDRESS: p->change_vma = what; p->vma_val = val; /* Drop through. */ - + case OPTION_CHANGE_SECTION_LMA: p->change_lma = what; p->lma_val = val; break; - + case OPTION_CHANGE_SECTION_VMA: p->change_vma = what; p->vma_val = val; @@ -1874,19 +2051,24 @@ copy_main (argc, argv) } } break; + case OPTION_CHANGE_ADDRESSES: change_section_address = parse_vma (optarg, "--change-addresses"); change_start = change_section_address; break; + case OPTION_CHANGE_WARNINGS: change_warn = true; break; + case OPTION_CHANGE_LEADING_CHAR: change_leading_char = true; break; + case OPTION_DEBUGGING: convert_debugging = true; break; + case OPTION_GAP_FILL: { bfd_vma gap_fill_vma; @@ -1896,25 +2078,61 @@ copy_main (argc, argv) if ((bfd_vma) gap_fill != gap_fill_vma) { char buff[20]; - + sprintf_vma (buff, gap_fill_vma); - + non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"), buff, gap_fill); } gap_fill_set = true; } break; + case OPTION_NO_CHANGE_WARNINGS: change_warn = false; break; + case OPTION_PAD_TO: pad_to = parse_vma (optarg, "--pad-to"); pad_to_set = true; break; + case OPTION_REMOVE_LEADING_CHAR: remove_leading_char = true; break; + + case OPTION_REDEFINE_SYM: + { + /* Push this redefinition onto redefine_symbol_list. */ + + int len; + const char *s; + const char *nextarg; + char *source, *target; + + s = strchr (optarg, '='); + if (s == NULL) + { + fatal (_("bad format for %s"), "--redefine-sym"); + } + + len = s - optarg; + source = (char *) xmalloc (len + 1); + strncpy (source, optarg, len); + source[len] = '\0'; + + nextarg = s + 1; + len = strlen (nextarg); + target = (char *) xmalloc (len + 1); + strcpy (target, nextarg); + + redefine_list_append (source, target); + + free (source); + free (target); + } + break; + case OPTION_SET_SECTION_FLAGS: { const char *s; @@ -1923,7 +2141,7 @@ copy_main (argc, argv) s = strchr (optarg, '='); if (s == NULL) - fatal (_("bad format for --set-section-flags")); + fatal (_("bad format for %s"), "--set-section-flags"); len = s - optarg; name = (char *) xmalloc (len + 1); @@ -1936,14 +2154,26 @@ copy_main (argc, argv) p->flags = parse_flags (s + 1); } break; + case OPTION_SET_START: set_start = parse_vma (optarg, "--set-start"); set_start_set = true; break; + + case OPTION_SREC_LEN: + Chunk = parse_vma (optarg, "--srec-len"); + break; + + case OPTION_SREC_FORCES3: + S3Forced = true; + break; + case 0: break; /* we've been given a long option */ + case 'h': copy_usage (stdout, 0); + default: copy_usage (stderr, 1); } @@ -1969,12 +2199,30 @@ copy_main (argc, argv) if (output_target == (char *) NULL) output_target = input_target; - if (preserve_dates) + if (binary_architecture != (char *) NULL) { - if (stat (input_filename, &statbuf) < 0) - fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno)); + if (input_target && strcmp (input_target, "binary") == 0) + { + const bfd_arch_info_type * temp_arch_info; + + temp_arch_info = bfd_scan_arch (binary_architecture); + + if (temp_arch_info != NULL) + bfd_external_binary_architecture = temp_arch_info->arch; + else + fatal (_("architecture %s unknown"), binary_architecture); + } + else + { + non_fatal (_("Warning: input target 'binary' required for binary architecture parameter.")); + non_fatal (_(" Argument %s ignored"), binary_architecture); + } } + if (preserve_dates) + if (stat (input_filename, & statbuf) < 0) + fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno)); + /* If there is no destination file then create a temp and rename the result into the input. */ @@ -1984,7 +2232,7 @@ copy_main (argc, argv) copy_file (input_filename, tmpname, input_target, output_target); if (status == 0) - { + { if (preserve_dates) set_times (tmpname, &statbuf); smart_rename (tmpname, input_filename, preserve_dates); @@ -2010,22 +2258,24 @@ copy_main (argc, argv) char buff [20]; sprintf_vma (buff, p->vma_val); - + /* xgettext:c-format */ - non_fatal (_("Warning: --change-section-vma %s%c0x%s never used"), + non_fatal (_("%s %s%c0x%s never used"), + "--change-section-vma", p->name, p->change_vma == CHANGE_SET ? '=' : '+', buff); } - + if (p->change_lma != CHANGE_IGNORE) { char buff [20]; sprintf_vma (buff, p->lma_val); - + /* xgettext:c-format */ - non_fatal (_("Warning: --change-section-lma %s%c0x%s never used"), + non_fatal (_("%s %s%c0x%s never used"), + "--change-section-lma", p->name, p->change_lma == CHANGE_SET ? '=' : '+', buff); @@ -2062,7 +2312,15 @@ main (argc, argv) if (is_strip < 0) { int i = strlen (program_name); - is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0); +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + /* Drop the .exe suffix, if any. */ + if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0) + { + i -= 4; + program_name[i] = '\0'; + } +#endif + is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0); } if (is_strip)