bfd_get_size cache
[binutils-gdb.git] / bfd / bfdwin.c
index a44265efa752e1f572c9644b4ef93ff1281218ac..6beed1f1ba31815800374859219748da1ccbecea 100644 (file)
@@ -1,6 +1,5 @@
 /* Support for memory-mapped windows into a BFD.
 /* Support for memory-mapped windows into a BFD.
-   Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
 #include "bfd.h"
 #include "libbfd.h"
 
 #include "bfd.h"
 #include "libbfd.h"
 
-/* Currently, if USE_MMAP is undefined, none if the window stuff is
-   used.  Okay, so it's mis-named.  At least the command-line option
-   "--without-mmap" is more obvious than "--without-windows" or some
-   such.  */
+/* Currently, if USE_MMAP is undefined, none of the window stuff is
+   used.  Enabled by --with-mmap.  */
 
 #ifdef USE_MMAP
 
 
 #ifdef USE_MMAP
 
@@ -80,7 +77,7 @@ bfd_free_window (bfd_window *windowp)
   i->refcount--;
   if (debug_windows)
     fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
   i->refcount--;
   if (debug_windows)
     fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
-            windowp, windowp->data, windowp->size, windowp->i);
+            windowp, windowp->data, (unsigned long) windowp->size, windowp->i);
   if (i->refcount != 0)
     return;
 
   if (i->refcount != 0)
     return;
 
@@ -130,17 +127,16 @@ bfd_get_file_window (bfd *abfd,
   if (pagesize == 0)
     abort ();
 
   if (pagesize == 0)
     abort ();
 
-  if (i == 0)
+  if (i == NULL)
     {
       i = bfd_zmalloc (sizeof (bfd_window_internal));
     {
       i = bfd_zmalloc (sizeof (bfd_window_internal));
-      windowp->i = i;
-      if (i == 0)
+      if (i == NULL)
        return FALSE;
        return FALSE;
-      i->data = 0;
+      i->data = NULL;
     }
 #ifdef HAVE_MMAP
   if (ok_to_map
     }
 #ifdef HAVE_MMAP
   if (ok_to_map
-      && (i->data == 0 || i->mapped == 1)
+      && (i->data == NULL || i->mapped == 1)
       && (abfd->flags & BFD_IN_MEMORY) == 0)
     {
       file_ptr file_offset, offset2;
       && (abfd->flags & BFD_IN_MEMORY) == 0)
     {
       file_ptr file_offset, offset2;
@@ -148,7 +144,8 @@ bfd_get_file_window (bfd *abfd,
       int fd;
 
       /* Find the real file and the real offset into it.  */
       int fd;
 
       /* Find the real file and the real offset into it.  */
-      while (abfd->my_archive != NULL)
+      while (abfd->my_archive != NULL
+            && !bfd_is_thin_archive (abfd->my_archive))
        {
          offset += abfd->origin;
          abfd = abfd->my_archive;
        {
          offset += abfd->origin;
          abfd = abfd->my_archive;
@@ -158,9 +155,9 @@ bfd_get_file_window (bfd *abfd,
       if (abfd->iostream == NULL
          && (abfd->iovec == NULL
              || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
       if (abfd->iostream == NULL
          && (abfd->iovec == NULL
              || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
-       return FALSE;
-      fd = fileno ((FILE *) abfd->iostream);
+       goto free_and_fail;
 
 
+      fd = fileno ((FILE *) abfd->iostream);
       /* Compute offsets and size for mmap and for the user's data.  */
       offset2 = offset % pagesize;
       if (offset2 < 0)
       /* Compute offsets and size for mmap and for the user's data.  */
       offset2 = offset % pagesize;
       if (offset2 < 0)
@@ -171,10 +168,10 @@ bfd_get_file_window (bfd *abfd,
       real_size -= real_size % pagesize;
 
       /* If we're re-using a memory region, make sure it's big enough.  */
       real_size -= real_size % pagesize;
 
       /* If we're re-using a memory region, make sure it's big enough.  */
-      if (i->data && i->size < size)
+      if (i->data != NULL && i->size < size)
        {
          munmap (i->data, i->size);
        {
          munmap (i->data, i->size);
-         i->data = 0;
+         i->data = NULL;
        }
       i->data = mmap (i->data, real_size,
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
        }
       i->data = mmap (i->data, real_size,
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
@@ -187,11 +184,10 @@ bfd_get_file_window (bfd *abfd,
          /* An error happened.  Report it, or try using malloc, or
             something.  */
          bfd_set_error (bfd_error_system_call);
          /* An error happened.  Report it, or try using malloc, or
             something.  */
          bfd_set_error (bfd_error_system_call);
-         i->data = 0;
          windowp->data = 0;
          if (debug_windows)
            fprintf (stderr, "\t\tmmap failed!\n");
          windowp->data = 0;
          if (debug_windows)
            fprintf (stderr, "\t\tmmap failed!\n");
-         return FALSE;
+         goto free_and_fail;
        }
       if (debug_windows)
        fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
        }
       if (debug_windows)
        fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
@@ -200,6 +196,8 @@ bfd_get_file_window (bfd *abfd,
       windowp->data = (bfd_byte *) i->data + offset2;
       windowp->size = size;
       i->mapped = 1;
       windowp->data = (bfd_byte *) i->data + offset2;
       windowp->size = size;
       i->mapped = 1;
+      i->refcount = 1;
+      windowp->i = i;
       return TRUE;
     }
   else if (debug_windows)
       return TRUE;
     }
   else if (debug_windows)
@@ -224,21 +222,24 @@ bfd_get_file_window (bfd *abfd,
   if (debug_windows)
     fprintf (stderr, "\n\t%s(%6ld)",
             i->data ? "realloc" : " malloc", (long) size_to_alloc);
   if (debug_windows)
     fprintf (stderr, "\n\t%s(%6ld)",
             i->data ? "realloc" : " malloc", (long) size_to_alloc);
-  i->data = bfd_realloc (i->data, size_to_alloc);
+  i->data = bfd_realloc_or_free (i->data, size_to_alloc);
   if (debug_windows)
     fprintf (stderr, "\t-> %p\n", i->data);
   if (debug_windows)
     fprintf (stderr, "\t-> %p\n", i->data);
-  i->refcount = 1;
   if (i->data == NULL)
     {
       if (size_to_alloc == 0)
   if (i->data == NULL)
     {
       if (size_to_alloc == 0)
-       return TRUE;
-      return FALSE;
+       {
+         windowp->i = i;
+         return TRUE;
+       }
+      goto free_and_fail;
     }
     }
+  i->refcount = 1;
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
-    return FALSE;
+    goto free_and_fail;
   i->size = bfd_bread (i->data, size, abfd);
   if (i->size != size)
   i->size = bfd_bread (i->data, size, abfd);
   if (i->size != size)
-    return FALSE;
+    goto free_and_fail;
   i->mapped = 0;
 #ifdef HAVE_MPROTECT
   if (!writable)
   i->mapped = 0;
 #ifdef HAVE_MPROTECT
   if (!writable)
@@ -251,7 +252,13 @@ bfd_get_file_window (bfd *abfd,
 #endif
   windowp->data = i->data;
   windowp->size = i->size;
 #endif
   windowp->data = i->data;
   windowp->size = i->size;
+  windowp->i = i;
   return TRUE;
   return TRUE;
+
+ free_and_fail:
+  /* We have a bfd_window_internal, but an error occurred.  Free it. */
+  free (i);
+  return FALSE;
 }
 
 #endif /* USE_MMAP */
 }
 
 #endif /* USE_MMAP */