*** empty log message ***
[deliverable/binutils-gdb.git] / binutils / objcopy.c
index 31ac0a2bb3ee09dce92a53475adbda704eced7d0..1200eb6270de75b9d34bc2b50c532f61a9d9b3fb 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, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -30,7 +30,6 @@
 #include "filenames.h"
 #include "fnmatch.h"
 #include "elf-bfd.h"
-#include <sys/stat.h>
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
@@ -87,6 +86,7 @@ static int copy_width = 1;
 
 static bfd_boolean verbose;            /* Print file and target names.  */
 static bfd_boolean preserve_dates;     /* Preserve input file timestamp.  */
+static int deterministic = -1;         /* Enable deterministic archives.  */
 static int status = 0;         /* Exit status.  */
 
 enum strip_action
@@ -96,11 +96,13 @@ enum strip_action
     STRIP_DEBUG,               /* Strip all debugger symbols.  */
     STRIP_UNNEEDED,            /* Strip unnecessary symbols.  */
     STRIP_NONDEBUG,            /* Strip everything but debug info.  */
+    STRIP_DWO,                 /* Strip all DWO info.  */
+    STRIP_NONDWO,              /* Strip everything but DWO info.  */
     STRIP_ALL                  /* Strip all symbols.  */
   };
 
 /* Which symbols to remove.  */
-static enum strip_action strip_symbols;
+static enum strip_action strip_symbols = STRIP_UNDEF;
 
 enum locals_action
   {
@@ -314,15 +316,19 @@ enum command_line_switch
     OPTION_SECTION_ALIGNMENT,
     OPTION_STACK,
     OPTION_INTERLEAVE_WIDTH,
-    OPTION_SUBSYSTEM
+    OPTION_SUBSYSTEM,
+    OPTION_EXTRACT_DWO,
+    OPTION_STRIP_DWO
   };
 
 /* Options to handle if running as "strip".  */
 
 static struct option strip_options[] =
 {
+  {"disable-deterministic-archives", no_argument, 0, 'U'},
   {"discard-all", no_argument, 0, 'x'},
   {"discard-locals", no_argument, 0, 'X'},
+  {"enable-deterministic-archives", no_argument, 0, 'D'},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"help", no_argument, 0, 'h'},
   {"info", no_argument, 0, OPTION_FORMATS_INFO},
@@ -338,6 +344,7 @@ static struct option strip_options[] =
   {"remove-section", required_argument, 0, 'R'},
   {"strip-all", no_argument, 0, 's'},
   {"strip-debug", no_argument, 0, 'S'},
+  {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
   {"strip-symbol", required_argument, 0, 'N'},
   {"target", required_argument, 0, 'F'},
@@ -370,8 +377,11 @@ static struct option copy_options[] =
   {"compress-debug-sections", no_argument, 0, OPTION_COMPRESS_DEBUG_SECTIONS},
   {"debugging", no_argument, 0, OPTION_DEBUGGING},
   {"decompress-debug-sections", no_argument, 0, OPTION_DECOMPRESS_DEBUG_SECTIONS},
+  {"disable-deterministic-archives", no_argument, 0, 'U'},
   {"discard-all", no_argument, 0, 'x'},
   {"discard-locals", no_argument, 0, 'X'},
+  {"enable-deterministic-archives", no_argument, 0, 'D'},
+  {"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
   {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
@@ -418,6 +428,7 @@ static struct option copy_options[] =
   {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
   {"strip-all", no_argument, 0, 'S'},
   {"strip-debug", no_argument, 0, 'g'},
+  {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
   {"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},
@@ -460,6 +471,7 @@ extern bfd_boolean S3Forced;
 /* Forward declarations.  */
 static void setup_section (bfd *, asection *, void *);
 static void setup_bfd_headers (bfd *, bfd *);
+static void copy_relocations_in_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 *);
@@ -479,18 +491,33 @@ copy_usage (FILE *stream, int exit_status)
   -B --binary-architecture <arch>  Set output arch, when input is arch-less\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\
+  -p --preserve-dates              Copy modified/access timestamps to the output\n"));
+  if (DEFAULT_AR_DETERMINISTIC)
+    fprintf (stream, _("\
+  -D --enable-deterministic-archives\n\
+                                   Produce deterministic output when stripping archives (default)\n\
+  -U --disable-deterministic-archives\n\
+                                   Disable -D behavior\n"));
+  else
+    fprintf (stream, _("\
+  -D --enable-deterministic-archives\n\
+                                   Produce deterministic output when stripping archives\n\
+  -U --disable-deterministic-archives\n\
+                                   Disable -D behavior (default)\n"));
+  fprintf (stream, _("\
   -j --only-section <name>         Only copy section <name> into the output\n\
      --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\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 & sections\n\
+     --strip-dwo                   Remove all DWO 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\
+     --extract-dwo                 Copy only DWO sections\n\
      --extract-symbol              Remove section contents but keep symbols\n\
   -K --keep-symbol <name>          Do not strip symbol <name>\n\
      --keep-file-symbols           Do not strip file symbol(s)\n\
@@ -588,9 +615,24 @@ strip_usage (FILE *stream, int exit_status)
   -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\
+"));
+  if (DEFAULT_AR_DETERMINISTIC)
+    fprintf (stream, _("\
+  -D --enable-deterministic-archives\n\
+                                   Produce deterministic output when stripping archives (default)\n\
+  -U --disable-deterministic-archives\n\
+                                   Disable -D behavior\n"));
+  else
+    fprintf (stream, _("\
+  -D --enable-deterministic-archives\n\
+                                   Produce deterministic output when stripping archives\n\
+  -U --disable-deterministic-archives\n\
+                                   Disable -D behavior (default)\n"));
+  fprintf (stream, _("\
   -R --remove-section=<name>       Remove section <name> from the output\n\
   -s --strip-all                   Remove all symbol and relocation information\n\
   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
+     --strip-dwo                   Remove all DWO 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\
@@ -648,6 +690,8 @@ parse_flags (const char *s)
       PARSE_FLAG ("rom", SEC_ROM);
       PARSE_FLAG ("share", SEC_COFF_SHARED);
       PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
+      PARSE_FLAG ("merge", SEC_MERGE);
+      PARSE_FLAG ("strings", SEC_STRINGS);
 #undef PARSE_FLAG
       else
        {
@@ -658,7 +702,7 @@ parse_flags (const char *s)
          copy[len] = '\0';
          non_fatal (_("unrecognized section flag `%s'"), copy);
          fatal (_("supported flags: %s"),
-                "alloc, load, noload, readonly, debug, code, data, rom, share, contents");
+                "alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings");
        }
 
       s = snext;
@@ -925,6 +969,17 @@ group_signature (asection *group)
   return NULL;
 }
 
+/* Return TRUE if the section is a DWO section.  */
+
+static bfd_boolean
+is_dwo_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+{
+  const char *name = bfd_get_section_name (abfd, sec);
+  int len = strlen (name);
+
+  return strncmp (name + len - 4, ".dwo", 4) == 0;
+}
+
 /* See if a non-group section is being removed.  */
 
 static bfd_boolean
@@ -949,12 +1004,24 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
          || strip_symbols == STRIP_ALL
          || discard_locals == LOCALS_ALL
          || convert_debugging)
-       return TRUE;
+       {
+         /* By default we don't want to strip .reloc section.
+            This section has for pe-coff special meaning.   See
+            pe-dll.c file in ld, and peXXigen.c in bfd for details.  */
+         if (strcmp (bfd_get_section_name (abfd, sec), ".reloc") != 0)
+           return TRUE;
+       }
+
+      if (strip_symbols == STRIP_DWO)
+       return is_dwo_section (abfd, sec);
 
       if (strip_symbols == STRIP_NONDEBUG)
        return FALSE;
     }
 
+  if (strip_symbols == STRIP_NONDWO)
+    return !is_dwo_section (abfd, sec);
+
   return FALSE;
 }
 
@@ -1842,6 +1909,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
       || strip_symbols == STRIP_ALL
       || strip_symbols == STRIP_UNNEEDED
       || strip_symbols == STRIP_NONDEBUG
+      || strip_symbols == STRIP_DWO
+      || strip_symbols == STRIP_NONDWO
       || discard_locals != LOCALS_UNDEF
       || localize_hidden
       || htab_elements (strip_specific_htab) != 0
@@ -1886,6 +1955,9 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
 
   bfd_set_symtab (obfd, osympp, symcount);
 
+  /* This has to happen before section positions are set.  */
+  bfd_map_over_sections (ibfd, copy_relocations_in_section, obfd);
+
   /* This has to happen after the symbol table has been set.  */
   bfd_map_over_sections (ibfd, copy_section, obfd);
 
@@ -2027,9 +2099,15 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
       fatal (_("cannot create tempdir for archive copying (error: %s)"),
           strerror (errno));
 
-  obfd->has_armap = ibfd->has_armap;
+  if (strip_symbols == STRIP_ALL)
+    obfd->has_armap = FALSE;
+  else
+    obfd->has_armap = ibfd->has_armap;
   obfd->is_thin_archive = ibfd->is_thin_archive;
 
+  if (deterministic)
+    obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
+
   list = NULL;
 
   this_element = bfd_openr_next_archived_file (ibfd, NULL);
@@ -2589,47 +2667,59 @@ loser:
   bfd_nonfatal_message (NULL, obfd, osection, err);
 }
 
-/* Copy the data of input section ISECTION of IBFD
-   to an output section with the same name in OBFD.
-   If stripping then don't copy any relocation info.  */
+/* Return TRUE if input section ISECTION should be skipped.  */
 
-static void
-copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+static bfd_boolean
+skip_section (bfd *ibfd, sec_ptr isection)
 {
-  bfd *obfd = (bfd *) obfdarg;
-  struct section_list *p;
-  arelent **relpp;
-  long relcount;
   sec_ptr osection;
   bfd_size_type size;
-  long relsize;
   flagword flags;
 
   /* If we have already failed earlier on,
      do not keep on generating complaints now.  */
   if (status != 0)
-    return;
+    return TRUE;
+
+  if (extract_symbol)
+    return TRUE;
 
   if (is_strip_section (ibfd, isection))
-    return;
+    return TRUE;
 
   flags = bfd_get_section_flags (ibfd, isection);
   if ((flags & SEC_GROUP) != 0)
-    return;
+    return TRUE;
 
   osection = isection->output_section;
   size = bfd_get_section_size (isection);
 
   if (size == 0 || osection == 0)
-    return;
+    return TRUE;
 
-  if (extract_symbol)
+  return FALSE;
+}
+
+/* Copy relocations in input section ISECTION of IBFD to an output
+   section with the same name in OBFDARG.  If stripping then don't
+   copy any relocation info.  */
+
+static void
+copy_relocations_in_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+{
+  bfd *obfd = (bfd *) obfdarg;
+  long relsize;
+  arelent **relpp;
+  long relcount;
+  sec_ptr osection;
+
+  if (skip_section (ibfd, isection))
     return;
 
-  p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
+  osection = isection->output_section;
 
-  /* Core files do not need to be relocated.  */
-  if (bfd_get_format (obfd) == bfd_core)
+  /* Core files and DWO files do not need to be relocated.  */
+  if (bfd_get_format (obfd) == bfd_core || strip_symbols == STRIP_NONDWO)
     relsize = 0;
   else
     {
@@ -2650,7 +2740,10 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
     }
 
   if (relsize == 0)
-    bfd_set_reloc (obfd, osection, NULL, 0);
+    {
+      bfd_set_reloc (obfd, osection, NULL, 0);
+      osection->flags &= ~SEC_RELOC;
+    }
   else
     {
       relpp = (arelent **) xmalloc (relsize);
@@ -2683,8 +2776,31 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 
       bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
       if (relcount == 0)
-       free (relpp);
+       {
+         osection->flags &= ~SEC_RELOC;
+         free (relpp);
+       }
     }
+}
+
+/* Copy the data of input section ISECTION of IBFD
+   to an output section with the same name in OBFD.  */
+
+static void
+copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+{
+  bfd *obfd = (bfd *) obfdarg;
+  struct section_list *p;
+  sec_ptr osection;
+  bfd_size_type size;
+
+  if (skip_section (ibfd, isection))
+    return;
+
+  osection = isection->output_section;
+  size = bfd_get_section_size (isection);
+
+  p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
 
   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
       && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
@@ -2734,7 +2850,11 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 
          for (; from < end; from += interleave)
            for (i = 0; i < copy_width; i++)
-             *to++ = from[i];
+             {
+               if (&from[i] >= end)
+                 break;
+               *to++ = from[i];
+             }
 
          size = (size + interleave - 1 - copy_byte) / interleave * copy_width;
          osection->lma /= interleave;
@@ -2932,6 +3052,15 @@ write_debugging_info (bfd *obfd, void *dhandle,
   return FALSE;
 }
 
+/* If neither -D nor -U was specified explicitly,
+   then use the configured default.  */
+static void
+default_deterministic (void)
+{
+  if (deterministic < 0)
+    deterministic = DEFAULT_AR_DETERMINISTIC;
+}
+
 static int
 strip_main (int argc, char *argv[])
 {
@@ -2971,6 +3100,9 @@ strip_main (int argc, char *argv[])
        case 'd':       /* Historic BSD alias for -g.  Used by early NetBSD.  */
          strip_symbols = STRIP_DEBUG;
          break;
+       case OPTION_STRIP_DWO:
+         strip_symbols = STRIP_DWO;
+         break;
        case OPTION_STRIP_UNNEEDED:
          strip_symbols = STRIP_UNNEEDED;
          break;
@@ -2986,6 +3118,12 @@ strip_main (int argc, char *argv[])
        case 'p':
          preserve_dates = TRUE;
          break;
+       case 'D':
+         deterministic = TRUE;
+         break;
+       case 'U':
+         deterministic = FALSE;
+         break;
        case 'x':
          discard_locals = LOCALS_ALL;
          break;
@@ -3030,6 +3168,8 @@ strip_main (int argc, char *argv[])
   if (show_version)
     print_version ("strip");
 
+  default_deterministic ();
+
   /* Default is to strip all symbols.  */
   if (strip_symbols == STRIP_UNDEF
       && discard_locals == LOCALS_UNDEF
@@ -3112,7 +3252,7 @@ set_pe_subsystem (const char *s)
     }
   v[] =
     {
-      { "native", 0, IMAGE_SUBSYSTEM_NATIVE },  
+      { "native", 0, IMAGE_SUBSYSTEM_NATIVE },
       { "windows", 0, IMAGE_SUBSYSTEM_WINDOWS_GUI },
       { "console", 0, IMAGE_SUBSYSTEM_WINDOWS_CUI },
       { "posix", 0, IMAGE_SUBSYSTEM_POSIX_CUI },
@@ -3298,6 +3438,10 @@ copy_main (int argc, char *argv[])
          strip_symbols = STRIP_DEBUG;
          break;
 
+       case OPTION_STRIP_DWO:
+         strip_symbols = STRIP_DWO;
+         break;
+
        case OPTION_STRIP_UNNEEDED:
          strip_symbols = STRIP_UNNEEDED;
          break;
@@ -3311,6 +3455,7 @@ copy_main (int argc, char *argv[])
          break;
 
        case OPTION_ADD_GNU_DEBUGLINK:
+         long_section_names = ENABLE ;
          gnu_debuglink_filename = optarg;
          break;
 
@@ -3346,6 +3491,14 @@ copy_main (int argc, char *argv[])
          preserve_dates = TRUE;
          break;
 
+       case 'D':
+         deterministic = TRUE;
+         break;
+
+       case 'U':
+         deterministic = FALSE;
+         break;
+
        case 'w':
          wildcard = TRUE;
          break;
@@ -3755,6 +3908,10 @@ copy_main (int argc, char *argv[])
          bfd_flags_to_set &= ~D_PAGED;
          break;
 
+       case OPTION_EXTRACT_DWO:
+         strip_symbols = STRIP_NONDWO;
+         break;
+
        case OPTION_EXTRACT_SYMBOL:
          extract_symbol = TRUE;
          break;
@@ -3776,7 +3933,7 @@ copy_main (int argc, char *argv[])
        case OPTION_FILE_ALIGNMENT:
          pe_file_alignment = parse_vma (optarg, "--file-alignment");
          break;
-       
+
        case OPTION_HEAP:
            {
              char *end;
@@ -3794,20 +3951,20 @@ copy_main (int argc, char *argv[])
                }
            }
          break;
-       
+
        case OPTION_IMAGE_BASE:
          pe_image_base = parse_vma (optarg, "--image-base");
          break;
-       
+
        case OPTION_SECTION_ALIGNMENT:
          pe_section_alignment = parse_vma (optarg,
                                            "--section-alignment");
          break;
-       
+
        case OPTION_SUBSYSTEM:
          set_pe_subsystem (optarg);
          break;
-       
+
        case OPTION_STACK:
            {
              char *end;
@@ -3825,7 +3982,7 @@ copy_main (int argc, char *argv[])
                }
            }
          break;
-       
+
        case 0:
          /* We've been given a long option.  */
          break;
@@ -3864,6 +4021,8 @@ copy_main (int argc, char *argv[])
   if (optind + 1 < argc)
     output_filename = argv[optind + 1];
 
+  default_deterministic ();
+
   /* Default is to strip no symbols.  */
   if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
     strip_symbols = STRIP_NONE;
This page took 0.029098 seconds and 4 git commands to generate.