Add comment about commented-out bfd_release calls.
[deliverable/binutils-gdb.git] / bfd / archive.c
index 4999469fe386e763ff663f9e029c1c6e7ee4f820..2f91901394f48d6521b8d029e9a0b740cd1189bf 100644 (file)
@@ -1,6 +1,4 @@
 
-/*** archive.c -- an attempt at combining the machine-independent parts of
-  archives */
 
 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
 
@@ -21,6 +19,21 @@ along with BFD; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
+/*doc*
+@setfilename archive-info
+@section Archives
+
+Gumby, you promised to write this bit...
+
+Archives are supported in bfd in @code{archive.c}.
+
+An archive is represented internally just like another bfd, with a
+pointer to a chain of contained bfds. Archives can be created by
+opening bfds, linking them together and attatching them as children to
+another bfd and then closing the parent bfd. 
+
+*-*/
+
 /* Assumes:
    o - all archive elements start on an even boundary, newline padded;
    o - all arch headers are char *;
@@ -29,7 +42,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* $Id$ */
 
-#include "sysdep.h"
+#include <sysdep.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "ar.h"
@@ -72,6 +85,10 @@ _bfd_generic_mkarchive (abfd)
   return true;
 }
 
+/*proto* bfd_get_next_mapent
+What this does
+*; PROTO(symindex, bfd_get_next_mapent, (bfd *, symindex, carsym **));
+*/
 symindex
 bfd_get_next_mapent (abfd, prev, entry)
      bfd *abfd;
@@ -107,9 +124,16 @@ _bfd_create_empty_archive_element_shell (obfd)
   return nbfd;
 }
 
+/*proto* bfd_set_archive_head
+Used whilst processing archives. Sets the head of the chain of bfds
+contained in an archive to @var{new_head}. (see chapter on archives)
+*; PROTO(boolean, bfd_set_archive_head, (bfd *output, bfd *new_head));
+*/
+
 boolean
-bfd_set_archive_head (output_archive, new_head)
-     bfd *output_archive, *new_head;
+DEFUN(bfd_set_archive_head,(output_archive, new_head),
+     bfd *output_archive AND 
+     bfd *new_head)
 {
 
   output_archive->archive_head = new_head;
@@ -169,6 +193,9 @@ get_extended_arelt_filename (arch, name)
      bfd *arch;
      char *name;
 {
+#ifndef errno
+  extern int errno;
+#endif
     unsigned long index = 0;
 
     /* Should extract string so that I can guarantee not to overflow into
@@ -196,7 +223,10 @@ struct areltdata *
 snarf_ar_hdr (abfd)
      bfd *abfd;
 {
-    extern int errno;
+#ifndef errno
+  extern int errno;
+#endif
+
     struct ar_hdr hdr;
     char *hdrp = (char *) &hdr;
     unsigned int parsed_size;
@@ -223,8 +253,10 @@ snarf_ar_hdr (abfd)
        return NULL;
     }
 
-    /* extract the filename from the archive */
-    if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
+    /* extract the filename from the archive - there are two ways to
+       specify an extendend name table, either the first char of the
+       name is a space, or it's a slash  */
+    if ((hdr.ar_name[0] == '/' || hdr.ar_name[0] == ' ') && bfd_ardata (abfd)->extended_names != NULL) {
        filename = get_extended_arelt_filename (abfd, hdr.ar_name);
        if (filename == NULL) {
            bfd_error = malformed_archive;
@@ -319,10 +351,22 @@ bfd_get_elt_at_index (abfd, index)
   return result;
 }
 
-/* If you've got an archive, call this to read each subfile. */
+/*proto* bfd_openr_next_archived_file
+Initially provided a bfd containing an archive and NULL, opens a bfd
+on the first contained element and returns that. Subsequent calls to
+bfd_openr_next_archived_file should pass the archive and the previous
+return value to return a created bfd to the next contained element.
+NULL is returned when there are no more.
+
+*; PROTO(bfd*, bfd_openr_next_archived_file,
+               (bfd *archive, bfd *previous));
+
+*/
+
 bfd *
-bfd_openr_next_archived_file (archive, last_file)
-     bfd *archive, *last_file;
+DEFUN(bfd_openr_next_archived_file,(archive, last_file),
+     bfd *archive AND  
+      bfd*last_file)
 {
 
   if ((bfd_get_format (archive) != bfd_archive) ||
@@ -405,6 +449,7 @@ boolean
 bfd_slurp_bsd_armap (abfd)
      bfd *abfd;
 {
+
   struct areltdata *mapdata;
   char nextname[17];
   unsigned int counter = 0;
@@ -444,7 +489,7 @@ bfd_slurp_bsd_armap (abfd)
          goto byebye;
       }
 
-      ardata->symdef_count = *raw_armap / sizeof (struct symdef);
+      ardata->symdef_count = bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef);
       ardata->cache = 0;
       rbase = raw_armap+1;
       ardata->symdefs = (carsym *) rbase;
@@ -452,7 +497,8 @@ bfd_slurp_bsd_armap (abfd)
 
       for (;counter < ardata->symdef_count; counter++) {
          struct symdef *sym = ((struct symdef *) rbase) + counter;
-         sym->s.name = sym->s.string_offset + stringbase;
+         sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase;
+         sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset)));
       }
   
       ardata->first_file_filepos = bfd_tell (abfd);
@@ -493,13 +539,16 @@ bfd_slurp_coff_armap (abfd)
   if (mapdata == NULL) return false;
 
   raw_armap = (int *) bfd_alloc(abfd,mapdata->parsed_size);
-  if (raw_armap == NULL) {
+
+  if (raw_armap == NULL) 
+      {
     bfd_error = no_memory;
   byebye:
     bfd_release (abfd, (PTR)mapdata);
     return false;
   }
 
+  /* read in the raw map */
   if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
       mapdata->parsed_size) {
     bfd_error = malformed_archive;
@@ -544,19 +593,25 @@ bfd_slurp_coff_armap (abfd)
   ardata->first_file_filepos = bfd_tell (abfd);
   /* Pad to an even boundary if you have to */
   ardata->first_file_filepos += (ardata->first_file_filepos) %2;
-  bfd_release (abfd, (PTR)raw_armap);
-  bfd_release (abfd, (PTR)mapdata);
+
+  /* We'd like to release these allocations, but we have allocated stuff
+     since then (using the same obstack, if bfd_release is obstack based).
+     So they will stick around until the bfd is closed.  */
+  /*  bfd_release (abfd, (PTR)raw_armap);
+      bfd_release (abfd, (PTR)mapdata);  */
   bfd_has_map (abfd) = true;
   return true;
 }
 \f
 /** Extended name table.
 
-  Normally archives support only 14-character filenames.  Intel has extended
-  the format: longer names are stored in a special element (the first in the
-  archive, or second if there is an armap); the name in the ar_hdr is replaced
-  by <space><index into filename element>.  Index is the P.R. of an int (radix:
-  8). */
+  Normally archives support only 14-character filenames.
+
+  Intel has extended the format: longer names are stored in a special
+  element (the first in the archive, or second if there is an armap);
+  the name in the ar_hdr is replaced by <space><index into filename
+  element>.  Index is the P.R. of an int (radix: 8).  Data General have
+  extended the format by using the prefix // for the special element */
 
 /* Returns false on error, true otherwise */
 boolean
@@ -570,49 +625,52 @@ _bfd_slurp_extended_name_table (abfd)
      we probably don't want to return true.  */
   if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
 
-  bfd_seek (abfd, -16L, SEEK_CUR);
+    bfd_seek (abfd, -16L, SEEK_CUR);
 
-  if (strncmp (nextname, "ARFILENAMES/    ", 16)) {
-    bfd_ardata (abfd)->extended_names = NULL;
-    return true;
-  }
+    if (strncmp (nextname, "ARFILENAMES/    ", 16) != 0 &&
+       strncmp (nextname, "//              ", 16) != 0) 
+       {
+      bfd_ardata (abfd)->extended_names = NULL;
+      return true;
+    }
 
-  namedata = snarf_ar_hdr (abfd);
-  if (namedata == NULL) return false;
+    namedata = snarf_ar_hdr (abfd);
+    if (namedata == NULL) return false;
   
-  bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
-  if (bfd_ardata (abfd)->extended_names == NULL) {
-    bfd_error = no_memory;
-  byebye:
-    bfd_release (abfd, (PTR)namedata);
-    return false;
-  }
+    bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
+    if (bfd_ardata (abfd)->extended_names == NULL) {
+      bfd_error = no_memory;
+    byebye:
+      bfd_release (abfd, (PTR)namedata);
+      return false;
+    }
 
-  if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
-               namedata->parsed_size, abfd) != namedata->parsed_size) {
-    bfd_error = malformed_archive;
-    bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
-    bfd_ardata (abfd)->extended_names = NULL;
-    goto byebye;
-  }
+    if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
+                 namedata->parsed_size, abfd) != namedata->parsed_size) {
+      bfd_error = malformed_archive;
+      bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
+      bfd_ardata (abfd)->extended_names = NULL;
+      goto byebye;
+    }
 
-  /* It appears that the extended names are newline-padded, not null padded.
-     */
-  {
-    char *temp = bfd_ardata (abfd)->extended_names;
-    for (; *temp != '\0'; ++temp)
-      if (*temp == '\n') *temp = '\0';
-  }
+    /* Since the archive is supposed to be printable if it contains
+       text, the entries in the list are newline-padded, not null
+       padded. We'll fix that there..  */
+      {
+       char *temp = bfd_ardata (abfd)->extended_names;
+       for (; *temp != '\0'; ++temp)
+         if (*temp == '\n') *temp = '\0';
+      }
   
-  /* Pad to an even boundary if you have to */
-  bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
-  bfd_ardata (abfd)->first_file_filepos +=
-    (bfd_ardata (abfd)->first_file_filepos) %2;
-
-  /* FIXME, we can't release namedata here because it was allocated
-     below extended_names on the obstack... */
-  /* bfd_release (abfd, namedata); */
-}
+    /* Pad to an even boundary if you have to */
+    bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
+    bfd_ardata (abfd)->first_file_filepos +=
+      (bfd_ardata (abfd)->first_file_filepos) %2;
+
+    /* FIXME, we can't release namedata here because it was allocated
+       below extended_names on the obstack... */
+    /* bfd_release (abfd, namedata); */
+  }
   return true;
 }
 
@@ -795,7 +853,7 @@ bfd_generic_stat_arch_elt (abfd, buf)
 void
 bfd_dont_truncate_arname (abfd, pathname, arhdr)
      bfd *abfd;
-     char *pathname;
+     CONST char *pathname;
      char *arhdr;
 {
   /* FIXME: This interacts unpleasantly with ar's quick-append option.
@@ -805,7 +863,7 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr)
    
   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
   int length;
-  char *filename = strrchr (pathname, '/');
+  CONST char *filename = strrchr (pathname, '/');
   int maxlen = ar_maxnamelen (abfd);
 
   if (filename == NULL)
@@ -826,12 +884,12 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr)
 void
 bfd_bsd_truncate_arname (abfd, pathname, arhdr)
      bfd *abfd;
-     char *pathname;
+     CONST char *pathname;
      char *arhdr;
 {
   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
   int length;
-  char *filename = strrchr (pathname, '/');
+  CONST char *filename = strrchr (pathname, '/');
   int maxlen = ar_maxnamelen (abfd);
 
 
@@ -864,12 +922,12 @@ bfd_bsd_truncate_arname (abfd, pathname, arhdr)
 void
 bfd_gnu_truncate_arname (abfd, pathname, arhdr)
      bfd *abfd;
-     char *pathname;
+     CONST char *pathname;
      char *arhdr;
 {
   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
   int length;
-  char *filename = strrchr (pathname, '/');
+  CONST char *filename = strrchr (pathname, '/');
   int maxlen = ar_maxnamelen (abfd);
        
   if (filename == NULL)
@@ -967,7 +1025,7 @@ _bfd_write_archive_contents (arch)
     hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
     for (i = 0; i < sizeof (struct ar_hdr); i++)
       if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
-    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+    bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
     bfd_write (etable, 1, elength, arch);
     if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
 
@@ -979,7 +1037,7 @@ _bfd_write_archive_contents (arch)
     struct ar_hdr *hdr = arch_hdr(current);
     /* write ar header */
 
-    if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
+    if (bfd_write ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
     syserr:
        bfd_error = system_call_error;
        return false;
@@ -1061,8 +1119,8 @@ compute_and_write_armap (arch, elength)
                                                    orl_max * sizeof (struct orl));
                    }
 
-               (map[orl_count]).name = &((syms[src_count])->name);
-               (map[orl_count]).pos = elt_no;
+               (map[orl_count]).name = (char **) &((syms[src_count])->name);
+               (map[orl_count]).pos = (file_ptr) current;
                (map[orl_count]).namidx = stridx;
 
                stridx += strlen ((syms[src_count])->name) + 1;
@@ -1083,9 +1141,6 @@ compute_and_write_armap (arch, elength)
   return true;
 }
 
-\f
- /* FIXME -- have to byte-swap this */
-
 boolean
 bsd_write_armap (arch, elength, map, orl_count, stridx)
      bfd *arch;
@@ -1099,7 +1154,7 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
   unsigned int mapsize = stringsize + ranlibsize;
   file_ptr firstreal;
   bfd *current = arch->archive_head;
-  int last_eltno = 0;          /* last element arch seen */
+  bfd *last_elt = current;             /* last element arch seen */
   int temp;
   int count;
   struct ar_hdr hdr;
@@ -1114,35 +1169,38 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
   stat (arch->filename, &statbuf);
   memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
   sprintf (hdr.ar_name, RANLIBMAG);
-  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
   sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
+  sprintf (hdr.ar_uid, "%d", getuid());
+  sprintf (hdr.ar_gid, "%d", getgid());
+  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
   hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
   for (i = 0; i < sizeof (struct ar_hdr); i++)
     if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
-  bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
-
-  temp = orl_count /* + 4 */;
+  bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
+  bfd_h_put_32(arch, ranlibsize, (PTR)&temp);
   bfd_write (&temp, 1, sizeof (temp), arch);
   
   for (count = 0; count < orl_count; count++) {
     struct symdef outs;
     struct symdef *outp = &outs;
     
-    if ((map[count]).pos != last_eltno) {
-      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
-      firstreal += firstreal % 2;
-    last_eltno = (map[count]).pos;
-      current = current->next;
-    }
-
-    outs.s.string_offset = ((map[count]).namidx) +4;
-    outs.file_offset = firstreal;
+    if (((bfd *)(map[count]).pos) != last_elt) {
+           do {
+                   firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+                   firstreal += firstreal % 2;
+                   current = current->next;
+           } while (current != (bfd *)(map[count]).pos);
+    } /* if new archive element */
+
+    last_elt = current;
+    bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset);
+    bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset);
     bfd_write ((char *)outp, 1, sizeof (outs), arch);
   }
 
   /* now write the strings themselves */
-  temp = stridx + 4;
-  bfd_write (&temp, 1, sizeof (temp), arch);
+  bfd_h_put_32(arch, stridx, (PTR)&temp);
+  bfd_write ((PTR)&temp, 1, sizeof (temp), arch);
   for (count = 0; count < orl_count; count++)
     bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
 
@@ -1209,8 +1267,9 @@ coff_write_armap (arch, elength, map, orl_count, stridx)
 
     /* Write the ar header for this item and the number of symbols */
 
-    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
-    bfd_write (&orl_count, 1, sizeof (orl_count), arch);
+    bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch);
+    /* FIXME, this needs to be byte-swapped */
+    bfd_write ((PTR)&orl_count, 1, sizeof (orl_count), arch);
 
     /* Two passes, first write the file offsets for each symbol -
        remembering that each offset is on a two byte boundary
@@ -1226,7 +1285,8 @@ coff_write_armap (arch, elength, map, orl_count, stridx)
            current = current->next;
            last_eltno++;
        }
-       bfd_write (&archive_member_file_ptr,
+       /* FIXME, this needs to be byte-swapped */
+       bfd_write ((PTR)&archive_member_file_ptr,
                   1,
                   sizeof (archive_member_file_ptr),
                   arch);
@@ -1234,7 +1294,7 @@ coff_write_armap (arch, elength, map, orl_count, stridx)
 
     /* now write the strings themselves */
     for (count = 0; count < orl_count; count++) {
-       bfd_write (*((map[count]).name),
+       bfd_write ((PTR)*((map[count]).name),
                   1,
                   strlen (*((map[count]).name))+1, arch);
 
This page took 0.030188 seconds and 4 git commands to generate.