* configure: Regenerate.
[binutils-gdb.git] / binutils / objcopy.c
index 2048827f8e17f21d9bdf06545466247f7b2b1fc2..a9b0d3717d804c1d231eccba250c109b623bbfd2 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
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -442,11 +442,6 @@ 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 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 setup_bfd_headers (bfd *, bfd *);
@@ -466,7 +461,7 @@ copy_usage (FILE *stream, int exit_status)
   fprintf (stream, _("\
   -I --input-target <bfdname>      Assume input file is in format <bfdname>\n\
   -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
-  -B --binary-architecture <arch>  Set arch of output file, when input is binary\n\
+  -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\
@@ -1237,7 +1232,7 @@ add_redefine_syms_file (const char *filename)
           filename, strerror (errno));
 
   bufsize = 100;
-  buf = (char *) xmalloc (bufsize);
+  buf = (char *) xmalloc (bufsize + 1 /* For the terminating NUL.  */);
 
   lineno = 1;
   c = getc (file);
@@ -1254,7 +1249,7 @@ add_redefine_syms_file (const char *filename)
          if (len >= bufsize)
            {
              bufsize *= 2;
-             buf = (char *) xrealloc (buf, bufsize);
+             buf = (char *) xrealloc (buf, bufsize + 1);
            }
          c = getc (file);
        }
@@ -1280,7 +1275,7 @@ add_redefine_syms_file (const char *filename)
          if (len >= bufsize)
            {
              bufsize *= 2;
-             buf = (char *) xrealloc (buf, bufsize);
+             buf = (char *) xrealloc (buf, bufsize + 1);
            }
          c = getc (file);
        }
@@ -1401,7 +1396,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd)
    Returns TRUE upon success, FALSE otherwise.  */
 
 static bfd_boolean
-copy_object (bfd *ibfd, bfd *obfd)
+copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
 {
   bfd_vma start;
   long symcount;
@@ -1466,6 +1461,18 @@ copy_object (bfd *ibfd, bfd *obfd)
   /* Copy architecture of input file to output file.  */
   iarch = bfd_get_arch (ibfd);
   imach = bfd_get_mach (ibfd);
+  if (input_arch)
+    {
+      if (bfd_get_arch_info (ibfd) == NULL
+         || bfd_get_arch_info (ibfd)->arch == bfd_arch_unknown)
+       {
+         iarch = input_arch->arch;
+         imach = input_arch->mach;
+       }
+      else
+       non_fatal (_("Input file `%s' ignores binary architecture parameter."),
+                  bfd_get_archive_filename (ibfd));
+    }
   if (!bfd_set_arch_mach (obfd, iarch, imach)
       && (ibfd->target_defaulted
          || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
@@ -1474,7 +1481,7 @@ copy_object (bfd *ibfd, bfd *obfd)
        non_fatal (_("Unable to recognise the format of the input file `%s'"),
                   bfd_get_archive_filename (ibfd));
       else
-       non_fatal (_("Warning: Output file cannot represent architecture `%s'"),
+       non_fatal (_("Output file cannot represent architecture `%s'"),
                   bfd_printable_arch_mach (bfd_get_arch (ibfd),
                                            bfd_get_mach (ibfd)));
       return FALSE;
@@ -1601,7 +1608,12 @@ copy_object (bfd *ibfd, bfd *obfd)
            }
          else
            {
-             padd->section = bfd_make_section_with_flags (obfd, padd->name, flags);
+             /* We use LINKER_CREATED here so that the backend hooks
+                will create any special section type information,
+                instead of presuming we know what we're doing merely
+                because we set the flags.  */
+             padd->section = bfd_make_section_with_flags
+               (obfd, padd->name, flags | SEC_LINKER_CREATED);
              if (padd->section == NULL)
                {
                  bfd_nonfatal_message (NULL, obfd, NULL,
@@ -1956,7 +1968,8 @@ copy_object (bfd *ibfd, bfd *obfd)
 
 static void
 copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
-             bfd_boolean force_output_target)
+             bfd_boolean force_output_target,
+             const bfd_arch_info_type *input_arch)
 {
   struct name_list
     {
@@ -2050,7 +2063,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
              return;
            }
 
-         del = ! copy_object (this_element, output_bfd);
+         del = ! copy_object (this_element, output_bfd, input_arch);
 
          if (! del
              || bfd_get_arch (this_element) != bfd_arch_unknown)
@@ -2155,7 +2168,8 @@ set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_h
 
 static void
 copy_file (const char *input_filename, const char *output_filename,
-          const char *input_target,   const char *output_target)
+          const char *input_target,   const char *output_target,
+          const bfd_arch_info_type *input_arch)
 {
   bfd *ibfd;
   char **obj_matching;
@@ -2206,7 +2220,7 @@ copy_file (const char *input_filename, const char *output_filename,
       /* This is a no-op on non-Coff targets.  */
       set_long_section_mode (obfd, ibfd, long_section_names);
 
-      copy_archive (ibfd, obfd, output_target, force_output_target);
+      copy_archive (ibfd, obfd, output_target, force_output_target, input_arch);
     }
   else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
     {
@@ -2228,7 +2242,7 @@ copy_file (const char *input_filename, const char *output_filename,
       /* This is a no-op on non-Coff targets.  */
       set_long_section_mode (obfd, ibfd, long_section_names);
 
-      if (! copy_object (ibfd, obfd))
+      if (! copy_object (ibfd, obfd, input_arch))
        status = 1;
 
       if (!bfd_close (obfd))
@@ -2286,28 +2300,28 @@ static void
 add_section_rename (const char * old_name, const char * new_name,
                    flagword flags)
 {
-  section_rename * rename;
+  section_rename * srename;
 
   /* Check for conflicts first.  */
-  for (rename = section_rename_list; rename != NULL; rename = rename->next)
-    if (strcmp (rename->old_name, old_name) == 0)
+  for (srename = section_rename_list; srename != NULL; srename = srename->next)
+    if (strcmp (srename->old_name, old_name) == 0)
       {
        /* Silently ignore duplicate definitions.  */
-       if (strcmp (rename->new_name, new_name) == 0
-           && rename->flags == flags)
+       if (strcmp (srename->new_name, new_name) == 0
+           && srename->flags == flags)
          return;
 
        fatal (_("Multiple renames of section %s"), old_name);
       }
 
-  rename = (section_rename *) xmalloc (sizeof (* rename));
+  srename = (section_rename *) xmalloc (sizeof (* srename));
 
-  rename->old_name = old_name;
-  rename->new_name = new_name;
-  rename->flags    = flags;
-  rename->next     = section_rename_list;
+  srename->old_name = old_name;
+  srename->new_name = new_name;
+  srename->flags    = flags;
+  srename->next     = section_rename_list;
 
-  section_rename_list = rename;
+  section_rename_list = srename;
 }
 
 /* Check the section rename list for a new name of the input section
@@ -2319,18 +2333,18 @@ find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
                     flagword * returned_flags)
 {
   const char * old_name = bfd_section_name (ibfd, isection);
-  section_rename * rename;
+  section_rename * srename;
 
   /* Default to using the flags of the input section.  */
   * returned_flags = bfd_get_section_flags (ibfd, isection);
 
-  for (rename = section_rename_list; rename != NULL; rename = rename->next)
-    if (strcmp (rename->old_name, old_name) == 0)
+  for (srename = section_rename_list; srename != NULL; srename = srename->next)
+    if (strcmp (srename->old_name, old_name) == 0)
       {
-       if (rename->flags != (flagword) -1)
-         * returned_flags = rename->flags;
+       if (srename->flags != (flagword) -1)
+         * returned_flags = srename->flags;
 
-       return rename->new_name;
+       return srename->new_name;
       }
 
   return old_name;
@@ -3009,7 +3023,7 @@ strip_main (int argc, char *argv[])
        }
 
       status = 0;
-      copy_file (argv[i], tmpname, input_target, output_target);
+      copy_file (argv[i], tmpname, input_target, output_target, NULL);
       if (status == 0)
        {
          if (preserve_dates)
@@ -3144,7 +3158,6 @@ convert_efi_target (char *efi)
 static int
 copy_main (int argc, char *argv[])
 {
-  char * binary_architecture = NULL;
   char *input_filename = NULL;
   char *output_filename = NULL;
   char *tmpname;
@@ -3156,6 +3169,7 @@ copy_main (int argc, char *argv[])
   int c;
   struct section_list *p;
   struct stat statbuf;
+  const bfd_arch_info_type *input_arch = NULL;
 
   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)
@@ -3169,7 +3183,9 @@ copy_main (int argc, char *argv[])
          break;
 
        case 'B':
-         binary_architecture = optarg;
+         input_arch = bfd_scan_arch (optarg);
+         if (input_arch == NULL)
+           fatal (_("architecture %s unknown"), optarg);
          break;
 
        case 'i':
@@ -3295,10 +3311,8 @@ copy_main (int argc, char *argv[])
        case OPTION_ADD_SECTION:
          {
            const char *s;
-           off_t size;
+           size_t off, alloc;
            struct section_add *pa;
-           int len;
-           char *name;
            FILE *f;
 
            s = strchr (optarg, '=');
@@ -3306,34 +3320,40 @@ copy_main (int argc, char *argv[])
            if (s == NULL)
              fatal (_("bad format for %s"), "--add-section");
 
-           size = get_file_size (s + 1);
-           if (size < 1)
-             {
-               status = 1;
-               break;
-             }
-
            pa = (struct section_add *) xmalloc (sizeof (struct section_add));
-
-           len = s - optarg;
-           name = (char *) xmalloc (len + 1);
-           strncpy (name, optarg, len);
-           name[len] = '\0';
-           pa->name = name;
-
+           pa->name = xstrndup (optarg, s - optarg);
            pa->filename = s + 1;
-           pa->size = size;
-           pa->contents = (bfd_byte *) xmalloc (size);
 
-           f = fopen (pa->filename, FOPEN_RB);
+           /* We don't use get_file_size so that we can do
+                --add-section .note.GNU_stack=/dev/null
+              get_file_size doesn't work on /dev/null.  */
 
+           f = fopen (pa->filename, FOPEN_RB);
            if (f == NULL)
              fatal (_("cannot open: %s: %s"),
                     pa->filename, strerror (errno));
 
-           if (fread (pa->contents, 1, pa->size, f) == 0
-               || ferror (f))
-             fatal (_("%s: fread failed"), pa->filename);
+           off = 0;
+           alloc = 4096;
+           pa->contents = (bfd_byte *) xmalloc (alloc);
+           while (!feof (f))
+             {
+               off_t got;
+
+               if (off == alloc)
+                 {
+                   alloc <<= 1;
+                   pa->contents = (bfd_byte *) xrealloc (pa->contents, alloc);
+                 }
+
+               got = fread (pa->contents + off, 1, alloc - off, f);
+               if (ferror (f))
+                 fatal (_("%s: fread failed"), pa->filename);
+
+               off += got;
+             }
+
+           pa->size = off;
 
            fclose (f);
 
@@ -3824,29 +3844,6 @@ copy_main (int argc, char *argv[])
       convert_efi_target (efi);
     }
 
-  if (binary_architecture != NULL)
-    {
-      if (input_target && strcmp (input_target, "binary") == 0)
-       {
-         const bfd_arch_info_type * temp_arch_info;
-
-         temp_arch_info = bfd_scan_arch (binary_architecture);
-
-         if (temp_arch_info != NULL)
-           {
-             bfd_external_binary_architecture = temp_arch_info->arch;
-             bfd_external_machine             = temp_arch_info->mach;
-           }
-         else
-           fatal (_("architecture %s unknown"), binary_architecture);
-       }
-      else
-       {
-         non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
-         non_fatal (_(" Argument %s ignored"), binary_architecture);
-       }
-    }
-
   if (preserve_dates)
     if (stat (input_filename, & statbuf) < 0)
       fatal (_("warning: could not locate '%s'.  System error message: %s"),
@@ -3863,7 +3860,7 @@ copy_main (int argc, char *argv[])
     fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
           input_filename, strerror (errno));
 
-  copy_file (input_filename, tmpname, input_target, output_target);
+  copy_file (input_filename, tmpname, input_target, output_target, input_arch);
   if (status == 0)
     {
       if (preserve_dates)