* archive.c (_bfd_generic_read_ar_hdr_mag): Simplify end-of-name test.
[binutils-gdb.git] / bfd / archive.c
index fba52a6985f4abcdc0f2f69423cb758207b0b15d..33ef321434e125f4f3c0074aaa95d74c97e87d35 100644 (file)
@@ -1,5 +1,6 @@
 /* BFD back-end for archive files (libraries).
-   Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
+   Free Software Foundation, Inc.
    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -142,12 +143,9 @@ extern int errno;
 #define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB)
 #endif
 
-/* Can't define this in hosts/foo.h, because (e.g. in gprof) the hosts file
-   is included, then obstack.h, which thinks if offsetof is defined, it
-   doesn't need to include stddef.h.  */
 /* Define offsetof for those systems which lack it */
 
-#if !defined (offsetof)
+#ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
 #endif
 
@@ -355,10 +353,17 @@ PTR
 _bfd_generic_read_ar_hdr (abfd)
      bfd *abfd;
 {
-#ifndef errno
-  extern int errno;
-#endif
+  return _bfd_generic_read_ar_hdr_mag (abfd, (const char *) NULL);
+}
 
+/* Alpha ECOFF uses an optional different ARFMAG value, so we have a
+   variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */
+
+PTR
+_bfd_generic_read_ar_hdr_mag (abfd, mag)
+     bfd *abfd;
+     const char *mag;
+{
   struct ar_hdr hdr;
   char *hdrp = (char *) &hdr;
   unsigned int parsed_size;
@@ -375,7 +380,9 @@ _bfd_generic_read_ar_hdr (abfd)
        bfd_set_error (bfd_error_no_more_archived_files);
       return NULL;
     }
-  if (strncmp (hdr.ar_fmag, ARFMAG, 2))
+  if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
+      && (mag == NULL
+         || strncmp (hdr.ar_fmag, mag, 2) != 0))
     {
       bfd_set_error (bfd_error_malformed_archive);
       return NULL;
@@ -406,8 +413,10 @@ _bfd_generic_read_ar_hdr (abfd)
     }
   /* BSD4.4-style long filename.
      Only implemented for reading, so far! */
-  else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1'
-          && hdr.ar_name[2] == '/' && isdigit (hdr.ar_name[3]))
+  else if (hdr.ar_name[0] == '#'
+          && hdr.ar_name[1] == '1'
+          && hdr.ar_name[2] == '/'
+          && isdigit ((unsigned char) hdr.ar_name[3]))
     {
       /* BSD-4.4 extended name */
       namelen = atoi (&hdr.ar_name[3]);
@@ -434,21 +443,21 @@ _bfd_generic_read_ar_hdr (abfd)
         Note:  The SYSV format (terminated by '/') allows embedded
         spaces, so only look for ' ' if we don't find '/'. */
 
-      namelen = 0;
-      while (hdr.ar_name[namelen] != '\0' &&
-            hdr.ar_name[namelen] != '/')
+      char *e;
+      e = memchr(hdr.ar_name, '\0', ar_maxnamelen (abfd));
+      if (e == NULL)
        {
-         namelen++;
-         if (namelen == (unsigned) ar_maxnamelen (abfd))
-           {
-             namelen = 0;
-             while (hdr.ar_name[namelen] != ' '
-                    && namelen < (unsigned) ar_maxnamelen (abfd))
-               namelen++;
-             break;
-           }
+          e = memchr(hdr.ar_name, '/', ar_maxnamelen (abfd));
+         if (e == NULL)
+            e = memchr(hdr.ar_name, ' ', ar_maxnamelen (abfd));
+       }
+      if (e == NULL)
+       {
+         bfd_set_error (bfd_error_malformed_archive);
+         return NULL;
        }
 
+      namelen = e - hdr.ar_name;
       allocsize += namelen + 1;
     }
 
@@ -521,23 +530,13 @@ _bfd_get_elt_at_filepos (archive, filepos)
   return NULL;
 }
 
-/*
-FUNCTION
-       bfd_get_elt_at_index
-
-SYNOPSIS
-       bfd *bfd_get_elt_at_index(bfd *archive, int index);
+/* Return the BFD which is referenced by the symbol in ABFD indexed by
+   INDEX.  INDEX should have been returned by bfd_get_next_mapent.  */
 
-DESCRIPTION
-       Return the BFD which is referenced by the symbol in @var{archive}
-       indexed by @var{index}.  @var{index} should have been returned by
-       <<bfd_get_next_mapent>> (q.v.).
-
-*/
 bfd *
-bfd_get_elt_at_index (abfd, index)
+_bfd_generic_get_elt_at_index (abfd, index)
      bfd *abfd;
-     int index;
+     symindex index;
 {
   carsym *entry;
 
@@ -647,6 +646,8 @@ bfd_generic_archive_p (abfd)
     {
       bfd_release (abfd, bfd_ardata (abfd));
       abfd->tdata.aout_ar_data = tdata_hold;
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
@@ -654,6 +655,8 @@ bfd_generic_archive_p (abfd)
     {
       bfd_release (abfd, bfd_ardata (abfd));
       abfd->tdata.aout_ar_data = tdata_hold;
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
@@ -662,9 +665,11 @@ bfd_generic_archive_p (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.
+        are object files.  Make sure that if the first file in the
+        archive can be recognized as an object file, it is for this
+        target.  If not, assume that this is the wrong format.  If
+        the first file is not an object file, somebody is doing
+        something weird, and we permit it so that ar -t will work.
 
         This is done because any normal format will recognize any
         normal archive, regardless of the format of the object files.
@@ -677,22 +682,13 @@ bfd_generic_archive_p (abfd)
 
          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)
+         if (bfd_check_format (first, bfd_object)
+             && first->xvec != abfd->xvec)
            {
-             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);
+             bfd_set_error (bfd_error_wrong_format);
              return NULL;
            }
 
@@ -788,7 +784,7 @@ do_slurp_bsd_armap (abfd)
   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
   /* FIXME, we should provide some way to free raw_ardata when
      we are done using the strings from it.  For now, it seems
-     to be allocated on an obstack anyway... */
+     to be allocated on an objalloc anyway... */
   bfd_has_map (abfd) = true;
   return true;
 }
@@ -834,7 +830,9 @@ do_slurp_coff_armap (abfd)
      little, because our tools changed.  Here's a horrible hack to clean
      up the crap.  */
 
-  if (stringsize > 0xfffff)
+  if (stringsize > 0xfffff
+      && bfd_get_arch (abfd) == bfd_arch_i960
+      && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
     {
       /* This looks dangerous, let's do it the other way around */
       nsymz = bfd_getl32 ((PTR) int_buf);
@@ -938,6 +936,12 @@ bfd_slurp_armap (abfd)
     return do_slurp_bsd_armap (abfd);
   else if (!strncmp (nextname, "/               ", 16))
     return do_slurp_coff_armap (abfd);
+  else if (!strncmp (nextname, "/SYM64/         ", 16))
+    {
+      /* Irix 6 archive--must be recognized by code in elf64-mips.c.  */
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
 
   bfd_has_map (abfd) = false;
   return true;
@@ -1042,7 +1046,7 @@ bfd_slurp_bsd_armap_f2 (abfd)
   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
   /* FIXME, we should provide some way to free raw_ardata when
      we are done using the strings from it.  For now, it seems
-     to be allocated on an obstack anyway... */
+     to be allocated on an objalloc anyway... */
   bfd_has_map (abfd) = true;
   return true;
 }
@@ -1125,7 +1129,7 @@ _bfd_slurp_extended_name_table (abfd)
        (bfd_ardata (abfd)->first_file_filepos) % 2;
 
       /* FIXME, we can't release namedata here because it was allocated
-        below extended_names on the obstack... */
+        below extended_names on the objalloc... */
       /* bfd_release (abfd, namedata); */
     }
   return true;
@@ -1393,10 +1397,12 @@ bfd_ar_hdr_from_filesystem (abfd, filename)
     a strong stomach to write this, and it does, but it takes even a
     stronger stomach to try to code around such a thing!  */
 
+struct ar_hdr *bfd_special_undocumented_glue PARAMS ((bfd *, const char *));
+
 struct ar_hdr *
 bfd_special_undocumented_glue (abfd, filename)
      bfd *abfd;
-     char *filename;
+     const char *filename;
 {
   struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename);
   if (ar_elt == NULL)
@@ -1724,11 +1730,11 @@ _bfd_compute_and_write_armap (arch, elength)
     elength += sizeof (struct ar_hdr);
   elength += elength % 2;
 
-  map = (struct orl *) malloc (orl_max * sizeof (struct orl));
+  map = (struct orl *) bfd_malloc (orl_max * sizeof (struct orl));
   if (map == NULL)
-    goto no_memory_return;
+    goto error_return;
 
-  /* We put the symbol names on the arch obstack, and then discard
+  /* We put the symbol names on the arch objalloc, and then discard
      them when done.  */
   first_name = bfd_alloc (arch, 1);
   if (first_name == NULL)
@@ -1763,9 +1769,9 @@ _bfd_compute_and_write_armap (arch, elength)
                  if (syms_max > 0)
                    free (syms);
                  syms_max = storage;
-                 syms = (asymbol **) malloc ((size_t) syms_max);
+                 syms = (asymbol **) bfd_malloc ((size_t) syms_max);
                  if (syms == NULL)
-                   goto no_memory_return;
+                   goto error_return;
                }
              symcount = bfd_canonicalize_symtab (current, syms);
              if (symcount < 0)
@@ -1790,11 +1796,11 @@ _bfd_compute_and_write_armap (arch, elength)
                      if (orl_count == orl_max)
                        {
                          orl_max *= 2;
-                         new_map = ((struct orl *)
-                                    realloc ((PTR) map,
-                                             orl_max * sizeof (struct orl)));
+                         new_map =
+                           ((struct orl *)
+                            bfd_realloc (map, orl_max * sizeof (struct orl)));
                          if (new_map == (struct orl *) NULL)
-                           goto no_memory_return;
+                           goto error_return;
 
                          map = new_map;
                        }
@@ -1838,9 +1844,6 @@ _bfd_compute_and_write_armap (arch, elength)
 
   return ret;
 
- no_memory_return:
-  bfd_set_error (bfd_error_no_memory);
-
  error_return:
   if (syms_max > 0)
     free (syms);
@@ -1884,8 +1887,13 @@ 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);
+#ifndef _WIN32
   sprintf (hdr.ar_uid, "%ld", (long) getuid ());
   sprintf (hdr.ar_gid, "%ld", (long) getgid ());
+#else
+  sprintf (hdr.ar_uid, "%ld", (long) 666);
+  sprintf (hdr.ar_gid, "%ld", (long) 42);
+#endif
   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
   strncpy (hdr.ar_fmag, ARFMAG, 2);
   for (i = 0; i < sizeof (struct ar_hdr); i++)