xref: /dflybsd-src/contrib/gdb-7/bfd/cache.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* BFD library -- caching of file descriptors.
25796c8dcSSimon Schubert 
35796c8dcSSimon Schubert    Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002,
45796c8dcSSimon Schubert    2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
95796c8dcSSimon Schubert 
105796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
115796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
125796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
135796c8dcSSimon Schubert    (at your option) any later version.
145796c8dcSSimon Schubert 
155796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
165796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
175796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
185796c8dcSSimon Schubert    GNU General Public License for more details.
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
215796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
225796c8dcSSimon Schubert    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
235796c8dcSSimon Schubert    MA 02110-1301, USA.  */
245796c8dcSSimon Schubert 
255796c8dcSSimon Schubert /*
265796c8dcSSimon Schubert SECTION
275796c8dcSSimon Schubert 	File caching
285796c8dcSSimon Schubert 
295796c8dcSSimon Schubert 	The file caching mechanism is embedded within BFD and allows
305796c8dcSSimon Schubert 	the application to open as many BFDs as it wants without
315796c8dcSSimon Schubert 	regard to the underlying operating system's file descriptor
325796c8dcSSimon Schubert 	limit (often as low as 20 open files).  The module in
335796c8dcSSimon Schubert 	<<cache.c>> maintains a least recently used list of
345796c8dcSSimon Schubert 	<<BFD_CACHE_MAX_OPEN>> files, and exports the name
355796c8dcSSimon Schubert 	<<bfd_cache_lookup>>, which runs around and makes sure that
365796c8dcSSimon Schubert 	the required BFD is open. If not, then it chooses a file to
375796c8dcSSimon Schubert 	close, closes it and opens the one wanted, returning its file
385796c8dcSSimon Schubert 	handle.
395796c8dcSSimon Schubert 
405796c8dcSSimon Schubert SUBSECTION
415796c8dcSSimon Schubert 	Caching functions
425796c8dcSSimon Schubert */
435796c8dcSSimon Schubert 
445796c8dcSSimon Schubert #include "sysdep.h"
455796c8dcSSimon Schubert #include "bfd.h"
465796c8dcSSimon Schubert #include "libbfd.h"
475796c8dcSSimon Schubert #include "libiberty.h"
48a45ae5f8SJohn Marino #include "bfd_stdint.h"
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert #ifdef HAVE_MMAP
515796c8dcSSimon Schubert #include <sys/mman.h>
525796c8dcSSimon Schubert #endif
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert /* In some cases we can optimize cache operation when reopening files.
555796c8dcSSimon Schubert    For instance, a flush is entirely unnecessary if the file is already
565796c8dcSSimon Schubert    closed, so a flush would use CACHE_NO_OPEN.  Similarly, a seek using
575796c8dcSSimon Schubert    SEEK_SET or SEEK_END need not first seek to the current position.
585796c8dcSSimon Schubert    For stat we ignore seek errors, just in case the file has changed
595796c8dcSSimon Schubert    while we weren't looking.  If it has, then it's possible that the
605796c8dcSSimon Schubert    file is shorter and we don't want a seek error to prevent us doing
615796c8dcSSimon Schubert    the stat.  */
625796c8dcSSimon Schubert enum cache_flag {
635796c8dcSSimon Schubert   CACHE_NORMAL = 0,
645796c8dcSSimon Schubert   CACHE_NO_OPEN = 1,
655796c8dcSSimon Schubert   CACHE_NO_SEEK = 2,
665796c8dcSSimon Schubert   CACHE_NO_SEEK_ERROR = 4
675796c8dcSSimon Schubert };
685796c8dcSSimon Schubert 
695796c8dcSSimon Schubert /* The maximum number of files which the cache will keep open at
705796c8dcSSimon Schubert    one time.  */
715796c8dcSSimon Schubert 
725796c8dcSSimon Schubert #define BFD_CACHE_MAX_OPEN 10
735796c8dcSSimon Schubert 
745796c8dcSSimon Schubert /* The number of BFD files we have open.  */
755796c8dcSSimon Schubert 
765796c8dcSSimon Schubert static int open_files;
775796c8dcSSimon Schubert 
785796c8dcSSimon Schubert /* Zero, or a pointer to the topmost BFD on the chain.  This is
795796c8dcSSimon Schubert    used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
805796c8dcSSimon Schubert    determine when it can avoid a function call.  */
815796c8dcSSimon Schubert 
825796c8dcSSimon Schubert static bfd *bfd_last_cache = NULL;
835796c8dcSSimon Schubert 
845796c8dcSSimon Schubert /* Insert a BFD into the cache.  */
855796c8dcSSimon Schubert 
865796c8dcSSimon Schubert static void
insert(bfd * abfd)875796c8dcSSimon Schubert insert (bfd *abfd)
885796c8dcSSimon Schubert {
895796c8dcSSimon Schubert   if (bfd_last_cache == NULL)
905796c8dcSSimon Schubert     {
915796c8dcSSimon Schubert       abfd->lru_next = abfd;
925796c8dcSSimon Schubert       abfd->lru_prev = abfd;
935796c8dcSSimon Schubert     }
945796c8dcSSimon Schubert   else
955796c8dcSSimon Schubert     {
965796c8dcSSimon Schubert       abfd->lru_next = bfd_last_cache;
975796c8dcSSimon Schubert       abfd->lru_prev = bfd_last_cache->lru_prev;
985796c8dcSSimon Schubert       abfd->lru_prev->lru_next = abfd;
995796c8dcSSimon Schubert       abfd->lru_next->lru_prev = abfd;
1005796c8dcSSimon Schubert     }
1015796c8dcSSimon Schubert   bfd_last_cache = abfd;
1025796c8dcSSimon Schubert }
1035796c8dcSSimon Schubert 
1045796c8dcSSimon Schubert /* Remove a BFD from the cache.  */
1055796c8dcSSimon Schubert 
1065796c8dcSSimon Schubert static void
snip(bfd * abfd)1075796c8dcSSimon Schubert snip (bfd *abfd)
1085796c8dcSSimon Schubert {
1095796c8dcSSimon Schubert   abfd->lru_prev->lru_next = abfd->lru_next;
1105796c8dcSSimon Schubert   abfd->lru_next->lru_prev = abfd->lru_prev;
1115796c8dcSSimon Schubert   if (abfd == bfd_last_cache)
1125796c8dcSSimon Schubert     {
1135796c8dcSSimon Schubert       bfd_last_cache = abfd->lru_next;
1145796c8dcSSimon Schubert       if (abfd == bfd_last_cache)
1155796c8dcSSimon Schubert 	bfd_last_cache = NULL;
1165796c8dcSSimon Schubert     }
1175796c8dcSSimon Schubert }
1185796c8dcSSimon Schubert 
1195796c8dcSSimon Schubert /* Close a BFD and remove it from the cache.  */
1205796c8dcSSimon Schubert 
1215796c8dcSSimon Schubert static bfd_boolean
bfd_cache_delete(bfd * abfd)1225796c8dcSSimon Schubert bfd_cache_delete (bfd *abfd)
1235796c8dcSSimon Schubert {
1245796c8dcSSimon Schubert   bfd_boolean ret;
1255796c8dcSSimon Schubert 
1265796c8dcSSimon Schubert   if (fclose ((FILE *) abfd->iostream) == 0)
1275796c8dcSSimon Schubert     ret = TRUE;
1285796c8dcSSimon Schubert   else
1295796c8dcSSimon Schubert     {
1305796c8dcSSimon Schubert       ret = FALSE;
1315796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
1325796c8dcSSimon Schubert     }
1335796c8dcSSimon Schubert 
1345796c8dcSSimon Schubert   snip (abfd);
1355796c8dcSSimon Schubert 
1365796c8dcSSimon Schubert   abfd->iostream = NULL;
1375796c8dcSSimon Schubert   --open_files;
1385796c8dcSSimon Schubert 
1395796c8dcSSimon Schubert   return ret;
1405796c8dcSSimon Schubert }
1415796c8dcSSimon Schubert 
1425796c8dcSSimon Schubert /* We need to open a new file, and the cache is full.  Find the least
1435796c8dcSSimon Schubert    recently used cacheable BFD and close it.  */
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert static bfd_boolean
close_one(void)1465796c8dcSSimon Schubert close_one (void)
1475796c8dcSSimon Schubert {
148cf7f2e2dSJohn Marino   register bfd *to_kill;
1495796c8dcSSimon Schubert 
1505796c8dcSSimon Schubert   if (bfd_last_cache == NULL)
151cf7f2e2dSJohn Marino     to_kill = NULL;
1525796c8dcSSimon Schubert   else
1535796c8dcSSimon Schubert     {
154cf7f2e2dSJohn Marino       for (to_kill = bfd_last_cache->lru_prev;
155cf7f2e2dSJohn Marino 	   ! to_kill->cacheable;
156cf7f2e2dSJohn Marino 	   to_kill = to_kill->lru_prev)
1575796c8dcSSimon Schubert 	{
158cf7f2e2dSJohn Marino 	  if (to_kill == bfd_last_cache)
1595796c8dcSSimon Schubert 	    {
160cf7f2e2dSJohn Marino 	      to_kill = NULL;
1615796c8dcSSimon Schubert 	      break;
1625796c8dcSSimon Schubert 	    }
1635796c8dcSSimon Schubert 	}
1645796c8dcSSimon Schubert     }
1655796c8dcSSimon Schubert 
166cf7f2e2dSJohn Marino   if (to_kill == NULL)
1675796c8dcSSimon Schubert     {
1685796c8dcSSimon Schubert       /* There are no open cacheable BFD's.  */
1695796c8dcSSimon Schubert       return TRUE;
1705796c8dcSSimon Schubert     }
1715796c8dcSSimon Schubert 
172cf7f2e2dSJohn Marino   to_kill->where = real_ftell ((FILE *) to_kill->iostream);
1735796c8dcSSimon Schubert 
174cf7f2e2dSJohn Marino   return bfd_cache_delete (to_kill);
1755796c8dcSSimon Schubert }
1765796c8dcSSimon Schubert 
1775796c8dcSSimon Schubert /* Check to see if the required BFD is the same as the last one
1785796c8dcSSimon Schubert    looked up. If so, then it can use the stream in the BFD with
1795796c8dcSSimon Schubert    impunity, since it can't have changed since the last lookup;
1805796c8dcSSimon Schubert    otherwise, it has to perform the complicated lookup function.  */
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert #define bfd_cache_lookup(x, flag) \
1835796c8dcSSimon Schubert   ((x) == bfd_last_cache			\
1845796c8dcSSimon Schubert    ? (FILE *) (bfd_last_cache->iostream)	\
1855796c8dcSSimon Schubert    : bfd_cache_lookup_worker (x, flag))
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert /* Called when the macro <<bfd_cache_lookup>> fails to find a
1885796c8dcSSimon Schubert    quick answer.  Find a file descriptor for @var{abfd}.  If
1895796c8dcSSimon Schubert    necessary, it open it.  If there are already more than
1905796c8dcSSimon Schubert    <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
1915796c8dcSSimon Schubert    avoid running out of file descriptors.  It will return NULL
1925796c8dcSSimon Schubert    if it is unable to (re)open the @var{abfd}.  */
1935796c8dcSSimon Schubert 
1945796c8dcSSimon Schubert static FILE *
bfd_cache_lookup_worker(bfd * abfd,enum cache_flag flag)1955796c8dcSSimon Schubert bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
1965796c8dcSSimon Schubert {
1975796c8dcSSimon Schubert   bfd *orig_bfd = abfd;
1985796c8dcSSimon Schubert   if ((abfd->flags & BFD_IN_MEMORY) != 0)
1995796c8dcSSimon Schubert     abort ();
2005796c8dcSSimon Schubert 
201*ef5ccd6cSJohn Marino   while (abfd->my_archive)
2025796c8dcSSimon Schubert     abfd = abfd->my_archive;
2035796c8dcSSimon Schubert 
2045796c8dcSSimon Schubert   if (abfd->iostream != NULL)
2055796c8dcSSimon Schubert     {
2065796c8dcSSimon Schubert       /* Move the file to the start of the cache.  */
2075796c8dcSSimon Schubert       if (abfd != bfd_last_cache)
2085796c8dcSSimon Schubert 	{
2095796c8dcSSimon Schubert 	  snip (abfd);
2105796c8dcSSimon Schubert 	  insert (abfd);
2115796c8dcSSimon Schubert 	}
2125796c8dcSSimon Schubert       return (FILE *) abfd->iostream;
2135796c8dcSSimon Schubert     }
2145796c8dcSSimon Schubert 
2155796c8dcSSimon Schubert   if (flag & CACHE_NO_OPEN)
2165796c8dcSSimon Schubert     return NULL;
2175796c8dcSSimon Schubert 
2185796c8dcSSimon Schubert   if (bfd_open_file (abfd) == NULL)
2195796c8dcSSimon Schubert     ;
2205796c8dcSSimon Schubert   else if (!(flag & CACHE_NO_SEEK)
2215796c8dcSSimon Schubert 	   && real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0
2225796c8dcSSimon Schubert 	   && !(flag & CACHE_NO_SEEK_ERROR))
2235796c8dcSSimon Schubert     bfd_set_error (bfd_error_system_call);
2245796c8dcSSimon Schubert   else
2255796c8dcSSimon Schubert     return (FILE *) abfd->iostream;
2265796c8dcSSimon Schubert 
2275796c8dcSSimon Schubert   (*_bfd_error_handler) (_("reopening %B: %s\n"),
2285796c8dcSSimon Schubert 			 orig_bfd, bfd_errmsg (bfd_get_error ()));
2295796c8dcSSimon Schubert   return NULL;
2305796c8dcSSimon Schubert }
2315796c8dcSSimon Schubert 
2325796c8dcSSimon Schubert static file_ptr
cache_btell(struct bfd * abfd)2335796c8dcSSimon Schubert cache_btell (struct bfd *abfd)
2345796c8dcSSimon Schubert {
2355796c8dcSSimon Schubert   FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
2365796c8dcSSimon Schubert   if (f == NULL)
2375796c8dcSSimon Schubert     return abfd->where;
2385796c8dcSSimon Schubert   return real_ftell (f);
2395796c8dcSSimon Schubert }
2405796c8dcSSimon Schubert 
2415796c8dcSSimon Schubert static int
cache_bseek(struct bfd * abfd,file_ptr offset,int whence)2425796c8dcSSimon Schubert cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
2435796c8dcSSimon Schubert {
2445796c8dcSSimon Schubert   FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL);
2455796c8dcSSimon Schubert   if (f == NULL)
2465796c8dcSSimon Schubert     return -1;
2475796c8dcSSimon Schubert   return real_fseek (f, offset, whence);
2485796c8dcSSimon Schubert }
2495796c8dcSSimon Schubert 
2505796c8dcSSimon Schubert /* Note that archive entries don't have streams; they share their parent's.
2515796c8dcSSimon Schubert    This allows someone to play with the iostream behind BFD's back.
2525796c8dcSSimon Schubert 
2535796c8dcSSimon Schubert    Also, note that the origin pointer points to the beginning of a file's
2545796c8dcSSimon Schubert    contents (0 for non-archive elements).  For archive entries this is the
2555796c8dcSSimon Schubert    first octet in the file, NOT the beginning of the archive header.  */
2565796c8dcSSimon Schubert 
2575796c8dcSSimon Schubert static file_ptr
cache_bread_1(struct bfd * abfd,void * buf,file_ptr nbytes)2585796c8dcSSimon Schubert cache_bread_1 (struct bfd *abfd, void *buf, file_ptr nbytes)
2595796c8dcSSimon Schubert {
2605796c8dcSSimon Schubert   FILE *f;
2615796c8dcSSimon Schubert   file_ptr nread;
2625796c8dcSSimon Schubert   /* FIXME - this looks like an optimization, but it's really to cover
2635796c8dcSSimon Schubert      up for a feature of some OSs (not solaris - sigh) that
2645796c8dcSSimon Schubert      ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
2655796c8dcSSimon Schubert      internally and tries to link against them.  BFD seems to be smart
2665796c8dcSSimon Schubert      enough to realize there are no symbol records in the "file" that
2675796c8dcSSimon Schubert      doesn't exist but attempts to read them anyway.  On Solaris,
2685796c8dcSSimon Schubert      attempting to read zero bytes from a NULL file results in a core
2695796c8dcSSimon Schubert      dump, but on other platforms it just returns zero bytes read.
2705796c8dcSSimon Schubert      This makes it to something reasonable. - DJ */
2715796c8dcSSimon Schubert   if (nbytes == 0)
2725796c8dcSSimon Schubert     return 0;
2735796c8dcSSimon Schubert 
2745796c8dcSSimon Schubert   f = bfd_cache_lookup (abfd, CACHE_NORMAL);
2755796c8dcSSimon Schubert   if (f == NULL)
2765796c8dcSSimon Schubert     return 0;
2775796c8dcSSimon Schubert 
2785796c8dcSSimon Schubert #if defined (__VAX) && defined (VMS)
2795796c8dcSSimon Schubert   /* Apparently fread on Vax VMS does not keep the record length
2805796c8dcSSimon Schubert      information.  */
2815796c8dcSSimon Schubert   nread = read (fileno (f), buf, nbytes);
2825796c8dcSSimon Schubert   /* Set bfd_error if we did not read as much data as we expected.  If
2835796c8dcSSimon Schubert      the read failed due to an error set the bfd_error_system_call,
2845796c8dcSSimon Schubert      else set bfd_error_file_truncated.  */
2855796c8dcSSimon Schubert   if (nread == (file_ptr)-1)
2865796c8dcSSimon Schubert     {
2875796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
2885796c8dcSSimon Schubert       return -1;
2895796c8dcSSimon Schubert     }
2905796c8dcSSimon Schubert #else
2915796c8dcSSimon Schubert   nread = fread (buf, 1, nbytes, f);
2925796c8dcSSimon Schubert   /* Set bfd_error if we did not read as much data as we expected.  If
2935796c8dcSSimon Schubert      the read failed due to an error set the bfd_error_system_call,
2945796c8dcSSimon Schubert      else set bfd_error_file_truncated.  */
2955796c8dcSSimon Schubert   if (nread < nbytes && ferror (f))
2965796c8dcSSimon Schubert     {
2975796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
2985796c8dcSSimon Schubert       return -1;
2995796c8dcSSimon Schubert     }
3005796c8dcSSimon Schubert #endif
3015796c8dcSSimon Schubert   if (nread < nbytes)
3025796c8dcSSimon Schubert     /* This may or may not be an error, but in case the calling code
3035796c8dcSSimon Schubert        bails out because of it, set the right error code.  */
3045796c8dcSSimon Schubert     bfd_set_error (bfd_error_file_truncated);
3055796c8dcSSimon Schubert   return nread;
3065796c8dcSSimon Schubert }
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert static file_ptr
cache_bread(struct bfd * abfd,void * buf,file_ptr nbytes)3095796c8dcSSimon Schubert cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
3105796c8dcSSimon Schubert {
3115796c8dcSSimon Schubert   file_ptr nread = 0;
3125796c8dcSSimon Schubert 
3135796c8dcSSimon Schubert   /* Some filesystems are unable to handle reads that are too large
3145796c8dcSSimon Schubert      (for instance, NetApp shares with oplocks turned off).  To avoid
3155796c8dcSSimon Schubert      hitting this limitation, we read the buffer in chunks of 8MB max.  */
3165796c8dcSSimon Schubert   while (nread < nbytes)
3175796c8dcSSimon Schubert     {
3185796c8dcSSimon Schubert       const file_ptr max_chunk_size = 0x800000;
3195796c8dcSSimon Schubert       file_ptr chunk_size = nbytes - nread;
3205796c8dcSSimon Schubert       file_ptr chunk_nread;
3215796c8dcSSimon Schubert 
3225796c8dcSSimon Schubert       if (chunk_size > max_chunk_size)
3235796c8dcSSimon Schubert         chunk_size = max_chunk_size;
3245796c8dcSSimon Schubert 
3255796c8dcSSimon Schubert       chunk_nread = cache_bread_1 (abfd, (char *) buf + nread, chunk_size);
3265796c8dcSSimon Schubert 
3275796c8dcSSimon Schubert       /* Update the nread count.
3285796c8dcSSimon Schubert 
3295796c8dcSSimon Schubert          We just have to be careful of the case when cache_bread_1 returns
3305796c8dcSSimon Schubert          a negative count:  If this is our first read, then set nread to
3315796c8dcSSimon Schubert          that negative count in order to return that negative value to the
3325796c8dcSSimon Schubert          caller.  Otherwise, don't add it to our total count, or we would
3335796c8dcSSimon Schubert          end up returning a smaller number of bytes read than we actually
3345796c8dcSSimon Schubert          did.  */
3355796c8dcSSimon Schubert       if (nread == 0 || chunk_nread > 0)
3365796c8dcSSimon Schubert         nread += chunk_nread;
3375796c8dcSSimon Schubert 
3385796c8dcSSimon Schubert       if (chunk_nread < chunk_size)
3395796c8dcSSimon Schubert         break;
3405796c8dcSSimon Schubert     }
3415796c8dcSSimon Schubert 
3425796c8dcSSimon Schubert   return nread;
3435796c8dcSSimon Schubert }
3445796c8dcSSimon Schubert 
3455796c8dcSSimon Schubert static file_ptr
cache_bwrite(struct bfd * abfd,const void * where,file_ptr nbytes)3465796c8dcSSimon Schubert cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
3475796c8dcSSimon Schubert {
3485796c8dcSSimon Schubert   file_ptr nwrite;
3495796c8dcSSimon Schubert   FILE *f = bfd_cache_lookup (abfd, CACHE_NORMAL);
3505796c8dcSSimon Schubert 
3515796c8dcSSimon Schubert   if (f == NULL)
3525796c8dcSSimon Schubert     return 0;
3535796c8dcSSimon Schubert   nwrite = fwrite (where, 1, nbytes, f);
3545796c8dcSSimon Schubert   if (nwrite < nbytes && ferror (f))
3555796c8dcSSimon Schubert     {
3565796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
3575796c8dcSSimon Schubert       return -1;
3585796c8dcSSimon Schubert     }
3595796c8dcSSimon Schubert   return nwrite;
3605796c8dcSSimon Schubert }
3615796c8dcSSimon Schubert 
3625796c8dcSSimon Schubert static int
cache_bclose(struct bfd * abfd)3635796c8dcSSimon Schubert cache_bclose (struct bfd *abfd)
3645796c8dcSSimon Schubert {
365*ef5ccd6cSJohn Marino   return bfd_cache_close (abfd) - 1;
3665796c8dcSSimon Schubert }
3675796c8dcSSimon Schubert 
3685796c8dcSSimon Schubert static int
cache_bflush(struct bfd * abfd)3695796c8dcSSimon Schubert cache_bflush (struct bfd *abfd)
3705796c8dcSSimon Schubert {
3715796c8dcSSimon Schubert   int sts;
3725796c8dcSSimon Schubert   FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN);
3735796c8dcSSimon Schubert 
3745796c8dcSSimon Schubert   if (f == NULL)
3755796c8dcSSimon Schubert     return 0;
3765796c8dcSSimon Schubert   sts = fflush (f);
3775796c8dcSSimon Schubert   if (sts < 0)
3785796c8dcSSimon Schubert     bfd_set_error (bfd_error_system_call);
3795796c8dcSSimon Schubert   return sts;
3805796c8dcSSimon Schubert }
3815796c8dcSSimon Schubert 
3825796c8dcSSimon Schubert static int
cache_bstat(struct bfd * abfd,struct stat * sb)3835796c8dcSSimon Schubert cache_bstat (struct bfd *abfd, struct stat *sb)
3845796c8dcSSimon Schubert {
3855796c8dcSSimon Schubert   int sts;
3865796c8dcSSimon Schubert   FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
3875796c8dcSSimon Schubert 
3885796c8dcSSimon Schubert   if (f == NULL)
3895796c8dcSSimon Schubert     return -1;
3905796c8dcSSimon Schubert   sts = fstat (fileno (f), sb);
3915796c8dcSSimon Schubert   if (sts < 0)
3925796c8dcSSimon Schubert     bfd_set_error (bfd_error_system_call);
3935796c8dcSSimon Schubert   return sts;
3945796c8dcSSimon Schubert }
3955796c8dcSSimon Schubert 
3965796c8dcSSimon Schubert 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)3975796c8dcSSimon Schubert cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
3985796c8dcSSimon Schubert 	     void *addr ATTRIBUTE_UNUSED,
3995796c8dcSSimon Schubert 	     bfd_size_type len ATTRIBUTE_UNUSED,
4005796c8dcSSimon Schubert 	     int prot ATTRIBUTE_UNUSED,
4015796c8dcSSimon Schubert 	     int flags ATTRIBUTE_UNUSED,
402a45ae5f8SJohn Marino 	     file_ptr offset ATTRIBUTE_UNUSED,
403a45ae5f8SJohn Marino              void **map_addr ATTRIBUTE_UNUSED,
404a45ae5f8SJohn Marino              bfd_size_type *map_len ATTRIBUTE_UNUSED)
4055796c8dcSSimon Schubert {
4065796c8dcSSimon Schubert   void *ret = (void *) -1;
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert   if ((abfd->flags & BFD_IN_MEMORY) != 0)
4095796c8dcSSimon Schubert     abort ();
4105796c8dcSSimon Schubert #ifdef HAVE_MMAP
4115796c8dcSSimon Schubert   else
4125796c8dcSSimon Schubert     {
413a45ae5f8SJohn Marino       static uintptr_t pagesize_m1;
414a45ae5f8SJohn Marino       FILE *f;
415a45ae5f8SJohn Marino       file_ptr pg_offset;
416a45ae5f8SJohn Marino       bfd_size_type pg_len;
417a45ae5f8SJohn Marino 
418a45ae5f8SJohn Marino       f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
4195796c8dcSSimon Schubert       if (f == NULL)
4205796c8dcSSimon Schubert 	return ret;
4215796c8dcSSimon Schubert 
422a45ae5f8SJohn Marino       if (pagesize_m1 == 0)
423a45ae5f8SJohn Marino         pagesize_m1 = getpagesize () - 1;
424a45ae5f8SJohn Marino 
425a45ae5f8SJohn Marino       /* Handle archive members.  */
426a45ae5f8SJohn Marino       if (abfd->my_archive != NULL)
427a45ae5f8SJohn Marino         offset += abfd->origin;
428a45ae5f8SJohn Marino 
429a45ae5f8SJohn Marino       /* Align.  */
430a45ae5f8SJohn Marino       pg_offset = offset & ~pagesize_m1;
431a45ae5f8SJohn Marino       pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1;
432a45ae5f8SJohn Marino 
433a45ae5f8SJohn Marino       ret = mmap (addr, pg_len, prot, flags, fileno (f), pg_offset);
4345796c8dcSSimon Schubert       if (ret == (void *) -1)
4355796c8dcSSimon Schubert 	bfd_set_error (bfd_error_system_call);
436a45ae5f8SJohn Marino       else
437a45ae5f8SJohn Marino         {
438a45ae5f8SJohn Marino           *map_addr = ret;
439a45ae5f8SJohn Marino           *map_len = pg_len;
440*ef5ccd6cSJohn Marino           ret = (char *) ret + (offset & pagesize_m1);
441a45ae5f8SJohn Marino         }
4425796c8dcSSimon Schubert     }
4435796c8dcSSimon Schubert #endif
4445796c8dcSSimon Schubert 
4455796c8dcSSimon Schubert   return ret;
4465796c8dcSSimon Schubert }
4475796c8dcSSimon Schubert 
4485796c8dcSSimon Schubert static const struct bfd_iovec cache_iovec =
4495796c8dcSSimon Schubert {
4505796c8dcSSimon Schubert   &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
4515796c8dcSSimon Schubert   &cache_bclose, &cache_bflush, &cache_bstat, &cache_bmmap
4525796c8dcSSimon Schubert };
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert /*
4555796c8dcSSimon Schubert INTERNAL_FUNCTION
4565796c8dcSSimon Schubert 	bfd_cache_init
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert SYNOPSIS
4595796c8dcSSimon Schubert 	bfd_boolean bfd_cache_init (bfd *abfd);
4605796c8dcSSimon Schubert 
4615796c8dcSSimon Schubert DESCRIPTION
4625796c8dcSSimon Schubert 	Add a newly opened BFD to the cache.
4635796c8dcSSimon Schubert */
4645796c8dcSSimon Schubert 
4655796c8dcSSimon Schubert bfd_boolean
bfd_cache_init(bfd * abfd)4665796c8dcSSimon Schubert bfd_cache_init (bfd *abfd)
4675796c8dcSSimon Schubert {
4685796c8dcSSimon Schubert   BFD_ASSERT (abfd->iostream != NULL);
4695796c8dcSSimon Schubert   if (open_files >= BFD_CACHE_MAX_OPEN)
4705796c8dcSSimon Schubert     {
4715796c8dcSSimon Schubert       if (! close_one ())
4725796c8dcSSimon Schubert 	return FALSE;
4735796c8dcSSimon Schubert     }
4745796c8dcSSimon Schubert   abfd->iovec = &cache_iovec;
4755796c8dcSSimon Schubert   insert (abfd);
4765796c8dcSSimon Schubert   ++open_files;
4775796c8dcSSimon Schubert   return TRUE;
4785796c8dcSSimon Schubert }
4795796c8dcSSimon Schubert 
4805796c8dcSSimon Schubert /*
4815796c8dcSSimon Schubert INTERNAL_FUNCTION
4825796c8dcSSimon Schubert 	bfd_cache_close
4835796c8dcSSimon Schubert 
4845796c8dcSSimon Schubert SYNOPSIS
4855796c8dcSSimon Schubert 	bfd_boolean bfd_cache_close (bfd *abfd);
4865796c8dcSSimon Schubert 
4875796c8dcSSimon Schubert DESCRIPTION
4885796c8dcSSimon Schubert 	Remove the BFD @var{abfd} from the cache. If the attached file is open,
4895796c8dcSSimon Schubert 	then close it too.
4905796c8dcSSimon Schubert 
4915796c8dcSSimon Schubert RETURNS
4925796c8dcSSimon Schubert 	<<FALSE>> is returned if closing the file fails, <<TRUE>> is
4935796c8dcSSimon Schubert 	returned if all is well.
4945796c8dcSSimon Schubert */
4955796c8dcSSimon Schubert 
4965796c8dcSSimon Schubert bfd_boolean
bfd_cache_close(bfd * abfd)4975796c8dcSSimon Schubert bfd_cache_close (bfd *abfd)
4985796c8dcSSimon Schubert {
4995796c8dcSSimon Schubert   if (abfd->iovec != &cache_iovec)
5005796c8dcSSimon Schubert     return TRUE;
5015796c8dcSSimon Schubert 
5025796c8dcSSimon Schubert   if (abfd->iostream == NULL)
5035796c8dcSSimon Schubert     /* Previously closed.  */
5045796c8dcSSimon Schubert     return TRUE;
5055796c8dcSSimon Schubert 
5065796c8dcSSimon Schubert   return bfd_cache_delete (abfd);
5075796c8dcSSimon Schubert }
5085796c8dcSSimon Schubert 
5095796c8dcSSimon Schubert /*
5105796c8dcSSimon Schubert FUNCTION
5115796c8dcSSimon Schubert 	bfd_cache_close_all
5125796c8dcSSimon Schubert 
5135796c8dcSSimon Schubert SYNOPSIS
5145796c8dcSSimon Schubert 	bfd_boolean bfd_cache_close_all (void);
5155796c8dcSSimon Schubert 
5165796c8dcSSimon Schubert DESCRIPTION
5175796c8dcSSimon Schubert 	Remove all BFDs from the cache. If the attached file is open,
5185796c8dcSSimon Schubert 	then close it too.
5195796c8dcSSimon Schubert 
5205796c8dcSSimon Schubert RETURNS
5215796c8dcSSimon Schubert 	<<FALSE>> is returned if closing one of the file fails, <<TRUE>> is
5225796c8dcSSimon Schubert 	returned if all is well.
5235796c8dcSSimon Schubert */
5245796c8dcSSimon Schubert 
5255796c8dcSSimon Schubert bfd_boolean
bfd_cache_close_all()5265796c8dcSSimon Schubert bfd_cache_close_all ()
5275796c8dcSSimon Schubert {
5285796c8dcSSimon Schubert   bfd_boolean ret = TRUE;
5295796c8dcSSimon Schubert 
5305796c8dcSSimon Schubert   while (bfd_last_cache != NULL)
5315796c8dcSSimon Schubert     ret &= bfd_cache_close (bfd_last_cache);
5325796c8dcSSimon Schubert 
5335796c8dcSSimon Schubert   return ret;
5345796c8dcSSimon Schubert }
5355796c8dcSSimon Schubert 
5365796c8dcSSimon Schubert /*
5375796c8dcSSimon Schubert INTERNAL_FUNCTION
5385796c8dcSSimon Schubert 	bfd_open_file
5395796c8dcSSimon Schubert 
5405796c8dcSSimon Schubert SYNOPSIS
5415796c8dcSSimon Schubert 	FILE* bfd_open_file (bfd *abfd);
5425796c8dcSSimon Schubert 
5435796c8dcSSimon Schubert DESCRIPTION
5445796c8dcSSimon Schubert 	Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
5455796c8dcSSimon Schubert 	(possibly <<NULL>>) that results from this operation.  Set up the
5465796c8dcSSimon Schubert 	BFD so that future accesses know the file is open. If the <<FILE *>>
5475796c8dcSSimon Schubert 	returned is <<NULL>>, then it won't have been put in the
5485796c8dcSSimon Schubert 	cache, so it won't have to be removed from it.
5495796c8dcSSimon Schubert */
5505796c8dcSSimon Schubert 
5515796c8dcSSimon Schubert FILE *
bfd_open_file(bfd * abfd)5525796c8dcSSimon Schubert bfd_open_file (bfd *abfd)
5535796c8dcSSimon Schubert {
5545796c8dcSSimon Schubert   abfd->cacheable = TRUE;	/* Allow it to be closed later.  */
5555796c8dcSSimon Schubert 
5565796c8dcSSimon Schubert   if (open_files >= BFD_CACHE_MAX_OPEN)
5575796c8dcSSimon Schubert     {
5585796c8dcSSimon Schubert       if (! close_one ())
5595796c8dcSSimon Schubert 	return NULL;
5605796c8dcSSimon Schubert     }
5615796c8dcSSimon Schubert 
5625796c8dcSSimon Schubert   switch (abfd->direction)
5635796c8dcSSimon Schubert     {
5645796c8dcSSimon Schubert     case read_direction:
5655796c8dcSSimon Schubert     case no_direction:
566*ef5ccd6cSJohn Marino       abfd->iostream = real_fopen (abfd->filename, FOPEN_RB);
5675796c8dcSSimon Schubert       break;
5685796c8dcSSimon Schubert     case both_direction:
5695796c8dcSSimon Schubert     case write_direction:
5705796c8dcSSimon Schubert       if (abfd->opened_once)
5715796c8dcSSimon Schubert 	{
572*ef5ccd6cSJohn Marino 	  abfd->iostream = real_fopen (abfd->filename, FOPEN_RUB);
5735796c8dcSSimon Schubert 	  if (abfd->iostream == NULL)
574*ef5ccd6cSJohn Marino 	    abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB);
5755796c8dcSSimon Schubert 	}
5765796c8dcSSimon Schubert       else
5775796c8dcSSimon Schubert 	{
5785796c8dcSSimon Schubert 	  /* Create the file.
5795796c8dcSSimon Schubert 
5805796c8dcSSimon Schubert 	     Some operating systems won't let us overwrite a running
5815796c8dcSSimon Schubert 	     binary.  For them, we want to unlink the file first.
5825796c8dcSSimon Schubert 
5835796c8dcSSimon Schubert 	     However, gcc 2.95 will create temporary files using
5845796c8dcSSimon Schubert 	     O_EXCL and tight permissions to prevent other users from
5855796c8dcSSimon Schubert 	     substituting other .o files during the compilation.  gcc
5865796c8dcSSimon Schubert 	     will then tell the assembler to use the newly created
5875796c8dcSSimon Schubert 	     file as an output file.  If we unlink the file here, we
5885796c8dcSSimon Schubert 	     open a brief window when another user could still
5895796c8dcSSimon Schubert 	     substitute a file.
5905796c8dcSSimon Schubert 
5915796c8dcSSimon Schubert 	     So we unlink the output file if and only if it has
5925796c8dcSSimon Schubert 	     non-zero size.  */
5935796c8dcSSimon Schubert #ifndef __MSDOS__
5945796c8dcSSimon Schubert 	  /* Don't do this for MSDOS: it doesn't care about overwriting
5955796c8dcSSimon Schubert 	     a running binary, but if this file is already open by
5965796c8dcSSimon Schubert 	     another BFD, we will be in deep trouble if we delete an
5975796c8dcSSimon Schubert 	     open file.  In fact, objdump does just that if invoked with
5985796c8dcSSimon Schubert 	     the --info option.  */
5995796c8dcSSimon Schubert 	  struct stat s;
6005796c8dcSSimon Schubert 
6015796c8dcSSimon Schubert 	  if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
6025796c8dcSSimon Schubert 	    unlink_if_ordinary (abfd->filename);
6035796c8dcSSimon Schubert #endif
604*ef5ccd6cSJohn Marino 	  abfd->iostream = real_fopen (abfd->filename, FOPEN_WUB);
6055796c8dcSSimon Schubert 	  abfd->opened_once = TRUE;
6065796c8dcSSimon Schubert 	}
6075796c8dcSSimon Schubert       break;
6085796c8dcSSimon Schubert     }
6095796c8dcSSimon Schubert 
6105796c8dcSSimon Schubert   if (abfd->iostream == NULL)
6115796c8dcSSimon Schubert     bfd_set_error (bfd_error_system_call);
6125796c8dcSSimon Schubert   else
6135796c8dcSSimon Schubert     {
6145796c8dcSSimon Schubert       if (! bfd_cache_init (abfd))
6155796c8dcSSimon Schubert 	return NULL;
6165796c8dcSSimon Schubert     }
6175796c8dcSSimon Schubert 
6185796c8dcSSimon Schubert   return (FILE *) abfd->iostream;
6195796c8dcSSimon Schubert }
620