Add --binary-architecture switch to objcopy to allow the output architecture
[binutils-gdb.git] / binutils / objcopy.c
index f2455baf650f562f9fb1639f76dae937acda459c..abcf6a3aad97af66a75fe8ee3d4d0b1a4decf5eb 100644 (file)
@@ -1,5 +1,5 @@
 /* objcopy.c -- copy object file from input to output, optionally massaging it.
 /* 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.
    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 "getopt.h"
 #include "libiberty.h"
 #include "budbg.h"
+#include "filenames.h"
 #include <sys/stat.h>
 
 /* A list of symbols to explicitly strip out, or to keep.  A linked
 #include <sys/stat.h>
 
 /* A list of symbols to explicitly strip out, or to keep.  A linked
@@ -38,6 +39,14 @@ struct symlist
   struct symlist *next;
 };
 
   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 *));
 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 **));
   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;}
 
 
 #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;
 
 
 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 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).  */
 
 
 /* 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_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".  */
 
 
 /* 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},
   {"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},
   {"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'},
   {"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}
 };
 
   {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;
 
    -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;
 {
 
 static void
 copy_usage (stream, exit_status)
      FILE *stream;
      int exit_status;
 {
+  fprintf (stream, _("Usage: %s <switches> in-file [out-file]\n"), program_name);
+  fprintf (stream, _(" The switches are:\n"));
   fprintf (stream, _("\
   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 <bfdname>      Assume input file is in format <bfdname>\n\
+  -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
+  -B --binary-architecture <arch>  Set arch of output file, when input is binary\n\
+  -F --target <bfdname>            Set both input and output format to <bfdname>\n\
+     --debugging                   Convert debugging information, if possible\n\
+  -p --preserve-dates              Copy modified/access timestamps to the output\n\
+  -j --only-section <name>         Only copy section <name> into the output\n\
+  -R --remove-section <name>       Remove section <name> 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 <name>         Do not copy symbol <name>\n\
+  -K --keep-symbol <name>          Only copy symbol <name>\n\
+  -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
+  -W --weaken-symbol <name>        Force symbol <name> 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 <number>         Only copy one out of every <number> bytes\n\
+  -b --byte <num>                  Select byte <num> in every interleaved block\n\
+     --gap-fill <val>              Fill gaps between sections with <val>\n\
+     --pad-to <addr>               Pad the last section up to address <addr>\n\
+     --set-start <addr>            Set the start address to <addr>\n\
+    {--change-start|--adjust-start} <incr>\n\
+                                   Add <incr> to the start address\n\
+    {--change-addresses|--adjust-vma} <incr>\n\
+                                   Add <incr> to LMA, VMA and start addresses\n\
+    {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\
+                                   Change LMA and VMA of section <name> by <val>\n\
+     --change-section-lma <name>{=|+|-}<val>\n\
+                                   Change the LMA of section <name> by <val>\n\
+     --change-section-vma <name>{=|+|-}<val>\n\
+                                   Change the VMA of section <name> by <val>\n\
+    {--[no-]change-warnings|--[no-]adjust-warnings}\n\
+                                   Warn if a named section does not exist\n\
+     --set-section-flags <name>=<flags>\n\
+                                   Set section <name>'s properties to <flags>\n\
+     --add-section <name>=<file>   Add section <name> found in <file> 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 <old>=<new>    Redefine symbol name <old> to <new>\n\
+     --srec-len <number>           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)
   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);
 }
 
   exit (exit_status);
 }
 
@@ -329,17 +384,30 @@ strip_usage (stream, exit_status)
      FILE *stream;
      int exit_status;
 {
      FILE *stream;
      int exit_status;
 {
+  fprintf (stream, _("Usage: %s <switches> in-file(s)\n"), program_name);
+  fprintf (stream, _(" The switches are:\n"));
   fprintf (stream, _("\
   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 <bfdname>      Assume input file is in format <bfdname>\n\
+  -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
+  -F --target <bfdname>            Set both input and output format to <bfdname>\n\
+  -p --preserve-dates              Copy modified/access timestamps to the output\n\
+  -R --remove-section <name>       Remove section <name> 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 <name>         Do not copy symbol <name>\n\
+  -K --keep-symbol <name>          Only copy symbol <name>\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 <file>                        Place stripped output into <file>\n\
+"));
+
   list_supported_targets (program_name, stream);
   if (exit_status == 0)
   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);
 }
 
   exit (exit_status);
 }
 
@@ -389,7 +457,8 @@ parse_flags (s)
          strncpy (copy, s, len);
          copy[len] = '\0';
          non_fatal (_("unrecognized section flag `%s'"), copy);
          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;
        }
 
       s = snext;
@@ -435,7 +504,7 @@ find_section_list (name, add)
 
 /* Add a symbol to strip_specific_list.  */
 
 
 /* Add a symbol to strip_specific_list.  */
 
-static void 
+static void
 add_specific_symbol (name, list)
      const char *name;
      struct symlist **list;
 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;
 {
   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++)
     {
 
   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;
 
       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))
       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;
                   && ((*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))
       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;
 }
 
   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.  */
 
 /* 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;
 
   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));
 
   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)));
     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 (!bfd_set_format (obfd, bfd_get_format (ibfd)))
     RETURN_NONFATAL (bfd_get_filename (ibfd));
 
   if (isympp)
     free (isympp);
-  
+
   if (osympp != isympp)
     free (osympp);
 
   if (osympp != isympp)
     free (osympp);
 
@@ -688,7 +836,7 @@ copy_object (ibfd, obfd)
          else
            {
              flagword flags;
          else
            {
              flagword flags;
-             
+
              if (! bfd_set_section_size (obfd, padd->section, padd->size))
                RETURN_NONFATAL (bfd_get_filename (obfd));
 
              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;
                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));
 
              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_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 (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)))
                      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));
   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));
   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 (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
       || 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
       || 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.
       || 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
         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);
   else
     {
       bfd_nonfatal (input_filename);
-      
+
       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
        {
          list_matching_formats (matching);
          free (matching);
        }
       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
        {
          list_matching_formats (matching);
          free (matching);
        }
-      
+
       status = 1;
     }
 }
       status = 1;
     }
 }
@@ -1128,7 +1277,7 @@ setup_section (ibfd, isection, obfdarg)
   bfd_vma vma;
   bfd_vma lma;
   flagword flags;
   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
 
   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));
     return;
 
   osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
-  
+
   if (osection == NULL)
     {
   if (osection == NULL)
     {
-      err = "making";
+      err = _("making");
       goto loser;
     }
 
       goto loser;
     }
 
@@ -1160,10 +1309,10 @@ setup_section (ibfd, isection, obfdarg)
     size = (size + interleave - 1) / interleave;
   if (! bfd_set_section_size (obfd, osection, size))
     {
     size = (size + interleave - 1) / interleave;
   if (! bfd_set_section_size (obfd, osection, size))
     {
-      err = "size";
+      err = _("size");
       goto loser;
     }
       goto loser;
     }
-  
+
   vma = bfd_section_vma (ibfd, isection);
   if (p != NULL && p->change_vma == CHANGE_MODIFY)
     vma += p->vma_val;
   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;
     vma = p->vma_val;
   else
     vma += change_section_address;
-  
+
   if (! bfd_set_section_vma (obfd, osection, vma))
     {
   if (! bfd_set_section_vma (obfd, osection, vma))
     {
-      err = "vma";
+      err = _("vma");
       goto loser;
     }
 
       goto loser;
     }
 
@@ -1190,7 +1339,7 @@ setup_section (ibfd, isection, obfdarg)
     }
   else
     lma += change_section_address;
     }
   else
     lma += change_section_address;
-  
+
   osection->lma = lma;
 
   /* FIXME: This is probably not enough.  If we change the LMA we
   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)
     {
                                 bfd_section_alignment (ibfd, isection))
       == false)
     {
-      err = "alignment";
+      err = _("alignment");
       goto loser;
     }
 
       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))
     {
     flags = p->flags | (flags & SEC_HAS_CONTENTS);
   if (!bfd_set_section_flags (obfd, osection, flags))
     {
-      err = "flags";
+      err = _("flags");
       goto loser;
     }
 
       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))
     {
      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;
     }
 
       goto loser;
     }
 
@@ -1260,7 +1409,7 @@ copy_section (ibfd, isection, obfdarg)
      complaints now.  */
   if (status != 0)
     return;
      complaints now.  */
   if (status != 0)
     return;
-  
+
   if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
       && (strip_symbols == STRIP_DEBUG
          || strip_symbols == STRIP_UNNEEDED
   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));
   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
   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));
       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
       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;
          arelent **temp_relpp;
          long temp_relcount = 0;
          long i;
-         
+
          temp_relpp = (arelent **) xmalloc (relsize);
          for (i = 0; i < relcount; i++)
            if (is_specified_symbol
          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);
     }
       bfd_set_reloc (obfd, osection,
                     (relcount == 0 ? (arelent **) NULL : relpp), relcount);
     }
-  
+
   isection->_cooked_size = isection->_raw_size;
   isection->reloc_done = true;
 
   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));
 
                                     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,
        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;
 
   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)
                           strip_options, (int *) 0)) != EOF)
     {
       switch (c)
@@ -1569,6 +1718,7 @@ strip_main (argc, argv)
          break;
        case 'S':
        case 'g':
          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:
          strip_symbols = STRIP_DEBUG;
          break;
        case OPTION_STRIP_UNNEEDED:
@@ -1668,6 +1818,7 @@ copy_main (argc, argv)
      int argc;
      char *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;
   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;
 
   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)
                           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;
          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':
          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 'I':
        case 's':               /* "source" - 'I' is preferred */
          input_target = optarg;
          break;
+
        case 'O':
        case 'd':               /* "destination" - 'O' is preferred */
          output_target = optarg;
          break;
        case 'O':
        case 'd':               /* "destination" - 'O' is preferred */
          output_target = optarg;
          break;
+
        case 'F':
          input_target = output_target = optarg;
          break;
        case 'F':
          input_target = output_target = optarg;
          break;
+
        case 'j':
          p = find_section_list (optarg, true);
          if (p->remove)
        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;
          p->copy = true;
          sections_copied = true;
          break;
+
        case 'R':
          p = find_section_list (optarg, true);
          if (p->copy)
        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;
          p->remove = true;
          sections_removed = true;
          break;
+
        case 'S':
          strip_symbols = STRIP_ALL;
          break;
        case 'S':
          strip_symbols = STRIP_ALL;
          break;
+
        case 'g':
          strip_symbols = STRIP_DEBUG;
          break;
        case 'g':
          strip_symbols = STRIP_DEBUG;
          break;
+
        case OPTION_STRIP_UNNEEDED:
          strip_symbols = STRIP_UNNEEDED;
          break;
        case OPTION_STRIP_UNNEEDED:
          strip_symbols = STRIP_UNNEEDED;
          break;
+
        case 'K':
          add_specific_symbol (optarg, &keep_specific_list);
          break;
        case 'K':
          add_specific_symbol (optarg, &keep_specific_list);
          break;
+
        case 'N':
          add_specific_symbol (optarg, &strip_specific_list);
          break;
        case 'N':
          add_specific_symbol (optarg, &strip_specific_list);
          break;
+
        case 'L':
          add_specific_symbol (optarg, &localize_specific_list);
          break;
        case 'L':
          add_specific_symbol (optarg, &localize_specific_list);
          break;
+
        case 'W':
          add_specific_symbol (optarg, &weaken_specific_list);
          break;
        case 'W':
          add_specific_symbol (optarg, &weaken_specific_list);
          break;
+
        case 'p':
          preserve_dates = true;
          break;
        case 'p':
          preserve_dates = true;
          break;
+
        case 'x':
          discard_locals = LOCALS_ALL;
          break;
        case 'x':
          discard_locals = LOCALS_ALL;
          break;
+
        case 'X':
          discard_locals = LOCALS_START_L;
          break;
        case 'X':
          discard_locals = LOCALS_START_L;
          break;
+
        case 'v':
          verbose = true;
          break;
        case 'v':
          verbose = true;
          break;
+
        case 'V':
          show_version = true;
          break;
        case 'V':
          show_version = true;
          break;
+
        case OPTION_WEAKEN:
          weaken = true;
          break;
        case OPTION_WEAKEN:
          weaken = true;
          break;
+
        case OPTION_ADD_SECTION:
          {
            const char *s;
        case OPTION_ADD_SECTION:
          {
            const char *s;
@@ -1765,9 +1940,9 @@ copy_main (argc, argv)
            FILE *f;
 
            s = strchr (optarg, '=');
            FILE *f;
 
            s = strchr (optarg, '=');
-           
+
            if (s == NULL)
            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));
 
            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);
 
            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 (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);
            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;
            add_sections = pa;
          }
          break;
+
        case OPTION_CHANGE_START:
          change_start = parse_vma (optarg, "--change-start");
          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:
        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;
            char *option = NULL;
            bfd_vma val;
            enum change_action what = CHANGE_IGNORE;
-           
+
            switch (c)
              {
              case OPTION_CHANGE_SECTION_ADDRESS:
            switch (c)
              {
              case OPTION_CHANGE_SECTION_ADDRESS:
@@ -1826,7 +2003,7 @@ copy_main (argc, argv)
                option = "--change-section-vma";
                break;
              }
                option = "--change-section-vma";
                break;
              }
-           
+
            s = strchr (optarg, '=');
            if (s == NULL)
              {
            s = strchr (optarg, '=');
            if (s == NULL)
              {
@@ -1854,19 +2031,19 @@ copy_main (argc, argv)
              case '-': val  = - val; /* Drop through.  */
              case '+': what = CHANGE_MODIFY; break;
              }
              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.  */
            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_LMA:
                p->change_lma = what;
                p->lma_val    = val;
                break;
-               
+
              case OPTION_CHANGE_SECTION_VMA:
                p->change_vma = what;
                p->vma_val    = val;
              case OPTION_CHANGE_SECTION_VMA:
                p->change_vma = what;
                p->vma_val    = val;
@@ -1874,19 +2051,24 @@ copy_main (argc, argv)
              }
          }
          break;
              }
          }
          break;
+
        case OPTION_CHANGE_ADDRESSES:
          change_section_address = parse_vma (optarg, "--change-addresses");
          change_start = change_section_address;
          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_WARNINGS:
          change_warn = true;
          break;
+
        case OPTION_CHANGE_LEADING_CHAR:
          change_leading_char = true;
          break;
        case OPTION_CHANGE_LEADING_CHAR:
          change_leading_char = true;
          break;
+
        case OPTION_DEBUGGING:
          convert_debugging = true;
          break;
        case OPTION_DEBUGGING:
          convert_debugging = true;
          break;
+
        case OPTION_GAP_FILL:
          {
            bfd_vma gap_fill_vma;
        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];
            if ((bfd_vma) gap_fill != gap_fill_vma)
              {
                char buff[20];
-               
+
                sprintf_vma (buff, gap_fill_vma);
                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;
                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_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_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_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;
        case OPTION_SET_SECTION_FLAGS:
          {
            const char *s;
@@ -1923,7 +2141,7 @@ copy_main (argc, argv)
 
            s = strchr (optarg, '=');
            if (s == NULL)
 
            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);
 
            len = s - optarg;
            name = (char *) xmalloc (len + 1);
@@ -1936,14 +2154,26 @@ copy_main (argc, argv)
            p->flags = parse_flags (s + 1);
          }
          break;
            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_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 0:
          break;                /* we've been given a long option */
+
        case 'h':
          copy_usage (stdout, 0);
        case 'h':
          copy_usage (stdout, 0);
+
        default:
          copy_usage (stderr, 1);
        }
        default:
          copy_usage (stderr, 1);
        }
@@ -1969,12 +2199,30 @@ copy_main (argc, argv)
   if (output_target == (char *) NULL)
     output_target = input_target;
 
   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.  */
 
   /* 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)
 
       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);
          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);
                  char buff [20];
 
                  sprintf_vma (buff, p->vma_val);
-                 
+
                  /* xgettext:c-format */
                  /* 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);
                }
                             p->name,
                             p->change_vma == CHANGE_SET ? '=' : '+',
                             buff);
                }
-             
+
              if (p->change_lma != CHANGE_IGNORE)
                {
                  char buff [20];
 
                  sprintf_vma (buff, p->lma_val);
              if (p->change_lma != CHANGE_IGNORE)
                {
                  char buff [20];
 
                  sprintf_vma (buff, p->lma_val);
-                 
+
                  /* xgettext:c-format */
                  /* 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);
                             p->name,
                             p->change_lma == CHANGE_SET ? '=' : '+',
                             buff);
@@ -2062,7 +2312,15 @@ main (argc, argv)
   if (is_strip < 0)
     {
       int i = strlen (program_name);
   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)
     }
 
   if (is_strip)