summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-04-12 08:12:18 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-07-13 13:31:17 -0700
commit727aa8de0510fc89c2e021452ad35d2c5f7b2c21 (patch)
tree1eed88528204a4ce9ddc93acdf20d0e790b9f294
parent37567a2cdd8823c5700ec83b757179083446bf07 (diff)
downloadbinutils-gdb-users/hjl/mmap/write.tar.gz
-rw-r--r--bfd/Makefile.am4
-rw-r--r--bfd/Makefile.in11
-rw-r--r--bfd/bfd-in2.h3
-rw-r--r--bfd/bfd.c4
-rw-r--r--bfd/cache.c2
-rw-r--r--bfd/config.in12
-rwxr-xr-xbfd/configure74
-rw-r--r--bfd/configure.ac24
-rw-r--r--bfd/doc/Makefile.am5
-rw-r--r--bfd/doc/Makefile.in5
-rw-r--r--bfd/libbfd.h5
-rw-r--r--bfd/mmap.c227
-rw-r--r--bfd/opncls.c4
13 files changed, 363 insertions, 17 deletions
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 6720f863047..afbc9589913 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -80,7 +80,7 @@ BFD64_LIBS = archive64.lo
BFD32_LIBS_CFILES = \
archive.c archures.c bfd.c bfdio.c bfdwin.c \
cache.c coff-bfd.c compress.c corefile.c format.c hash.c \
- init.c libbfd.c linker.c merge.c opncls.c reloc.c \
+ init.c libbfd.c linker.c mmap.c merge.c opncls.c reloc.c \
section.c simple.c stab-syms.c stabs.c syms.c targets.c \
binary.c ihex.c srec.c tekhex.c verilog.c
@@ -1002,7 +1002,7 @@ BFD_H_FILES = bfd-in.h init.c opncls.c libbfd.c section.c archures.c \
archive.c corefile.c targets.c format.c compress.c
BFD64_H_FILES = archive64.c
LIBBFD_H_FILES = libbfd-in.h init.c libbfd.c bfdio.c bfdwin.c \
- cache.c reloc.c archures.c elf.c
+ cache.c reloc.c archures.c elf.c mmap.c
LIBCOFF_H_FILES = libcoff-in.h coffcode.h
# Could really use a "copy-if-change"...
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 7283ed95b48..02c37d59860 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -146,9 +146,9 @@ LTLIBRARIES = $(bfdlib_LTLIBRARIES) $(noinst_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__objects_1 = archive.lo archures.lo bfd.lo bfdio.lo bfdwin.lo \
cache.lo coff-bfd.lo compress.lo corefile.lo format.lo hash.lo \
- init.lo libbfd.lo linker.lo merge.lo opncls.lo reloc.lo \
- section.lo simple.lo stab-syms.lo stabs.lo syms.lo targets.lo \
- binary.lo ihex.lo srec.lo tekhex.lo verilog.lo
+ init.lo libbfd.lo linker.lo mmap.lo merge.lo opncls.lo \
+ reloc.lo section.lo simple.lo stab-syms.lo stabs.lo syms.lo \
+ targets.lo binary.lo ihex.lo srec.lo tekhex.lo verilog.lo
am_libbfd_la_OBJECTS = $(am__objects_1)
libbfd_la_OBJECTS = $(am_libbfd_la_OBJECTS)
libbfd_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -412,7 +412,7 @@ BFD64_LIBS = archive64.lo
BFD32_LIBS_CFILES = \
archive.c archures.c bfd.c bfdio.c bfdwin.c \
cache.c coff-bfd.c compress.c corefile.c format.c hash.c \
- init.c libbfd.c linker.c merge.c opncls.c reloc.c \
+ init.c libbfd.c linker.c mmap.c merge.c opncls.c reloc.c \
section.c simple.c stab-syms.c stabs.c syms.c targets.c \
binary.c ihex.c srec.c tekhex.c verilog.c
@@ -1175,7 +1175,7 @@ BFD_H_FILES = bfd-in.h init.c opncls.c libbfd.c section.c archures.c \
BFD64_H_FILES = archive64.c
LIBBFD_H_FILES = libbfd-in.h init.c libbfd.c bfdio.c bfdwin.c \
- cache.c reloc.c archures.c elf.c
+ cache.c reloc.c archures.c elf.c mmap.c
LIBCOFF_H_FILES = libcoff-in.h coffcode.h
MOSTLYCLEANFILES = ofiles stamp-ofiles
@@ -1579,6 +1579,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mipsbsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netbsd-core.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/newsos3.Plo@am__quote@
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 3f2d93b03cd..72462afc35e 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6783,6 +6783,9 @@ struct bfd
/* Pointer to structure which contains architecture information. */
const struct bfd_arch_info *arch_info;
+ /* Used by mmap_iovec. */
+ int mmap_fd;
+ file_ptr mmap_size;
/* Stuff only useful for archives. */
void *arelt_data;
struct bfd *my_archive; /* The containing archive BFD. */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 806b9fb33f5..1d92e0f0e54 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -283,6 +283,10 @@ CODE_FRAGMENT
. {* Pointer to structure which contains architecture information. *}
. const struct bfd_arch_info *arch_info;
.
+. {* Used by mmap_iovec. *}
+. int mmap_fd;
+. file_ptr mmap_size;
+
. {* Stuff only useful for archives. *}
. void *arelt_data;
. struct bfd *my_archive; {* The containing archive BFD. *}
diff --git a/bfd/cache.c b/bfd/cache.c
index 8efbcb9e22f..7918b67c46c 100644
--- a/bfd/cache.c
+++ b/bfd/cache.c
@@ -656,7 +656,7 @@ bfd_open_file (bfd *abfd)
bfd_set_error (bfd_error_system_call);
else
{
- if (! bfd_cache_init (abfd))
+ if (! bfd_mmap_init (abfd))
return NULL;
}
diff --git a/bfd/config.in b/bfd/config.in
index 341afae4329..572b5f7c0f5 100644
--- a/bfd/config.in
+++ b/bfd/config.in
@@ -91,6 +91,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if you have the `fallocate' function. */
+#undef HAVE_FALLOCATE
+
/* Define to 1 if you have the `fcntl' function. */
#undef HAVE_FCNTL
@@ -160,9 +163,18 @@
/* Define to 1 if you have the `mprotect' function. */
#undef HAVE_MPROTECT
+/* Define to 1 if you have the mremap function with MREMAP_MAYMOVE support */
+#undef HAVE_MREMAP
+
+/* Define to 1 if you have the msync function with MS_SYNC support */
+#undef HAVE_MSYNC
+
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
+/* Define to 1 if you have the `posix_fallocate' function. */
+#undef HAVE_POSIX_FALLOCATE
+
/* Define if <sys/procfs.h> has prpsinfo32_t. */
#undef HAVE_PRPSINFO32_T
diff --git a/bfd/configure b/bfd/configure
index bc49dc4c3d7..a401e66c43e 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13689,7 +13689,7 @@ _ACEOF
fi
done
-for ac_func in strtoull getrlimit
+for ac_func in strtoull getrlimit posix_fallocate fallocate
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -16027,6 +16027,78 @@ $as_echo "#define USE_MMAP 1" >>confdefs.h
;;
esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking mremap with MREMAP_MAYMOVE" >&5
+$as_echo_n "checking mremap with MREMAP_MAYMOVE... " >&6; }
+if test "${bfd_cv_mremap_maymove+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+#include <sys/mman.h>
+void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); }
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ bfd_cv_mremap_maymove=yes
+else
+ bfd_cv_mremap_maymove=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_mremap_maymove" >&5
+$as_echo "$bfd_cv_mremap_maymove" >&6; }
+if test "$bfd_cv_mremap_maymove" = "yes"; then
+
+$as_echo "#define HAVE_MREMAP 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking msync with MS_SYNC" >&5
+$as_echo_n "checking msync with MS_SYNC... " >&6; }
+if test "${bfd_cv_msync_ms_sync+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+#include <sys/mman.h>
+void f() { msync (0, 0, MS_SYNC); }
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ bfd_cv_msync_ms_sync=yes
+else
+ bfd_cv_msync_ms_sync=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_msync_ms_sync" >&5
+$as_echo "$bfd_cv_msync_ms_sync" >&6; }
+if test "$bfd_cv_msync_ms_sync" = "yes"; then
+
+$as_echo "#define HAVE_MSYNC 1" >>confdefs.h
+
+fi
+
rm -f doc/config.status
ac_config_files="$ac_config_files Makefile doc/Makefile bfd-in3.h:bfd-in2.h po/Makefile.in:po/Make-in"
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 669cff7532a..3f3d504bdf8 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -204,7 +204,7 @@ AC_HEADER_DIRENT
ACX_HEADER_STRING
AC_CHECK_FUNCS(fcntl getpagesize setitimer sysconf fdopen getuid getgid fileno)
-AC_CHECK_FUNCS(strtoull getrlimit)
+AC_CHECK_FUNCS(strtoull getrlimit posix_fallocate fallocate)
AC_CHECK_DECLS(basename)
AC_CHECK_DECLS(ftello)
@@ -1182,6 +1182,28 @@ case ${want_mmap}+${ac_cv_func_mmap_fixed_mapped} in
true+yes ) AC_DEFINE(USE_MMAP, 1, [Use mmap if it's available?]) ;;
esac
+AC_CACHE_CHECK([mremap with MREMAP_MAYMOVE], [bfd_cv_mremap_maymove],
+[AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[
+#include <sys/mman.h>
+void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); }
+]])], [bfd_cv_mremap_maymove=yes], [bfd_cv_mremap_maymove=no])])
+if test "$bfd_cv_mremap_maymove" = "yes"; then
+ AC_DEFINE(HAVE_MREMAP, 1,
+ [Define to 1 if you have the mremap function with MREMAP_MAYMOVE support])
+fi
+
+AC_CACHE_CHECK([msync with MS_SYNC], [bfd_cv_msync_ms_sync],
+[AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[
+#include <sys/mman.h>
+void f() { msync (0, 0, MS_SYNC); }
+]])], [bfd_cv_msync_ms_sync=yes], [bfd_cv_msync_ms_sync=no])])
+if test "$bfd_cv_msync_ms_sync" = "yes"; then
+ AC_DEFINE(HAVE_MSYNC, 1,
+ [Define to 1 if you have the msync function with MS_SYNC support])
+fi
+
rm -f doc/config.status
AC_CONFIG_FILES([Makefile doc/Makefile bfd-in3.h:bfd-in2.h po/Makefile.in:po/Make-in])
diff --git a/bfd/doc/Makefile.am b/bfd/doc/Makefile.am
index c44c8030334..10fcb7d8069 100644
--- a/bfd/doc/Makefile.am
+++ b/bfd/doc/Makefile.am
@@ -50,7 +50,7 @@ SRCDOC = $(srcdir)/../aoutx.h $(srcdir)/../archive.c \
$(srcdir)/../reloc.c $(srcdir)/../section.c \
$(srcdir)/../syms.c $(srcdir)/../targets.c \
$(srcdir)/../hash.c $(srcdir)/../linker.c \
- $(srcdir)/../mmo.c
+ $(srcdir)/../mmo.c $(srcdir)/../mmap.c
SRCPROT = $(srcdir)/../archive.c $(srcdir)/../archures.c \
$(srcdir)/../bfd.c $(srcdir)/../coffcode.h $(srcdir)/../corefile.c \
@@ -64,7 +64,7 @@ SRCIPROT = $(srcdir)/../cache.c $(srcdir)/../libbfd.c \
$(srcdir)/../bfdio.c $(srcdir)/../bfdwin.c \
$(srcdir)/../reloc.c $(srcdir)/../cpu-h8300.c \
$(srcdir)/../cpu-i960.c $(srcdir)/../archures.c \
- $(srcdir)/../init.c
+ $(srcdir)/../init.c $(srcdir)/../mmap.c
TEXIDIR = $(srcdir)/../../texinfo/fsf
@@ -260,6 +260,7 @@ LIBBFD_H_DEP = \
$(srcdir)/../reloc.c \
$(srcdir)/../archures.c \
$(srcdir)/../elf.c \
+ $(srcdir)/../mmap.c \
$(srcdir)/header.sed \
$(srcdir)/proto.str \
$(MKDOC)
diff --git a/bfd/doc/Makefile.in b/bfd/doc/Makefile.in
index be737f67fc0..9a19c6fc9f0 100644
--- a/bfd/doc/Makefile.in
+++ b/bfd/doc/Makefile.in
@@ -353,7 +353,7 @@ SRCDOC = $(srcdir)/../aoutx.h $(srcdir)/../archive.c \
$(srcdir)/../reloc.c $(srcdir)/../section.c \
$(srcdir)/../syms.c $(srcdir)/../targets.c \
$(srcdir)/../hash.c $(srcdir)/../linker.c \
- $(srcdir)/../mmo.c
+ $(srcdir)/../mmo.c $(srcdir)/../mmap.c
SRCPROT = $(srcdir)/../archive.c $(srcdir)/../archures.c \
$(srcdir)/../bfd.c $(srcdir)/../coffcode.h $(srcdir)/../corefile.c \
@@ -367,7 +367,7 @@ SRCIPROT = $(srcdir)/../cache.c $(srcdir)/../libbfd.c \
$(srcdir)/../bfdio.c $(srcdir)/../bfdwin.c \
$(srcdir)/../reloc.c $(srcdir)/../cpu-h8300.c \
$(srcdir)/../cpu-i960.c $(srcdir)/../archures.c \
- $(srcdir)/../init.c
+ $(srcdir)/../init.c $(srcdir)/../mmap.c
TEXIDIR = $(srcdir)/../../texinfo/fsf
info_TEXINFOS = bfd.texinfo
@@ -386,6 +386,7 @@ LIBBFD_H_DEP = \
$(srcdir)/../reloc.c \
$(srcdir)/../archures.c \
$(srcdir)/../elf.c \
+ $(srcdir)/../mmap.c \
$(srcdir)/header.sed \
$(srcdir)/proto.str \
$(MKDOC)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 2b1777ef21f..616671d1f99 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1,6 +1,6 @@
/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
generated from "libbfd-in.h", "init.c", "libbfd.c", "bfdio.c",
- "bfdwin.c", "cache.c", "reloc.c", "archures.c" and "elf.c".
+ "bfdwin.c", "cache.c", "reloc.c", "archures.c", "elf.c" and "mmap.c".
Run "make headers" in your build bfd/ to regenerate. */
/* libbfd.h -- Declarations used by bfd library *implementation*.
@@ -3171,6 +3171,9 @@ void *bfd_arch_default_fill (bfd_size_type count,
bfd_boolean code);
/* Extracted from elf.c. */
+/* Extracted from mmap.c. */
+bfd_boolean bfd_mmap_init (bfd *abfd);
+
#ifdef __cplusplus
}
#endif
diff --git a/bfd/mmap.c b/bfd/mmap.c
new file mode 100644
index 00000000000..a28dd6a76eb
--- /dev/null
+++ b/bfd/mmap.c
@@ -0,0 +1,227 @@
+/* BFD library -- mmap of file descriptors.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+
+#ifdef HAVE_MMAP
+#include "bfd.h"
+#include "libbfd.h"
+#include "libiberty.h"
+#include "bfd_stdint.h"
+
+#include <sys/mman.h>
+
+static file_ptr
+mmap_btell (struct bfd *abfd)
+{
+ return abfd->where;
+}
+
+/* Copied and modified from gold_fallocate in gold. */
+
+static int
+mmap_fallocate (int fd, file_ptr offset, file_ptr len)
+{
+#ifdef HAVE_FALLOCATE
+ if (fallocate (fd, 0, offset, len) == 0)
+ return 0;
+#endif
+#ifdef HAVE_POSIX_FALLOCATE
+ return posix_fallocate (fd, offset, len);
+#endif
+ if (ftruncate (fd, offset + len) < 0)
+ return errno;
+ return 0;
+}
+
+static int
+mmap_resize (bfd *abfd, file_ptr size)
+{
+ if (mmap_fallocate (abfd->mmap_fd, 0, size) != 0)
+ {
+syscall_error:
+ bfd_set_error (bfd_error_system_call);
+ abfd->mmap_size = 0;
+ return -1;
+ }
+ if (abfd->mmap_size != 0)
+ {
+#ifdef HAVE_MREMAP
+ abfd->iostream = mremap (abfd->iostream, abfd->mmap_size,
+ size, MREMAP_MAYMOVE);
+ if (abfd->iostream == MAP_FAILED)
+ goto syscall_error;
+ else
+ goto success;
+#else
+ if (munmap (abfd->iostream, abfd->mmap_size) != 0)
+ goto syscall_error;
+#endif
+ }
+ abfd->iostream = mmap (NULL, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, abfd->mmap_fd, 0);
+ if (abfd->iostream == MAP_FAILED)
+ goto syscall_error;
+
+success:
+ abfd->mmap_size = size;
+ return 0;
+}
+
+static int
+mmap_bseek (bfd *abfd, file_ptr position, int direction)
+{
+ file_ptr nwhere;
+
+ if (direction == SEEK_SET)
+ nwhere = position;
+ else
+ nwhere = abfd->where + position;
+
+ if (nwhere < 0)
+ {
+ abfd->where = 0;
+ errno = EINVAL;
+ return -1;
+ }
+ else if (nwhere >= abfd->mmap_size && mmap_resize (abfd, nwhere) != 0)
+ return -1;
+
+ return 0;
+}
+
+static file_ptr
+mmap_bread (struct bfd *abfd, void *buf, file_ptr size)
+{
+ memcpy (buf, abfd->iostream + abfd->where, size);
+ return size;
+}
+
+static file_ptr
+mmap_bwrite (bfd *abfd, const void *ptr, file_ptr size)
+{
+ file_ptr filesize = abfd->where + size;
+
+ if (filesize > abfd->mmap_size && mmap_resize (abfd, filesize) != 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return 0;
+ }
+
+ memcpy (abfd->iostream + abfd->where, ptr, size);
+ return size;
+}
+
+static int
+mmap_bclose (struct bfd *abfd)
+{
+ int status = munmap (abfd->iostream, abfd->mmap_size);
+ if (status == 0)
+ status = close (abfd->mmap_fd);
+ if (status != 0)
+ bfd_set_error (bfd_error_system_call);
+
+ abfd->iostream = MAP_FAILED;
+ abfd->mmap_size = 0;
+ abfd->mmap_fd = -1;
+
+ return status;
+}
+
+static int
+mmap_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_MSYNC
+ int status = msync (abfd->iostream, abfd->mmap_size, MS_SYNC);
+ if (status != 0)
+ bfd_set_error (bfd_error_system_call);
+ return status;
+#else
+ return 0;
+#endif
+}
+
+static int
+mmap_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, struct stat *sb)
+{
+ int status;
+ status = fstat (abfd->mmap_fd, sb);
+ if (status < 0)
+ bfd_set_error (bfd_error_system_call);
+ return status;
+}
+
+static void *
+mmap_bmmap (struct 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)
+{
+ /* Unsupported. */
+ abort ();
+ return 0;
+}
+
+static const struct bfd_iovec mmap_iovec =
+{
+ &mmap_bread, &mmap_bwrite, &mmap_btell, &mmap_bseek,
+ &mmap_bclose, &mmap_bflush, &mmap_bstat, &mmap_bmmap
+};
+#endif
+
+/*
+INTERNAL_FUNCTION
+ bfd_mmap_init
+
+SYNOPSIS
+ bfd_boolean bfd_mmap_init (bfd *abfd);
+
+DESCRIPTION
+ Use mmap on BFD. Fallback to bfd_cache_init.
+*/
+
+bfd_boolean
+bfd_mmap_init (bfd *abfd)
+{
+#ifdef HAVE_MMAP
+ /* Only suport write before writing starts. */
+ if (abfd->direction == write_direction
+ && !abfd->output_has_begun)
+ {
+ if (abfd->mmap_size != 0 || abfd->iostream == NULL)
+ abort ();
+
+ abfd->mmap_fd = dup (fileno (abfd->iostream));
+ if (abfd->mmap_fd < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return FALSE;
+ }
+
+ abfd->iovec = &mmap_iovec;
+ return TRUE;
+ }
+#endif
+
+ return bfd_cache_init (abfd);
+}
diff --git a/bfd/opncls.c b/bfd/opncls.c
index b86bbab1d30..b1da1cd477d 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -242,7 +242,7 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
else
nbfd->direction = write_direction;
- if (! bfd_cache_init (nbfd))
+ if (! bfd_mmap_init (nbfd))
{
_bfd_delete_bfd (nbfd);
return NULL;
@@ -400,7 +400,7 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg)
nbfd->filename = xstrdup (filename);
nbfd->direction = read_direction;
- if (! bfd_cache_init (nbfd))
+ if (! bfd_mmap_init (nbfd))
{
_bfd_delete_bfd (nbfd);
return NULL;