2004-02-24 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / binutils / objcopy.c
index aa96e837d6e259244b8eecde1f13f0dd714fda2e..96233986c3e01b5c1ed1e2f4439a0b2e4b619b7f 100644 (file)
@@ -1,6 +1,6 @@
 /* objcopy.c -- copy object file from input to output, optionally massaging it.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003
+   2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -27,6 +27,8 @@
 #include "libiberty.h"
 #include "budbg.h"
 #include "filenames.h"
+#include "fnmatch.h"
+#include "elf-bfd.h"
 #include <sys/stat.h>
 
 /* A list of symbols to explicitly strip out, or to keep.  A linked
@@ -60,59 +62,6 @@ section_rename;
 /* List of sections to be renamed.  */
 static section_rename *section_rename_list;
 
-static void copy_usage
-  (FILE *, int);
-static void strip_usage
-  (FILE *, int);
-static flagword parse_flags
-  (const char *);
-static struct section_list *find_section_list
-  (const char *, bfd_boolean);
-static void setup_section
-  (bfd *, asection *, void *);
-static void copy_section
-  (bfd *, asection *, void *);
-static void get_sections
-  (bfd *, asection *, void *);
-static int compare_section_lma
-  (const void *, const void *);
-static void add_specific_symbol
-  (const char *, struct symlist **);
-static void add_specific_symbols
-  (const char *, struct symlist **);
-static bfd_boolean is_specified_symbol
-  (const char *, struct symlist *);
-static bfd_boolean is_strip_section
-  (bfd *, asection *);
-static unsigned int filter_symbols
-  (bfd *, bfd *, asymbol **, asymbol **, long);
-static void mark_symbols_used_in_relocations
-  (bfd *, asection *, void *);
-static void filter_bytes
-  (char *, bfd_size_type *);
-static bfd_boolean write_debugging_info
-  (bfd *, void *, long *, asymbol ***);
-static void copy_object
-  (bfd *, bfd *);
-static void copy_archive
-  (bfd *, bfd *, const char *);
-static void copy_file
-  (const char *, const char *, const char *, const char *);
-static int strip_main
-  (int, char **);
-static int copy_main
-  (int, char **);
-static const char *lookup_sym_redefinition
-  (const char *);
-static void redefine_list_append
-  (const char *, const char *, const char *);
-static const char * find_section_rename
-  (bfd *, sec_ptr, flagword *);
-static void add_section_rename
-  (const char *, const char *, flagword);
-static void add_redefine_syms_file 
-  (const char *);
-
 #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
 
 static asymbol **isympp = NULL;        /* Input symbols.  */
@@ -200,6 +149,10 @@ static bfd_vma pad_to;
 /* Use alternate machine code?  */
 static int use_alt_mach_code = 0;
 
+/* Output BFD flags user wants to set or clear */
+static flagword bfd_flags_to_set;
+static flagword bfd_flags_to_clear;
+
 /* List of sections to add.  */
 struct section_add
 {
@@ -233,6 +186,9 @@ static bfd_boolean change_leading_char = FALSE;
 /* Whether to remove the leading character from global symbol names.  */
 static bfd_boolean remove_leading_char = FALSE;
 
+/* Whether to permit wildcard in symbol comparison.  */
+static bfd_boolean wildcard = FALSE;
+
 /* List of symbols to strip, keep, localize, keep-global, weaken,
    or redefine.  */
 static struct symlist *strip_specific_list = NULL;
@@ -286,7 +242,11 @@ enum command_line_switch
     OPTION_PREFIX_ALLOC_SECTIONS,
     OPTION_FORMATS_INFO,
     OPTION_ADD_GNU_DEBUGLINK,
-    OPTION_ONLY_KEEP_DEBUG
+    OPTION_ONLY_KEEP_DEBUG,
+    OPTION_READONLY_TEXT,
+    OPTION_WRITABLE_TEXT,
+    OPTION_PURE,
+    OPTION_IMPURE
   };
 
 /* Options to handle if running as "strip".  */
@@ -314,6 +274,7 @@ static struct option strip_options[] =
   {"target", required_argument, 0, 'F'},
   {"verbose", no_argument, 0, 'v'},
   {"version", no_argument, 0, 'V'},
+  {"wildcard", no_argument, 0, 'w'},
   {0, no_argument, 0, 0}
 };
 
@@ -343,6 +304,7 @@ static struct option copy_options[] =
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
   {"help", no_argument, 0, 'h'},
+  {"impure", no_argument, 0, OPTION_IMPURE},
   {"info", no_argument, 0, OPTION_FORMATS_INFO},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
   {"input-target", required_argument, 0, 'I'},
@@ -364,6 +326,8 @@ static struct option copy_options[] =
   {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
   {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
   {"preserve-dates", no_argument, 0, 'p'},
+  {"pure", no_argument, 0, OPTION_PURE},
+  {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
   {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
   {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
   {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
@@ -384,6 +348,8 @@ static struct option copy_options[] =
   {"weaken", no_argument, 0, OPTION_WEAKEN},
   {"weaken-symbol", required_argument, 0, 'W'},
   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
+  {"wildcard", no_argument, 0, 'w'},
+  {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
   {0, no_argument, 0, 0}
 };
 
@@ -404,9 +370,19 @@ extern unsigned int Chunk;
    on by the --srec-forceS3 command line switch.  */
 extern bfd_boolean S3Forced;
 
-/* Defined in bfd/binary.c.  Used to set architecture of input binary files.  */
-extern enum bfd_architecture bfd_external_binary_architecture;
-
+/* Defined in bfd/binary.c.  Used to set architecture and machine of input
+   binary files.  */
+extern enum bfd_architecture  bfd_external_binary_architecture;
+extern unsigned long          bfd_external_machine;
+
+/* Forward declarations.  */
+static void setup_section (bfd *, asection *, void *);
+static void copy_section (bfd *, asection *, void *);
+static void get_sections (bfd *, asection *, void *);
+static int compare_section_lma (const void *, const void *);
+static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
+static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
+static const char *lookup_sym_redefinition (const char *);
 \f
 static void
 copy_usage (FILE *stream, int exit_status)
@@ -428,11 +404,13 @@ copy_usage (FILE *stream, int exit_status)
   -g --strip-debug                 Remove all debugging symbols & sections\n\
      --strip-unneeded              Remove all symbols not needed by relocations\n\
   -N --strip-symbol <name>         Do not copy symbol <name>\n\
+     --only-keep-debug             Strip everything but the debug information\n\
   -K --keep-symbol <name>          Only copy symbol <name>\n\
   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
   -G --keep-global-symbol <name>   Localize all symbols except <name>\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\
+  -w --wildcard                    Permit wildcard in symbol comparasion\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\
@@ -469,6 +447,10 @@ copy_usage (FILE *stream, int exit_status)
      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
      --alt-machine-code <index>    Use alternate machine code for output\n\
+     --writable-text               Mark the output text as writable\n\
+     --readonly-text               Make the output text write protected\n\
+     --pure                        Mark the output file as demand paged\n\
+     --impure                      Mark the output file as impure\n\
      --prefix-symbols <prefix>     Add <prefix> to start of every symbol name\n\
      --prefix-sections <prefix>    Add <prefix> to start of every section name\n\
      --prefix-alloc-sections <prefix>\n\
@@ -500,8 +482,10 @@ strip_usage (FILE *stream, int exit_status)
   -s --strip-all                   Remove all symbol and relocation information\n\
   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
      --strip-unneeded              Remove all symbols not needed by relocations\n\
+     --only-keep-debug             Strip everything but the debug information\n\
   -N --strip-symbol=<name>         Do not copy symbol <name>\n\
   -K --keep-symbol=<name>          Only copy symbol <name>\n\
+  -w --wildcard                    Permit wildcard in symbol comparasion\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\
@@ -587,7 +571,7 @@ find_section_list (const char *name, bfd_boolean add)
   if (! add)
     return NULL;
 
-  p = (struct section_list *) xmalloc (sizeof (struct section_list));
+  p = xmalloc (sizeof (struct section_list));
   p->name = name;
   p->used = FALSE;
   p->remove = FALSE;
@@ -612,7 +596,7 @@ add_specific_symbol (const char *name, struct symlist **list)
 {
   struct symlist *tmp_list;
 
-  tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist));
+  tmp_list = xmalloc (sizeof (struct symlist));
   tmp_list->name = name;
   tmp_list->next = *list;
   *list = tmp_list;
@@ -626,28 +610,27 @@ add_specific_symbol (const char *name, struct symlist **list)
 static void
 add_specific_symbols (const char *filename, struct symlist **list)
 {
-  struct stat st;
+  off_t  size;
   FILE * f;
   char * line;
   char * buffer;
   unsigned int line_count;
 
-  if (stat (filename, & st) < 0)
-    fatal (_("cannot stat: %s: %s"), filename, strerror (errno));
-  if (st.st_size == 0)
+  size = get_file_size (filename);
+  if (size == 0)
     return;
 
-  buffer = (char *) xmalloc (st.st_size + 2);
+  buffer = xmalloc (size + 2);
   f = fopen (filename, FOPEN_RT);
   if (f == NULL)
-    fatal (_("cannot open: %s: %s"), filename, strerror (errno));
+    fatal (_("cannot open '%s': %s"), filename, strerror (errno));
 
-  if (fread (buffer, 1, st.st_size, f) == 0 || ferror (f))
+  if (fread (buffer, 1, size, f) == 0 || ferror (f))
     fatal (_("%s: fread failed"), filename);
 
   fclose (f);
-  buffer [st.st_size] = '\n';
-  buffer [st.st_size + 1] = '\0';
+  buffer [size] = '\n';
+  buffer [size + 1] = '\0';
 
   line_count = 1;
 
@@ -740,9 +723,26 @@ is_specified_symbol (const char *name, struct symlist *list)
 {
   struct symlist *tmp_list;
 
-  for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
-    if (strcmp (name, tmp_list->name) == 0)
-      return TRUE;
+  if (wildcard)
+    {
+      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
+       if (*(tmp_list->name) != '!')
+         {
+           if (!fnmatch (tmp_list->name, name, 0))
+             return TRUE;
+         }
+       else
+         {
+           if (fnmatch (tmp_list->name + 1, name, 0))
+             return TRUE;
+         }
+    }
+  else
+    {
+      for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
+       if (strcmp (name, tmp_list->name) == 0)
+         return TRUE;
+    }
 
   return FALSE;
 }
@@ -777,7 +777,7 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
        return FALSE;
     }
 
-  return strip_symbols == STRIP_NONDEBUG ? TRUE : FALSE;
+  return FALSE;
 }
 
 /* Choose which symbol entries to copy; put the result in OSYMS.
@@ -965,7 +965,7 @@ redefine_list_append (const char *cause, const char *source, const char *target)
               cause, target);
     }
 
-  new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
+  new_node = xmalloc (sizeof (struct redefine_node));
 
   new_node->source = strdup (source);
   new_node->target = strdup (target);
@@ -988,12 +988,12 @@ add_redefine_syms_file (const char *filename)
   int c, lineno;
 
   file = fopen (filename, "r");
-  if (file == (FILE *) NULL)
+  if (file == NULL)
     fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
           filename, strerror (errno));
 
   bufsize = 100;
-  buf = (char *) xmalloc (bufsize);
+  buf = xmalloc (bufsize);
 
   lineno = 1;
   c = getc (file);
@@ -1085,26 +1085,10 @@ add_redefine_syms_file (const char *filename)
   free (buf);
 }
 
-/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
-   Adjust *SIZE.  */
-
-static void
-filter_bytes (char *memhunk, bfd_size_type *size)
-{
-  char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
-
-  for (; from < end; from += interleave)
-    *to++ = *from;
-
-  if (*size % interleave > (bfd_size_type) copy_byte)
-    *size = (*size / interleave) + 1;
-  else
-    *size /= interleave;
-}
-
-/* Copy object file IBFD onto OBFD.  */
+/* Copy object file IBFD onto OBFD.
+   Returns TRUE upon success, FALSE otherwise.  */
 
-static void
+static bfd_boolean
 copy_object (bfd *ibfd, bfd *obfd)
 {
   bfd_vma start;
@@ -1121,13 +1105,13 @@ copy_object (bfd *ibfd, bfd *obfd)
   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;
-    }
+    fatal (_("Unable to change endianness of input file(s)"));
 
   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
-    RETURN_NONFATAL (bfd_get_filename (obfd));
+    {
+      bfd_nonfatal (bfd_get_filename (obfd));
+      return FALSE;
+    }
 
   if (verbose)
     printf (_("copy from %s(%s) to %s(%s)\n"),
@@ -1144,11 +1128,19 @@ copy_object (bfd *ibfd, bfd *obfd)
      need to be set for a core file.  */
   if (bfd_get_format (obfd) != bfd_core)
     {
+      flagword flags;
+
+      flags = bfd_get_file_flags (ibfd);
+      flags |= bfd_flags_to_set;
+      flags &= ~bfd_flags_to_clear;
+      flags &= bfd_applicable_file_flags (obfd);
+
       if (!bfd_set_start_address (obfd, start)
-         || !bfd_set_file_flags (obfd,
-                                 (bfd_get_file_flags (ibfd)
-                                  & bfd_applicable_file_flags (obfd))))
-       RETURN_NONFATAL (bfd_get_filename (ibfd));
+         || !bfd_set_file_flags (obfd, flags))
+       {
+         bfd_nonfatal (bfd_get_filename (ibfd));
+         return FALSE;
+       }
     }
 
   /* Copy architecture of input file to output file.  */
@@ -1157,12 +1149,24 @@ copy_object (bfd *ibfd, bfd *obfd)
   if (!bfd_set_arch_mach (obfd, iarch, imach)
       && (ibfd->target_defaulted
          || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
-    non_fatal (_("Warning: Output file cannot represent architecture %s"),
-              bfd_printable_arch_mach (bfd_get_arch (ibfd),
-                                       bfd_get_mach (ibfd)));
+    {
+      if (bfd_get_arch (ibfd) == bfd_arch_unknown)
+       fatal (_("Unable to recognise the format of the input file %s"),
+              bfd_get_filename (ibfd));
+      else
+       {
+         non_fatal (_("Warning: Output file cannot represent architecture %s"),
+                    bfd_printable_arch_mach (bfd_get_arch (ibfd),
+                                             bfd_get_mach (ibfd)));
+         return FALSE;
+       }
+    }
 
   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
-    RETURN_NONFATAL (bfd_get_filename (ibfd));
+    {
+      bfd_nonfatal (bfd_get_filename (ibfd));
+      return FALSE;
+    }
 
   if (isympp)
     free (isympp);
@@ -1172,7 +1176,7 @@ copy_object (bfd *ibfd, bfd *obfd)
 
   /* BFD mandates that all output sections be created and sizes set before
      any output is done.  Thus, we traverse all sections multiple times.  */
-  bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
+  bfd_map_over_sections (ibfd, setup_section, obfd);
 
   if (add_sections != NULL)
     {
@@ -1188,12 +1192,14 @@ copy_object (bfd *ibfd, bfd *obfd)
            {
              non_fatal (_("can't create section `%s': %s"),
                       padd->name, bfd_errmsg (bfd_get_error ()));
-             status = 1;
-             return;
+             return FALSE;
            }
 
          if (! bfd_set_section_size (obfd, padd->section, padd->size))
-           RETURN_NONFATAL (bfd_get_filename (obfd));
+           {
+             bfd_nonfatal (bfd_get_filename (obfd));
+             return FALSE;
+           }
 
          pset = find_section_list (padd->name, FALSE);
          if (pset != NULL)
@@ -1205,23 +1211,32 @@ copy_object (bfd *ibfd, bfd *obfd)
            flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
 
          if (! bfd_set_section_flags (obfd, padd->section, flags))
-           RETURN_NONFATAL (bfd_get_filename (obfd));
+           {
+             bfd_nonfatal (bfd_get_filename (obfd));
+             return FALSE;
+           }
 
          if (pset != NULL)
            {
              if (pset->change_vma != CHANGE_IGNORE)
                if (! bfd_set_section_vma (obfd, padd->section,
                                           pset->vma_val))
-                 RETURN_NONFATAL (bfd_get_filename (obfd));
+                 {
+                   bfd_nonfatal (bfd_get_filename (obfd));
+                   return FALSE;
+                 }
 
              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)))
-                   RETURN_NONFATAL (bfd_get_filename (obfd));
+                   {
+                     bfd_nonfatal (bfd_get_filename (obfd));
+                     return FALSE;
+                   }
                }
            }
        }
@@ -1233,7 +1248,16 @@ copy_object (bfd *ibfd, bfd *obfd)
        (obfd, gnu_debuglink_filename);
 
       if (gnu_debuglink_section == NULL)
-       RETURN_NONFATAL (gnu_debuglink_filename);
+       {
+         bfd_nonfatal (gnu_debuglink_filename);
+         return FALSE;
+       }
+    }
+
+  if (bfd_count_sections (obfd) == 0)
+    {
+      non_fatal (_("there are no sections to be copied!"));
+      return FALSE;
     }
 
   if (gap_fill_set || pad_to_set)
@@ -1248,13 +1272,13 @@ copy_object (bfd *ibfd, bfd *obfd)
         We write out the gap contents below.  */
 
       c = bfd_count_sections (obfd);
-      osections = (asection **) xmalloc (c * sizeof (asection *));
+      osections = xmalloc (c * sizeof (asection *));
       set = osections;
-      bfd_map_over_sections (obfd, get_sections, (void *) &set);
+      bfd_map_over_sections (obfd, get_sections, &set);
 
       qsort (osections, c, sizeof (asection *), compare_section_lma);
 
-      gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
+      gaps = xmalloc (c * sizeof (bfd_size_type));
       memset (gaps, 0, c * sizeof (bfd_size_type));
 
       if (gap_fill_set)
@@ -1323,12 +1347,18 @@ copy_object (bfd *ibfd, bfd *obfd)
   dhandle = NULL;
   symsize = bfd_get_symtab_upper_bound (ibfd);
   if (symsize < 0)
-    RETURN_NONFATAL (bfd_get_filename (ibfd));
+    {
+      bfd_nonfatal (bfd_get_filename (ibfd));
+      return FALSE;
+    }
 
-  osympp = isympp = (asymbol **) xmalloc (symsize);
+  osympp = isympp = xmalloc (symsize);
   symcount = bfd_canonicalize_symtab (ibfd, isympp);
   if (symcount < 0)
-    RETURN_NONFATAL (bfd_get_filename (ibfd));
+    {
+      bfd_nonfatal (bfd_get_filename (ibfd));
+      return FALSE;
+    }
 
   if (convert_debugging)
     dhandle = read_debugging_info (ibfd, isympp, symcount);
@@ -1363,8 +1393,8 @@ copy_object (bfd *ibfd, bfd *obfd)
       if (strip_symbols != STRIP_ALL)
        bfd_map_over_sections (ibfd,
                               mark_symbols_used_in_relocations,
-                              (void *) isympp);
-      osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
+                              isympp);
+      osympp = xmalloc ((symcount + 1) * sizeof (asymbol *));
       symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
     }
 
@@ -1373,14 +1403,14 @@ copy_object (bfd *ibfd, bfd *obfd)
       if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
        {
          status = 1;
-         return;
+         return FALSE;
        }
     }
 
   bfd_set_symtab (obfd, osympp, symcount);
 
   /* This has to happen after the symbol table has been set.  */
-  bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
+  bfd_map_over_sections (ibfd, copy_section, obfd);
 
   if (add_sections != NULL)
     {
@@ -1388,11 +1418,12 @@ copy_object (bfd *ibfd, bfd *obfd)
 
       for (padd = add_sections; padd != NULL; padd = padd->next)
        {
-         if (! bfd_set_section_contents (obfd, padd->section,
-                                         (void *) padd->contents,
-                                         (file_ptr) 0,
-                                         (bfd_size_type) padd->size))
-           RETURN_NONFATAL (bfd_get_filename (obfd));
+         if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
+                                         0, padd->size))
+           {
+             bfd_nonfatal (bfd_get_filename (obfd));
+             return FALSE;
+           }
        }
     }
 
@@ -1400,7 +1431,10 @@ copy_object (bfd *ibfd, bfd *obfd)
     {
       if (! bfd_fill_in_gnu_debuglink_section
          (obfd, gnu_debuglink_section, gnu_debuglink_filename))
-       RETURN_NONFATAL (gnu_debuglink_filename);
+       {
+         bfd_nonfatal (gnu_debuglink_filename);
+         return FALSE;
+       }
     }
 
   if (gap_fill_set || pad_to_set)
@@ -1411,8 +1445,8 @@ copy_object (bfd *ibfd, bfd *obfd)
       /* Fill in the gaps.  */
       if (max_gap > 8192)
        max_gap = 8192;
-      buf = (bfd_byte *) xmalloc (max_gap);
-      memset (buf, gap_fill, (size_t) max_gap);
+      buf = xmalloc (max_gap);
+      memset (buf, gap_fill, max_gap);
 
       c = bfd_count_sections (obfd);
       for (i = 0; i < c; i++)
@@ -1436,7 +1470,10 @@ copy_object (bfd *ibfd, bfd *obfd)
 
                  if (! bfd_set_section_contents (obfd, osections[i], buf,
                                                  off, now))
-                   RETURN_NONFATAL (bfd_get_filename (obfd));
+                   {
+                     bfd_nonfatal (bfd_get_filename (obfd));
+                     return FALSE;
+                   }
 
                  left -= now;
                  off += now;
@@ -1459,18 +1496,17 @@ copy_object (bfd *ibfd, bfd *obfd)
       non_fatal (_("%s: error copying private BFD data: %s"),
                 bfd_get_filename (obfd),
                 bfd_errmsg (bfd_get_error ()));
-      status = 1;
-      return;
+      return FALSE;
     }
 
   /* Switch to the alternate machine code.  We have to do this at the
      very end, because we only initialize the header when we create
      the first section.  */
-  if (use_alt_mach_code != 0)
-    {
-      if (!bfd_alt_mach_code (obfd, use_alt_mach_code))
-       non_fatal (_("unknown alternate machine code, ignored"));
-    }
+  if (use_alt_mach_code != 0
+      && ! bfd_alt_mach_code (obfd, use_alt_mach_code))
+    non_fatal (_("unknown alternate machine code, ignored"));
+
+  return TRUE;
 }
 
 #undef MKDIR
@@ -1510,13 +1546,14 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
     RETURN_NONFATAL (bfd_get_filename (obfd));
 
-  while (!status && this_element != (bfd *) NULL)
+  while (!status && this_element != NULL)
     {
       char *output_name;
       bfd *output_bfd;
       bfd *last_element;
       struct stat buf;
       int stat_status = 0;
+      bfd_boolean delete = TRUE;
 
       /* Create an output file for this member.  */
       output_name = concat (dir, "/",
@@ -1530,7 +1567,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
            fatal (_("cannot mkdir %s for archive copying (error: %s)"),
                   output_name, strerror (errno));
 
-         l = (struct name_list *) xmalloc (sizeof (struct name_list));
+         l = xmalloc (sizeof (struct name_list));
          l->name = output_name;
          l->next = list;
          l->obfd = NULL;
@@ -1549,16 +1586,16 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
                       bfd_get_filename (this_element));
        }
 
-      l = (struct name_list *) xmalloc (sizeof (struct name_list));
+      l = xmalloc (sizeof (struct name_list));
       l->name = output_name;
       l->next = list;
       list = l;
 
-      if (output_bfd == (bfd *) NULL)
+      if (output_bfd == NULL)
        RETURN_NONFATAL (output_name);
 
       if (bfd_check_format (this_element, bfd_object))
-       copy_object (this_element, output_bfd);
+       delete = ! copy_object (this_element, output_bfd);
 
       if (!bfd_close (output_bfd))
        {
@@ -1567,24 +1604,32 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
          status = 1;
        }
 
-      if (preserve_dates && stat_status == 0)
-       set_times (output_name, &buf);
+      if (delete)
+       {
+         unlink (output_name);
+         status = 1;
+       }
+      else
+       {
+         if (preserve_dates && stat_status == 0)
+           set_times (output_name, &buf);
 
-      /* Open the newly output file and attach to our list.  */
-      output_bfd = bfd_openr (output_name, output_target);
+         /* Open the newly output file and attach to our list.  */
+         output_bfd = bfd_openr (output_name, output_target);
 
-      l->obfd = output_bfd;
+         l->obfd = output_bfd;
 
-      *ptr = output_bfd;
-      ptr = &output_bfd->next;
+         *ptr = output_bfd;
+         ptr = &output_bfd->next;
 
-      last_element = this_element;
+         last_element = this_element;
 
-      this_element = bfd_openr_next_archived_file (ibfd, last_element);
+         this_element = bfd_openr_next_archived_file (ibfd, last_element);
 
-      bfd_close (last_element);
+         bfd_close (last_element);
+       }
     }
-  *ptr = (bfd *) NULL;
+  *ptr = NULL;
 
   if (!bfd_close (obfd))
     RETURN_NONFATAL (bfd_get_filename (obfd));
@@ -1616,6 +1661,12 @@ copy_file (const char *input_filename, const char *output_filename,
   char **obj_matching;
   char **core_matching;
 
+  if (get_file_size (input_filename) < 1)
+    {
+      status = 1;
+      return;
+    }
+
   /* To allow us to do "strip *" without dying on the first
      non-object file, failures are nonfatal.  */
   ibfd = bfd_openr (input_filename, input_target);
@@ -1640,7 +1691,9 @@ copy_file (const char *input_filename, const char *output_filename,
   else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
     {
       bfd *obfd;
+      bfd_boolean delete;
     do_copy:
+
       /* bfd_get_target does not return the correct value until
          bfd_check_format succeeds.  */
       if (output_target == NULL)
@@ -1650,13 +1703,19 @@ copy_file (const char *input_filename, const char *output_filename,
       if (obfd == NULL)
        RETURN_NONFATAL (output_filename);
 
-      copy_object (ibfd, obfd);
+      delete = ! copy_object (ibfd, obfd);
 
       if (!bfd_close (obfd))
        RETURN_NONFATAL (output_filename);
 
       if (!bfd_close (ibfd))
        RETURN_NONFATAL (input_filename);
+
+      if (delete)
+       {
+         unlink (output_filename);
+         status = 1;
+       }
     }
   else
     {
@@ -1713,7 +1772,7 @@ add_section_rename (const char * old_name, const char * new_name,
        fatal (_("Multiple renames of section %s"), old_name);
       }
 
-  rename = (section_rename *) xmalloc (sizeof (* rename));
+  rename = xmalloc (sizeof (* rename));
 
   rename->old_name = old_name;
   rename->new_name = new_name;
@@ -1755,7 +1814,7 @@ find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
 static void
 setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 {
-  bfd *obfd = (bfd *) obfdarg;
+  bfd *obfd = obfdarg;
   struct section_list *p;
   sec_ptr osection;
   bfd_size_type size;
@@ -1851,6 +1910,13 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 
   if (p != NULL && p->set_flags)
     flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
+  else if (strip_symbols == STRIP_NONDEBUG && (flags & SEC_ALLOC) != 0)
+    {
+      flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
+      if (obfd->xvec->flavour == bfd_target_elf_flavour)
+       elf_section_type (osection) = SHT_NOBITS;
+    }
+
   if (!bfd_set_section_flags (obfd, osection, flags))
     {
       err = _("flags");
@@ -1897,7 +1963,7 @@ loser:
 static void
 copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 {
-  bfd *obfd = (bfd *) obfdarg;
+  bfd *obfd = obfdarg;
   struct section_list *p;
   arelent **relpp;
   long relcount;
@@ -1930,16 +1996,24 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
   if (bfd_get_format (obfd) == bfd_core)
     relsize = 0;
   else
-    relsize = bfd_get_reloc_upper_bound (ibfd, isection);
+    {
+      relsize = bfd_get_reloc_upper_bound (ibfd, isection);
 
-  if (relsize < 0)
-    RETURN_NONFATAL (bfd_get_filename (ibfd));
+      if (relsize < 0)
+       {
+         /* Do not complain if the target does not support relocations.  */
+         if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
+           relsize = 0;
+         else
+           RETURN_NONFATAL (bfd_get_filename (ibfd));
+       }
+    }
 
   if (relsize == 0)
-    bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
+    bfd_set_reloc (obfd, osection, NULL, 0);
   else
     {
-      relpp = (arelent **) xmalloc (relsize);
+      relpp = xmalloc (relsize);
       relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
       if (relcount < 0)
        RETURN_NONFATAL (bfd_get_filename (ibfd));
@@ -1952,19 +2026,19 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
          long temp_relcount = 0;
          long i;
 
-         temp_relpp = (arelent **) xmalloc (relsize);
+         temp_relpp = xmalloc (relsize);
          for (i = 0; i < relcount; i++)
-           if (is_specified_symbol
-               (bfd_asymbol_name (*relpp [i]->sym_ptr_ptr),
-                keep_specific_list))
+           if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
+                                    keep_specific_list))
              temp_relpp [temp_relcount++] = relpp [i];
          relcount = temp_relcount;
          free (relpp);
          relpp = temp_relpp;
        }
 
-      bfd_set_reloc (obfd, osection,
-                    (relcount == 0 ? (arelent **) NULL : relpp), relcount);
+      bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
+      if (relcount == 0)
+       free (relpp);
     }
 
   isection->_cooked_size = isection->_raw_size;
@@ -1973,24 +2047,33 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
       && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
     {
-      void *memhunk = (void *) xmalloc ((unsigned) size);
+      void *memhunk = xmalloc (size);
 
-      if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
-                                    size))
+      if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
        RETURN_NONFATAL (bfd_get_filename (ibfd));
 
       if (copy_byte >= 0)
-       filter_bytes (memhunk, &size);
+       {
+         /* Keep only every `copy_byte'th byte in MEMHUNK.  */
+         char *from = (char *) memhunk + copy_byte;
+         char *to = memhunk;
+         char *end = (char *) memhunk + size;
 
-      if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
-                                    size))
+         for (; from < end; from += interleave)
+           *to++ = *from;
+
+         size = (size + interleave - 1 - copy_byte) / interleave;
+         osection->lma /= interleave;
+       }
+
+      if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
        RETURN_NONFATAL (bfd_get_filename (obfd));
 
       free (memhunk);
     }
   else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
     {
-      void * memhunk = (void *) xmalloc ((unsigned) size);
+      void *memhunk = xmalloc (size);
 
       /* We don't permit the user to turn off the SEC_HAS_CONTENTS
         flag--they can just remove the section entirely and add it
@@ -1999,8 +2082,7 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
         contents should be zeroed out.  */
 
       memset (memhunk, 0, size);
-      if (! bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
-                                     size))
+      if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
        RETURN_NONFATAL (bfd_get_filename (obfd));
       free (memhunk);
     }
@@ -2012,7 +2094,7 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 static void
 get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
 {
-  asection ***secppp = (asection ***) secppparg;
+  asection ***secppp = secppparg;
 
   **secppp = osection;
   ++(*secppp);
@@ -2025,8 +2107,8 @@ get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
 static int
 compare_section_lma (const void *arg1, const void *arg2)
 {
-  const asection **sec1 = (const asection **) arg1;
-  const asection **sec2 = (const asection **) arg2;
+  const asection *const *sec1 = arg1;
+  const asection *const *sec2 = arg2;
   flagword flags1, flags2;
 
   /* Sort non loadable sections to the front.  */
@@ -2069,7 +2151,7 @@ compare_section_lma (const void *arg1, const void *arg2)
 static void
 mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
 {
-  asymbol **symbols = (asymbol **) symbolsarg;
+  asymbol **symbols = symbolsarg;
   long relsize;
   arelent **relpp;
   long relcount, i;
@@ -2080,12 +2162,17 @@ mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
 
   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
   if (relsize < 0)
-    bfd_fatal (bfd_get_filename (ibfd));
+    {
+      /* Do not complain if the target does not support relocations.  */
+      if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
+       return;
+      bfd_fatal (bfd_get_filename (ibfd));
+    }
 
   if (relsize == 0)
     return;
 
-  relpp = (arelent **) xmalloc (relsize);
+  relpp = xmalloc (relsize);
   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
   if (relcount < 0)
     bfd_fatal (bfd_get_filename (ibfd));
@@ -2153,10 +2240,9 @@ write_debugging_info (bfd *obfd, void *dhandle,
          the next thing the caller is going to do is copy over the
          real sections.  We may someday have to split the contents
          setting out of this function.  */
-      if (! bfd_set_section_contents (obfd, stabsec, syms, (file_ptr) 0,
-                                     symsize)
-         || ! bfd_set_section_contents (obfd, stabstrsec, strings,
-                                        (file_ptr) 0, stringsize))
+      if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
+         || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
+                                        stringsize))
        {
          non_fatal (_("%s: can't set debugging section contents: %s"),
                     bfd_get_filename (obfd),
@@ -2184,7 +2270,7 @@ strip_main (int argc, char *argv[])
   struct section_list *p;
   char *output_file = NULL;
 
-  while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVv",
+  while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw",
                           strip_options, (int *) 0)) != EOF)
     {
       switch (c)
@@ -2247,6 +2333,9 @@ strip_main (int argc, char *argv[])
        case 0:
          /* We've been given a long option.  */
          break;
+       case 'w':
+         wildcard = TRUE;
+         break;
        case 'H':
        case 'h':
          strip_usage (stdout, 0);
@@ -2270,7 +2359,7 @@ strip_main (int argc, char *argv[])
       && strip_specific_list == NULL)
     strip_symbols = STRIP_ALL;
 
-  if (output_target == (char *) NULL)
+  if (output_target == NULL)
     output_target = input_target;
 
   i = optind;
@@ -2284,14 +2373,13 @@ strip_main (int argc, char *argv[])
       struct stat statbuf;
       char *tmpname;
 
+      if (get_file_size (argv[i]) < 1)
+       continue;
+
       if (preserve_dates)
-       {
-         if (stat (argv[i], &statbuf) < 0)
-           {
-             non_fatal (_("%s: cannot stat: %s"), argv[i], strerror (errno));
-             continue;
-           }
-       }
+       /* No need to check the return value of stat().
+          It has already been checked in get_file_size().  */
+       stat (argv[i], &statbuf);
 
       if (output_file != NULL)
        tmpname = output_file;
@@ -2332,7 +2420,7 @@ copy_main (int argc, char *argv[])
   struct section_list *p;
   struct stat statbuf;
 
-  while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:",
+  while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w",
                           copy_options, (int *) 0)) != EOF)
     {
       switch (c)
@@ -2427,6 +2515,10 @@ copy_main (int argc, char *argv[])
          preserve_dates = TRUE;
          break;
 
+       case 'w':
+         wildcard = TRUE;
+         break;
+
        case 'x':
          discard_locals = LOCALS_ALL;
          break;
@@ -2454,7 +2546,7 @@ copy_main (int argc, char *argv[])
        case OPTION_ADD_SECTION:
          {
            const char *s;
-           struct stat st;
+           off_t size;
            struct section_add *pa;
            int len;
            char *name;
@@ -2465,22 +2557,22 @@ copy_main (int argc, char *argv[])
            if (s == NULL)
              fatal (_("bad format for %s"), "--add-section");
 
-           if (stat (s + 1, & st) < 0)
-             fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno));
+           size = get_file_size (s + 1);
+           if (size < 1)
+             break;
 
-           pa = (struct section_add *) xmalloc (sizeof (struct section_add));
+           pa = xmalloc (sizeof (struct section_add));
 
            len = s - optarg;
-           name = (char *) xmalloc (len + 1);
+           name = xmalloc (len + 1);
            strncpy (name, optarg, len);
            name[len] = '\0';
            pa->name = name;
 
            pa->filename = s + 1;
+           pa->size = size;
+           pa->contents = xmalloc (size);
 
-           pa->size = st.st_size;
-
-           pa->contents = (bfd_byte *) xmalloc (pa->size);
            f = fopen (pa->filename, FOPEN_RB);
 
            if (f == NULL)
@@ -2539,7 +2631,7 @@ copy_main (int argc, char *argv[])
              }
 
            len = s - optarg;
-           name = (char *) xmalloc (len + 1);
+           name = xmalloc (len + 1);
            strncpy (name, optarg, len);
            name[len] = '\0';
 
@@ -2637,13 +2729,13 @@ copy_main (int argc, char *argv[])
              fatal (_("bad format for %s"), "--redefine-sym");
 
            len = s - optarg;
-           source = (char *) xmalloc (len + 1);
+           source = xmalloc (len + 1);
            strncpy (source, optarg, len);
            source[len] = '\0';
 
            nextarg = s + 1;
            len = strlen (nextarg);
-           target = (char *) xmalloc (len + 1);
+           target = xmalloc (len + 1);
            strcpy (target, nextarg);
 
            redefine_list_append ("--redefine-sym", source, target);
@@ -2668,7 +2760,7 @@ copy_main (int argc, char *argv[])
              fatal (_("bad format for %s"), "--set-section-flags");
 
            len = s - optarg;
-           name = (char *) xmalloc (len + 1);
+           name = xmalloc (len + 1);
            strncpy (name, optarg, len);
            name[len] = '\0';
 
@@ -2695,7 +2787,7 @@ copy_main (int argc, char *argv[])
            if (len == 0)
              fatal (_("bad format for %s"), "--rename-section");
 
-           old_name = (char *) xmalloc (len + 1);
+           old_name = xmalloc (len + 1);
            strncpy (old_name, optarg, len);
            old_name[len] = 0;
 
@@ -2715,7 +2807,7 @@ copy_main (int argc, char *argv[])
            if (len == 0)
              fatal (_("bad format for %s"), "--rename-section");
 
-           new_name = (char *) xmalloc (len + 1);
+           new_name = xmalloc (len + 1);
            strncpy (new_name, eq, len);
            new_name[len] = 0;
 
@@ -2774,6 +2866,26 @@ copy_main (int argc, char *argv[])
          prefix_alloc_sections_string = optarg;
          break;
 
+       case OPTION_READONLY_TEXT:
+         bfd_flags_to_set |= WP_TEXT;
+         bfd_flags_to_clear &= ~WP_TEXT;
+         break;
+
+       case OPTION_WRITABLE_TEXT:
+         bfd_flags_to_clear |= WP_TEXT;
+         bfd_flags_to_set &= ~WP_TEXT;
+         break;
+
+       case OPTION_PURE:
+         bfd_flags_to_set |= D_PAGED;
+         bfd_flags_to_clear &= ~D_PAGED;
+         break;
+
+       case OPTION_IMPURE:
+         bfd_flags_to_clear |= D_PAGED;
+         bfd_flags_to_set &= ~D_PAGED;
+         break;
+
        case 0:
          /* We've been given a long option.  */
          break;
@@ -2810,10 +2922,10 @@ copy_main (int argc, char *argv[])
   if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
     strip_symbols = STRIP_NONE;
 
-  if (output_target == (char *) NULL)
+  if (output_target == NULL)
     output_target = input_target;
 
-  if (binary_architecture != (char *) NULL)
+  if (binary_architecture != NULL)
     {
       if (input_target && strcmp (input_target, "binary") == 0)
        {
@@ -2822,7 +2934,10 @@ copy_main (int argc, char *argv[])
          temp_arch_info = bfd_scan_arch (binary_architecture);
 
          if (temp_arch_info != NULL)
-           bfd_external_binary_architecture = temp_arch_info->arch;
+           {
+             bfd_external_binary_architecture = temp_arch_info->arch;
+             bfd_external_machine             = temp_arch_info->mach;
+           }
          else
            fatal (_("architecture %s unknown"), binary_architecture);
        }
@@ -2835,12 +2950,12 @@ copy_main (int argc, char *argv[])
 
   if (preserve_dates)
     if (stat (input_filename, & statbuf) < 0)
-      fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno));
+      fatal (_("warning: could not locate '%s'.  System error message: %s"),
+            input_filename, strerror (errno));
 
   /* If there is no destination file, or the source and destination files
-     are the same,  then create a temp and rename the result into the input.  */
-  if ((output_filename == (char *) NULL) ||
-      (strcmp (input_filename, output_filename) == 0))
+     are the same, then create a temp and rename the result into the input.  */
+  if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
     {
       char *tmpname = make_tempname (input_filename);
 
This page took 0.03814 seconds and 4 git commands to generate.