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 161

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 161 khays
.  {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
162
.     mmap parameter, except that LEN and OFFSET do not need to be page
163
.     aligned.  Returns (void *)-1 on failure, mmapped address on success.
164
.     Also write in MAP_ADDR the address of the page aligned buffer and in
165
.     MAP_LEN the size mapped (a page multiple).  Use unmap with MAP_ADDR and
166
.     MAP_LEN to unmap.  *}
167 14 khays
.  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
168 161 khays
.                  int prot, int flags, file_ptr offset,
169
.                  void **map_addr, bfd_size_type *map_len);
170 14 khays
.};
171
 
172
.extern const struct bfd_iovec _bfd_memory_iovec;
173
 
174
*/
175
 
176
 
177
/* Return value is amount read.  */
178
 
179
bfd_size_type
180
bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
181
{
182
  size_t nread;
183
 
184
  /* If this is an archive element, don't read past the end of
185
     this element.  */
186
  if (abfd->arelt_data != NULL)
187
    {
188
      size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size;
189
      if (abfd->where + size > maxbytes)
190
        {
191
          if (abfd->where >= maxbytes)
192
            return 0;
193
          size = maxbytes - abfd->where;
194
        }
195
    }
196
 
197
  if (abfd->iovec)
198
    nread = abfd->iovec->bread (abfd, ptr, size);
199
  else
200
    nread = 0;
201
  if (nread != (size_t) -1)
202
    abfd->where += nread;
203
 
204
  return nread;
205
}
206
 
207
bfd_size_type
208
bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
209
{
210
  size_t nwrote;
211
 
212
  if (abfd->iovec)
213
    nwrote = abfd->iovec->bwrite (abfd, ptr, size);
214
  else
215
    nwrote = 0;
216
 
217
  if (nwrote != (size_t) -1)
218
    abfd->where += nwrote;
219
  if (nwrote != size)
220
    {
221
#ifdef ENOSPC
222
      errno = ENOSPC;
223
#endif
224
      bfd_set_error (bfd_error_system_call);
225
    }
226
  return nwrote;
227
}
228
 
229
file_ptr
230
bfd_tell (bfd *abfd)
231
{
232
  file_ptr ptr;
233
 
234
  if (abfd->iovec)
235
    {
236
      ptr = abfd->iovec->btell (abfd);
237
 
238
      if (abfd->my_archive)
239
        ptr -= abfd->origin;
240
    }
241
  else
242
    ptr = 0;
243
 
244
  abfd->where = ptr;
245
  return ptr;
246
}
247
 
248
int
249
bfd_flush (bfd *abfd)
250
{
251
  if (abfd->iovec)
252
    return abfd->iovec->bflush (abfd);
253
  return 0;
254
}
255
 
256
/* Returns 0 for success, negative value for failure (in which case
257
   bfd_get_error can retrieve the error code).  */
258
int
259
bfd_stat (bfd *abfd, struct stat *statbuf)
260
{
261
  int result;
262
 
263
  if (abfd->iovec)
264
    result = abfd->iovec->bstat (abfd, statbuf);
265
  else
266
    result = -1;
267
 
268
  if (result < 0)
269
    bfd_set_error (bfd_error_system_call);
270
  return result;
271
}
272
 
273
/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
274
   can retrieve the error code).  */
275
 
276
int
277
bfd_seek (bfd *abfd, file_ptr position, int direction)
278
{
279
  int result;
280
  file_ptr file_position;
281
  /* For the time being, a BFD may not seek to it's end.  The problem
282
     is that we don't easily have a way to recognize the end of an
283
     element in an archive.  */
284
 
285
  BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
286
 
287
  if (direction == SEEK_CUR && position == 0)
288
    return 0;
289
 
290
  if (abfd->format != bfd_archive && abfd->my_archive == 0)
291
    {
292
      if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
293
        return 0;
294
    }
295
  else
296
    {
297
      /* We need something smarter to optimize access to archives.
298
         Currently, anything inside an archive is read via the file
299
         handle for the archive.  Which means that a bfd_seek on one
300
         component affects the `current position' in the archive, as
301
         well as in any other component.
302
 
303
         It might be sufficient to put a spike through the cache
304
         abstraction, and look to the archive for the file position,
305
         but I think we should try for something cleaner.
306
 
307
         In the meantime, no optimization for archives.  */
308
    }
309
 
310
  file_position = position;
311
  if (direction == SEEK_SET && abfd->my_archive != NULL)
312
    file_position += abfd->origin;
313
 
314
  if (abfd->iovec)
315
    result = abfd->iovec->bseek (abfd, file_position, direction);
316
  else
317
    result = -1;
318
 
319
  if (result != 0)
320
    {
321
      int hold_errno = errno;
322
 
323
      /* Force redetermination of `where' field.  */
324
      bfd_tell (abfd);
325
 
326
      /* An EINVAL error probably means that the file offset was
327
         absurd.  */
328
      if (hold_errno == EINVAL)
329
        bfd_set_error (bfd_error_file_truncated);
330
      else
331
        {
332
          bfd_set_error (bfd_error_system_call);
333
          errno = hold_errno;
334
        }
335
    }
336
  else
337
    {
338
      /* Adjust `where' field.  */
339
      if (direction == SEEK_SET)
340
        abfd->where = position;
341
      else
342
        abfd->where += position;
343
    }
344
  return result;
345
}
346
 
347
/*
348
FUNCTION
349
        bfd_get_mtime
350
 
351
SYNOPSIS
352
        long bfd_get_mtime (bfd *abfd);
353
 
354
DESCRIPTION
355
        Return the file modification time (as read from the file system, or
356
        from the archive header for archive members).
357
 
358
*/
359
 
360
long
361
bfd_get_mtime (bfd *abfd)
362
{
363
  struct stat buf;
364
 
365
  if (abfd->mtime_set)
366
    return abfd->mtime;
367
 
368
  if (abfd->iovec == NULL)
369
    return 0;
370
 
371
  if (abfd->iovec->bstat (abfd, &buf) != 0)
372
    return 0;
373
 
374
  abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
375
  return buf.st_mtime;
376
}
377
 
378
/*
379
FUNCTION
380
        bfd_get_size
381
 
382
SYNOPSIS
383
        file_ptr bfd_get_size (bfd *abfd);
384
 
385
DESCRIPTION
386
        Return the file size (as read from file system) for the file
387
        associated with BFD @var{abfd}.
388
 
389
        The initial motivation for, and use of, this routine is not
390
        so we can get the exact size of the object the BFD applies to, since
391
        that might not be generally possible (archive members for example).
392
        It would be ideal if someone could eventually modify
393
        it so that such results were guaranteed.
394
 
395
        Instead, we want to ask questions like "is this NNN byte sized
396
        object I'm about to try read from file offset YYY reasonable?"
397
        As as example of where we might do this, some object formats
398
        use string tables for which the first <<sizeof (long)>> bytes of the
399
        table contain the size of the table itself, including the size bytes.
400
        If an application tries to read what it thinks is one of these
401
        string tables, without some way to validate the size, and for
402
        some reason the size is wrong (byte swapping error, wrong location
403
        for the string table, etc.), the only clue is likely to be a read
404
        error when it tries to read the table, or a "virtual memory
405
        exhausted" error when it tries to allocate 15 bazillon bytes
406
        of space for the 15 bazillon byte table it is about to read.
407
        This function at least allows us to answer the question, "is the
408
        size reasonable?".
409
*/
410
 
411
file_ptr
412
bfd_get_size (bfd *abfd)
413
{
414
  struct stat buf;
415
 
416
  if (abfd->iovec == NULL)
417
    return 0;
418
 
419
  if (abfd->iovec->bstat (abfd, &buf) != 0)
420
    return 0;
421
 
422
  return buf.st_size;
423
}
424
 
425
 
426
/*
427
FUNCTION
428
        bfd_mmap
429
 
430
SYNOPSIS
431
        void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
432 161 khays
                        int prot, int flags, file_ptr offset,
433
                        void **map_addr, bfd_size_type *map_len);
434 14 khays
 
435
DESCRIPTION
436
        Return mmap()ed region of the file, if possible and implemented.
437 161 khays
        LEN and OFFSET do not need to be page aligned.  The page aligned
438
        address and length are written to MAP_ADDR and MAP_LEN.
439 14 khays
 
440
*/
441
 
442
void *
443
bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
444 161 khays
          int prot, int flags, file_ptr offset,
445
          void **map_addr, bfd_size_type *map_len)
446 14 khays
{
447
  void *ret = (void *)-1;
448
 
449
  if (abfd->iovec == NULL)
450
    return ret;
451
 
452 161 khays
  return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
453
                             map_addr, map_len);
454 14 khays
}
455
 
456
/* Memory file I/O operations.  */
457
 
458
static file_ptr
459
memory_bread (bfd *abfd, void *ptr, file_ptr size)
460
{
461
  struct bfd_in_memory *bim;
462
  bfd_size_type get;
463
 
464
  bim = (struct bfd_in_memory *) abfd->iostream;
465
  get = size;
466
  if (abfd->where + get > bim->size)
467
    {
468
      if (bim->size < (bfd_size_type) abfd->where)
469
        get = 0;
470
      else
471
        get = bim->size - abfd->where;
472
      bfd_set_error (bfd_error_file_truncated);
473
    }
474
  memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
475
  return get;
476
}
477
 
478
static file_ptr
479
memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
480
{
481
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
482
 
483
  if (abfd->where + size > bim->size)
484
    {
485
      bfd_size_type newsize, oldsize;
486
 
487
      oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
488
      bim->size = abfd->where + size;
489
      /* Round up to cut down on memory fragmentation */
490
      newsize = (bim->size + 127) & ~(bfd_size_type) 127;
491
      if (newsize > oldsize)
492
        {
493
          bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
494
          if (bim->buffer == NULL)
495
            {
496
              bim->size = 0;
497
              return 0;
498
            }
499
          if (newsize > bim->size)
500
            memset (bim->buffer + bim->size, 0, newsize - bim->size);
501
        }
502
    }
503
  memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
504
  return size;
505
}
506
 
507
static file_ptr
508
memory_btell (bfd *abfd)
509
{
510
  return abfd->where;
511
}
512
 
513
static int
514
memory_bseek (bfd *abfd, file_ptr position, int direction)
515
{
516
  file_ptr nwhere;
517
  struct bfd_in_memory *bim;
518
 
519
  bim = (struct bfd_in_memory *) abfd->iostream;
520
 
521
  if (direction == SEEK_SET)
522
    nwhere = position;
523
  else
524
    nwhere = abfd->where + position;
525
 
526
  if (nwhere < 0)
527
    {
528
      abfd->where = 0;
529
      errno = EINVAL;
530
      return -1;
531
    }
532
 
533
  if ((bfd_size_type)nwhere > bim->size)
534
    {
535
      if (abfd->direction == write_direction
536
          || abfd->direction == both_direction)
537
        {
538
          bfd_size_type newsize, oldsize;
539
 
540
          oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
541
          bim->size = nwhere;
542
          /* Round up to cut down on memory fragmentation */
543
          newsize = (bim->size + 127) & ~(bfd_size_type) 127;
544
          if (newsize > oldsize)
545
            {
546
              bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
547
              if (bim->buffer == NULL)
548
                {
549
                  errno = EINVAL;
550
                  bim->size = 0;
551
                  return -1;
552
                }
553
              memset (bim->buffer + oldsize, 0, newsize - oldsize);
554
            }
555
        }
556
      else
557
        {
558
          abfd->where = bim->size;
559
          errno = EINVAL;
560
          bfd_set_error (bfd_error_file_truncated);
561
          return -1;
562
        }
563
    }
564
  return 0;
565
}
566
 
567
static int
568
memory_bclose (struct bfd *abfd)
569
{
570
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
571
 
572
  if (bim->buffer != NULL)
573
    free (bim->buffer);
574
  free (bim);
575
  abfd->iostream = NULL;
576
 
577
  return TRUE;
578
}
579
 
580
static int
581
memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
582
{
583
  return 0;
584
}
585
 
586
static int
587
memory_bstat (bfd *abfd, struct stat *statbuf)
588
{
589
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
590
 
591
  memset (statbuf, 0, sizeof (*statbuf));
592
  statbuf->st_size = bim->size;
593
 
594
  return 0;
595
}
596
 
597
static void *
598
memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
599
              bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
600 161 khays
              int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
601
              void **map_addr ATTRIBUTE_UNUSED,
602
              bfd_size_type *map_len ATTRIBUTE_UNUSED)
603 14 khays
{
604
  return (void *)-1;
605
}
606
 
607
const struct bfd_iovec _bfd_memory_iovec =
608
{
609
  &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
610
  &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
611
};

powered by: WebSVN 2.1.0

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