OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [bfdio.c] - Blame information for rev 146

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* Low-level I/O routines for BFDs.
2
 
3
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4
   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
5
   Free Software Foundation, Inc.
6
 
7
   Written by Cygnus Support.
8
 
9
   This file is part of BFD, the Binary File Descriptor library.
10
 
11
   This program is free software; you can redistribute it and/or modify
12
   it under the terms of the GNU General Public License as published by
13
   the Free Software Foundation; either version 3 of the License, or
14
   (at your option) any later version.
15
 
16
   This program is distributed in the hope that it will be useful,
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
   GNU General Public License for more details.
20
 
21
   You should have received a copy of the GNU General Public License
22
   along with this program; if not, write to the Free Software
23
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24
   MA 02110-1301, USA.  */
25
 
26
#include "sysdep.h"
27
#include <limits.h>
28
#include "bfd.h"
29
#include "libbfd.h"
30
 
31
#ifndef S_IXUSR
32
#define S_IXUSR 0100    /* Execute by owner.  */
33
#endif
34
#ifndef S_IXGRP
35
#define S_IXGRP 0010    /* Execute by group.  */
36
#endif
37
#ifndef S_IXOTH
38
#define S_IXOTH 0001    /* Execute by others.  */
39
#endif
40
 
41
#ifndef FD_CLOEXEC
42
#define FD_CLOEXEC 1
43
#endif
44
 
45
file_ptr
46
real_ftell (FILE *file)
47
{
48
#if defined (HAVE_FTELLO64)
49
  return ftello64 (file);
50
#elif defined (HAVE_FTELLO)
51
  return ftello (file);
52
#else
53
  return ftell (file);
54
#endif
55
}
56
 
57
int
58
real_fseek (FILE *file, file_ptr offset, int whence)
59
{
60
#if defined (HAVE_FSEEKO64)
61
  return fseeko64 (file, offset, whence);
62
#elif defined (HAVE_FSEEKO)
63
  return fseeko (file, offset, whence);
64
#else
65
  return fseek (file, offset, whence);
66
#endif
67
}
68
 
69
/* Mark FILE as close-on-exec.  Return FILE.  FILE may be NULL, in
70
   which case nothing is done.  */
71
static FILE *
72
close_on_exec (FILE *file)
73
{
74
#if defined (HAVE_FILENO) && defined (F_GETFD)
75
  if (file)
76
    {
77
      int fd = fileno (file);
78
      int old = fcntl (fd, F_GETFD, 0);
79
      if (old >= 0)
80
        fcntl (fd, F_SETFD, old | FD_CLOEXEC);
81
    }
82
#endif
83
  return file;
84
}
85
 
86
FILE *
87
real_fopen (const char *filename, const char *modes)
88
{
89
#ifdef VMS
90
  char vms_modes[4];
91
  char *vms_attr;
92
 
93
  /* On VMS, fopen allows file attributes as optionnal arguments.
94
     We need to use them but we'd better to use the common prototype.
95
     In fopen-vms.h, they are separated from the mode with a comma.
96
     Split here.  */
97
  vms_attr = strchr (modes, ',');
98
  if (vms_attr == NULL)
99
    {
100
      /* No attributes.  */
101
      return close_on_exec (fopen (filename, modes));
102
    }
103
  else
104
    {
105
      /* Attributes found.  Split.  */
106
      size_t modes_len = strlen (modes) + 1;
107
      char attrs[modes_len + 1];
108
      char *at[3];
109
      int i;
110
 
111
      memcpy (attrs, modes, modes_len);
112
      at[0] = attrs;
113
      for (i = 0; i < 2; i++)
114
        {
115
          at[i + 1] = strchr (at[i], ',');
116
          BFD_ASSERT (at[i + 1] != NULL);
117
          *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it.  */
118
        }
119
      return close_on_exec (fopen (filename, at[0], at[1], at[2]));
120
    }
121
#else /* !VMS */
122
#if defined (HAVE_FOPEN64)
123
  return close_on_exec (fopen64 (filename, modes));
124
#else
125
  return close_on_exec (fopen (filename, modes));
126
#endif
127
#endif /* !VMS */
128
}
129
 
130
/*
131
INTERNAL_DEFINITION
132
        struct bfd_iovec
133
 
134
DESCRIPTION
135
 
136
        The <<struct bfd_iovec>> contains the internal file I/O class.
137
        Each <<BFD>> has an instance of this class and all file I/O is
138
        routed through it (it is assumed that the instance implements
139
        all methods listed below).
140
 
141
.struct bfd_iovec
142
.{
143
.  {* To avoid problems with macros, a "b" rather than "f"
144
.     prefix is prepended to each method name.  *}
145
.  {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
146
.     bytes starting at PTR.  Return the number of bytes actually
147
.     transfered (a read past end-of-file returns less than NBYTES),
148
.     or -1 (setting <<bfd_error>>) if an error occurs.  *}
149
.  file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
150
.  file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
151
.                      file_ptr nbytes);
152
.  {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
153
.     if an error occurs.  *}
154
.  file_ptr (*btell) (struct bfd *abfd);
155
.  {* For the following, on successful completion a value of 0 is returned.
156
.     Otherwise, a value of -1 is returned (and  <<bfd_error>> is set).  *}
157
.  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
158
.  int (*bclose) (struct bfd *abfd);
159
.  int (*bflush) (struct bfd *abfd);
160
.  int (*bstat) (struct bfd *abfd, struct stat *sb);
161
.  {* Just like mmap: (void*)-1 on failure, mmapped address on success.  *}
162
.  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
163
.                  int prot, int flags, file_ptr offset);
164
.};
165
 
166
.extern const struct bfd_iovec _bfd_memory_iovec;
167
 
168
*/
169
 
170
 
171
/* Return value is amount read.  */
172
 
173
bfd_size_type
174
bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
175
{
176
  size_t nread;
177
 
178
  /* If this is an archive element, don't read past the end of
179
     this element.  */
180
  if (abfd->arelt_data != NULL)
181
    {
182
      size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size;
183
      if (abfd->where + size > maxbytes)
184
        {
185
          if (abfd->where >= maxbytes)
186
            return 0;
187
          size = maxbytes - abfd->where;
188
        }
189
    }
190
 
191
  if (abfd->iovec)
192
    nread = abfd->iovec->bread (abfd, ptr, size);
193
  else
194
    nread = 0;
195
  if (nread != (size_t) -1)
196
    abfd->where += nread;
197
 
198
  return nread;
199
}
200
 
201
bfd_size_type
202
bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
203
{
204
  size_t nwrote;
205
 
206
  if (abfd->iovec)
207
    nwrote = abfd->iovec->bwrite (abfd, ptr, size);
208
  else
209
    nwrote = 0;
210
 
211
  if (nwrote != (size_t) -1)
212
    abfd->where += nwrote;
213
  if (nwrote != size)
214
    {
215
#ifdef ENOSPC
216
      errno = ENOSPC;
217
#endif
218
      bfd_set_error (bfd_error_system_call);
219
    }
220
  return nwrote;
221
}
222
 
223
file_ptr
224
bfd_tell (bfd *abfd)
225
{
226
  file_ptr ptr;
227
 
228
  if (abfd->iovec)
229
    {
230
      ptr = abfd->iovec->btell (abfd);
231
 
232
      if (abfd->my_archive)
233
        ptr -= abfd->origin;
234
    }
235
  else
236
    ptr = 0;
237
 
238
  abfd->where = ptr;
239
  return ptr;
240
}
241
 
242
int
243
bfd_flush (bfd *abfd)
244
{
245
  if (abfd->iovec)
246
    return abfd->iovec->bflush (abfd);
247
  return 0;
248
}
249
 
250
/* Returns 0 for success, negative value for failure (in which case
251
   bfd_get_error can retrieve the error code).  */
252
int
253
bfd_stat (bfd *abfd, struct stat *statbuf)
254
{
255
  int result;
256
 
257
  if (abfd->iovec)
258
    result = abfd->iovec->bstat (abfd, statbuf);
259
  else
260
    result = -1;
261
 
262
  if (result < 0)
263
    bfd_set_error (bfd_error_system_call);
264
  return result;
265
}
266
 
267
/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
268
   can retrieve the error code).  */
269
 
270
int
271
bfd_seek (bfd *abfd, file_ptr position, int direction)
272
{
273
  int result;
274
  file_ptr file_position;
275
  /* For the time being, a BFD may not seek to it's end.  The problem
276
     is that we don't easily have a way to recognize the end of an
277
     element in an archive.  */
278
 
279
  BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
280
 
281
  if (direction == SEEK_CUR && position == 0)
282
    return 0;
283
 
284
  if (abfd->format != bfd_archive && abfd->my_archive == 0)
285
    {
286
      if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
287
        return 0;
288
    }
289
  else
290
    {
291
      /* We need something smarter to optimize access to archives.
292
         Currently, anything inside an archive is read via the file
293
         handle for the archive.  Which means that a bfd_seek on one
294
         component affects the `current position' in the archive, as
295
         well as in any other component.
296
 
297
         It might be sufficient to put a spike through the cache
298
         abstraction, and look to the archive for the file position,
299
         but I think we should try for something cleaner.
300
 
301
         In the meantime, no optimization for archives.  */
302
    }
303
 
304
  file_position = position;
305
  if (direction == SEEK_SET && abfd->my_archive != NULL)
306
    file_position += abfd->origin;
307
 
308
  if (abfd->iovec)
309
    result = abfd->iovec->bseek (abfd, file_position, direction);
310
  else
311
    result = -1;
312
 
313
  if (result != 0)
314
    {
315
      int hold_errno = errno;
316
 
317
      /* Force redetermination of `where' field.  */
318
      bfd_tell (abfd);
319
 
320
      /* An EINVAL error probably means that the file offset was
321
         absurd.  */
322
      if (hold_errno == EINVAL)
323
        bfd_set_error (bfd_error_file_truncated);
324
      else
325
        {
326
          bfd_set_error (bfd_error_system_call);
327
          errno = hold_errno;
328
        }
329
    }
330
  else
331
    {
332
      /* Adjust `where' field.  */
333
      if (direction == SEEK_SET)
334
        abfd->where = position;
335
      else
336
        abfd->where += position;
337
    }
338
  return result;
339
}
340
 
341
/*
342
FUNCTION
343
        bfd_get_mtime
344
 
345
SYNOPSIS
346
        long bfd_get_mtime (bfd *abfd);
347
 
348
DESCRIPTION
349
        Return the file modification time (as read from the file system, or
350
        from the archive header for archive members).
351
 
352
*/
353
 
354
long
355
bfd_get_mtime (bfd *abfd)
356
{
357
  struct stat buf;
358
 
359
  if (abfd->mtime_set)
360
    return abfd->mtime;
361
 
362
  if (abfd->iovec == NULL)
363
    return 0;
364
 
365
  if (abfd->iovec->bstat (abfd, &buf) != 0)
366
    return 0;
367
 
368
  abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
369
  return buf.st_mtime;
370
}
371
 
372
/*
373
FUNCTION
374
        bfd_get_size
375
 
376
SYNOPSIS
377
        file_ptr bfd_get_size (bfd *abfd);
378
 
379
DESCRIPTION
380
        Return the file size (as read from file system) for the file
381
        associated with BFD @var{abfd}.
382
 
383
        The initial motivation for, and use of, this routine is not
384
        so we can get the exact size of the object the BFD applies to, since
385
        that might not be generally possible (archive members for example).
386
        It would be ideal if someone could eventually modify
387
        it so that such results were guaranteed.
388
 
389
        Instead, we want to ask questions like "is this NNN byte sized
390
        object I'm about to try read from file offset YYY reasonable?"
391
        As as example of where we might do this, some object formats
392
        use string tables for which the first <<sizeof (long)>> bytes of the
393
        table contain the size of the table itself, including the size bytes.
394
        If an application tries to read what it thinks is one of these
395
        string tables, without some way to validate the size, and for
396
        some reason the size is wrong (byte swapping error, wrong location
397
        for the string table, etc.), the only clue is likely to be a read
398
        error when it tries to read the table, or a "virtual memory
399
        exhausted" error when it tries to allocate 15 bazillon bytes
400
        of space for the 15 bazillon byte table it is about to read.
401
        This function at least allows us to answer the question, "is the
402
        size reasonable?".
403
*/
404
 
405
file_ptr
406
bfd_get_size (bfd *abfd)
407
{
408
  struct stat buf;
409
 
410
  if (abfd->iovec == NULL)
411
    return 0;
412
 
413
  if (abfd->iovec->bstat (abfd, &buf) != 0)
414
    return 0;
415
 
416
  return buf.st_size;
417
}
418
 
419
 
420
/*
421
FUNCTION
422
        bfd_mmap
423
 
424
SYNOPSIS
425
        void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
426
                        int prot, int flags, file_ptr offset);
427
 
428
DESCRIPTION
429
        Return mmap()ed region of the file, if possible and implemented.
430
 
431
*/
432
 
433
void *
434
bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
435
          int prot, int flags, file_ptr offset)
436
{
437
  void *ret = (void *)-1;
438
 
439
  if (abfd->iovec == NULL)
440
    return ret;
441
 
442
  return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset);
443
}
444
 
445
/* Memory file I/O operations.  */
446
 
447
static file_ptr
448
memory_bread (bfd *abfd, void *ptr, file_ptr size)
449
{
450
  struct bfd_in_memory *bim;
451
  bfd_size_type get;
452
 
453
  bim = (struct bfd_in_memory *) abfd->iostream;
454
  get = size;
455
  if (abfd->where + get > bim->size)
456
    {
457
      if (bim->size < (bfd_size_type) abfd->where)
458
        get = 0;
459
      else
460
        get = bim->size - abfd->where;
461
      bfd_set_error (bfd_error_file_truncated);
462
    }
463
  memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
464
  return get;
465
}
466
 
467
static file_ptr
468
memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
469
{
470
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
471
 
472
  if (abfd->where + size > bim->size)
473
    {
474
      bfd_size_type newsize, oldsize;
475
 
476
      oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
477
      bim->size = abfd->where + size;
478
      /* Round up to cut down on memory fragmentation */
479
      newsize = (bim->size + 127) & ~(bfd_size_type) 127;
480
      if (newsize > oldsize)
481
        {
482
          bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
483
          if (bim->buffer == NULL)
484
            {
485
              bim->size = 0;
486
              return 0;
487
            }
488
          if (newsize > bim->size)
489
            memset (bim->buffer + bim->size, 0, newsize - bim->size);
490
        }
491
    }
492
  memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
493
  return size;
494
}
495
 
496
static file_ptr
497
memory_btell (bfd *abfd)
498
{
499
  return abfd->where;
500
}
501
 
502
static int
503
memory_bseek (bfd *abfd, file_ptr position, int direction)
504
{
505
  file_ptr nwhere;
506
  struct bfd_in_memory *bim;
507
 
508
  bim = (struct bfd_in_memory *) abfd->iostream;
509
 
510
  if (direction == SEEK_SET)
511
    nwhere = position;
512
  else
513
    nwhere = abfd->where + position;
514
 
515
  if (nwhere < 0)
516
    {
517
      abfd->where = 0;
518
      errno = EINVAL;
519
      return -1;
520
    }
521
 
522
  if ((bfd_size_type)nwhere > bim->size)
523
    {
524
      if (abfd->direction == write_direction
525
          || abfd->direction == both_direction)
526
        {
527
          bfd_size_type newsize, oldsize;
528
 
529
          oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
530
          bim->size = nwhere;
531
          /* Round up to cut down on memory fragmentation */
532
          newsize = (bim->size + 127) & ~(bfd_size_type) 127;
533
          if (newsize > oldsize)
534
            {
535
              bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
536
              if (bim->buffer == NULL)
537
                {
538
                  errno = EINVAL;
539
                  bim->size = 0;
540
                  return -1;
541
                }
542
              memset (bim->buffer + oldsize, 0, newsize - oldsize);
543
            }
544
        }
545
      else
546
        {
547
          abfd->where = bim->size;
548
          errno = EINVAL;
549
          bfd_set_error (bfd_error_file_truncated);
550
          return -1;
551
        }
552
    }
553
  return 0;
554
}
555
 
556
static int
557
memory_bclose (struct bfd *abfd)
558
{
559
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
560
 
561
  if (bim->buffer != NULL)
562
    free (bim->buffer);
563
  free (bim);
564
  abfd->iostream = NULL;
565
 
566
  return TRUE;
567
}
568
 
569
static int
570
memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
571
{
572
  return 0;
573
}
574
 
575
static int
576
memory_bstat (bfd *abfd, struct stat *statbuf)
577
{
578
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
579
 
580
  memset (statbuf, 0, sizeof (*statbuf));
581
  statbuf->st_size = bim->size;
582
 
583
  return 0;
584
}
585
 
586
static void *
587
memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
588
              bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
589
              int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED)
590
{
591
  return (void *)-1;
592
}
593
 
594
const struct bfd_iovec _bfd_memory_iovec =
595
{
596
  &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
597
  &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
598
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.