~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* BFD library -- caching of file descriptors.
 
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002
 
3
   Free Software Foundation, Inc.
 
4
   Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
 
5
 
 
6
This file is part of BFD, the Binary File Descriptor library.
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
21
 
 
22
/*
 
23
SECTION
 
24
        File caching
 
25
 
 
26
        The file caching mechanism is embedded within BFD and allows
 
27
        the application to open as many BFDs as it wants without
 
28
        regard to the underlying operating system's file descriptor
 
29
        limit (often as low as 20 open files).  The module in
 
30
        <<cache.c>> maintains a least recently used list of
 
31
        <<BFD_CACHE_MAX_OPEN>> files, and exports the name
 
32
        <<bfd_cache_lookup>>, which runs around and makes sure that
 
33
        the required BFD is open. If not, then it chooses a file to
 
34
        close, closes it and opens the one wanted, returning its file
 
35
        handle.
 
36
 
 
37
*/
 
38
 
 
39
#include "bfd.h"
 
40
#include "sysdep.h"
 
41
#include "libbfd.h"
 
42
 
 
43
static void insert PARAMS ((bfd *));
 
44
static void snip PARAMS ((bfd *));
 
45
static boolean close_one PARAMS ((void));
 
46
static boolean bfd_cache_delete PARAMS ((bfd *));
 
47
 
 
48
/*
 
49
INTERNAL_FUNCTION
 
50
        BFD_CACHE_MAX_OPEN macro
 
51
 
 
52
DESCRIPTION
 
53
        The maximum number of files which the cache will keep open at
 
54
        one time.
 
55
 
 
56
.#define BFD_CACHE_MAX_OPEN 10
 
57
 
 
58
*/
 
59
 
 
60
/* The number of BFD files we have open.  */
 
61
 
 
62
static int open_files;
 
63
 
 
64
/*
 
65
INTERNAL_FUNCTION
 
66
        bfd_last_cache
 
67
 
 
68
SYNOPSIS
 
69
        extern bfd *bfd_last_cache;
 
70
 
 
71
DESCRIPTION
 
72
        Zero, or a pointer to the topmost BFD on the chain.  This is
 
73
        used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
 
74
        determine when it can avoid a function call.
 
75
*/
 
76
 
 
77
bfd *bfd_last_cache;
 
78
 
 
79
/*
 
80
  INTERNAL_FUNCTION
 
81
        bfd_cache_lookup
 
82
 
 
83
  DESCRIPTION
 
84
        Check to see if the required BFD is the same as the last one
 
85
        looked up. If so, then it can use the stream in the BFD with
 
86
        impunity, since it can't have changed since the last lookup;
 
87
        otherwise, it has to perform the complicated lookup function.
 
88
 
 
89
  .#define bfd_cache_lookup(x) \
 
90
  .    ((x)==bfd_last_cache? \
 
91
  .      (FILE*) (bfd_last_cache->iostream): \
 
92
  .       bfd_cache_lookup_worker(x))
 
93
 
 
94
 */
 
95
 
 
96
/* Insert a BFD into the cache.  */
 
97
 
 
98
static INLINE void
 
99
insert (abfd)
 
100
     bfd *abfd;
 
101
{
 
102
  if (bfd_last_cache == NULL)
 
103
    {
 
104
      abfd->lru_next = abfd;
 
105
      abfd->lru_prev = abfd;
 
106
    }
 
107
  else
 
108
    {
 
109
      abfd->lru_next = bfd_last_cache;
 
110
      abfd->lru_prev = bfd_last_cache->lru_prev;
 
111
      abfd->lru_prev->lru_next = abfd;
 
112
      abfd->lru_next->lru_prev = abfd;
 
113
    }
 
114
  bfd_last_cache = abfd;
 
115
}
 
116
 
 
117
/* Remove a BFD from the cache.  */
 
118
 
 
119
static INLINE void
 
120
snip (abfd)
 
121
     bfd *abfd;
 
122
{
 
123
  abfd->lru_prev->lru_next = abfd->lru_next;
 
124
  abfd->lru_next->lru_prev = abfd->lru_prev;
 
125
  if (abfd == bfd_last_cache)
 
126
    {
 
127
      bfd_last_cache = abfd->lru_next;
 
128
      if (abfd == bfd_last_cache)
 
129
        bfd_last_cache = NULL;
 
130
    }
 
131
}
 
132
 
 
133
/* We need to open a new file, and the cache is full.  Find the least
 
134
   recently used cacheable BFD and close it.  */
 
135
 
 
136
static boolean
 
137
close_one ()
 
138
{
 
139
  register bfd *kill;
 
140
 
 
141
  if (bfd_last_cache == NULL)
 
142
    kill = NULL;
 
143
  else
 
144
    {
 
145
      for (kill = bfd_last_cache->lru_prev;
 
146
           ! kill->cacheable;
 
147
           kill = kill->lru_prev)
 
148
        {
 
149
          if (kill == bfd_last_cache)
 
150
            {
 
151
              kill = NULL;
 
152
              break;
 
153
            }
 
154
        }
 
155
    }
 
156
 
 
157
  if (kill == NULL)
 
158
    {
 
159
      /* There are no open cacheable BFD's.  */
 
160
      return true;
 
161
    }
 
162
 
 
163
  kill->where = ftell ((FILE *) kill->iostream);
 
164
 
 
165
  return bfd_cache_delete (kill);
 
166
}
 
167
 
 
168
/* Close a BFD and remove it from the cache.  */
 
169
 
 
170
static boolean
 
171
bfd_cache_delete (abfd)
 
172
     bfd *abfd;
 
173
{
 
174
  boolean ret;
 
175
 
 
176
  if (fclose ((FILE *) abfd->iostream) == 0)
 
177
    ret = true;
 
178
  else
 
179
    {
 
180
      ret = false;
 
181
      bfd_set_error (bfd_error_system_call);
 
182
    }
 
183
 
 
184
  snip (abfd);
 
185
 
 
186
  abfd->iostream = NULL;
 
187
  --open_files;
 
188
 
 
189
  return ret;
 
190
}
 
191
 
 
192
/*
 
193
INTERNAL_FUNCTION
 
194
        bfd_cache_init
 
195
 
 
196
SYNOPSIS
 
197
        boolean bfd_cache_init (bfd *abfd);
 
198
 
 
199
DESCRIPTION
 
200
        Add a newly opened BFD to the cache.
 
201
*/
 
202
 
 
203
boolean
 
204
bfd_cache_init (abfd)
 
205
     bfd *abfd;
 
206
{
 
207
  BFD_ASSERT (abfd->iostream != NULL);
 
208
  if (open_files >= BFD_CACHE_MAX_OPEN)
 
209
    {
 
210
      if (! close_one ())
 
211
        return false;
 
212
    }
 
213
  insert (abfd);
 
214
  ++open_files;
 
215
  return true;
 
216
}
 
217
 
 
218
/*
 
219
INTERNAL_FUNCTION
 
220
        bfd_cache_close
 
221
 
 
222
SYNOPSIS
 
223
        boolean bfd_cache_close (bfd *abfd);
 
224
 
 
225
DESCRIPTION
 
226
        Remove the BFD @var{abfd} from the cache. If the attached file is open,
 
227
        then close it too.
 
228
 
 
229
RETURNS
 
230
        <<false>> is returned if closing the file fails, <<true>> is
 
231
        returned if all is well.
 
232
*/
 
233
 
 
234
boolean
 
235
bfd_cache_close (abfd)
 
236
     bfd *abfd;
 
237
{
 
238
  if (abfd->iostream == NULL
 
239
      || (abfd->flags & BFD_IN_MEMORY) != 0)
 
240
    return true;
 
241
 
 
242
  return bfd_cache_delete (abfd);
 
243
}
 
244
 
 
245
/*
 
246
INTERNAL_FUNCTION
 
247
        bfd_open_file
 
248
 
 
249
SYNOPSIS
 
250
        FILE* bfd_open_file(bfd *abfd);
 
251
 
 
252
DESCRIPTION
 
253
        Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
 
254
        (possibly <<NULL>>) that results from this operation.  Set up the
 
255
        BFD so that future accesses know the file is open. If the <<FILE *>>
 
256
        returned is <<NULL>>, then it won't have been put in the
 
257
        cache, so it won't have to be removed from it.
 
258
*/
 
259
 
 
260
FILE *
 
261
bfd_open_file (abfd)
 
262
     bfd *abfd;
 
263
{
 
264
  abfd->cacheable = true;       /* Allow it to be closed later.  */
 
265
 
 
266
  if (open_files >= BFD_CACHE_MAX_OPEN)
 
267
    {
 
268
      if (! close_one ())
 
269
        return NULL;
 
270
    }
 
271
 
 
272
  switch (abfd->direction)
 
273
    {
 
274
    case read_direction:
 
275
    case no_direction:
 
276
      abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
 
277
      break;
 
278
    case both_direction:
 
279
    case write_direction:
 
280
      if (abfd->opened_once)
 
281
        {
 
282
          abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
 
283
          if (abfd->iostream == NULL)
 
284
            abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
 
285
        }
 
286
      else
 
287
        {
 
288
          /* Create the file.
 
289
 
 
290
             Some operating systems won't let us overwrite a running
 
291
             binary.  For them, we want to unlink the file first.
 
292
 
 
293
             However, gcc 2.95 will create temporary files using
 
294
             O_EXCL and tight permissions to prevent other users from
 
295
             substituting other .o files during the compilation.  gcc
 
296
             will then tell the assembler to use the newly created
 
297
             file as an output file.  If we unlink the file here, we
 
298
             open a brief window when another user could still
 
299
             substitute a file.
 
300
 
 
301
             So we unlink the output file if and only if it has
 
302
             non-zero size.  */
 
303
#ifndef __MSDOS__
 
304
          /* Don't do this for MSDOS: it doesn't care about overwriting
 
305
             a running binary, but if this file is already open by
 
306
             another BFD, we will be in deep trouble if we delete an
 
307
             open file.  In fact, objdump does just that if invoked with
 
308
             the --info option.  */
 
309
          struct stat s;
 
310
 
 
311
          if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
 
312
            unlink (abfd->filename);
 
313
#endif
 
314
          abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
 
315
          abfd->opened_once = true;
 
316
        }
 
317
      break;
 
318
    }
 
319
 
 
320
  if (abfd->iostream != NULL)
 
321
    {
 
322
      if (! bfd_cache_init (abfd))
 
323
        return NULL;
 
324
    }
 
325
 
 
326
  return (FILE *) abfd->iostream;
 
327
}
 
328
 
 
329
/*
 
330
INTERNAL_FUNCTION
 
331
        bfd_cache_lookup_worker
 
332
 
 
333
SYNOPSIS
 
334
        FILE *bfd_cache_lookup_worker(bfd *abfd);
 
335
 
 
336
DESCRIPTION
 
337
        Called when the macro <<bfd_cache_lookup>> fails to find a
 
338
        quick answer.  Find a file descriptor for @var{abfd}.  If
 
339
        necessary, it open it.  If there are already more than
 
340
        <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
 
341
        avoid running out of file descriptors.
 
342
*/
 
343
 
 
344
FILE *
 
345
bfd_cache_lookup_worker (abfd)
 
346
     bfd *abfd;
 
347
{
 
348
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
 
349
    abort ();
 
350
 
 
351
  if (abfd->my_archive)
 
352
    abfd = abfd->my_archive;
 
353
 
 
354
  if (abfd->iostream != NULL)
 
355
    {
 
356
      /* Move the file to the start of the cache.  */
 
357
      if (abfd != bfd_last_cache)
 
358
        {
 
359
          snip (abfd);
 
360
          insert (abfd);
 
361
        }
 
362
    }
 
363
  else
 
364
    {
 
365
      if (bfd_open_file (abfd) == NULL)
 
366
        return NULL;
 
367
      if (abfd->where != (unsigned long) abfd->where)
 
368
        return NULL;
 
369
      if (fseek ((FILE *) abfd->iostream, (long) abfd->where, SEEK_SET) != 0)
 
370
        return NULL;
 
371
    }
 
372
 
 
373
  return (FILE *) abfd->iostream;
 
374
}