From 1844ecdb7752237df3db1f7996696c3b971485dc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 27 Mar 2017 10:19:10 +0200 Subject: Add mman.h/.c for win32 Change-Id: If9f591124799c680c8606772a9b733314eb19b41 Reviewed-by: Christian Kandeler --- libgnu/Makefile.am | 17 +++++- libgnu/mman_win32.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ libgnu/sys_mman.win32.h | 63 ++++++++++++++++++++++ 3 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 libgnu/mman_win32.c create mode 100644 libgnu/sys_mman.win32.h (limited to 'libgnu') 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 . */ + +#include +#include +#include +#include + +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 . */ + +#ifndef LIB_SYS_MMAN_H +#define LIB_SYS_MMAN_H + +#include +#include +#include + +#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 -- cgit v1.2.3