daily update
[deliverable/binutils-gdb.git] / bfd / cache.c
index 50674e88b0ece0b58f580dc5d07b179b56e4b75e..3842f517d1fe8c1942f157d195520ab49d8aab7e 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).
 
@@ -45,6 +45,11 @@ SUBSECTION
 #include "bfd.h"
 #include "libbfd.h"
 #include "libiberty.h"
+#include "bfd_stdint.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
@@ -140,33 +145,33 @@ bfd_cache_delete (bfd *abfd)
 static bfd_boolean
 close_one (void)
 {
-  register bfd *kill;
+  register bfd *to_kill;
 
   if (bfd_last_cache == NULL)
-    kill = NULL;
+    to_kill = NULL;
   else
     {
-      for (kill = bfd_last_cache->lru_prev;
-          ! kill->cacheable;
-          kill = kill->lru_prev)
+      for (to_kill = bfd_last_cache->lru_prev;
+          ! to_kill->cacheable;
+          to_kill = to_kill->lru_prev)
        {
-         if (kill == bfd_last_cache)
+         if (to_kill == bfd_last_cache)
            {
-             kill = NULL;
+             to_kill = NULL;
              break;
            }
        }
     }
 
-  if (kill == NULL)
+  if (to_kill == NULL)
     {
       /* There are no open cacheable BFD's.  */
       return TRUE;
     }
 
-  kill->where = real_ftell ((FILE *) kill->iostream);
+  to_kill->where = real_ftell ((FILE *) to_kill->iostream);
 
-  return bfd_cache_delete (kill);
+  return bfd_cache_delete (to_kill);
 }
 
 /* Check to see if the required BFD is the same as the last one
@@ -193,7 +198,7 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     abort ();
 
-  if (abfd->my_archive)
+  while (abfd->my_archive)
     abfd = abfd->my_archive;
 
   if (abfd->iostream != NULL)
@@ -236,7 +241,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 +271,7 @@ cache_bread_1 (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;
 
@@ -341,7 +346,7 @@ 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;
@@ -388,10 +393,62 @@ cache_bstat (struct bfd *abfd, struct stat *sb)
   return sts;
 }
 
+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 **map_addr ATTRIBUTE_UNUSED,
+             bfd_size_type *map_len ATTRIBUTE_UNUSED)
+{
+  void *ret = (void *) -1;
+
+  if ((abfd->flags & BFD_IN_MEMORY) != 0)
+    abort ();
+#ifdef HAVE_MMAP
+  else
+    {
+      static uintptr_t pagesize_m1;
+      FILE *f;
+      file_ptr pg_offset;
+      bfd_size_type pg_len;
+
+      f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
+      if (f == NULL)
+       return ret;
+
+      if (pagesize_m1 == 0)
+        pagesize_m1 = getpagesize () - 1;
+
+      /* Handle archive members.  */
+      if (abfd->my_archive != NULL)
+        offset += abfd->origin;
+
+      /* Align.  */
+      pg_offset = offset & ~pagesize_m1;
+      pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1;
+
+      ret = mmap (addr, pg_len, prot, flags, fileno (f), pg_offset);
+      if (ret == (void *) -1)
+       bfd_set_error (bfd_error_system_call);
+      else
+        {
+          *map_addr = ret;
+          *map_len = pg_len;
+          ret += offset & pagesize_m1;
+        }
+    }
+#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
 };
 
 /*
This page took 0.025524 seconds and 4 git commands to generate.