Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / bfdio.c
CommitLineData
93509525 1/* Low-level I/O routines for BFDs.
7c192733 2
250d07de 3 Copyright (C) 1990-2021 Free Software Foundation, Inc.
7c192733 4
93509525
KD
5 Written by Cygnus Support.
6
cd123cb7 7 This file is part of BFD, the Binary File Descriptor library.
93509525 8
cd123cb7
NC
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
93509525 13
cd123cb7
NC
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
93509525 18
cd123cb7
NC
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
93509525
KD
23
24#include "sysdep.h"
3db64b00 25#include <limits.h>
93509525
KD
26#include "bfd.h"
27#include "libbfd.h"
b570b954 28#include "aout/ar.h"
0b8448af
NC
29#if defined (_WIN32)
30#include <windows.h>
31#endif
93509525 32
93509525
KD
33#ifndef S_IXUSR
34#define S_IXUSR 0100 /* Execute by owner. */
35#endif
36#ifndef S_IXGRP
37#define S_IXGRP 0010 /* Execute by group. */
38#endif
39#ifndef S_IXOTH
40#define S_IXOTH 0001 /* Execute by others. */
41#endif
42
428b207a
TT
43#ifndef FD_CLOEXEC
44#define FD_CLOEXEC 1
45#endif
46
7c192733 47file_ptr
c7c3d11b 48_bfd_real_ftell (FILE *file)
7c192733
AC
49{
50#if defined (HAVE_FTELLO64)
51 return ftello64 (file);
52#elif defined (HAVE_FTELLO)
53 return ftello (file);
54#else
55 return ftell (file);
56#endif
57}
58
59int
c7c3d11b 60_bfd_real_fseek (FILE *file, file_ptr offset, int whence)
7c192733
AC
61{
62#if defined (HAVE_FSEEKO64)
63 return fseeko64 (file, offset, whence);
64#elif defined (HAVE_FSEEKO)
65 return fseeko (file, offset, whence);
66#else
67 return fseek (file, offset, whence);
68#endif
69}
70
428b207a
TT
71/* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
72 which case nothing is done. */
73static FILE *
74close_on_exec (FILE *file)
75{
76#if defined (HAVE_FILENO) && defined (F_GETFD)
77 if (file)
78 {
79 int fd = fileno (file);
80 int old = fcntl (fd, F_GETFD, 0);
81 if (old >= 0)
82 fcntl (fd, F_SETFD, old | FD_CLOEXEC);
83 }
84#endif
85 return file;
86}
87
2e6f4fae 88FILE *
c7c3d11b 89_bfd_real_fopen (const char *filename, const char *modes)
2e6f4fae 90{
d387240a 91#ifdef VMS
d387240a
TG
92 char *vms_attr;
93
9aff4b7a 94 /* On VMS, fopen allows file attributes as optional arguments.
d387240a
TG
95 We need to use them but we'd better to use the common prototype.
96 In fopen-vms.h, they are separated from the mode with a comma.
97 Split here. */
98 vms_attr = strchr (modes, ',');
0b8448af 99 if (vms_attr != NULL)
d387240a 100 {
0c376465
TG
101 /* Attributes found. Split. */
102 size_t modes_len = strlen (modes) + 1;
103 char attrs[modes_len + 1];
104 char *at[3];
105 int i;
106
107 memcpy (attrs, modes, modes_len);
108 at[0] = attrs;
109 for (i = 0; i < 2; i++)
110 {
111 at[i + 1] = strchr (at[i], ',');
112 BFD_ASSERT (at[i + 1] != NULL);
113 *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */
114 }
115 return close_on_exec (fopen (filename, at[0], at[1], at[2]));
d387240a 116 }
0b8448af
NC
117
118#elif defined (_WIN32)
17d60030
NC
119 size_t filelen;
120
121 /* PR 25713: Handle extra long path names.
122 For relative paths, convert them to absolute, in case that version is too long. */
123 if (! IS_ABSOLUTE_PATH (filename) && (strstr (filename, ".o") != NULL))
124 {
125 char cwd[1024];
126
127 getcwd (cwd, sizeof (cwd));
128 filelen = strlen (cwd) + 1;
129 strncat (cwd, "\\", sizeof (cwd) - filelen);
130 ++ filelen;
131 strncat (cwd, filename, sizeof (cwd) - filelen);
132
133 filename = cwd;
134 }
135
136 filelen = strlen (filename) + 1;
0b8448af
NC
137
138 if (filelen > MAX_PATH - 1)
139 {
ca859a89 140 FILE * file;
17d60030 141 char * fullpath;
ca859a89 142 int i;
0b8448af 143
17d60030
NC
144 fullpath = (char *) malloc (filelen + 8);
145
0b8448af
NC
146 /* Add a Microsoft recommended prefix that
147 will allow the extra-long path to work. */
148 strcpy (fullpath, "\\\\?\\");
149 strcat (fullpath, filename);
ca859a89
JC
150
151 /* Convert any UNIX style path separators into the DOS form. */
39a1432c 152 for (i = 0; fullpath[i]; i++)
ca859a89
JC
153 {
154 if (IS_UNIX_DIR_SEPARATOR (fullpath[i]))
155 fullpath[i] = '\\';
156 }
157
0b8448af
NC
158 file = close_on_exec (fopen (fullpath, modes));
159 free (fullpath);
160 return file;
161 }
162
163#elif defined (HAVE_FOPEN64)
428b207a 164 return close_on_exec (fopen64 (filename, modes));
2e6f4fae 165#endif
0b8448af
NC
166
167 return close_on_exec (fopen (filename, modes));
2e6f4fae
DJ
168}
169
40838a72
AC
170/*
171INTERNAL_DEFINITION
172 struct bfd_iovec
93509525 173
40838a72 174DESCRIPTION
93509525 175
40838a72
AC
176 The <<struct bfd_iovec>> contains the internal file I/O class.
177 Each <<BFD>> has an instance of this class and all file I/O is
178 routed through it (it is assumed that the instance implements
179 all methods listed below).
180
181.struct bfd_iovec
182.{
183. {* To avoid problems with macros, a "b" rather than "f"
184. prefix is prepended to each method name. *}
185. {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
186. bytes starting at PTR. Return the number of bytes actually
187. transfered (a read past end-of-file returns less than NBYTES),
188. or -1 (setting <<bfd_error>>) if an error occurs. *}
189. file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
190. file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
07d6d2b8 191. file_ptr nbytes);
40838a72
AC
192. {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
193. if an error occurs. *}
194. file_ptr (*btell) (struct bfd *abfd);
195. {* For the following, on successful completion a value of 0 is returned.
07d6d2b8 196. Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *}
40838a72 197. int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
405bf443 198. int (*bclose) (struct bfd *abfd);
40838a72
AC
199. int (*bflush) (struct bfd *abfd);
200. int (*bstat) (struct bfd *abfd, struct stat *sb);
4c95ab76
TG
201. {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
202. mmap parameter, except that LEN and OFFSET do not need to be page
203. aligned. Returns (void *)-1 on failure, mmapped address on success.
204. Also write in MAP_ADDR the address of the page aligned buffer and in
205. MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and
206. MAP_LEN to unmap. *}
f07749bb 207. void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
07d6d2b8
AM
208. int prot, int flags, file_ptr offset,
209. void **map_addr, bfd_size_type *map_len);
40838a72 210.};
93509525 211
65077aa8
TG
212.extern const struct bfd_iovec _bfd_memory_iovec;
213
40838a72 214*/
93509525 215
93509525
KD
216
217/* Return value is amount read. */
218
219bfd_size_type
c58b9523 220bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
93509525 221{
5c4ce239
AM
222 file_ptr nread;
223 bfd *element_bfd = abfd;
224 ufile_ptr offset = 0;
225
226 while (abfd->my_archive != NULL
227 && !bfd_is_thin_archive (abfd->my_archive))
228 {
229 offset += abfd->origin;
230 abfd = abfd->my_archive;
231 }
4d095f5b 232 offset += abfd->origin;
93509525 233
1fb41da4
AM
234 /* If this is an archive element, don't read past the end of
235 this element. */
5c4ce239 236 if (element_bfd->arelt_data != NULL)
1fb41da4 237 {
5c4ce239 238 bfd_size_type maxbytes = arelt_size (element_bfd);
f1bb16f8 239
5c4ce239 240 if (abfd->where < offset || abfd->where - offset >= maxbytes)
07d6d2b8 241 {
5c4ce239
AM
242 bfd_set_error (bfd_error_invalid_operation);
243 return -1;
07d6d2b8 244 }
5c4ce239
AM
245 if (abfd->where - offset + size > maxbytes)
246 size = maxbytes - (abfd->where - offset);
1fb41da4
AM
247 }
248
5c4ce239
AM
249 if (abfd->iovec == NULL)
250 {
251 bfd_set_error (bfd_error_invalid_operation);
252 return -1;
253 }
254
255 nread = abfd->iovec->bread (abfd, ptr, size);
256 if (nread != -1)
93509525
KD
257 abfd->where += nread;
258
93509525
KD
259 return nread;
260}
261
262bfd_size_type
c58b9523 263bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
93509525 264{
5c4ce239 265 file_ptr nwrote;
93509525 266
5c4ce239
AM
267 while (abfd->my_archive != NULL
268 && !bfd_is_thin_archive (abfd->my_archive))
269 abfd = abfd->my_archive;
69fd4758 270
5c4ce239
AM
271 if (abfd->iovec == NULL)
272 {
273 bfd_set_error (bfd_error_invalid_operation);
274 return -1;
275 }
276
277 nwrote = abfd->iovec->bwrite (abfd, ptr, size);
278 if (nwrote != -1)
93509525 279 abfd->where += nwrote;
5c4ce239 280 if ((bfd_size_type) nwrote != size)
93509525
KD
281 {
282#ifdef ENOSPC
283 errno = ENOSPC;
284#endif
285 bfd_set_error (bfd_error_system_call);
286 }
287 return nwrote;
288}
289
7c192733 290file_ptr
c58b9523 291bfd_tell (bfd *abfd)
93509525 292{
5c4ce239 293 ufile_ptr offset = 0;
93509525
KD
294 file_ptr ptr;
295
5c4ce239
AM
296 while (abfd->my_archive != NULL
297 && !bfd_is_thin_archive (abfd->my_archive))
69fd4758 298 {
5c4ce239
AM
299 offset += abfd->origin;
300 abfd = abfd->my_archive;
69fd4758 301 }
4d095f5b 302 offset += abfd->origin;
93509525 303
5c4ce239
AM
304 if (abfd->iovec == NULL)
305 return 0;
306
307 ptr = abfd->iovec->btell (abfd);
93509525 308 abfd->where = ptr;
5c4ce239 309 return ptr - offset;
93509525
KD
310}
311
312int
c58b9523 313bfd_flush (bfd *abfd)
93509525 314{
5c4ce239
AM
315 while (abfd->my_archive != NULL
316 && !bfd_is_thin_archive (abfd->my_archive))
317 abfd = abfd->my_archive;
318
319 if (abfd->iovec == NULL)
320 return 0;
321
322 return abfd->iovec->bflush (abfd);
93509525
KD
323}
324
325/* Returns 0 for success, negative value for failure (in which case
326 bfd_get_error can retrieve the error code). */
327int
c58b9523 328bfd_stat (bfd *abfd, struct stat *statbuf)
93509525 329{
93509525
KD
330 int result;
331
5c4ce239
AM
332 while (abfd->my_archive != NULL
333 && !bfd_is_thin_archive (abfd->my_archive))
334 abfd = abfd->my_archive;
69fd4758 335
5c4ce239
AM
336 if (abfd->iovec == NULL)
337 {
338 bfd_set_error (bfd_error_invalid_operation);
339 return -1;
340 }
341
342 result = abfd->iovec->bstat (abfd, statbuf);
93509525
KD
343 if (result < 0)
344 bfd_set_error (bfd_error_system_call);
345 return result;
346}
347
348/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
349 can retrieve the error code). */
350
351int
c58b9523 352bfd_seek (bfd *abfd, file_ptr position, int direction)
93509525
KD
353{
354 int result;
5c4ce239 355 ufile_ptr offset = 0;
93509525 356
5c4ce239
AM
357 while (abfd->my_archive != NULL
358 && !bfd_is_thin_archive (abfd->my_archive))
93509525 359 {
5c4ce239
AM
360 offset += abfd->origin;
361 abfd = abfd->my_archive;
93509525 362 }
4d095f5b 363 offset += abfd->origin;
93509525 364
5c4ce239 365 if (abfd->iovec == NULL)
660722b0 366 {
5c4ce239
AM
367 bfd_set_error (bfd_error_invalid_operation);
368 return -1;
660722b0 369 }
93509525 370
5c4ce239
AM
371 /* For the time being, a BFD may not seek to it's end. The problem
372 is that we don't easily have a way to recognize the end of an
373 element in an archive. */
374 BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
375
376 if (direction != SEEK_CUR)
377 position += offset;
69fd4758 378
ff91d2f0
AM
379 if ((direction == SEEK_CUR && position == 0)
380 || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
381 return 0;
382
5c4ce239 383 result = abfd->iovec->bseek (abfd, position, direction);
93509525
KD
384 if (result != 0)
385 {
93509525 386 /* An EINVAL error probably means that the file offset was
07d6d2b8 387 absurd. */
5c4ce239 388 if (errno == EINVAL)
93509525
KD
389 bfd_set_error (bfd_error_file_truncated);
390 else
5c4ce239 391 bfd_set_error (bfd_error_system_call);
93509525
KD
392 }
393 else
394 {
395 /* Adjust `where' field. */
5c4ce239 396 if (direction == SEEK_CUR)
93509525 397 abfd->where += position;
5c4ce239
AM
398 else
399 abfd->where = position;
93509525 400 }
5c4ce239 401
93509525
KD
402 return result;
403}
404
405/*
406FUNCTION
407 bfd_get_mtime
408
409SYNOPSIS
c58b9523 410 long bfd_get_mtime (bfd *abfd);
93509525
KD
411
412DESCRIPTION
413 Return the file modification time (as read from the file system, or
414 from the archive header for archive members).
415
416*/
417
418long
c58b9523 419bfd_get_mtime (bfd *abfd)
93509525 420{
93509525
KD
421 struct stat buf;
422
423 if (abfd->mtime_set)
424 return abfd->mtime;
425
5c4ce239 426 if (bfd_stat (abfd, &buf) != 0)
93509525
KD
427 return 0;
428
429 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
430 return buf.st_mtime;
431}
432
433/*
434FUNCTION
435 bfd_get_size
436
437SYNOPSIS
47fdcf63 438 ufile_ptr bfd_get_size (bfd *abfd);
93509525
KD
439
440DESCRIPTION
441 Return the file size (as read from file system) for the file
442 associated with BFD @var{abfd}.
443
444 The initial motivation for, and use of, this routine is not
445 so we can get the exact size of the object the BFD applies to, since
446 that might not be generally possible (archive members for example).
447 It would be ideal if someone could eventually modify
448 it so that such results were guaranteed.
449
450 Instead, we want to ask questions like "is this NNN byte sized
451 object I'm about to try read from file offset YYY reasonable?"
452 As as example of where we might do this, some object formats
453 use string tables for which the first <<sizeof (long)>> bytes of the
454 table contain the size of the table itself, including the size bytes.
455 If an application tries to read what it thinks is one of these
456 string tables, without some way to validate the size, and for
457 some reason the size is wrong (byte swapping error, wrong location
458 for the string table, etc.), the only clue is likely to be a read
459 error when it tries to read the table, or a "virtual memory
460 exhausted" error when it tries to allocate 15 bazillon bytes
461 of space for the 15 bazillon byte table it is about to read.
5c4491d3 462 This function at least allows us to answer the question, "is the
93509525 463 size reasonable?".
b03202e3
AM
464
465 A return value of zero indicates the file size is unknown.
93509525
KD
466*/
467
47fdcf63 468ufile_ptr
c58b9523 469bfd_get_size (bfd *abfd)
93509525 470{
b03202e3
AM
471 /* A size of 0 means we haven't yet called bfd_stat. A size of 1
472 means we have a cached value of 0, ie. unknown. */
473 if (abfd->size <= 1 || bfd_write_p (abfd))
474 {
475 struct stat buf;
93509525 476
b03202e3
AM
477 if (abfd->size == 1 && !bfd_write_p (abfd))
478 return 0;
93509525 479
b03202e3
AM
480 if (bfd_stat (abfd, &buf) != 0
481 || buf.st_size == 0
482 || buf.st_size - (ufile_ptr) buf.st_size != 0)
483 {
484 abfd->size = 1;
485 return 0;
486 }
487 abfd->size = buf.st_size;
488 }
489 return abfd->size;
93509525 490}
25b88f33 491
8e2f54bc
L
492/*
493FUNCTION
494 bfd_get_file_size
495
496SYNOPSIS
47fdcf63 497 ufile_ptr bfd_get_file_size (bfd *abfd);
8e2f54bc
L
498
499DESCRIPTION
500 Return the file size (as read from file system) for the file
501 associated with BFD @var{abfd}. It supports both normal files
502 and archive elements.
503
504*/
505
47fdcf63 506ufile_ptr
8e2f54bc
L
507bfd_get_file_size (bfd *abfd)
508{
b570b954
AM
509 ufile_ptr file_size, archive_size = (ufile_ptr) -1;
510
8e2f54bc
L
511 if (abfd->my_archive != NULL
512 && !bfd_is_thin_archive (abfd->my_archive))
b570b954
AM
513 {
514 struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
c01de193
AM
515 if (adata != NULL)
516 {
517 archive_size = adata->parsed_size;
518 /* If the archive is compressed we can't compare against
519 file size. */
520 if (adata->arch_header != NULL
521 && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
522 "Z\012", 2) == 0)
523 return archive_size;
524 abfd = abfd->my_archive;
525 }
b570b954 526 }
8e2f54bc 527
b570b954
AM
528 file_size = bfd_get_size (abfd);
529 if (archive_size < file_size)
530 return archive_size;
531 return file_size;
8e2f54bc 532}
25b88f33
PP
533
534/*
535FUNCTION
536 bfd_mmap
537
538SYNOPSIS
539 void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
07d6d2b8
AM
540 int prot, int flags, file_ptr offset,
541 void **map_addr, bfd_size_type *map_len);
25b88f33
PP
542
543DESCRIPTION
544 Return mmap()ed region of the file, if possible and implemented.
07d6d2b8
AM
545 LEN and OFFSET do not need to be page aligned. The page aligned
546 address and length are written to MAP_ADDR and MAP_LEN.
25b88f33
PP
547
548*/
549
550void *
551bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
4c95ab76 552 int prot, int flags, file_ptr offset,
07d6d2b8 553 void **map_addr, bfd_size_type *map_len)
25b88f33 554{
5c4ce239
AM
555 while (abfd->my_archive != NULL
556 && !bfd_is_thin_archive (abfd->my_archive))
557 {
558 offset += abfd->origin;
559 abfd = abfd->my_archive;
560 }
4d095f5b 561 offset += abfd->origin;
25b88f33
PP
562
563 if (abfd->iovec == NULL)
5c4ce239
AM
564 {
565 bfd_set_error (bfd_error_invalid_operation);
566 return (void *) -1;
567 }
25b88f33 568
4c95ab76 569 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
07d6d2b8 570 map_addr, map_len);
25b88f33 571}
65077aa8
TG
572
573/* Memory file I/O operations. */
574
575static file_ptr
576memory_bread (bfd *abfd, void *ptr, file_ptr size)
577{
578 struct bfd_in_memory *bim;
579 bfd_size_type get;
580
581 bim = (struct bfd_in_memory *) abfd->iostream;
582 get = size;
583 if (abfd->where + get > bim->size)
584 {
585 if (bim->size < (bfd_size_type) abfd->where)
07d6d2b8 586 get = 0;
65077aa8 587 else
07d6d2b8 588 get = bim->size - abfd->where;
65077aa8
TG
589 bfd_set_error (bfd_error_file_truncated);
590 }
591 memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
592 return get;
593}
594
595static file_ptr
596memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
597{
598 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
599
600 if (abfd->where + size > bim->size)
601 {
602 bfd_size_type newsize, oldsize;
603
604 oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
605 bim->size = abfd->where + size;
606 /* Round up to cut down on memory fragmentation */
607 newsize = (bim->size + 127) & ~(bfd_size_type) 127;
608 if (newsize > oldsize)
07d6d2b8
AM
609 {
610 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
611 if (bim->buffer == NULL)
612 {
613 bim->size = 0;
614 return 0;
615 }
616 if (newsize > bim->size)
617 memset (bim->buffer + bim->size, 0, newsize - bim->size);
618 }
65077aa8
TG
619 }
620 memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
621 return size;
622}
623
624static file_ptr
625memory_btell (bfd *abfd)
626{
627 return abfd->where;
628}
629
630static int
631memory_bseek (bfd *abfd, file_ptr position, int direction)
632{
633 file_ptr nwhere;
634 struct bfd_in_memory *bim;
635
636 bim = (struct bfd_in_memory *) abfd->iostream;
637
638 if (direction == SEEK_SET)
639 nwhere = position;
640 else
641 nwhere = abfd->where + position;
642
643 if (nwhere < 0)
644 {
645 abfd->where = 0;
646 errno = EINVAL;
647 return -1;
648 }
649
650 if ((bfd_size_type)nwhere > bim->size)
651 {
652 if (abfd->direction == write_direction
07d6d2b8
AM
653 || abfd->direction == both_direction)
654 {
655 bfd_size_type newsize, oldsize;
656
657 oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
658 bim->size = nwhere;
659 /* Round up to cut down on memory fragmentation */
660 newsize = (bim->size + 127) & ~(bfd_size_type) 127;
661 if (newsize > oldsize)
662 {
663 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
664 if (bim->buffer == NULL)
665 {
666 errno = EINVAL;
667 bim->size = 0;
668 return -1;
669 }
670 memset (bim->buffer + oldsize, 0, newsize - oldsize);
671 }
672 }
65077aa8 673 else
07d6d2b8
AM
674 {
675 abfd->where = bim->size;
676 errno = EINVAL;
677 bfd_set_error (bfd_error_file_truncated);
678 return -1;
679 }
65077aa8
TG
680 }
681 return 0;
682}
683
405bf443 684static int
65077aa8
TG
685memory_bclose (struct bfd *abfd)
686{
687 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
688
c9594989 689 free (bim->buffer);
65077aa8
TG
690 free (bim);
691 abfd->iostream = NULL;
692
405bf443 693 return 0;
65077aa8
TG
694}
695
696static int
697memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
698{
699 return 0;
700}
701
702static int
703memory_bstat (bfd *abfd, struct stat *statbuf)
704{
705 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
706
b5dee4ea 707 memset (statbuf, 0, sizeof (*statbuf));
65077aa8
TG
708 statbuf->st_size = bim->size;
709
710 return 0;
711}
712
713static void *
714memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
07d6d2b8
AM
715 bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
716 int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
717 void **map_addr ATTRIBUTE_UNUSED,
718 bfd_size_type *map_len ATTRIBUTE_UNUSED)
65077aa8
TG
719{
720 return (void *)-1;
721}
722
723const struct bfd_iovec _bfd_memory_iovec =
724{
725 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
726 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
727};
This page took 1.009185 seconds and 4 git commands to generate.