[PATCH] Add mman.h/.c for win32

Ulf Hermann ulf.hermann@qt.io
Thu May 4 08:31:00 GMT 2017


We cannot get mmap() and friends from gnulib and they don't exist on windows.
The functionality we need can be implemnted using native win32 functions, though.

Signed-off-by: Ulf Hermann <ulf.hermann@qt.io>
---
 configure.ac            |   7 +++
 libgnu/Makefile.am      |  17 +++++-
 libgnu/mman_win32.c     | 140 ++++++++++++++++++++++++++++++++++++++++++++++++
 libgnu/sys_mman.win32.h |  63 ++++++++++++++++++++++
 4 files changed, 226 insertions(+), 1 deletion(-)
 create mode 100644 libgnu/mman_win32.c
 create mode 100644 libgnu/sys_mman.win32.h

diff --git a/configure.ac b/configure.ac
index 1e6c844..6a2f991 100644
--- a/configure.ac
+++ b/configure.ac
@@ -550,6 +550,13 @@ AM_CONDITIONAL(HAVE_ENDIAN_H, [test "x$ac_cv_have_decl_BYTE_ORDER" = "xyes"])
 AC_CHECK_DECLS([bswap_32], [], [], [[#include <byteswap.h>]])
 AM_CONDITIONAL(HAVE_BYTESWAP_H, [test "x$ac_cv_have_decl_bswap_32" = "xyes"])
 
+AC_CHECK_HEADERS(sys/mman.h)
+AM_CONDITIONAL(HAVE_SYS_MMAN_H, [test "x$ac_cv_header_sys_mman_h" = "xyes"])
+if test "x$ac_cv_header_sys_mman_h" != "xyes"; then
+	AC_CHECK_DECLS([MapViewOfFile], [], [], [[#include <windows.h>]])
+fi
+AM_CONDITIONAL(USE_WIN32_MMAN, [test "x$ac_cv_have_decl_MapViewOfFile" = "xyes"])
+
 dnl Check if we have <linux/bpf.h> for EM_BPF disassembly.
 AC_CHECK_HEADERS(linux/bpf.h)
 AM_CONDITIONAL(HAVE_LINUX_BPF_H, [test "x$ac_cv_header_linux_bpf_h" = "xyes"])
diff --git a/libgnu/Makefile.am b/libgnu/Makefile.am
index 37fdb9c..5af121a 100644
--- a/libgnu/Makefile.am
+++ b/libgnu/Makefile.am
@@ -35,7 +35,7 @@ noinst_LIBRARIES =
 MOSTLYCLEANFILES =
 MOSTLYCLEANDIRS =
 BUILT_SOURCES =
-EXTRA_DIST = endian.in.h byteswap.in.h
+EXTRA_DIST = endian.in.h byteswap.in.h sys_mman.win32.h mman_win32.c
 CLEANFILES =
 SUFFIXES =
 
@@ -53,4 +53,19 @@ BUILT_SOURCES += byteswap.h
 MOSTLYCLEANFILES += byteswap.h
 endif
 
+if !HAVE_SYS_MMAN_H
+if USE_WIN32_MMAN
+sys/mman.h: sys_mman.win32.h
+	$(AM_V_GEN)rm -f $@ && mkdir -p sys && cat $< > $@
+BUILT_SOURCES += sys/mman.h
+MOSTLYCLEANFILES += sys/mman.h
+endif
+endif
+
 include gnulib.am
+
+if !HAVE_SYS_MMAN_H
+if USE_WIN32_MMAN
+libgnu_a_SOURCES += mman_win32.c
+endif
+endif
diff --git a/libgnu/mman_win32.c b/libgnu/mman_win32.c
new file mode 100644
index 0000000..78966c2
--- /dev/null
+++ b/libgnu/mman_win32.c
@@ -0,0 +1,140 @@
+/* Replacement for mmap(2) and friends on windows
+   Copyright (C) 2017 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <sys/mman.h>
+#include <windows.h>
+#include <io.h>
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
+{
+    if (fd == -1) {
+        errno = EBADF;
+        return MAP_FAILED;
+    }
+
+    HANDLE file = (HANDLE)_get_osfhandle(fd);
+    if (file == INVALID_HANDLE_VALUE) {
+        errno = EBADF;
+        return MAP_FAILED;
+    }
+
+    // Apparently there is no writeonly - we might get the write-copy mode to work, though.
+    DWORD flProtect = PROT_NONE;
+    if (prot & PROT_READ) {
+        if (prot & PROT_WRITE) {
+            if (prot & PROT_EXEC) {
+                if (flags & MAP_PRIVATE)
+                    flProtect = PAGE_EXECUTE_WRITECOPY;
+                else
+                    flProtect = PAGE_EXECUTE_READWRITE;
+            } else {
+                if (flags & MAP_PRIVATE)
+                    flProtect = PAGE_WRITECOPY;
+                else
+                    flProtect = PAGE_READWRITE;
+            }
+        } else if (prot & PROT_EXEC) {
+            flProtect = PAGE_EXECUTE_READ;
+        }
+    } else if (prot & PROT_EXEC) {
+        flProtect = PAGE_EXECUTE;
+    } else {
+        errno = EPERM;
+        return MAP_FAILED;
+    }
+
+    HANDLE fileMapping = CreateFileMapping(file, NULL, flProtect, 0, 0, NULL);
+    if (fileMapping == NULL) {
+        errno = EINVAL; // windows docs say this happens on disk full. EINVAL is close enough.
+        return MAP_FAILED;
+    }
+
+    // you can only have either read-only, read-write, copy-on-write access. Either can be combined
+    // with exec. We try to map the given flags and prot parameters as best as we can.
+    DWORD access = 0;
+    if (flags & MAP_PRIVATE)
+        access |= FILE_MAP_COPY;
+    else if (prot & PROT_WRITE)
+        access |= FILE_MAP_WRITE;
+    else
+        access |= FILE_MAP_READ;
+
+    if (prot & PROT_EXEC)
+        access |= FILE_MAP_EXECUTE;
+
+
+    void *viewMapping = MapViewOfFileEx(fileMapping, access, 0, offset, length, addr);
+    CloseHandle(fileMapping);
+
+    if (viewMapping == NULL) {
+        errno = EINVAL;
+        return MAP_FAILED;
+    }
+
+    return viewMapping;
+}
+
+int munmap(void *addr, size_t length) {
+    // We cannot honor length here. We just unmap everything
+    // That is enough for elfutils, though.
+    (void) length;
+
+    if (UnmapViewOfFile(addr))
+        return 0;
+
+    errno = EINVAL;
+    return -1;
+}
+
+int msync(void *addr, size_t length, int flags) {
+    (void) flags;
+
+    if (FlushViewOfFile(addr, length))
+        return 0;
+
+    errno = EINVAL;
+    return -1;
+}
+
+int posix_madvise(void *addr, size_t len, int advice)
+{
+    (void) addr;
+    (void) len;
+    (void) advice;
+    return 0;
+}
+
+int mprotect(void *addr, size_t len, int prot)
+{
+    (void) addr;
+    (void) len;
+    (void) prot;
+    errno = EACCES;
+    return -1;
+}
diff --git a/libgnu/sys_mman.win32.h b/libgnu/sys_mman.win32.h
new file mode 100644
index 0000000..9ad54af
--- /dev/null
+++ b/libgnu/sys_mman.win32.h
@@ -0,0 +1,63 @@
+/* Replacement for mmap(2) and friends on windows
+   Copyright (C) 2017 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LIB_SYS_MMAN_H
+#define LIB_SYS_MMAN_H
+
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define PROT_NONE    0x00
+#define PROT_READ    0x04
+#define PROT_WRITE   0x02
+#define PROT_EXEC    0x01
+
+#define MAP_FAILED  ((void *) -1)
+
+#define MAP_SHARED   0x01
+#define MAP_PRIVATE  0x02
+#define MAP_FIXED    0x10
+
+#define MS_ASYNC      1
+#define MS_INVALIDATE 2
+#define MS_SYNC       4
+
+#define POSIX_MADV_NORMAL     0
+#define POSIX_MADV_SEQUENTIAL 1
+#define POSIX_MADV_RANDOM     2
+#define POSIX_MADV_WILLNEED   3
+#define POSIX_MADV_DONTNEED   4
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
+int munmap(void *addr, size_t length);
+int msync(void *addr, size_t length, int flags);
+int posix_madvise(void *addr, size_t len, int advice);
+int mprotect(void *addr, size_t len, int prot);
+
+#endif // MMAN_H
-- 
2.1.4



More information about the Elfutils-devel mailing list