* Makefile.am: Use a temporary file to build chew.
[deliverable/binutils-gdb.git] / binutils / objcopy.c
index d5931b8dbbe1a2c45e0c260fd9511fa786f4e7fc..d8feae60d8fbf3c952add55a32f758acd0d53205 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, 2004
+   2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 \f
 #include "bfd.h"
 #include "progress.h"
@@ -192,8 +192,10 @@ static bfd_boolean wildcard = FALSE;
 /* List of symbols to strip, keep, localize, keep-global, weaken,
    or redefine.  */
 static struct symlist *strip_specific_list = NULL;
+static struct symlist *strip_unneeded_list = NULL;
 static struct symlist *keep_specific_list = NULL;
 static struct symlist *localize_specific_list = NULL;
+static struct symlist *globalize_specific_list = NULL;
 static struct symlist *keepglobal_specific_list = NULL;
 static struct symlist *weaken_specific_list = NULL;
 static struct redefine_node *redefine_sym_list = NULL;
@@ -231,8 +233,12 @@ enum command_line_switch
     OPTION_SREC_LEN,
     OPTION_SREC_FORCES3,
     OPTION_STRIP_SYMBOLS,
+    OPTION_STRIP_UNNEEDED_SYMBOL,
+    OPTION_STRIP_UNNEEDED_SYMBOLS,
     OPTION_KEEP_SYMBOLS,
     OPTION_LOCALIZE_SYMBOLS,
+    OPTION_GLOBALIZE_SYMBOL,
+    OPTION_GLOBALIZE_SYMBOLS,
     OPTION_KEEPGLOBAL_SYMBOLS,
     OPTION_WEAKEN_SYMBOLS,
     OPTION_RENAME_SECTION,
@@ -303,6 +309,8 @@ static struct option copy_options[] =
   {"discard-locals", no_argument, 0, 'X'},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
+  {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
+  {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
   {"help", no_argument, 0, 'h'},
   {"impure", no_argument, 0, OPTION_IMPURE},
   {"info", no_argument, 0, OPTION_FORMATS_INFO},
@@ -340,6 +348,8 @@ static struct option copy_options[] =
   {"strip-all", no_argument, 0, 'S'},
   {"strip-debug", no_argument, 0, 'g'},
   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
+  {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
+  {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
   {"strip-symbol", required_argument, 0, 'N'},
   {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
   {"target", required_argument, 0, 'F'},
@@ -405,9 +415,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\
+     --strip-unneeded-symbol <name>\n\
+                                   Do not copy symbol <name> unless needed by\n\
+                                     relocations\n\
      --only-keep-debug             Strip everything but the debug information\n\
-  -K --keep-symbol <name>          Only copy symbol <name>\n\
+  -K --keep-symbol <name>          Do not strip symbol <name>\n\
   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
+     --globalize-symbol <name>     Force symbol <name> to be marked as a global\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\
@@ -443,8 +457,12 @@ copy_usage (FILE *stream, int exit_status)
      --srec-len <number>           Restrict the length of generated Srecords\n\
      --srec-forceS3                Restrict the type of generated Srecords to S3\n\
      --strip-symbols <file>        -N for all symbols listed in <file>\n\
+     --strip-unneeded-symbols <file>\n\
+                                   --strip-unneeded-symbol for all symbols listed\n\
+                                     in <file>\n\
      --keep-symbols <file>         -K for all symbols listed in <file>\n\
      --localize-symbols <file>     -L for all symbols listed in <file>\n\
+     --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
      --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\
@@ -485,7 +503,7 @@ strip_usage (FILE *stream, int exit_status)
      --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\
+  -K --keep-symbol=<name>          Do not strip symbol <name>\n\
   -w --wildcard                    Permit wildcard in symbol comparison\n\
   -x --discard-all                 Remove all non-global symbols\n\
   -X --discard-locals              Remove any compiler-generated symbols\n\
@@ -536,7 +554,7 @@ parse_flags (const char *s)
       PARSE_FLAG ("code", SEC_CODE);
       PARSE_FLAG ("data", SEC_DATA);
       PARSE_FLAG ("rom", SEC_ROM);
-      PARSE_FLAG ("share", SEC_SHARED);
+      PARSE_FLAG ("share", SEC_COFF_SHARED);
       PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
 #undef PARSE_FLAG
       else
@@ -903,28 +921,44 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
 
       if (keep && is_specified_symbol (name, strip_specific_list))
        keep = 0;
+      if (keep
+         && !(flags & BSF_KEEP)
+         && is_specified_symbol (name, strip_unneeded_list))
+       keep = 0;
       if (!keep && is_specified_symbol (name, keep_specific_list))
        keep = 1;
       if (keep && is_strip_section (abfd, bfd_get_section (sym)))
        keep = 0;
 
-      if (keep && (flags & BSF_GLOBAL) != 0
-         && (weaken || is_specified_symbol (name, weaken_specific_list)))
-       {
-         sym->flags &=~ BSF_GLOBAL;
-         sym->flags |= BSF_WEAK;
-       }
-      if (keep && !undefined && (flags & (BSF_GLOBAL | BSF_WEAK))
-         && (is_specified_symbol (name, localize_specific_list)
-             || (keepglobal_specific_list != NULL
-                 && ! is_specified_symbol (name, keepglobal_specific_list))))
+      if (keep)
        {
-         sym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
-         sym->flags |= BSF_LOCAL;
-       }
+         if ((flags & BSF_GLOBAL) != 0
+             && (weaken || is_specified_symbol (name, weaken_specific_list)))
+           {
+             sym->flags &= ~ BSF_GLOBAL;
+             sym->flags |= BSF_WEAK;
+           }
 
-      if (keep)
-       to[dst_count++] = sym;
+         if (!undefined
+             && (flags & (BSF_GLOBAL | BSF_WEAK))
+             && (is_specified_symbol (name, localize_specific_list)
+                 || (keepglobal_specific_list != NULL
+                     && ! is_specified_symbol (name, keepglobal_specific_list))))
+           {
+             sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
+             sym->flags |= BSF_LOCAL;
+           }
+
+         if (!undefined
+             && (flags & BSF_LOCAL) 
+             && is_specified_symbol (name, globalize_specific_list))
+           {
+             sym->flags &= ~ BSF_LOCAL;
+             sym->flags |= BSF_GLOBAL;
+           }
+
+         to[dst_count++] = sym;
+       }
     }
 
   to[dst_count] = NULL;
@@ -1374,6 +1408,7 @@ copy_object (bfd *ibfd, bfd *obfd)
       || strip_specific_list != NULL
       || keep_specific_list != NULL
       || localize_specific_list != NULL
+      || globalize_specific_list != NULL
       || keepglobal_specific_list != NULL
       || weaken_specific_list != NULL
       || prefix_symbols_string
@@ -1592,6 +1627,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
       l = xmalloc (sizeof (struct name_list));
       l->name = output_name;
       l->next = list;
+      l->obfd = NULL;
       list = l;
 
       if (output_bfd == NULL)
@@ -1666,6 +1702,7 @@ copy_file (const char *input_filename, const char *output_filename,
 
   if (get_file_size (input_filename) < 1)
     {
+      non_fatal (_("error: the input file '%s' is empty"), input_filename);
       status = 1;
       return;
     }
@@ -1694,7 +1731,6 @@ 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
@@ -1706,7 +1742,8 @@ copy_file (const char *input_filename, const char *output_filename,
       if (obfd == NULL)
        RETURN_NONFATAL (output_filename);
 
-      delete = ! copy_object (ibfd, obfd);
+      if (! copy_object (ibfd, obfd))
+       status = 1;
 
       if (!bfd_close (obfd))
        RETURN_NONFATAL (output_filename);
@@ -1714,11 +1751,6 @@ copy_file (const char *input_filename, const char *output_filename,
       if (!bfd_close (ibfd))
        RETURN_NONFATAL (input_filename);
 
-      if (delete)
-       {
-         unlink (output_filename);
-         status = 1;
-       }
     }
   else
     {
@@ -2423,7 +2455,7 @@ strip_main (int argc, char *argv[])
          status = hold_status;
        }
       else
-       unlink (tmpname);
+       unlink_if_ordinary (tmpname);
       if (output_file == NULL)
        free (tmpname);
     }
@@ -2525,10 +2557,18 @@ copy_main (int argc, char *argv[])
          add_specific_symbol (optarg, &strip_specific_list);
          break;
 
+       case OPTION_STRIP_UNNEEDED_SYMBOL:
+         add_specific_symbol (optarg, &strip_unneeded_list);
+         break;
+
        case 'L':
          add_specific_symbol (optarg, &localize_specific_list);
          break;
 
+       case OPTION_GLOBALIZE_SYMBOL:
+         add_specific_symbol (optarg, &globalize_specific_list);
+         break;
+
        case 'G':
          add_specific_symbol (optarg, &keepglobal_specific_list);
          break;
@@ -2858,6 +2898,10 @@ copy_main (int argc, char *argv[])
          add_specific_symbols (optarg, &strip_specific_list);
          break;
 
+       case OPTION_STRIP_UNNEEDED_SYMBOLS:
+         add_specific_symbols (optarg, &strip_unneeded_list);
+         break;
+
        case OPTION_KEEP_SYMBOLS:
          add_specific_symbols (optarg, &keep_specific_list);
          break;
@@ -2866,6 +2910,10 @@ copy_main (int argc, char *argv[])
          add_specific_symbols (optarg, &localize_specific_list);
          break;
 
+       case OPTION_GLOBALIZE_SYMBOLS:
+         add_specific_symbols (optarg, &globalize_specific_list);
+         break;
+
        case OPTION_KEEPGLOBAL_SYMBOLS:
          add_specific_symbols (optarg, &keepglobal_specific_list);
          break;
@@ -3001,6 +3049,8 @@ copy_main (int argc, char *argv[])
 
       if (status == 0 && preserve_dates)
        set_times (output_filename, &statbuf);
+      else if (status != 0)
+       unlink_if_ordinary (output_filename);
     }
 
   if (change_warn)
This page took 0.026912 seconds and 4 git commands to generate.