Automatic date update in version.in
[binutils-gdb.git] / bfd / bfdio.c
1 /* Low-level I/O routines for BFDs.
2
3 Copyright (C) 1990-2022 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 #if defined (_WIN32)
30 #include <windows.h>
31 #endif
32
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
43 #ifndef FD_CLOEXEC
44 #define FD_CLOEXEC 1
45 #endif
46
47 file_ptr
48 _bfd_real_ftell (FILE *file)
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
59 int
60 _bfd_real_fseek (FILE *file, file_ptr offset, int whence)
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
71 /* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
72 which case nothing is done. */
73 static FILE *
74 close_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
88 FILE *
89 _bfd_real_fopen (const char *filename, const char *modes)
90 {
91 #ifdef VMS
92 char *vms_attr;
93
94 /* On VMS, fopen allows file attributes as optional arguments.
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, ',');
99 if (vms_attr != NULL)
100 {
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]));
116 }
117
118 #elif defined (_WIN32)
119 /* PR 25713: Handle extra long path names possibly containing '..' and '.'. */
120 wchar_t ** lpFilePart = {NULL};
121 const wchar_t prefix[] = L"\\\\?\\";
122 const wchar_t ccs[] = L", ccs=UNICODE";
123 const size_t partPathLen = strlen (filename) + 1;
124
125 /* Converting the partial path from ascii to unicode.
126 1) Get the length: Calling with lpWideCharStr set to null returns the length.
127 2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null. */
128 size_t partPathWSize = MultiByteToWideChar (CP_UTF8, 0, filename, -1, NULL, 0);
129 wchar_t * partPath = calloc (partPathWSize, sizeof(wchar_t));
130 size_t ix;
131
132 MultiByteToWideChar (CP_UTF8, 0, filename, -1, partPath, partPathWSize);
133
134 /* Convert any UNIX style path separators into the DOS i.e. backslash separator. */
135 for (ix = 0; ix < partPathLen; ix++)
136 if (IS_UNIX_DIR_SEPARATOR(filename[ix]))
137 partPath[ix] = '\\';
138
139 /* Getting the full path from the provided partial path.
140 1) Get the length.
141 2) Resolve the path. */
142 long fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart);
143 wchar_t * fullPath = calloc (fullPathWSize + sizeof(prefix) + 1, sizeof(wchar_t));
144
145 wcscpy (fullPath, prefix);
146
147 int prefixLen = sizeof(prefix) / sizeof(wchar_t);
148 wchar_t * fullPathOffset = fullPath + prefixLen - 1;
149
150 GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
151 free (partPath);
152
153 /* It is non-standard for modes to exceed 16 characters. */
154 wchar_t modesW[16 + sizeof(ccs)];
155
156 MultiByteToWideChar (CP_UTF8, 0, modes, -1, modesW, sizeof(modesW));
157 wcscat (modesW, ccs);
158
159 FILE * file = _wfopen (fullPath, modesW);
160 free (fullPath);
161
162 return close_on_exec (file);
163
164 #elif defined (HAVE_FOPEN64)
165 return close_on_exec (fopen64 (filename, modes));
166
167 #else
168 return close_on_exec (fopen (filename, modes));
169 #endif
170 }
171
172 /*
173 INTERNAL_DEFINITION
174 struct bfd_iovec
175
176 DESCRIPTION
177
178 The <<struct bfd_iovec>> contains the internal file I/O class.
179 Each <<BFD>> has an instance of this class and all file I/O is
180 routed through it (it is assumed that the instance implements
181 all methods listed below).
182
183 .struct bfd_iovec
184 .{
185 . {* To avoid problems with macros, a "b" rather than "f"
186 . prefix is prepended to each method name. *}
187 . {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
188 . bytes starting at PTR. Return the number of bytes actually
189 . transfered (a read past end-of-file returns less than NBYTES),
190 . or -1 (setting <<bfd_error>>) if an error occurs. *}
191 . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
192 . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
193 . file_ptr nbytes);
194 . {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
195 . if an error occurs. *}
196 . file_ptr (*btell) (struct bfd *abfd);
197 . {* For the following, on successful completion a value of 0 is returned.
198 . Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *}
199 . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
200 . int (*bclose) (struct bfd *abfd);
201 . int (*bflush) (struct bfd *abfd);
202 . int (*bstat) (struct bfd *abfd, struct stat *sb);
203 . {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
204 . mmap parameter, except that LEN and OFFSET do not need to be page
205 . aligned. Returns (void *)-1 on failure, mmapped address on success.
206 . Also write in MAP_ADDR the address of the page aligned buffer and in
207 . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and
208 . MAP_LEN to unmap. *}
209 . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
210 . int prot, int flags, file_ptr offset,
211 . void **map_addr, bfd_size_type *map_len);
212 .};
213
214 .extern const struct bfd_iovec _bfd_memory_iovec;
215
216 */
217
218
219 /* Return value is amount read. */
220
221 bfd_size_type
222 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
223 {
224 file_ptr nread;
225 bfd *element_bfd = abfd;
226 ufile_ptr offset = 0;
227
228 while (abfd->my_archive != NULL
229 && !bfd_is_thin_archive (abfd->my_archive))
230 {
231 offset += abfd->origin;
232 abfd = abfd->my_archive;
233 }
234 offset += abfd->origin;
235
236 /* If this is a non-thin archive element, don't read past the end of
237 this element. */
238 if (element_bfd->arelt_data != NULL
239 && element_bfd->my_archive != NULL
240 && !bfd_is_thin_archive (element_bfd->my_archive))
241 {
242 bfd_size_type maxbytes = arelt_size (element_bfd);
243
244 if (abfd->where < offset || abfd->where - offset >= maxbytes)
245 {
246 bfd_set_error (bfd_error_invalid_operation);
247 return -1;
248 }
249 if (abfd->where - offset + size > maxbytes)
250 size = maxbytes - (abfd->where - offset);
251 }
252
253 if (abfd->iovec == NULL)
254 {
255 bfd_set_error (bfd_error_invalid_operation);
256 return -1;
257 }
258
259 nread = abfd->iovec->bread (abfd, ptr, size);
260 if (nread != -1)
261 abfd->where += nread;
262
263 return nread;
264 }
265
266 bfd_size_type
267 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
268 {
269 file_ptr nwrote;
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 {
277 bfd_set_error (bfd_error_invalid_operation);
278 return -1;
279 }
280
281 nwrote = abfd->iovec->bwrite (abfd, ptr, size);
282 if (nwrote != -1)
283 abfd->where += nwrote;
284 if ((bfd_size_type) nwrote != size)
285 {
286 #ifdef ENOSPC
287 errno = ENOSPC;
288 #endif
289 bfd_set_error (bfd_error_system_call);
290 }
291 return nwrote;
292 }
293
294 file_ptr
295 bfd_tell (bfd *abfd)
296 {
297 ufile_ptr offset = 0;
298 file_ptr ptr;
299
300 while (abfd->my_archive != NULL
301 && !bfd_is_thin_archive (abfd->my_archive))
302 {
303 offset += abfd->origin;
304 abfd = abfd->my_archive;
305 }
306 offset += abfd->origin;
307
308 if (abfd->iovec == NULL)
309 return 0;
310
311 ptr = abfd->iovec->btell (abfd);
312 abfd->where = ptr;
313 return ptr - offset;
314 }
315
316 int
317 bfd_flush (bfd *abfd)
318 {
319 while (abfd->my_archive != NULL
320 && !bfd_is_thin_archive (abfd->my_archive))
321 abfd = abfd->my_archive;
322
323 if (abfd->iovec == NULL)
324 return 0;
325
326 return abfd->iovec->bflush (abfd);
327 }
328
329 /* Returns 0 for success, negative value for failure (in which case
330 bfd_get_error can retrieve the error code). */
331 int
332 bfd_stat (bfd *abfd, struct stat *statbuf)
333 {
334 int result;
335
336 while (abfd->my_archive != NULL
337 && !bfd_is_thin_archive (abfd->my_archive))
338 abfd = abfd->my_archive;
339
340 if (abfd->iovec == NULL)
341 {
342 bfd_set_error (bfd_error_invalid_operation);
343 return -1;
344 }
345
346 result = abfd->iovec->bstat (abfd, statbuf);
347 if (result < 0)
348 bfd_set_error (bfd_error_system_call);
349 return result;
350 }
351
352 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
353 can retrieve the error code). */
354
355 int
356 bfd_seek (bfd *abfd, file_ptr position, int direction)
357 {
358 int result;
359 ufile_ptr offset = 0;
360
361 while (abfd->my_archive != NULL
362 && !bfd_is_thin_archive (abfd->my_archive))
363 {
364 offset += abfd->origin;
365 abfd = abfd->my_archive;
366 }
367 offset += abfd->origin;
368
369 if (abfd->iovec == NULL)
370 {
371 bfd_set_error (bfd_error_invalid_operation);
372 return -1;
373 }
374
375 /* For the time being, a BFD may not seek to it's end. The problem
376 is that we don't easily have a way to recognize the end of an
377 element in an archive. */
378 BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
379
380 if (direction != SEEK_CUR)
381 position += offset;
382
383 if ((direction == SEEK_CUR && position == 0)
384 || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
385 return 0;
386
387 result = abfd->iovec->bseek (abfd, position, direction);
388 if (result != 0)
389 {
390 /* An EINVAL error probably means that the file offset was
391 absurd. */
392 if (errno == EINVAL)
393 bfd_set_error (bfd_error_file_truncated);
394 else
395 bfd_set_error (bfd_error_system_call);
396 }
397 else
398 {
399 /* Adjust `where' field. */
400 if (direction == SEEK_CUR)
401 abfd->where += position;
402 else
403 abfd->where = position;
404 }
405
406 return result;
407 }
408
409 /*
410 FUNCTION
411 bfd_get_mtime
412
413 SYNOPSIS
414 long bfd_get_mtime (bfd *abfd);
415
416 DESCRIPTION
417 Return the file modification time (as read from the file system, or
418 from the archive header for archive members).
419
420 */
421
422 long
423 bfd_get_mtime (bfd *abfd)
424 {
425 struct stat buf;
426
427 if (abfd->mtime_set)
428 return abfd->mtime;
429
430 if (bfd_stat (abfd, &buf) != 0)
431 return 0;
432
433 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
434 return buf.st_mtime;
435 }
436
437 /*
438 FUNCTION
439 bfd_get_size
440
441 SYNOPSIS
442 ufile_ptr bfd_get_size (bfd *abfd);
443
444 DESCRIPTION
445 Return the file size (as read from file system) for the file
446 associated with BFD @var{abfd}.
447
448 The initial motivation for, and use of, this routine is not
449 so we can get the exact size of the object the BFD applies to, since
450 that might not be generally possible (archive members for example).
451 It would be ideal if someone could eventually modify
452 it so that such results were guaranteed.
453
454 Instead, we want to ask questions like "is this NNN byte sized
455 object I'm about to try read from file offset YYY reasonable?"
456 As as example of where we might do this, some object formats
457 use string tables for which the first <<sizeof (long)>> bytes of the
458 table contain the size of the table itself, including the size bytes.
459 If an application tries to read what it thinks is one of these
460 string tables, without some way to validate the size, and for
461 some reason the size is wrong (byte swapping error, wrong location
462 for the string table, etc.), the only clue is likely to be a read
463 error when it tries to read the table, or a "virtual memory
464 exhausted" error when it tries to allocate 15 bazillon bytes
465 of space for the 15 bazillon byte table it is about to read.
466 This function at least allows us to answer the question, "is the
467 size reasonable?".
468
469 A return value of zero indicates the file size is unknown.
470 */
471
472 ufile_ptr
473 bfd_get_size (bfd *abfd)
474 {
475 /* A size of 0 means we haven't yet called bfd_stat. A size of 1
476 means we have a cached value of 0, ie. unknown. */
477 if (abfd->size <= 1 || bfd_write_p (abfd))
478 {
479 struct stat buf;
480
481 if (abfd->size == 1 && !bfd_write_p (abfd))
482 return 0;
483
484 if (bfd_stat (abfd, &buf) != 0
485 || buf.st_size == 0
486 || buf.st_size - (ufile_ptr) buf.st_size != 0)
487 {
488 abfd->size = 1;
489 return 0;
490 }
491 abfd->size = buf.st_size;
492 }
493 return abfd->size;
494 }
495
496 /*
497 FUNCTION
498 bfd_get_file_size
499
500 SYNOPSIS
501 ufile_ptr bfd_get_file_size (bfd *abfd);
502
503 DESCRIPTION
504 Return the file size (as read from file system) for the file
505 associated with BFD @var{abfd}. It supports both normal files
506 and archive elements.
507
508 */
509
510 ufile_ptr
511 bfd_get_file_size (bfd *abfd)
512 {
513 ufile_ptr file_size, archive_size = (ufile_ptr) -1;
514
515 if (abfd->my_archive != NULL
516 && !bfd_is_thin_archive (abfd->my_archive))
517 {
518 struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
519 if (adata != NULL)
520 {
521 archive_size = adata->parsed_size;
522 /* If the archive is compressed we can't compare against
523 file size. */
524 if (adata->arch_header != NULL
525 && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
526 "Z\012", 2) == 0)
527 return archive_size;
528 abfd = abfd->my_archive;
529 }
530 }
531
532 file_size = bfd_get_size (abfd);
533 if (archive_size < file_size)
534 return archive_size;
535 return file_size;
536 }
537
538 /*
539 FUNCTION
540 bfd_mmap
541
542 SYNOPSIS
543 void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
544 int prot, int flags, file_ptr offset,
545 void **map_addr, bfd_size_type *map_len);
546
547 DESCRIPTION
548 Return mmap()ed region of the file, if possible and implemented.
549 LEN and OFFSET do not need to be page aligned. The page aligned
550 address and length are written to MAP_ADDR and MAP_LEN.
551
552 */
553
554 void *
555 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
556 int prot, int flags, file_ptr offset,
557 void **map_addr, bfd_size_type *map_len)
558 {
559 while (abfd->my_archive != NULL
560 && !bfd_is_thin_archive (abfd->my_archive))
561 {
562 offset += abfd->origin;
563 abfd = abfd->my_archive;
564 }
565 offset += abfd->origin;
566
567 if (abfd->iovec == NULL)
568 {
569 bfd_set_error (bfd_error_invalid_operation);
570 return (void *) -1;
571 }
572
573 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
574 map_addr, map_len);
575 }
576
577 /* Memory file I/O operations. */
578
579 static file_ptr
580 memory_bread (bfd *abfd, void *ptr, file_ptr size)
581 {
582 struct bfd_in_memory *bim;
583 bfd_size_type get;
584
585 bim = (struct bfd_in_memory *) abfd->iostream;
586 get = size;
587 if (abfd->where + get > bim->size)
588 {
589 if (bim->size < (bfd_size_type) abfd->where)
590 get = 0;
591 else
592 get = bim->size - abfd->where;
593 bfd_set_error (bfd_error_file_truncated);
594 }
595 memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
596 return get;
597 }
598
599 static file_ptr
600 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
601 {
602 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
603
604 if (abfd->where + size > bim->size)
605 {
606 bfd_size_type newsize, oldsize;
607
608 oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
609 bim->size = abfd->where + size;
610 /* Round up to cut down on memory fragmentation */
611 newsize = (bim->size + 127) & ~(bfd_size_type) 127;
612 if (newsize > oldsize)
613 {
614 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
615 if (bim->buffer == NULL)
616 {
617 bim->size = 0;
618 return 0;
619 }
620 if (newsize > bim->size)
621 memset (bim->buffer + bim->size, 0, newsize - bim->size);
622 }
623 }
624 memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
625 return size;
626 }
627
628 static file_ptr
629 memory_btell (bfd *abfd)
630 {
631 return abfd->where;
632 }
633
634 static int
635 memory_bseek (bfd *abfd, file_ptr position, int direction)
636 {
637 file_ptr nwhere;
638 struct bfd_in_memory *bim;
639
640 bim = (struct bfd_in_memory *) abfd->iostream;
641
642 if (direction == SEEK_SET)
643 nwhere = position;
644 else
645 nwhere = abfd->where + position;
646
647 if (nwhere < 0)
648 {
649 abfd->where = 0;
650 errno = EINVAL;
651 return -1;
652 }
653
654 if ((bfd_size_type)nwhere > bim->size)
655 {
656 if (abfd->direction == write_direction
657 || abfd->direction == both_direction)
658 {
659 bfd_size_type newsize, oldsize;
660
661 oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
662 bim->size = nwhere;
663 /* Round up to cut down on memory fragmentation */
664 newsize = (bim->size + 127) & ~(bfd_size_type) 127;
665 if (newsize > oldsize)
666 {
667 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
668 if (bim->buffer == NULL)
669 {
670 errno = EINVAL;
671 bim->size = 0;
672 return -1;
673 }
674 memset (bim->buffer + oldsize, 0, newsize - oldsize);
675 }
676 }
677 else
678 {
679 abfd->where = bim->size;
680 errno = EINVAL;
681 bfd_set_error (bfd_error_file_truncated);
682 return -1;
683 }
684 }
685 return 0;
686 }
687
688 static int
689 memory_bclose (struct bfd *abfd)
690 {
691 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
692
693 free (bim->buffer);
694 free (bim);
695 abfd->iostream = NULL;
696
697 return 0;
698 }
699
700 static int
701 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
702 {
703 return 0;
704 }
705
706 static int
707 memory_bstat (bfd *abfd, struct stat *statbuf)
708 {
709 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
710
711 memset (statbuf, 0, sizeof (*statbuf));
712 statbuf->st_size = bim->size;
713
714 return 0;
715 }
716
717 static void *
718 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
719 bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
720 int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
721 void **map_addr ATTRIBUTE_UNUSED,
722 bfd_size_type *map_len ATTRIBUTE_UNUSED)
723 {
724 return (void *)-1;
725 }
726
727 const struct bfd_iovec _bfd_memory_iovec =
728 {
729 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
730 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
731 };