diff options
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | libgnu/Makefile.am | 17 | ||||
-rw-r--r-- | libgnu/mman_win32.c | 140 | ||||
-rw-r--r-- | libgnu/sys_mman.win32.h | 63 |
4 files changed, 226 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 1e6c8442..6a2f991c 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 37fdb9ca..5af121af 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 00000000..78966c2e --- /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 00000000..9ad54af5 --- /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 |