2005-06-14 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 14 Jun 2005 13:26:42 +0000 (13:26 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 14 Jun 2005 13:26:42 +0000 (13:26 +0000)
PR 995
* ar.c (BUFSIZE): Moved to ...
* bucomm.h (BUFSIZE): Here.

* bucomm.c: Include <assert.h>.
(bfd_get_archive_filename): New.
* bucomm.h (bfd_get_archive_filename): New.

* objcopy.c (copy_unknown_object): New.
(copy_object): Use bfd_get_archive_filename when reporting input
error. Don't call fatal on unknown arch.
(copy_archive): Call copy_unknown_object on unknown format or
arch.

binutils/ChangeLog
binutils/ar.c
binutils/bucomm.c
binutils/bucomm.h
binutils/objcopy.c

index 4fa37ba9418c9717daaa5bd1e48708ccb030e76c..d60f6a2bf2c53a1a41075c7aaa422b012a2e548c 100644 (file)
@@ -1,3 +1,19 @@
+2005-06-14  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 995
+       * ar.c (BUFSIZE): Moved to ...
+       * bucomm.h (BUFSIZE): Here.
+
+       * bucomm.c: Include <assert.h>.
+       (bfd_get_archive_filename): New.
+       * bucomm.h (bfd_get_archive_filename): New.
+
+       * objcopy.c (copy_unknown_object): New.
+       (copy_object): Use bfd_get_archive_filename when reporting input
+       error. Don't call fatal on unknown arch.
+       (copy_archive): Call copy_unknown_object on unknown format or
+       arch.
+
 2005-06-14  Jakub Jelinek  <jakub@redhat.com>
 
        * readelf.c (cmalloc, xcmalloc, xcrealloc): New functions.
index e8b03790522628c51dfadafa2676f168dc5aa5ee..4e53c787d0730da08735b912bb3e7c14992c8e43 100644 (file)
@@ -49,8 +49,6 @@
 #define O_BINARY 0
 #endif
 
-#define BUFSIZE 8192
-
 /* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
 
 struct ar_hdr *
index f29e6663ab540e7e415827a00e2188e5ffc910ca..a2caa2f01c1307e7a33ff5057861bffbab55c73c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <sys/stat.h>
 #include <time.h>              /* ctime, maybe time_t */
+#include <assert.h>
 
 #ifndef HAVE_TIME_T_IN_TIME_H
 #ifndef HAVE_TIME_T_IN_TYPES_H
@@ -475,3 +476,38 @@ get_file_size (const char * file_name)
 
   return 0;
 }
+
+/* Return the filename in a static buffer.  */
+
+const char *
+bfd_get_archive_filename (bfd *abfd)
+{
+  static size_t curr = 0;
+  static char *buf;
+  size_t needed;
+
+  assert (abfd != NULL);
+  
+  if (!abfd->my_archive)
+    return bfd_get_filename (abfd);
+
+  needed = (strlen (bfd_get_filename (abfd->my_archive))
+           + strlen (bfd_get_filename (abfd)) + 3);
+  if (needed > curr)
+    {
+      if (curr)
+       free (buf);
+      curr = needed + (needed >> 1);
+      buf = bfd_malloc (curr);
+      /* If we can't malloc, fail safe by returning just the file name.
+        This function is only used when building error messages.  */
+      if (!buf)
+       {
+         curr = 0;
+         return bfd_get_filename (abfd);
+       }
+    }
+  sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
+          bfd_get_filename (abfd));
+  return buf;
+}
index aa152fa83af9e738b1d1a4ecd7c53a872d42d478..863964611caf81441cea9ec9a7cade2bd495ef21 100644 (file)
@@ -147,7 +147,14 @@ void *alloca ();
 # define N_(String) (String)
 #endif
 
+/* Used by ar.c and objcopy.c.  */
+#define BUFSIZE 8192
+
 /* bucomm.c */
+
+/* Return the filename in a static buffer.  */
+const char *bfd_get_archive_filename (bfd *);
+
 void bfd_nonfatal (const char *);
 
 void bfd_fatal (const char *) ATTRIBUTE_NORETURN;
index d8feae60d8fbf3c952add55a32f758acd0d53205..4dfba3c7b79a1cf48f83b971f63fd56c17ced122 100644 (file)
@@ -1120,6 +1120,74 @@ add_redefine_syms_file (const char *filename)
   free (buf);
 }
 
+/* Copy unkown object file IBFD onto OBFD.
+   Returns TRUE upon success, FALSE otherwise.  */
+
+static bfd_boolean
+copy_unknown_object (bfd *ibfd, bfd *obfd)
+{
+  char *cbuf;
+  int tocopy;
+  long ncopied;
+  long size;
+  struct stat buf;
+
+  if (bfd_stat_arch_elt (ibfd, &buf) != 0)
+    {
+      bfd_nonfatal (bfd_get_archive_filename (ibfd));
+      return FALSE;
+    }
+
+  size = buf.st_size;
+  if (size < 0)
+    {
+      non_fatal (_("stat returns negative size for `%s'"),
+                bfd_get_archive_filename (ibfd));
+      return FALSE;
+    }
+
+  if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0)
+    {
+      bfd_nonfatal (bfd_get_archive_filename (ibfd));
+      return FALSE;
+    }
+
+  if (verbose)
+    printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
+           bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
+
+  cbuf = xmalloc (BUFSIZE);
+  ncopied = 0;
+  while (ncopied < size)
+    {
+      tocopy = size - ncopied;
+      if (tocopy > BUFSIZE)
+       tocopy = BUFSIZE;
+
+      if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
+         != (bfd_size_type) tocopy)
+       {
+         bfd_nonfatal (bfd_get_archive_filename (ibfd));
+         free (cbuf);
+         return FALSE;
+       }
+
+      if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
+         != (bfd_size_type) tocopy)
+       {
+         bfd_nonfatal (bfd_get_filename (obfd));
+         free (cbuf);
+         return FALSE;
+       }
+
+      ncopied += tocopy;
+    }
+
+  chmod (bfd_get_filename (obfd), buf.st_mode);
+  free (cbuf);
+  return TRUE;
+}
+
 /* Copy object file IBFD onto OBFD.
    Returns TRUE upon success, FALSE otherwise.  */
 
@@ -1149,8 +1217,8 @@ copy_object (bfd *ibfd, bfd *obfd)
     }
 
   if (verbose)
-    printf (_("copy from %s(%s) to %s(%s)\n"),
-           bfd_get_filename (ibfd), bfd_get_target (ibfd),
+    printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
+           bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
            bfd_get_filename (obfd), bfd_get_target (obfd));
 
   if (set_start_set)
@@ -1173,7 +1241,7 @@ copy_object (bfd *ibfd, bfd *obfd)
       if (!bfd_set_start_address (obfd, start)
          || !bfd_set_file_flags (obfd, flags))
        {
-         bfd_nonfatal (bfd_get_filename (ibfd));
+         bfd_nonfatal (bfd_get_archive_filename (ibfd));
          return FALSE;
        }
     }
@@ -1186,20 +1254,18 @@ copy_object (bfd *ibfd, bfd *obfd)
          || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
     {
       if (bfd_get_arch (ibfd) == bfd_arch_unknown)
-       fatal (_("Unable to recognise the format of the input file %s"),
-              bfd_get_filename (ibfd));
+       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"),
-                    bfd_printable_arch_mach (bfd_get_arch (ibfd),
-                                             bfd_get_mach (ibfd)));
-         return FALSE;
-       }
+       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)))
     {
-      bfd_nonfatal (bfd_get_filename (ibfd));
+      bfd_nonfatal (bfd_get_archive_filename (ibfd));
       return FALSE;
     }
 
@@ -1385,7 +1451,7 @@ copy_object (bfd *ibfd, bfd *obfd)
   symsize = bfd_get_symtab_upper_bound (ibfd);
   if (symsize < 0)
     {
-      bfd_nonfatal (bfd_get_filename (ibfd));
+      bfd_nonfatal (bfd_get_archive_filename (ibfd));
       return FALSE;
     }
 
@@ -1634,13 +1700,35 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
        RETURN_NONFATAL (output_name);
 
       if (bfd_check_format (this_element, bfd_object))
-       delete = ! copy_object (this_element, output_bfd);
+       {
+         delete = ! copy_object (this_element, output_bfd);
 
-      if (!bfd_close (output_bfd))
+         if (! delete
+             || bfd_get_arch (this_element) != bfd_arch_unknown)
+           {
+             if (!bfd_close (output_bfd))
+               {
+                 bfd_nonfatal (bfd_get_filename (output_bfd));
+                 /* Error in new object file. Don't change archive.  */
+                 status = 1;
+               }
+           }
+         else
+           goto copy_unknown_element;
+       }
+      else
        {
-         bfd_nonfatal (bfd_get_filename (output_bfd));
-         /* Error in new object file. Don't change archive.  */
-         status = 1;
+         non_fatal (_("Unable to recognise the format of the input file `%s'"),
+                    bfd_get_archive_filename (this_element));
+
+copy_unknown_element:
+         delete = !copy_unknown_object (this_element, output_bfd);
+         if (!bfd_close_all_done (output_bfd))
+           {
+             bfd_nonfatal (bfd_get_filename (output_bfd));
+             /* Error in new object file. Don't change archive.  */
+             status = 1;
+           }
        }
 
       if (delete)