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