]> oss.titaniummirror.com Git - msp430-binutils.git/blobdiff - bfd/cache.c
Imported binutils-2.20
[msp430-binutils.git] / bfd / cache.c
index 039c1a941b4e53ea91935eb667f24a728232cd40..cf1869d0ed5c1139a67f78d9195b1034b58e80eb 100644 (file)
@@ -1,7 +1,7 @@
 /* BFD library -- caching of file descriptors.
 
    Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002,
-   2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
 
@@ -46,6 +46,10 @@ SUBSECTION
 #include "libbfd.h"
 #include "libiberty.h"
 
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
 /* In some cases we can optimize cache operation when reopening files.
    For instance, a flush is entirely unnecessary if the file is already
    closed, so a flush would use CACHE_NO_OPEN.  Similarly, a seek using
@@ -166,22 +170,6 @@ close_one (void)
 
   kill->where = real_ftell ((FILE *) kill->iostream);
 
-  /* Save the file st_mtime.  This is a hack so that gdb can detect when
-     an executable has been deleted and recreated.  The only thing that
-     makes this reasonable is that st_mtime doesn't change when a file
-     is unlinked, so saving st_mtime makes BFD's file cache operation
-     a little more transparent for this particular usage pattern.  If we
-     hadn't closed the file then we would not have lost the original
-     contents, st_mtime etc.  Of course, if something is writing to an
-     existing file, then this is the wrong thing to do.
-     FIXME: gdb should save these times itself on first opening a file,
-     and this hack be removed.  */
-  if (kill->direction == no_direction || kill->direction == read_direction)
-    {
-      bfd_get_mtime (kill);
-      kill->mtime_set = TRUE;
-    }
-
   return bfd_cache_delete (kill);
 }
 
@@ -252,7 +240,7 @@ cache_btell (struct bfd *abfd)
 static int
 cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
 {
-  FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : 0);
+  FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL);
   if (f == NULL)
     return -1;
   return real_fseek (f, offset, whence);
@@ -266,7 +254,7 @@ cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
    first octet in the file, NOT the beginning of the archive header.  */
 
 static file_ptr
-cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
+cache_bread_1 (struct bfd *abfd, void *buf, file_ptr nbytes)
 {
   FILE *f;
   file_ptr nread;
@@ -282,7 +270,7 @@ cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
   if (nbytes == 0)
     return 0;
 
-  f = bfd_cache_lookup (abfd, 0);
+  f = bfd_cache_lookup (abfd, CACHE_NORMAL);
   if (f == NULL)
     return 0;
 
@@ -309,6 +297,47 @@ cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
       return -1;
     }
 #endif
+  if (nread < nbytes)
+    /* This may or may not be an error, but in case the calling code
+       bails out because of it, set the right error code.  */
+    bfd_set_error (bfd_error_file_truncated);
+  return nread;
+}
+
+static file_ptr
+cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
+{
+  file_ptr nread = 0;
+
+  /* Some filesystems are unable to handle reads that are too large
+     (for instance, NetApp shares with oplocks turned off).  To avoid
+     hitting this limitation, we read the buffer in chunks of 8MB max.  */
+  while (nread < nbytes)
+    {
+      const file_ptr max_chunk_size = 0x800000;
+      file_ptr chunk_size = nbytes - nread;
+      file_ptr chunk_nread;
+
+      if (chunk_size > max_chunk_size)
+        chunk_size = max_chunk_size;
+
+      chunk_nread = cache_bread_1 (abfd, (char *) buf + nread, chunk_size);
+
+      /* Update the nread count.
+
+         We just have to be careful of the case when cache_bread_1 returns
+         a negative count:  If this is our first read, then set nread to
+         that negative count in order to return that negative value to the
+         caller.  Otherwise, don't add it to our total count, or we would
+         end up returning a smaller number of bytes read than we actually
+         did.  */
+      if (nread == 0 || chunk_nread > 0)
+        nread += chunk_nread;
+
+      if (chunk_nread < chunk_size)
+        break;
+    }
+
   return nread;
 }
 
@@ -316,7 +345,8 @@ static file_ptr
 cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
 {
   file_ptr nwrite;
-  FILE *f = bfd_cache_lookup (abfd, 0);
+  FILE *f = bfd_cache_lookup (abfd, CACHE_NORMAL);
+
   if (f == NULL)
     return 0;
   nwrite = fwrite (where, 1, nbytes, f);
@@ -339,6 +369,7 @@ cache_bflush (struct bfd *abfd)
 {
   int sts;
   FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
+
   if (f == NULL)
     return 0;
   sts = fflush (f);
@@ -352,6 +383,7 @@ cache_bstat (struct bfd *abfd, struct stat *sb)
 {
   int sts;
   FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
+
   if (f == NULL)
     return -1;
   sts = fstat (fileno (f), sb);
@@ -360,9 +392,38 @@ cache_bstat (struct bfd *abfd, struct stat *sb)
   return sts;
 }
 
-static const struct bfd_iovec cache_iovec = {
+static void *
+cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
+            void *addr ATTRIBUTE_UNUSED,
+            bfd_size_type len ATTRIBUTE_UNUSED,
+            int prot ATTRIBUTE_UNUSED,
+            int flags ATTRIBUTE_UNUSED,
+            file_ptr offset ATTRIBUTE_UNUSED)
+{
+  void *ret = (void *) -1;
+
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    abort ();
+#ifdef HAVE_MMAP
+  else
+    {
+      FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
+      if (f == NULL)
+       return ret;
+
+      ret = mmap (addr, len, prot, flags, fileno (f), offset);
+      if (ret == (void *) -1)
+       bfd_set_error (bfd_error_system_call);
+    }
+#endif
+
+  return ret;
+}
+
+static const struct bfd_iovec cache_iovec =
+{
   &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
-  &cache_bclose, &cache_bflush, &cache_bstat
+  &cache_bclose, &cache_bflush, &cache_bstat, &cache_bmmap
 };
 
 /*