1 /* Low-level I/O routines for BFDs.
2 
3    Copyright (C) 1990-2021 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
_bfd_real_ftell(FILE * file)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
_bfd_real_fseek(FILE * file,file_ptr offset,int whence)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 *
close_on_exec(FILE * 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 *
_bfd_real_fopen(const char * filename,const char * modes)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   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;
137 
138   if (filelen > MAX_PATH - 1)
139     {
140       FILE * file;
141       char * fullpath;
142       int    i;
143 
144       fullpath = (char *) malloc (filelen + 8);
145 
146       /* Add a Microsoft recommended prefix that
147 	 will allow the extra-long path to work.  */
148       strcpy (fullpath, "\\\\?\\");
149       strcat (fullpath, filename);
150 
151       /* Convert any UNIX style path separators into the DOS form.  */
152       for (i = 0; fullpath[i]; i++)
153         {
154           if (IS_UNIX_DIR_SEPARATOR (fullpath[i]))
155 	    fullpath[i] = '\\';
156         }
157 
158       file = close_on_exec (fopen (fullpath, modes));
159       free (fullpath);
160       return file;
161     }
162 
163 #elif defined (HAVE_FOPEN64)
164   return close_on_exec (fopen64 (filename, modes));
165 #endif
166 
167   return close_on_exec (fopen (filename, modes));
168 }
169 
170 /*
171 INTERNAL_DEFINITION
172 	struct bfd_iovec
173 
174 DESCRIPTION
175 
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,
191 .		       file_ptr nbytes);
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.
196 .     Otherwise, a value of -1 is returned (and <<bfd_error>> is set).  *}
197 .  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
198 .  int (*bclose) (struct bfd *abfd);
199 .  int (*bflush) (struct bfd *abfd);
200 .  int (*bstat) (struct bfd *abfd, struct stat *sb);
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.  *}
207 .  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
208 .		   int prot, int flags, file_ptr offset,
209 .		   void **map_addr, bfd_size_type *map_len);
210 .};
211 
212 .extern const struct bfd_iovec _bfd_memory_iovec;
213 
214 */
215 
216 
217 /* Return value is amount read.  */
218 
219 bfd_size_type
bfd_bread(void * ptr,bfd_size_type size,bfd * abfd)220 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
221 {
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     }
232   offset += abfd->origin;
233 
234   /* If this is an archive element, don't read past the end of
235      this element.  */
236   if (element_bfd->arelt_data != NULL)
237     {
238       bfd_size_type maxbytes = arelt_size (element_bfd);
239 
240       if (abfd->where < offset || abfd->where - offset >= maxbytes)
241 	{
242 	  bfd_set_error (bfd_error_invalid_operation);
243 	  return -1;
244 	}
245       if (abfd->where - offset + size > maxbytes)
246 	size = maxbytes - (abfd->where - offset);
247     }
248 
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)
257     abfd->where += nread;
258 
259   return nread;
260 }
261 
262 bfd_size_type
bfd_bwrite(const void * ptr,bfd_size_type size,bfd * abfd)263 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
264 {
265   file_ptr nwrote;
266 
267   while (abfd->my_archive != NULL
268 	 && !bfd_is_thin_archive (abfd->my_archive))
269     abfd = abfd->my_archive;
270 
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)
279     abfd->where += nwrote;
280   if ((bfd_size_type) nwrote != size)
281     {
282 #ifdef ENOSPC
283       errno = ENOSPC;
284 #endif
285       bfd_set_error (bfd_error_system_call);
286     }
287   return nwrote;
288 }
289 
290 file_ptr
bfd_tell(bfd * abfd)291 bfd_tell (bfd *abfd)
292 {
293   ufile_ptr offset = 0;
294   file_ptr ptr;
295 
296   while (abfd->my_archive != NULL
297 	 && !bfd_is_thin_archive (abfd->my_archive))
298     {
299       offset += abfd->origin;
300       abfd = abfd->my_archive;
301     }
302   offset += abfd->origin;
303 
304   if (abfd->iovec == NULL)
305     return 0;
306 
307   ptr = abfd->iovec->btell (abfd);
308   abfd->where = ptr;
309   return ptr - offset;
310 }
311 
312 int
bfd_flush(bfd * abfd)313 bfd_flush (bfd *abfd)
314 {
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);
323 }
324 
325 /* Returns 0 for success, negative value for failure (in which case
326    bfd_get_error can retrieve the error code).  */
327 int
bfd_stat(bfd * abfd,struct stat * statbuf)328 bfd_stat (bfd *abfd, struct stat *statbuf)
329 {
330   int result;
331 
332   while (abfd->my_archive != NULL
333 	 && !bfd_is_thin_archive (abfd->my_archive))
334     abfd = abfd->my_archive;
335 
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);
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 
351 int
bfd_seek(bfd * abfd,file_ptr position,int direction)352 bfd_seek (bfd *abfd, file_ptr position, int direction)
353 {
354   int result;
355   ufile_ptr offset = 0;
356 
357   while (abfd->my_archive != NULL
358 	 && !bfd_is_thin_archive (abfd->my_archive))
359     {
360       offset += abfd->origin;
361       abfd = abfd->my_archive;
362     }
363   offset += abfd->origin;
364 
365   if (abfd->iovec == NULL)
366     {
367       bfd_set_error (bfd_error_invalid_operation);
368       return -1;
369     }
370 
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;
378 
379   if ((direction == SEEK_CUR && position == 0)
380       || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
381     return 0;
382 
383   result = abfd->iovec->bseek (abfd, position, direction);
384   if (result != 0)
385     {
386       /* An EINVAL error probably means that the file offset was
387 	 absurd.  */
388       if (errno == EINVAL)
389 	bfd_set_error (bfd_error_file_truncated);
390       else
391 	bfd_set_error (bfd_error_system_call);
392     }
393   else
394     {
395       /* Adjust `where' field.  */
396       if (direction == SEEK_CUR)
397 	abfd->where += position;
398       else
399 	abfd->where = position;
400     }
401 
402   return result;
403 }
404 
405 /*
406 FUNCTION
407 	bfd_get_mtime
408 
409 SYNOPSIS
410 	long bfd_get_mtime (bfd *abfd);
411 
412 DESCRIPTION
413 	Return the file modification time (as read from the file system, or
414 	from the archive header for archive members).
415 
416 */
417 
418 long
bfd_get_mtime(bfd * abfd)419 bfd_get_mtime (bfd *abfd)
420 {
421   struct stat buf;
422 
423   if (abfd->mtime_set)
424     return abfd->mtime;
425 
426   if (bfd_stat (abfd, &buf) != 0)
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 /*
434 FUNCTION
435 	bfd_get_size
436 
437 SYNOPSIS
438 	ufile_ptr bfd_get_size (bfd *abfd);
439 
440 DESCRIPTION
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.
462 	This function at least allows us to answer the question, "is the
463 	size reasonable?".
464 
465 	A return value of zero indicates the file size is unknown.
466 */
467 
468 ufile_ptr
bfd_get_size(bfd * abfd)469 bfd_get_size (bfd *abfd)
470 {
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;
476 
477       if (abfd->size == 1 && !bfd_write_p (abfd))
478 	return 0;
479 
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;
490 }
491 
492 /*
493 FUNCTION
494 	bfd_get_file_size
495 
496 SYNOPSIS
497 	ufile_ptr bfd_get_file_size (bfd *abfd);
498 
499 DESCRIPTION
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 
506 ufile_ptr
bfd_get_file_size(bfd * abfd)507 bfd_get_file_size (bfd *abfd)
508 {
509   ufile_ptr file_size, archive_size = (ufile_ptr) -1;
510 
511   if (abfd->my_archive != NULL
512       && !bfd_is_thin_archive (abfd->my_archive))
513     {
514       struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
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 	}
526     }
527 
528   file_size = bfd_get_size (abfd);
529   if (archive_size < file_size)
530     return archive_size;
531   return file_size;
532 }
533 
534 /*
535 FUNCTION
536 	bfd_mmap
537 
538 SYNOPSIS
539 	void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
540 			int prot, int flags, file_ptr offset,
541 			void **map_addr, bfd_size_type *map_len);
542 
543 DESCRIPTION
544 	Return mmap()ed region of the file, if possible and implemented.
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.
547 
548 */
549 
550 void *
bfd_mmap(bfd * abfd,void * addr,bfd_size_type len,int prot,int flags,file_ptr offset,void ** map_addr,bfd_size_type * map_len)551 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
552 	  int prot, int flags, file_ptr offset,
553 	  void **map_addr, bfd_size_type *map_len)
554 {
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     }
561   offset += abfd->origin;
562 
563   if (abfd->iovec == NULL)
564     {
565       bfd_set_error (bfd_error_invalid_operation);
566       return (void *) -1;
567     }
568 
569   return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
570 			     map_addr, map_len);
571 }
572 
573 /* Memory file I/O operations.  */
574 
575 static file_ptr
memory_bread(bfd * abfd,void * ptr,file_ptr size)576 memory_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)
586 	get = 0;
587       else
588 	get = bim->size - abfd->where;
589       bfd_set_error (bfd_error_file_truncated);
590     }
591   memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
592   return get;
593 }
594 
595 static file_ptr
memory_bwrite(bfd * abfd,const void * ptr,file_ptr size)596 memory_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)
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 	}
619     }
620   memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
621   return size;
622 }
623 
624 static file_ptr
memory_btell(bfd * abfd)625 memory_btell (bfd *abfd)
626 {
627   return abfd->where;
628 }
629 
630 static int
memory_bseek(bfd * abfd,file_ptr position,int direction)631 memory_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
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 	}
673       else
674 	{
675 	  abfd->where = bim->size;
676 	  errno = EINVAL;
677 	  bfd_set_error (bfd_error_file_truncated);
678 	  return -1;
679 	}
680     }
681   return 0;
682 }
683 
684 static int
memory_bclose(struct bfd * abfd)685 memory_bclose (struct bfd *abfd)
686 {
687   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
688 
689   free (bim->buffer);
690   free (bim);
691   abfd->iostream = NULL;
692 
693   return 0;
694 }
695 
696 static int
memory_bflush(bfd * abfd ATTRIBUTE_UNUSED)697 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
698 {
699   return 0;
700 }
701 
702 static int
memory_bstat(bfd * abfd,struct stat * statbuf)703 memory_bstat (bfd *abfd, struct stat *statbuf)
704 {
705   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
706 
707   memset (statbuf, 0, sizeof (*statbuf));
708   statbuf->st_size = bim->size;
709 
710   return 0;
711 }
712 
713 static void *
memory_bmmap(bfd * abfd ATTRIBUTE_UNUSED,void * addr ATTRIBUTE_UNUSED,bfd_size_type len ATTRIBUTE_UNUSED,int prot ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,file_ptr offset ATTRIBUTE_UNUSED,void ** map_addr ATTRIBUTE_UNUSED,bfd_size_type * map_len ATTRIBUTE_UNUSED)714 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
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)
719 {
720   return (void *)-1;
721 }
722 
723 const 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 };
728