X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=bfd%2Fcache.c;fp=bfd%2Fcache.c;h=cf1869d0ed5c1139a67f78d9195b1034b58e80eb;hp=039c1a941b4e53ea91935eb667f24a728232cd40;hb=88750007d7869f178f0ba528f41efd3b74c424cf;hpb=6df9443a374e2b81278c61b8afc0a1eef7db280b diff --git a/bfd/cache.c b/bfd/cache.c index 039c1a9..cf1869d 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -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 +#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 }; /*