X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcache.c;h=52268162c268ebf01486208b49e0a1b223d5e065;hb=405bf443e52b6986413e7b02cb783e4ae92b0dda;hp=3906335041d0cef17f31ef53357ae13b39eddda5;hpb=f12a02c018093a098f27099297903362c47ca150;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/cache.c b/bfd/cache.c index 3906335041..52268162c2 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). @@ -45,6 +45,11 @@ SUBSECTION #include "bfd.h" #include "libbfd.h" #include "libiberty.h" +#include "bfd_stdint.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 @@ -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; @@ -317,7 +322,7 @@ cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes) if (chunk_size > max_chunk_size) chunk_size = max_chunk_size; - chunk_nread = cache_bread_1 (abfd, buf + nread, chunk_size); + chunk_nread = cache_bread_1 (abfd, (char *) buf + nread, chunk_size); /* Update the nread count. @@ -341,7 +346,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); @@ -356,7 +362,7 @@ cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes) static int cache_bclose (struct bfd *abfd) { - return bfd_cache_close (abfd); + return bfd_cache_close (abfd) - 1; } static int @@ -364,6 +370,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); @@ -377,6 +384,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); @@ -385,9 +393,62 @@ 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 **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 = (char *) 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 }; /* @@ -502,15 +563,15 @@ bfd_open_file (bfd *abfd) { case read_direction: case no_direction: - abfd->iostream = (PTR) real_fopen (abfd->filename, FOPEN_RB); + abfd->iostream = real_fopen (abfd->filename, FOPEN_RB); break; case both_direction: case write_direction: if (abfd->opened_once) { - abfd->iostream = (PTR) real_fopen (abfd->filename, FOPEN_RUB); + abfd->iostream = real_fopen (abfd->filename, FOPEN_RUB); if (abfd->iostream == NULL) - abfd->iostream = (PTR) real_fopen (abfd->filename, FOPEN_WUB); + abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB); } else { @@ -540,7 +601,7 @@ bfd_open_file (bfd *abfd) if (stat (abfd->filename, &s) == 0 && s.st_size != 0) unlink_if_ordinary (abfd->filename); #endif - abfd->iostream = (PTR) real_fopen (abfd->filename, FOPEN_WUB); + abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB); abfd->opened_once = TRUE; } break;