Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / archive64.c
index 4fc8b851939cffa2f51653fecf6ed791f1d2f73b..37fecc28d4831269628786b015353c0a33654fdb 100644 (file)
@@ -1,6 +1,5 @@
-/* MIPS-specific support for 64-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006
-   Free Software Foundation, Inc.
+/* Support for 64-bit archives.
+   Copyright (C) 1996-2019 Free Software Foundation, Inc.
    Ian Lance Taylor, Cygnus Support
    Linker support added by Mark Mitchell, CodeSourcery, LLC.
    <mark@codesourcery.com>
    Ian Lance Taylor, Cygnus Support
    Linker support added by Mark Mitchell, CodeSourcery, LLC.
    <mark@codesourcery.com>
@@ -9,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-/* This file supports the 64-bit (MIPS) ELF archives.  */
+/* This file supports the 64-bit archives.  We use the same format as
+   the 64-bit (MIPS) ELF archives.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "aout/ar.h"
 
 /* Irix 6 defines a 64bit archive map format, so that they can
    have archives more than 4 GB in size.  */
 
 #include "libbfd.h"
 #include "aout/ar.h"
 
 /* Irix 6 defines a 64bit archive map format, so that they can
    have archives more than 4 GB in size.  */
 
-bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
-bfd_boolean bfd_elf64_archive_write_armap
-  (bfd *, unsigned int, struct orl *, unsigned int, int);
-
 /* Read an Irix 6 armap.  */
 
 bfd_boolean
 /* Read an Irix 6 armap.  */
 
 bfd_boolean
-bfd_elf64_archive_slurp_armap (bfd *abfd)
+_bfd_archive_64_bit_slurp_armap (bfd *abfd)
 {
   struct artdata *ardata = bfd_ardata (abfd);
   char nextname[17];
 {
   struct artdata *ardata = bfd_ardata (abfd);
   char nextname[17];
-  file_ptr arhdrpos;
   bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
   struct areltdata *mapdata;
   bfd_byte int_buf[8];
   char *stringbase;
   bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
   struct areltdata *mapdata;
   bfd_byte int_buf[8];
   char *stringbase;
+  char *stringend;
   bfd_byte *raw_armap = NULL;
   carsym *carsyms;
   bfd_size_type amt;
   bfd_byte *raw_armap = NULL;
   carsym *carsyms;
   bfd_size_type amt;
@@ -54,7 +51,6 @@ bfd_elf64_archive_slurp_armap (bfd *abfd)
   ardata->symdefs = NULL;
 
   /* Get the name of the first element.  */
   ardata->symdefs = NULL;
 
   /* Get the name of the first element.  */
-  arhdrpos = bfd_tell (abfd);
   i = bfd_bread (nextname, 16, abfd);
   if (i == 0)
     return TRUE;
   i = bfd_bread (nextname, 16, abfd);
   if (i == 0)
     return TRUE;
@@ -70,7 +66,7 @@ bfd_elf64_archive_slurp_armap (bfd *abfd)
 
   if (! CONST_STRNEQ (nextname, "/SYM64/         "))
     {
 
   if (! CONST_STRNEQ (nextname, "/SYM64/         "))
     {
-      bfd_has_map (abfd) = FALSE;
+      abfd->has_armap = FALSE;
       return TRUE;
     }
 
       return TRUE;
     }
 
@@ -78,7 +74,7 @@ bfd_elf64_archive_slurp_armap (bfd *abfd)
   if (mapdata == NULL)
     return FALSE;
   parsed_size = mapdata->parsed_size;
   if (mapdata == NULL)
     return FALSE;
   parsed_size = mapdata->parsed_size;
-  bfd_release (abfd, mapdata);
+  free (mapdata);
 
   if (bfd_bread (int_buf, 8, abfd) != 8)
     {
 
   if (bfd_bread (int_buf, 8, abfd) != 8)
     {
@@ -94,13 +90,25 @@ bfd_elf64_archive_slurp_armap (bfd *abfd)
   ptrsize = 8 * nsymz;
 
   amt = carsym_size + stringsize + 1;
   ptrsize = 8 * nsymz;
 
   amt = carsym_size + stringsize + 1;
-  ardata->symdefs = bfd_zalloc (abfd, amt);
+  if (/* Catch overflow in stringsize (and ptrsize) expression.  */
+      nsymz >= (bfd_size_type) -1 / 8
+      || stringsize > parsed_size
+      /* Catch overflow in carsym_size expression.  */
+      || nsymz > (bfd_size_type) -1 / sizeof (carsym)
+      /* Catch overflow in amt expression.  */
+      || amt <= carsym_size
+      || amt <= stringsize)
+    {
+      bfd_set_error (bfd_error_malformed_archive);
+      return FALSE;
+    }
+  ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
   if (ardata->symdefs == NULL)
     return FALSE;
   carsyms = ardata->symdefs;
   stringbase = ((char *) ardata->symdefs) + carsym_size;
 
   if (ardata->symdefs == NULL)
     return FALSE;
   carsyms = ardata->symdefs;
   stringbase = ((char *) ardata->symdefs) + carsym_size;
 
-  raw_armap = bfd_alloc (abfd, ptrsize);
+  raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
   if (raw_armap == NULL)
     goto release_symdefs;
 
   if (raw_armap == NULL)
     goto release_symdefs;
 
@@ -112,21 +120,24 @@ bfd_elf64_archive_slurp_armap (bfd *abfd)
       goto release_raw_armap;
     }
 
       goto release_raw_armap;
     }
 
+  stringend = stringbase + stringsize;
+  *stringend = 0;
   for (i = 0; i < nsymz; i++)
     {
       carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
       carsyms->name = stringbase;
   for (i = 0; i < nsymz; i++)
     {
       carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
       carsyms->name = stringbase;
-      stringbase += strlen (stringbase) + 1;
+      stringbase += strlen (stringbase);
+      if (stringbase != stringend)
+       ++stringbase;
       ++carsyms;
     }
       ++carsyms;
     }
-  *stringbase = '\0';
 
   ardata->symdef_count = nsymz;
   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;
 
 
   ardata->symdef_count = nsymz;
   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_has_map (abfd) = TRUE;
+  abfd->has_armap = TRUE;
   bfd_release (abfd, raw_armap);
 
   return TRUE;
   bfd_release (abfd, raw_armap);
 
   return TRUE;
@@ -143,11 +154,11 @@ release_symdefs:
    linker crashes.  */
 
 bfd_boolean
    linker crashes.  */
 
 bfd_boolean
-bfd_elf64_archive_write_armap (bfd *arch,
-                              unsigned int elength,
-                              struct orl *map,
-                              unsigned int symbol_count,
-                              int stridx)
+_bfd_archive_64_bit_write_armap (bfd *arch,
+                                unsigned int elength,
+                                struct orl *map,
+                                unsigned int symbol_count,
+                                int stridx)
 {
   unsigned int ranlibsize = (symbol_count * 8) + 8;
   unsigned int stringsize = stridx;
 {
   unsigned int ranlibsize = (symbol_count * 8) + 8;
   unsigned int stringsize = stridx;
@@ -170,10 +181,10 @@ bfd_elf64_archive_write_armap (bfd *arch,
 
   memset (&hdr, ' ', sizeof (struct ar_hdr));
   memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
 
   memset (&hdr, ' ', sizeof (struct ar_hdr));
   memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
-  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
-                    mapsize);
+  if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
+    return FALSE;
   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
-                    time (NULL));
+                   time (NULL));
   /* This, at least, is what Intel coff sets the values to.: */
   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
   /* This, at least, is what Intel coff sets the values to.: */
   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
@@ -195,27 +206,29 @@ bfd_elf64_archive_write_armap (bfd *arch,
 
   /* Write out the file offset for the file associated with each
      symbol, and remember to keep the offsets padded out.  */
 
   /* Write out the file offset for the file associated with each
      symbol, and remember to keep the offsets padded out.  */
-
-  current = arch->archive_head;
   count = 0;
   count = 0;
-  while (current != NULL && count < symbol_count)
+  for (current = arch->archive_head;
+       current != NULL && count < symbol_count;
+       current = current->archive_next)
     {
       /* For each symbol which is used defined in this object, write out
     {
       /* For each symbol which is used defined in this object, write out
-        the object file's address in the archive */
+        the object file's address in the archive */
 
 
-      while (map[count].u.abfd == current)
+      for (;
+          count < symbol_count && map[count].u.abfd == current;
+          count++)
        {
          bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
          if (bfd_bwrite (buf, 8, arch) != 8)
            return FALSE;
        {
          bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
          if (bfd_bwrite (buf, 8, arch) != 8)
            return FALSE;
-         count++;
        }
        }
+
       /* Add size of this archive entry */
       /* Add size of this archive entry */
-      archive_member_file_ptr += (arelt_size (current)
-                                 + sizeof (struct ar_hdr));
+      archive_member_file_ptr += sizeof (struct ar_hdr);
+      if (! bfd_is_thin_archive (arch))
+       archive_member_file_ptr += arelt_size (current);
       /* remember about the even alignment */
       archive_member_file_ptr += archive_member_file_ptr % 2;
       /* remember about the even alignment */
       archive_member_file_ptr += archive_member_file_ptr % 2;
-      current = current->next;
     }
 
   /* now write the strings themselves */
     }
 
   /* now write the strings themselves */
This page took 0.028185 seconds and 4 git commands to generate.