Add --only-keep-debug switch
[deliverable/binutils-gdb.git] / binutils / objcopy.c
index fc4bddadc89abb239cd1b93dc0fb943c30d14793..de777678962dd8e071fb66ca06dc5ba171dcc4fe 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
+   2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -105,11 +105,13 @@ static int copy_main
 static const char *lookup_sym_redefinition
   PARAMS((const char *));
 static void redefine_list_append
-  PARAMS ((const char *, const char *));
+  PARAMS ((const char *, const char *, const char *));
 static const char * find_section_rename
   PARAMS ((bfd *, sec_ptr, flagword *));
 static void add_section_rename
   PARAMS ((const char *, const char *, flagword));
+static void add_redefine_syms_file 
+  PARAMS ((const char *));
 
 #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
 
@@ -130,6 +132,7 @@ enum strip_action
     STRIP_NONE,                        /* don't strip */
     STRIP_DEBUG,               /* strip all debugger symbols */
     STRIP_UNNEEDED,            /* strip unnecessary symbols */
+    STRIP_NONDEBUG,            /* Strip everything but debug info.  */
     STRIP_ALL                  /* strip all symbols */
   };
 
@@ -217,6 +220,10 @@ struct section_add
 /* List of sections to add to the output BFD.  */
 static struct section_add *add_sections;
 
+/* If non-NULL the argument to --add-gnu-debuglink.
+   This should be the filename to store in the .gnu_debuglink section.  */
+static const char * gnu_debuglink_filename = NULL;
+
 /* Whether to convert debugging information.  */
 static bfd_boolean convert_debugging = FALSE;
 
@@ -238,6 +245,11 @@ static struct redefine_node *redefine_sym_list = NULL;
 /* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
 static bfd_boolean weaken = FALSE;
 
+/* Prefix symbols/sections.  */
+static char *prefix_symbols_string = 0;
+static char *prefix_sections_string = 0;
+static char *prefix_alloc_sections_string = 0;
+
 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
 
 #define OPTION_ADD_SECTION 150
@@ -258,7 +270,8 @@ static bfd_boolean weaken = FALSE;
 #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_REDEFINE_SYMS (OPTION_REDEFINE_SYM + 1)
+#define OPTION_SREC_LEN (OPTION_REDEFINE_SYMS + 1)
 #define OPTION_SREC_FORCES3 (OPTION_SREC_LEN + 1)
 #define OPTION_STRIP_SYMBOLS (OPTION_SREC_FORCES3 + 1)
 #define OPTION_KEEP_SYMBOLS (OPTION_STRIP_SYMBOLS + 1)
@@ -267,6 +280,12 @@ static bfd_boolean weaken = FALSE;
 #define OPTION_WEAKEN_SYMBOLS (OPTION_KEEPGLOBAL_SYMBOLS + 1)
 #define OPTION_RENAME_SECTION (OPTION_WEAKEN_SYMBOLS + 1)
 #define OPTION_ALT_MACH_CODE (OPTION_RENAME_SECTION + 1)
+#define OPTION_PREFIX_SYMBOLS (OPTION_ALT_MACH_CODE + 1)
+#define OPTION_PREFIX_SECTIONS (OPTION_PREFIX_SYMBOLS + 1)
+#define OPTION_PREFIX_ALLOC_SECTIONS (OPTION_PREFIX_SECTIONS + 1)
+#define OPTION_FORMATS_INFO (OPTION_PREFIX_ALLOC_SECTIONS + 1)
+#define OPTION_ADD_GNU_DEBUGLINK (OPTION_FORMATS_INFO + 1)
+#define OPTION_ONLY_KEEP_DEBUG (OPTION_ADD_GNU_DEBUGLINK + 1)
 
 /* Options to handle if running as "strip".  */
 
@@ -276,9 +295,11 @@ static struct option strip_options[] =
   {"discard-locals", no_argument, 0, 'X'},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"help", no_argument, 0, 'h'},
+  {"info", no_argument, 0, OPTION_FORMATS_INFO},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
   {"input-target", required_argument, 0, 'I'},
   {"keep-symbol", required_argument, 0, 'K'},
+  {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
   {"output-format", required_argument, 0, 'O'},        /* Obsolete */
   {"output-target", required_argument, 0, 'O'},
   {"output-file", required_argument, 0, 'o'},
@@ -298,11 +319,13 @@ static struct option strip_options[] =
 
 static struct option copy_options[] =
 {
+  {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
   {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
   {"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},
+  {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
   {"binary-architecture", required_argument, 0, 'B'},
   {"byte", required_argument, 0, 'b'},
   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
@@ -315,45 +338,50 @@ static struct option copy_options[] =
   {"debugging", no_argument, 0, OPTION_DEBUGGING},
   {"discard-all", no_argument, 0, 'x'},
   {"discard-locals", no_argument, 0, 'X'},
-  {"only-section", required_argument, 0, 'j'},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
   {"help", no_argument, 0, 'h'},
+  {"info", no_argument, 0, OPTION_FORMATS_INFO},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
   {"input-target", required_argument, 0, 'I'},
   {"interleave", required_argument, 0, 'i'},
+  {"keep-global-symbol", required_argument, 0, 'G'},
+  {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
   {"keep-symbol", required_argument, 0, 'K'},
+  {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
+  {"localize-symbol", required_argument, 0, 'L'},
+  {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
   {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
+  {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
+  {"only-section", required_argument, 0, 'j'},
   {"output-format", required_argument, 0, 'O'},        /* Obsolete */
   {"output-target", required_argument, 0, 'O'},
   {"pad-to", required_argument, 0, OPTION_PAD_TO},
+  {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
+  {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
+  {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
   {"preserve-dates", no_argument, 0, 'p'},
-  {"localize-symbol", required_argument, 0, 'L'},
-  {"keep-global-symbol", required_argument, 0, 'G'},
+  {"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},
   {"remove-section", required_argument, 0, 'R'},
   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
   {"set-start", required_argument, 0, OPTION_SET_START},
+  {"srec-len", required_argument, 0, OPTION_SREC_LEN},
+  {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
   {"strip-all", no_argument, 0, 'S'},
   {"strip-debug", no_argument, 0, 'g'},
   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
   {"strip-symbol", required_argument, 0, 'N'},
+  {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
   {"target", required_argument, 0, 'F'},
   {"verbose", no_argument, 0, 'v'},
   {"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},
-  {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
-  {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
-  {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
-  {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
-  {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
   {0, no_argument, 0, 0}
 };
 
@@ -394,9 +422,10 @@ copy_usage (stream, exit_status)
      --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\
+     --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\n\
+  -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\
   -K --keep-symbol <name>          Only copy symbol <name>\n\
@@ -430,6 +459,8 @@ copy_usage (stream, exit_status)
      --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\
+     --redefine-syms <file>        --redefine-sym for all symbol pairs \n\
+                                     listed in <file>\n\
      --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\
@@ -438,9 +469,15 @@ copy_usage (stream, 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\
+     --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\
+                                   Add <prefix> to start of every allocatable\n\
+                                     section name\n\
   -v --verbose                     List all object files modified\n\
   -V --version                     Display this program's version number\n\
   -h --help                        Display this output\n\
+     --info                        List object formats & architectures supported\n\
 "));
   list_supported_targets (program_name, stream);
   if (exit_status == 0)
@@ -463,7 +500,7 @@ strip_usage (stream, exit_status)
   -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 -d --strip-debug           Remove all debugging symbols\n\
+  -g -S -d --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\
   -K --keep-symbol=<name>          Only copy symbol <name>\n\
@@ -472,6 +509,7 @@ strip_usage (stream, exit_status)
   -v --verbose                     List all object files modified\n\
   -V --version                     Display this program's version number\n\
   -h --help                        Display this output\n\
+     --info                        List object formats & architectures supported\n\
   -o <file>                        Place stripped output into <file>\n\
 "));
 
@@ -727,25 +765,32 @@ is_strip_section (abfd, sec)
      bfd *abfd ATTRIBUTE_UNUSED;
      asection *sec;
 {
-  struct section_list *p;
+  if (sections_removed || sections_copied)
+    {
+      struct section_list *p;
+
+      p = find_section_list (bfd_get_section_name (abfd, sec), FALSE);
+
+      if (sections_removed && p != NULL && p->remove)
+       return TRUE;
+      if (sections_copied && (p == NULL || ! p->copy))
+       return TRUE;
+    }
 
-  if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0
-      && (strip_symbols == STRIP_DEBUG
+  if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0)
+    {
+      if (strip_symbols == STRIP_DEBUG
          || strip_symbols == STRIP_UNNEEDED
          || strip_symbols == STRIP_ALL
          || discard_locals == LOCALS_ALL
-         || convert_debugging))
-    return TRUE;
+         || convert_debugging)
+       return TRUE;
 
-  if (! sections_removed && ! sections_copied)
-    return FALSE;
+      if (strip_symbols == STRIP_NONDEBUG)
+       return FALSE;
+    }
 
-  p = find_section_list (bfd_get_section_name (abfd, sec), FALSE);
-  if (sections_removed && p != NULL && p->remove)
-    return TRUE;
-  if (sections_copied && (p == NULL || ! p->copy))
-    return TRUE;
-  return FALSE;
+  return strip_symbols == STRIP_NONDEBUG ? TRUE : FALSE;
 }
 
 /* Choose which symbol entries to copy; put the result in OSYMS.
@@ -768,51 +813,73 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount)
     {
       asymbol *sym = from[src_count];
       flagword flags = sym->flags;
-      const char *name = bfd_asymbol_name (sym);
+      char *name = (char *) bfd_asymbol_name (sym);
       int keep;
       bfd_boolean undefined;
+      bfd_boolean rem_leading_char;
+      bfd_boolean add_leading_char;
+
+      undefined = bfd_is_und_section (bfd_get_section (sym));
 
       if (redefine_sym_list)
        {
-         const char *old_name, *new_name;
+         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;
+         old_name = (char *) bfd_asymbol_name (sym);
+         new_name = (char *) lookup_sym_redefinition (old_name);
+         bfd_asymbol_name (sym) = new_name;
+         name = new_name;
        }
 
-      if (change_leading_char
-         && (bfd_get_symbol_leading_char (abfd)
-             != bfd_get_symbol_leading_char (obfd))
-         && (bfd_get_symbol_leading_char (abfd) == '\0'
-             || (name[0] == bfd_get_symbol_leading_char (abfd))))
-       {
-         if (bfd_get_symbol_leading_char (obfd) == '\0')
-           name = bfd_asymbol_name (sym) = name + 1;
-         else
-           {
-             char *n;
-
-             n = xmalloc (strlen (name) + 2);
-             n[0] = bfd_get_symbol_leading_char (obfd);
-             if (bfd_get_symbol_leading_char (abfd) == '\0')
-               strcpy (n + 1, name);
-             else
-               strcpy (n + 1, name + 1);
-             name = bfd_asymbol_name (sym) = n;
-           }
+      /* Check if we will remove the current leading character.  */
+      rem_leading_char =
+       (name[0] == bfd_get_symbol_leading_char (abfd))
+       && (change_leading_char
+           || (remove_leading_char
+               && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+                   || undefined
+                   || bfd_is_com_section (bfd_get_section (sym)))));
+
+      /* Check if we will add a new leading character.  */
+      add_leading_char =
+       change_leading_char
+       && (bfd_get_symbol_leading_char (obfd) != '\0')
+       && (bfd_get_symbol_leading_char (abfd) == '\0'
+           || (name[0] == bfd_get_symbol_leading_char (abfd)));
+
+      /* Short circuit for change_leading_char if we can do it in-place.  */
+      if (rem_leading_char && add_leading_char && !prefix_symbols_string)
+        {
+         name[0] = bfd_get_symbol_leading_char (obfd);
+         bfd_asymbol_name (sym) = name;
+         rem_leading_char = FALSE;
+         add_leading_char = FALSE;
+        }
+
+      /* Remove leading char.  */
+      if (rem_leading_char)
+       bfd_asymbol_name (sym) = ++name;
+
+      /* Add new leading char and/or prefix.  */
+      if (add_leading_char || prefix_symbols_string)
+        {
+          char *n, *ptr;
+
+          ptr = n = xmalloc (1 + strlen (prefix_symbols_string) + strlen (name) + 1);
+          if (add_leading_char)
+           *ptr++ = bfd_get_symbol_leading_char (obfd);
+
+          if (prefix_symbols_string)
+            {
+              strcpy (ptr, prefix_symbols_string);
+              ptr += strlen (prefix_symbols_string);
+           }
+
+          strcpy (ptr, name);
+          bfd_asymbol_name (sym) = n;
+          name = n;
        }
 
-      undefined = bfd_is_und_section (bfd_get_section (sym));
-
-      if (remove_leading_char
-         && ((flags & BSF_GLOBAL) != 0
-             || (flags & BSF_WEAK) != 0
-             || undefined
-             || bfd_is_com_section (bfd_get_section (sym)))
-         && name[0] == bfd_get_symbol_leading_char (abfd))
-       name = bfd_asymbol_name (sym) = name + 1;
-
       if (strip_symbols == STRIP_ALL)
        keep = 0;
       else if ((flags & BSF_KEEP) != 0         /* Used in relocation.  */
@@ -897,7 +964,8 @@ lookup_sym_redefinition (source)
 /* Add a node to a symbol redefine list.  */
 
 static void
-redefine_list_append (source, target)
+redefine_list_append (cause, source, target)
+     const char *cause;
      const char *source;
      const char *target;
 {
@@ -909,13 +977,11 @@ redefine_list_append (source, target)
     {
       if (strcmp (source, list->source) == 0)
        fatal (_("%s: Multiple redefinition of symbol \"%s\""),
-              "--redefine-sym",
-              source);
+              cause, source);
 
       if (strcmp (target, list->target) == 0)
        fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
-              "--redefine-sym",
-              target);
+              cause, target);
     }
 
   new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
@@ -927,6 +993,116 @@ redefine_list_append (source, target)
   *p = new_node;
 }
 
+/* Handle the --redefine-syms option.  Read lines containing "old new"
+   from the file, and add them to the symbol redefine list.  */
+
+static void
+add_redefine_syms_file (filename)
+     const char *filename;
+{
+  FILE *file;
+  char *buf;
+  size_t bufsize, len, outsym_off;
+  int c, lineno;
+
+  file = fopen (filename, "r");
+  if (file == (FILE *) NULL)
+    fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
+          filename, strerror (errno));
+
+  bufsize = 100;
+  buf = (char *) xmalloc (bufsize);
+
+  lineno = 1;
+  c = getc (file);
+  len = 0;
+  outsym_off = 0;
+  while (c != EOF)
+    {
+      /* Collect the input symbol name.  */
+      while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
+       {
+         if (c == '#')
+           goto comment;
+         buf[len++] = c;
+         if (len >= bufsize)
+           {
+             bufsize *= 2;
+             buf = xrealloc (buf, bufsize);
+           }
+         c = getc (file);
+       }
+      buf[len++] = '\0';
+      if (c == EOF)
+       break;
+
+      /* Eat white space between the symbol names.  */
+      while (IS_WHITESPACE (c))
+       c = getc (file);
+      if (c == '#' || IS_LINE_TERMINATOR (c))
+       goto comment;
+      if (c == EOF)
+       break;
+
+      /* Collect the output symbol name.  */
+      outsym_off = len;
+      while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
+       {
+         if (c == '#')
+           goto comment;
+         buf[len++] = c;
+         if (len >= bufsize)
+           {
+             bufsize *= 2;
+             buf = xrealloc (buf, bufsize);
+           }
+         c = getc (file);
+       }
+      buf[len++] = '\0';
+      if (c == EOF)
+       break;
+
+      /* Eat white space at end of line.  */
+      while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c))
+       c = getc (file);
+      if (c == '#')
+       goto comment;
+      /* Handle \r\n.  */
+      if ((c == '\r' && (c = getc (file)) == '\n')
+         || c == '\n' || c == EOF)
+       {
+ end_of_line:
+         /* Append the redefinition to the list.  */
+         if (buf[0] != '\0')
+           redefine_list_append (filename, &buf[0], &buf[outsym_off]);
+
+         lineno++;     
+         len = 0;
+         outsym_off = 0;
+         if (c == EOF)
+           break;
+         c = getc (file);
+         continue;
+       }
+      else
+       fatal (_("%s: garbage at end of line %d"), filename, lineno);
+ comment:
+      if (len != 0 && (outsym_off == 0 || outsym_off == len))
+       fatal (_("%s: missing new symbol name at line %d"), filename, lineno);
+      buf[len++] = '\0';
+
+      /* Eat the rest of the line and finish it.  */
+      while (c != '\n' && c != EOF)
+       c = getc (file);
+      goto end_of_line;
+    }
+
+  if (len != 0)
+    fatal (_("%s: premature end of file at line %d"), filename, lineno);
+
+  free (buf);
+}
+
 /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
    Adjust *SIZE.  */
 
@@ -960,6 +1136,8 @@ copy_object (ibfd, obfd)
   bfd_size_type max_gap = 0;
   long symsize;
   PTR dhandle;
+  enum bfd_architecture iarch;
+  unsigned int imach;
 
   if (ibfd->xvec->byteorder != obfd->xvec->byteorder
       && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
@@ -995,8 +1173,9 @@ copy_object (ibfd, obfd)
     }
 
   /* Copy architecture of input file to output file.  */
-  if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
-                         bfd_get_mach (ibfd))
+  iarch = bfd_get_arch (ibfd);
+  imach = bfd_get_mach (ibfd);
+  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"),
@@ -1023,6 +1202,8 @@ copy_object (ibfd, obfd)
 
       for (padd = add_sections; padd != NULL; padd = padd->next)
        {
+         flagword flags;
+
          padd->section = bfd_make_section (obfd, padd->name);
          if (padd->section == NULL)
            {
@@ -1031,45 +1212,47 @@ copy_object (ibfd, obfd)
              status = 1;
              return;
            }
-         else
-           {
-             flagword flags;
 
-             if (! bfd_set_section_size (obfd, padd->section, padd->size))
-               RETURN_NONFATAL (bfd_get_filename (obfd));
-
-             pset = find_section_list (padd->name, FALSE);
-             if (pset != NULL)
-               pset->used = TRUE;
+         if (! bfd_set_section_size (obfd, padd->section, padd->size))
+           RETURN_NONFATAL (bfd_get_filename (obfd));
 
-             if (pset != NULL && pset->set_flags)
-               flags = pset->flags | SEC_HAS_CONTENTS;
-             else
-               flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
+         pset = find_section_list (padd->name, FALSE);
+         if (pset != NULL)
+           pset->used = TRUE;
 
-             if (! bfd_set_section_flags (obfd, padd->section, flags))
-               RETURN_NONFATAL (bfd_get_filename (obfd));
+         if (pset != NULL && pset->set_flags)
+           flags = pset->flags | SEC_HAS_CONTENTS;
+         else
+           flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
 
-             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));
+         if (! bfd_set_section_flags (obfd, padd->section, flags))
+           RETURN_NONFATAL (bfd_get_filename (obfd));
 
-                 if (pset->change_lma != CHANGE_IGNORE)
-                   {
-                     padd->section->lma = pset->lma_val;
+         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));
 
-                     if (! bfd_set_section_alignment
-                         (obfd, padd->section,
-                          bfd_section_alignment (obfd, padd->section)))
-                       RETURN_NONFATAL (bfd_get_filename (obfd));
-                   }
+             if (pset->change_lma != CHANGE_IGNORE)
+               {
+                 padd->section->lma = pset->lma_val;
+                 
+                 if (! bfd_set_section_alignment
+                     (obfd, padd->section,
+                      bfd_section_alignment (obfd, padd->section)))
+                   RETURN_NONFATAL (bfd_get_filename (obfd));
                }
            }
        }
     }
 
+  if (gnu_debuglink_filename != NULL)
+    {
+      if (! bfd_add_gnu_debuglink (obfd, gnu_debuglink_filename))
+       RETURN_NONFATAL (gnu_debuglink_filename);
+    }
+
   if (gap_fill_set || pad_to_set)
     {
       asection **set;
@@ -1170,12 +1353,14 @@ copy_object (ibfd, obfd)
   if (strip_symbols == STRIP_DEBUG
       || strip_symbols == STRIP_ALL
       || strip_symbols == STRIP_UNNEEDED
+      || strip_symbols == STRIP_NONDEBUG
       || discard_locals != LOCALS_UNDEF
       || strip_specific_list != NULL
       || keep_specific_list != NULL
       || localize_specific_list != NULL
       || keepglobal_specific_list != NULL
       || weaken_specific_list != NULL
+      || prefix_symbols_string
       || sections_removed
       || sections_copied
       || convert_debugging
@@ -1274,7 +1459,12 @@ copy_object (ibfd, obfd)
      from the input BFD to the output BFD.  This is done last to
      permit the routine to look at the filtered symbol table, which is
      important for the ECOFF code at least.  */
-  if (! bfd_copy_private_bfd_data (ibfd, obfd))
+  if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+      && strip_symbols == STRIP_NONDEBUG)
+    /* Do not copy the private data when creating an ELF format
+       debug info file.  We do not want the program headers.  */
+    ;
+  else if (! bfd_copy_private_bfd_data (ibfd, obfd))
     {
       non_fatal (_("%s: error copying private BFD data: %s"),
                 bfd_get_filename (obfd),
@@ -1599,27 +1789,34 @@ setup_section (ibfd, isection, obfdarg)
   flagword flags;
   const char *err;
   const char * name;
+  char *prefix = NULL;
 
-  if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
-      && (strip_symbols == STRIP_DEBUG
-         || strip_symbols == STRIP_UNNEEDED
-         || strip_symbols == STRIP_ALL
-         || discard_locals == LOCALS_ALL
-         || convert_debugging))
+  if (is_strip_section (ibfd, isection))
     return;
 
   p = find_section_list (bfd_section_name (ibfd, isection), FALSE);
   if (p != NULL)
     p->used = TRUE;
 
-  if (sections_removed && p != NULL && p->remove)
-    return;
-  if (sections_copied && (p == NULL || ! p->copy))
-    return;
-
   /* Get the, possibly new, name of the output section.  */
   name = find_section_rename (ibfd, isection, & flags);
 
+  /* Prefix sections.  */
+  if ((prefix_alloc_sections_string) && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
+    prefix = prefix_alloc_sections_string;
+  else if (prefix_sections_string)
+    prefix = prefix_sections_string;
+
+  if (prefix)
+    {
+      char *n;
+
+      n = xmalloc (strlen (prefix) + strlen (name) + 1);
+      strcpy (n, prefix);
+      strcat (n, name);
+      name = n;
+    }
+
   osection = bfd_make_section_anyway (obfd, name);
 
   if (osection == NULL)
@@ -1695,7 +1892,12 @@ setup_section (ibfd, isection, obfdarg)
 
   /* Allow the BFD backend to copy any private data it understands
      from the input section to the output section.  */
-  if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
+  if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+      && strip_symbols == STRIP_NONDEBUG)
+    /* Do not copy the private data when creating an ELF format
+       debug info file.  We do not want the program headers.  */
+    ;
+  else if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
     {
       err = _("private data");
       goto loser;
@@ -1736,31 +1938,21 @@ copy_section (ibfd, isection, obfdarg)
   if (status != 0)
     return;
 
-  flags = bfd_get_section_flags (ibfd, isection);
-  if ((flags & SEC_DEBUGGING) != 0
-      && (strip_symbols == STRIP_DEBUG
-         || strip_symbols == STRIP_UNNEEDED
-         || strip_symbols == STRIP_ALL
-         || discard_locals == LOCALS_ALL
-         || convert_debugging))
+  if (is_strip_section (ibfd, isection))
     return;
 
+  flags = bfd_get_section_flags (ibfd, isection);
   if ((flags & SEC_GROUP) != 0)
     return;
 
-  p = find_section_list (bfd_section_name (ibfd, isection), FALSE);
-
-  if (sections_removed && p != NULL && p->remove)
-    return;
-  if (sections_copied && (p == NULL || ! p->copy))
-    return;
-
   osection = isection->output_section;
   size = bfd_get_section_size_before_reloc (isection);
 
   if (size == 0 || osection == 0)
     return;
 
+  p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
+
   /* Core files do not need to be relocated.  */
   if (bfd_get_format (obfd) == bfd_core)
     relsize = 0;
@@ -2022,9 +2214,12 @@ strip_main (argc, argv)
      int argc;
      char *argv[];
 {
-  char *input_target = NULL, *output_target = NULL;
+  char *input_target = NULL;
+  char *output_target = NULL;
   bfd_boolean show_version = FALSE;
-  int c, i;
+  bfd_boolean formats_info = FALSE;
+  int c;
+  int i;
   struct section_list *p;
   char *output_file = NULL;
 
@@ -2082,6 +2277,12 @@ strip_main (argc, argv)
        case 'V':
          show_version = TRUE;
          break;
+       case OPTION_FORMATS_INFO:
+         formats_info = TRUE;
+         break;
+       case OPTION_ONLY_KEEP_DEBUG:
+         strip_symbols = STRIP_NONDEBUG;
+         break;
        case 0:
          /* We've been given a long option.  */
          break;
@@ -2093,6 +2294,12 @@ strip_main (argc, argv)
        }
     }
 
+ if (formats_info)
+   {
+     display_info ();
+     return 0;
+   }
   if (show_version)
     print_version ("strip");
 
@@ -2155,10 +2362,13 @@ copy_main (argc, argv)
      char *argv[];
 {
   char * binary_architecture = NULL;
-  char *input_filename = NULL, *output_filename = NULL;
-  char *input_target = NULL, *output_target = NULL;
+  char *input_filename = NULL;
+  char *output_filename = NULL;
+  char *input_target = NULL;
+  char *output_target = NULL;
   bfd_boolean show_version = FALSE;
   bfd_boolean change_warn = TRUE;
+  bfd_boolean formats_info = FALSE;
   int c;
   struct section_list *p;
   struct stat statbuf;
@@ -2226,6 +2436,14 @@ copy_main (argc, argv)
          strip_symbols = STRIP_UNNEEDED;
          break;
 
+       case OPTION_ONLY_KEEP_DEBUG:
+         strip_symbols = STRIP_NONDEBUG;
+         break;
+
+       case OPTION_ADD_GNU_DEBUGLINK:
+         gnu_debuglink_filename = optarg;
+         break;
+
        case 'K':
          add_specific_symbol (optarg, &keep_specific_list);
          break;
@@ -2266,6 +2484,10 @@ copy_main (argc, argv)
          show_version = TRUE;
          break;
 
+       case OPTION_FORMATS_INFO:
+         formats_info = TRUE;
+         break;
+
        case OPTION_WEAKEN:
          weaken = TRUE;
          break;
@@ -2464,13 +2686,17 @@ copy_main (argc, argv)
            target = (char *) xmalloc (len + 1);
            strcpy (target, nextarg);
 
-           redefine_list_append (source, target);
+           redefine_list_append ("--redefine-sym", source, target);
 
            free (source);
            free (target);
          }
          break;
 
+       case OPTION_REDEFINE_SYMS:
+         add_redefine_syms_file (optarg);
+         break;
+
        case OPTION_SET_SECTION_FLAGS:
          {
            const char *s;
@@ -2576,8 +2802,21 @@ copy_main (argc, argv)
            fatal (_("alternate machine code index must be positive"));
          break;
 
+       case OPTION_PREFIX_SYMBOLS:
+         prefix_symbols_string = optarg;
+         break;
+
+       case OPTION_PREFIX_SECTIONS:
+         prefix_sections_string = optarg;
+         break;
+
+       case OPTION_PREFIX_ALLOC_SECTIONS:
+         prefix_alloc_sections_string = optarg;
+         break;
+
        case 0:
-         break;                /* we've been given a long option */
+         /* We've been given a long option.  */
+         break;
 
        case 'H':
        case 'h':
@@ -2588,6 +2827,12 @@ copy_main (argc, argv)
        }
     }
 
+  if (formats_info)
+    {
+      display_info ();
+      return 0;
+    }
   if (show_version)
     print_version ("objcopy");
 
@@ -2632,10 +2877,10 @@ copy_main (argc, argv)
     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 (output_filename == (char *) NULL)
+  /* 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))
     {
       char *tmpname = make_tempname (input_filename);
 
This page took 0.040016 seconds and 4 git commands to generate.