* configure: Ignore new autoconf configure options.
[binutils-gdb.git] / bfd / archive.c
index a968dd5d855499de1ca90e7a29274093f66c84d1..fba52a6985f4abcdc0f2f69423cb758207b0b15d 100644 (file)
@@ -16,7 +16,7 @@ GNU General Public License for more details.
 
 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
 @setfilename archive-info
@@ -175,11 +175,9 @@ static char *get_extended_arelt_filename PARAMS ((bfd *arch,
                                                  const char *name));
 static boolean do_slurp_bsd_armap PARAMS ((bfd *abfd));
 static boolean do_slurp_coff_armap PARAMS ((bfd *abfd));
-static const char *normalize PARAMS ((const char *file));
+static const char *normalize PARAMS ((bfd *, const char *file));
 static struct areltdata *bfd_ar_hdr_from_filesystem PARAMS ((bfd *abfd,
                                                             const char *));
-static boolean compute_and_write_armap PARAMS ((bfd *arch,
-                                               unsigned int elength));
 \f
 boolean
 _bfd_generic_mkarchive (abfd)
@@ -189,10 +187,7 @@ _bfd_generic_mkarchive (abfd)
                              bfd_zalloc (abfd, sizeof (struct artdata)));
 
   if (bfd_ardata (abfd) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   bfd_ardata (abfd)->cache = NULL;
   bfd_ardata (abfd)->archive_head = NULL;
@@ -238,7 +233,9 @@ bfd_get_next_mapent (abfd, prev, entry)
 
   if (prev == BFD_NO_MORE_SYMBOLS)
     prev = 0;
-  else if (++prev >= bfd_ardata (abfd)->symdef_count)
+  else
+    ++prev;
+  if (prev >= bfd_ardata (abfd)->symdef_count)
     return BFD_NO_MORE_SYMBOLS;
 
   *entry = (bfd_ardata (abfd)->symdefs + prev);
@@ -251,15 +248,7 @@ bfd *
 _bfd_create_empty_archive_element_shell (obfd)
      bfd *obfd;
 {
-  bfd *nbfd;
-
-  nbfd = _bfd_new_bfd_contained_in (obfd);
-  if (nbfd == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-  return nbfd;
+  return _bfd_new_bfd_contained_in (obfd);
 }
 
 /*
@@ -310,10 +299,7 @@ _bfd_add_bfd_to_archive_cache (arch_bfd, filepos, new_elt)
                                            sizeof (struct ar_cache)));
 
   if (new_cache == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   new_cache->ptr = filepos;
   new_cache->arelt = new_elt;
@@ -365,8 +351,8 @@ get_extended_arelt_filename (arch, name)
    could have been moved arbitrarily.
 */
 
-struct areltdata *
-_bfd_snarf_ar_hdr (abfd)
+PTR
+_bfd_generic_read_ar_hdr (abfd)
      bfd *abfd;
 {
 #ifndef errno
@@ -430,10 +416,7 @@ _bfd_snarf_ar_hdr (abfd)
 
       allocptr = bfd_zalloc (abfd, allocsize);
       if (allocptr == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return NULL;
-       }
+       return NULL;
       filename = (allocptr
                  + sizeof (struct areltdata)
                  + sizeof (struct ar_hdr));
@@ -473,10 +456,7 @@ _bfd_snarf_ar_hdr (abfd)
     {
       allocptr = bfd_zalloc (abfd, allocsize);
       if (allocptr == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return NULL;
-       }
+       return NULL;
     }
 
   ared = (struct areltdata *) allocptr;
@@ -496,7 +476,7 @@ _bfd_snarf_ar_hdr (abfd)
       ared->filename[namelen] = '\0';
     }
 
-  return ared;
+  return (PTR) ared;
 }
 \f
 /* This is an internal function; it's mainly used when indexing
@@ -518,7 +498,7 @@ _bfd_get_elt_at_filepos (archive, filepos)
   if (0 > bfd_seek (archive, filepos, SEEK_SET))
     return NULL;
 
-  if ((new_areldata = _bfd_snarf_ar_hdr (archive)) == NULL)
+  if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL)
     return NULL;
 
   n_nfd = _bfd_create_empty_archive_element_shell (archive);
@@ -627,8 +607,11 @@ const bfd_target *
 bfd_generic_archive_p (abfd)
      bfd *abfd;
 {
+  struct artdata *tdata_hold;
   char armag[SARMAG + 1];
 
+  tdata_hold = abfd->tdata.aout_ar_data;
+
   if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG)
     {
       if (bfd_get_error () != bfd_error_system_call)
@@ -651,10 +634,7 @@ bfd_generic_archive_p (abfd)
                              bfd_zalloc (abfd, sizeof (struct artdata)));
 
   if (bfd_ardata (abfd) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   bfd_ardata (abfd)->first_file_filepos = SARMAG;
   bfd_ardata (abfd)->cache = NULL;
@@ -666,17 +646,61 @@ bfd_generic_archive_p (abfd)
   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd)))
     {
       bfd_release (abfd, bfd_ardata (abfd));
-      abfd->tdata.aout_ar_data = NULL;
+      abfd->tdata.aout_ar_data = tdata_hold;
       return NULL;
     }
 
   if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
     {
       bfd_release (abfd, bfd_ardata (abfd));
-      abfd->tdata.aout_ar_data = NULL;
+      abfd->tdata.aout_ar_data = tdata_hold;
       return NULL;
     }
 
+  if (bfd_has_map (abfd))
+    {
+      bfd *first;
+
+      /* This archive has a map, so we may presume that the contents
+        are object files.  Make sure that the first file in the
+        archive can be recognized as an object file for this target.
+        If not, assume that this is the wrong format.
+
+        This is done because any normal format will recognize any
+        normal archive, regardless of the format of the object files.
+        We do accept an empty archive.  */
+
+      first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+      if (first != NULL)
+       {
+         boolean fail;
+
+         first->target_defaulted = false;
+         fail = false;
+         if (! bfd_check_format (first, bfd_object))
+           fail = true;
+         else if (first->xvec != abfd->xvec)
+           {
+             bfd_set_error (bfd_error_wrong_format);
+             fail = true;
+           }
+         if (fail)
+           {
+             bfd_error_type err;
+
+             err = bfd_get_error ();
+             (void) bfd_close (first);
+             bfd_release (abfd, bfd_ardata (abfd));
+             abfd->tdata.aout_ar_data = tdata_hold;
+             bfd_set_error (err);
+             return NULL;
+           }
+
+         /* We ought to close first here, but we can't, because we
+             have no way to remove it from the archive cache.  FIXME.  */
+       }
+    }
+
   return abfd->xvec;
 }
 
@@ -711,7 +735,7 @@ do_slurp_bsd_armap (abfd)
   unsigned int parsed_size;
   carsym *set;
 
-  mapdata = _bfd_snarf_ar_hdr (abfd);
+  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
   if (mapdata == NULL)
     return false;
   parsed_size = mapdata->parsed_size;
@@ -719,10 +743,7 @@ do_slurp_bsd_armap (abfd)
 
   raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
   if (raw_armap == (bfd_byte *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
     {
@@ -752,10 +773,7 @@ do_slurp_bsd_armap (abfd)
                                          (ardata->symdef_count
                                           * sizeof (carsym)));
   if (!ardata->symdefs)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   for (counter = 0, set = ardata->symdefs;
        counter < ardata->symdef_count;
@@ -792,7 +810,7 @@ do_slurp_coff_armap (abfd)
   char int_buf[sizeof (long)];
   unsigned int carsym_size, ptrsize, i;
 
-  mapdata = _bfd_snarf_ar_hdr (abfd);
+  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
   if (mapdata == NULL)
     return false;
   parsed_size = mapdata->parsed_size;
@@ -833,20 +851,14 @@ do_slurp_coff_armap (abfd)
 
   ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);
   if (ardata->symdefs == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   carsyms = ardata->symdefs;
   stringbase = ((char *) ardata->symdefs) + carsym_size;
 
   /* Allocate and read in the raw offsets. */
   raw_armap = (int *) bfd_alloc (abfd, ptrsize);
   if (raw_armap == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto release_symdefs;
-    }
+    goto release_symdefs;
   if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize
       || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize)
     {
@@ -871,8 +883,29 @@ do_slurp_coff_armap (abfd)
   /* Pad to an even boundary if you have to */
   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
 
+
   bfd_has_map (abfd) = true;
   bfd_release (abfd, (PTR) raw_armap);
+
+
+  /* Check for a second archive header (as used by PE) */
+  {
+    struct areltdata *tmp;
+
+    bfd_seek (abfd,   ardata->first_file_filepos, SEEK_SET);
+    tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+    if (tmp != NULL) 
+      {
+       if (tmp->arch_header[0] == '/'
+           && tmp->arch_header[1] == ' ') 
+         {
+           ardata->first_file_filepos +=
+             (tmp->parsed_size + sizeof(struct ar_hdr) + 1) & ~1;
+         }
+       bfd_release (abfd, tmp);
+      }
+  }
+
   return true;
 
 release_raw_armap:
@@ -950,14 +983,13 @@ bfd_slurp_bsd_armap_f2 (abfd)
       return true;
     }
 
-  mapdata = _bfd_snarf_ar_hdr (abfd);
+  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
   if (mapdata == NULL)
     return false;
 
   raw_armap = (bfd_byte *) bfd_zalloc (abfd, mapdata->parsed_size);
   if (raw_armap == NULL)
     {
-      bfd_set_error (bfd_error_no_memory);
     byebye:
       bfd_release (abfd, (PTR) mapdata);
       return false;
@@ -995,10 +1027,7 @@ bfd_slurp_bsd_armap_f2 (abfd)
                                          (ardata->symdef_count
                                           * BSD_SYMDEF_SIZE));
   if (!ardata->symdefs)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   for (counter = 0, set = ardata->symdefs;
        counter < ardata->symdef_count;
@@ -1038,9 +1067,9 @@ _bfd_slurp_extended_name_table (abfd)
 
   /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ,
      we probably don't want to return true.  */
+  bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
   if (bfd_read ((PTR) nextname, 1, 16, abfd) == 16)
     {
-
       if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
        return false;
 
@@ -1051,7 +1080,7 @@ _bfd_slurp_extended_name_table (abfd)
          return true;
        }
 
-      namedata = _bfd_snarf_ar_hdr (abfd);
+      namedata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
       if (namedata == NULL)
        return false;
 
@@ -1059,7 +1088,6 @@ _bfd_slurp_extended_name_table (abfd)
        bfd_zalloc (abfd, namedata->parsed_size);
       if (bfd_ardata (abfd)->extended_names == NULL)
        {
-         bfd_set_error (bfd_error_no_memory);
        byebye:
          bfd_release (abfd, (PTR) namedata);
          return false;
@@ -1078,13 +1106,17 @@ _bfd_slurp_extended_name_table (abfd)
       /* Since the archive is supposed to be printable if it contains
         text, the entries in the list are newline-padded, not null
         padded. In SVR4-style archives, the names also have a
-        trailing '/'.  We'll fix both problems here..  */
+        trailing '/'.  DOS/NT created archive often have \ in them
+        We'll fix all problems here..  */
       {
        char *temp = bfd_ardata (abfd)->extended_names;
        char *limit = temp + namedata->parsed_size;
-       for (; temp < limit; ++temp)
+       for (; temp < limit; ++temp) {
          if (*temp == '\012')
            temp[temp[-1] == '/' ? -1 : 0] = '\0';
+         if (*temp == '\\')
+           *temp = '/';
+       }
       }
 
       /* Pad to an even boundary if you have to */
@@ -1104,7 +1136,8 @@ _bfd_slurp_extended_name_table (abfd)
 /* Return a copy of the stuff in the filename between any :]> and a
    semicolon */
 static const char *
-normalize (file)
+normalize (abfd, file)
+     bfd *abfd;
      const char *file;
 {
   CONST char *first;
@@ -1126,10 +1159,9 @@ normalize (file)
       first--;
     }
 
-
-  copy = malloc (last - first + 1);
-  if (!copy)
-    return copy;
+  copy = (char *) bfd_alloc (abfd, last - first + 1);
+  if (copy == NULL)
+    return NULL;
 
   memcpy (copy, first, last - first);
   copy[last - first] = 0;
@@ -1139,10 +1171,11 @@ normalize (file)
 
 #else
 static const char *
-normalize (file)
+normalize (abfd, file)
+     bfd *abfd;
      const char *file;
 {
-  CONST char *filename = strrchr (file, '/');
+  const char *filename = strrchr (file, '/');
 
   if (filename != (char *) NULL)
     filename++;
@@ -1203,15 +1236,19 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
   /* Figure out how long the table should be */
   for (current = abfd->archive_head; current != NULL; current = current->next)
     {
-      CONST char *normal = normalize (current->filename);
+      const char *normal;
       unsigned int thislen;
 
-      if (!normal)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+      normal = normalize (current, current->filename);
+      if (normal == NULL)
+       return false;
+
       thislen = strlen (normal);
+
+      if (thislen > maxname
+         && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
+       thislen = maxname;
+
       if (thislen > maxname)
        {
          /* Add one to leave room for \n.  */
@@ -1222,6 +1259,21 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
              ++total_namelen;
            }
        }
+      else
+       {
+         struct ar_hdr *hdr = arch_hdr (current);
+         if (strncmp (normal, hdr->ar_name, thislen) != 0
+             || (thislen < sizeof hdr->ar_name
+                 && hdr->ar_name[thislen] != ar_padchar (current)))
+           {
+             /* Must have been using extended format even though it
+                didn't need to.  Fix it to use normal format.  */
+             memcpy (hdr->ar_name, normal, thislen);
+             if (thislen < maxname
+                 || (thislen == maxname && thislen < sizeof hdr->ar_name))
+               hdr->ar_name[thislen] = ar_padchar (current);
+           }
+       }
     }
 
   if (total_namelen == 0)
@@ -1229,10 +1281,7 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
 
   *tabloc = bfd_zalloc (abfd, total_namelen);
   if (*tabloc == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   *tablen = total_namelen;
   strptr = *tabloc;
@@ -1240,14 +1289,13 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
   for (current = abfd->archive_head; current != NULL; current =
        current->next)
     {
-      CONST char *normal = normalize (current->filename);
+      const char *normal;
       unsigned int thislen;
 
-      if (!normal)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+      normal = normalize (current, current->filename);
+      if (normal == NULL)
+       return false;
+
       thislen = strlen (normal);
       if (thislen > maxname)
        {
@@ -1309,10 +1357,7 @@ bfd_ar_hdr_from_filesystem (abfd, filename)
   ared = (struct areltdata *) bfd_zalloc (abfd, sizeof (struct ar_hdr) +
                                          sizeof (struct areltdata));
   if (ared == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
   hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
 
   /* ar headers are space padded, not null padded! */
@@ -1403,9 +1448,22 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr)
      intel's release is out the door. */
 
   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
-  int length;
-  CONST char *filename = normalize (pathname);
-  int maxlen = ar_maxnamelen (abfd);
+  size_t length;
+  const char *filename;
+  size_t maxlen = ar_maxnamelen (abfd);
+
+  if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
+    {
+      bfd_bsd_truncate_arname (abfd, pathname, arhdr);
+      return;
+    }
+
+  filename = normalize (abfd, pathname);
+  if (filename == NULL)
+    {
+      /* FIXME */
+      abort ();
+    }
 
   length = strlen (filename);
 
@@ -1559,7 +1617,7 @@ _bfd_write_archive_contents (arch)
 
   if (makemap && hasobjects)
     {
-      if (compute_and_write_armap (arch, elength) != true)
+      if (_bfd_compute_and_write_armap (arch, elength) != true)
        return false;
     }
 
@@ -1569,7 +1627,9 @@ _bfd_write_archive_contents (arch)
 
       memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
       strcpy (hdr.ar_name, ename);
-      sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
+      /* Round size up to even number in archive header.  */
+      sprintf (&(hdr.ar_size[0]), "%-10d",
+              (int) ((elength + 1) & ~1));
       strncpy (hdr.ar_fmag, ARFMAG, 2);
       for (i = 0; i < sizeof (struct ar_hdr); i++)
        if (((char *) (&hdr))[i] == '\0')
@@ -1632,8 +1692,8 @@ _bfd_write_archive_contents (arch)
        {
          if (bfd_update_armap_timestamp (arch))
            break;
-         fprintf (stderr,
-                  "Warning: writing archive was slow: rewriting timestamp\n");
+         (*_bfd_error_handler)
+           ("Warning: writing archive was slow: rewriting timestamp\n");
        }
       while (++tries < 6);
     }
@@ -1643,8 +1703,8 @@ _bfd_write_archive_contents (arch)
 \f
 /* Note that the namidx for the first symbol is 0 */
 
-static boolean
-compute_and_write_armap (arch, elength)
+boolean
+_bfd_compute_and_write_armap (arch, elength)
      bfd *arch;
      unsigned int elength;
 {
@@ -1672,7 +1732,7 @@ compute_and_write_armap (arch, elength)
      them when done.  */
   first_name = bfd_alloc (arch, 1);
   if (first_name == NULL)
-    goto no_memory_return;
+    goto error_return;
 
   /* Drop all the files called __.SYMDEF, we're going to make our
      own */
@@ -1744,10 +1804,10 @@ compute_and_write_armap (arch, elength)
                                             bfd_alloc (arch,
                                                        sizeof (char *)));
                      if (map[orl_count].name == NULL)
-                       goto no_memory_return;
+                       goto error_return;
                      *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
                      if (*(map[orl_count].name) == NULL)
-                       goto no_memory_return;
+                       goto error_return;
                      strcpy (*(map[orl_count].name), syms[src_count]->name);
                      (map[orl_count]).pos = (file_ptr) current;
                      (map[orl_count]).namidx = stridx;
@@ -1809,7 +1869,7 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
   bfd *current = arch->archive_head;
   bfd *last_elt = current;     /* last element arch seen */
   bfd_byte temp[4];
-  int count;
+  unsigned int count;
   struct ar_hdr hdr;
   struct stat statbuf;
   unsigned int i;
@@ -1824,8 +1884,8 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
   bfd_ardata (arch)->armap_datepos = (SARMAG
                                      + offsetof (struct ar_hdr, ar_date[0]));
   sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
-  sprintf (hdr.ar_uid, "%d", getuid ());
-  sprintf (hdr.ar_gid, "%d", getgid ());
+  sprintf (hdr.ar_uid, "%ld", (long) getuid ());
+  sprintf (hdr.ar_gid, "%ld", (long) getgid ());
   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
   strncpy (hdr.ar_fmag, ARFMAG, 2);
   for (i = 0; i < sizeof (struct ar_hdr); i++)
@@ -1895,7 +1955,7 @@ _bfd_archive_bsd_update_armap_timestamp (arch)
 {
   struct stat archstat;
   struct ar_hdr hdr;
-  int i;
+  unsigned int i;
 
   /* Flush writes, get last-write timestamp from file, and compare it
      to the timestamp IN the file.  */
@@ -1962,7 +2022,7 @@ coff_write_armap (arch, elength, map, symbol_count, stridx)
   unsigned int mapsize = stringsize + ranlibsize;
   file_ptr archive_member_file_ptr;
   bfd *current = arch->archive_head;
-  int count;
+  unsigned int count;
   struct ar_hdr hdr;
   unsigned int i;
   int padit = mapsize & 1;