1 /*
2  * This code is derived from uClibc (original license follows).
3  * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c
4  */
5  /* mmap() replacement for Windows
6  *
7  * Author: Mike Frysinger <[email protected]>
8  * Placed into the public domain
9  */
10 
11 /* References:
12  * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
13  * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
14  * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
15  * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
16  */
17 
18 #if defined(_WIN32)
19 
20 #include "WindowsMMap.h"
21 #include "InstrProfiling.h"
22 
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 
26 #ifdef __USE_FILE_OFFSET64
27 # define DWORD_HI(x) (x >> 32)
28 # define DWORD_LO(x) ((x) & 0xffffffff)
29 #else
30 # define DWORD_HI(x) (0)
31 # define DWORD_LO(x) (x)
32 #endif
33 
34 COMPILER_RT_VISIBILITY
35 void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
36 {
37   if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
38     return MAP_FAILED;
39   if (fd == -1) {
40     if (!(flags & MAP_ANON) || offset)
41       return MAP_FAILED;
42   } else if (flags & MAP_ANON)
43     return MAP_FAILED;
44 
45   DWORD flProtect;
46   if (prot & PROT_WRITE) {
47     if (prot & PROT_EXEC)
48       flProtect = PAGE_EXECUTE_READWRITE;
49     else
50       flProtect = PAGE_READWRITE;
51   } else if (prot & PROT_EXEC) {
52     if (prot & PROT_READ)
53       flProtect = PAGE_EXECUTE_READ;
54     else if (prot & PROT_EXEC)
55       flProtect = PAGE_EXECUTE;
56   } else
57     flProtect = PAGE_READONLY;
58 
59   off_t end = length + offset;
60   HANDLE mmap_fd, h;
61   if (fd == -1)
62     mmap_fd = INVALID_HANDLE_VALUE;
63   else
64     mmap_fd = (HANDLE)_get_osfhandle(fd);
65   h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
66   if (h == NULL)
67     return MAP_FAILED;
68 
69   DWORD dwDesiredAccess;
70   if (prot & PROT_WRITE)
71     dwDesiredAccess = FILE_MAP_WRITE;
72   else
73     dwDesiredAccess = FILE_MAP_READ;
74   if (prot & PROT_EXEC)
75     dwDesiredAccess |= FILE_MAP_EXECUTE;
76   if (flags & MAP_PRIVATE)
77     dwDesiredAccess |= FILE_MAP_COPY;
78   void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
79   if (ret == NULL) {
80     CloseHandle(h);
81     ret = MAP_FAILED;
82   }
83   return ret;
84 }
85 
86 COMPILER_RT_VISIBILITY
87 void munmap(void *addr, size_t length)
88 {
89   UnmapViewOfFile(addr);
90   /* ruh-ro, we leaked handle from CreateFileMapping() ... */
91 }
92 
93 COMPILER_RT_VISIBILITY
94 int msync(void *addr, size_t length, int flags)
95 {
96   if (flags & MS_INVALIDATE)
97     return -1; /* Not supported. */
98 
99   /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
100   switch (flags & (MS_ASYNC | MS_SYNC)) {
101     case MS_SYNC:
102     case MS_ASYNC:
103       break;
104     default:
105       return -1;
106   }
107 
108   if (!FlushViewOfFile(addr, length))
109     return -1;
110 
111   if (flags & MS_SYNC) {
112     /* FIXME: No longer have access to handle from CreateFileMapping(). */
113     /*
114      * if (!FlushFileBuffers(h))
115      *   return -1;
116      */
117   }
118 
119   return 0;
120 }
121 
122 COMPILER_RT_VISIBILITY
123 int flock(int fd, int operation)
124 {
125   return -1; /* Not supported. */
126 }
127 
128 #undef DWORD_HI
129 #undef DWORD_LO
130 
131 #endif /* _WIN32 */
132