3 * Windows support for mapping code into the process address space
6 * Mono Team (mono-list@lists.ximian.com)
8 * Copyright 2001-2008 Novell, Inc.
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #if defined(HOST_WIN32)
17 #include "mono/utils/mono-mmap-windows-internals.h"
18 #include <mono/utils/mono-counters.h>
21 static void *malloced_shared_area
;
27 static int saved_pagesize
= 0;
29 return saved_pagesize
;
30 GetSystemInfo (&info
);
31 saved_pagesize
= info
.dwPageSize
;
32 return saved_pagesize
;
36 mono_valloc_granule (void)
39 static int saved_valloc_granule
= 0;
40 if (saved_valloc_granule
)
41 return saved_valloc_granule
;
42 GetSystemInfo (&info
);
43 saved_valloc_granule
= info
.dwAllocationGranularity
;
44 return saved_valloc_granule
;
48 mono_mmap_win_prot_from_flags (int flags
)
50 int prot
= flags
& (MONO_MMAP_READ
|MONO_MMAP_WRITE
|MONO_MMAP_EXEC
);
52 case 0: prot
= PAGE_NOACCESS
; break;
53 case MONO_MMAP_READ
: prot
= PAGE_READONLY
; break;
54 case MONO_MMAP_READ
|MONO_MMAP_EXEC
: prot
= PAGE_EXECUTE_READ
; break;
55 case MONO_MMAP_READ
|MONO_MMAP_WRITE
: prot
= PAGE_READWRITE
; break;
56 case MONO_MMAP_READ
|MONO_MMAP_WRITE
|MONO_MMAP_EXEC
: prot
= PAGE_EXECUTE_READWRITE
; break;
57 case MONO_MMAP_WRITE
: prot
= PAGE_READWRITE
; break;
58 case MONO_MMAP_WRITE
|MONO_MMAP_EXEC
: prot
= PAGE_EXECUTE_READWRITE
; break;
59 case MONO_MMAP_EXEC
: prot
= PAGE_EXECUTE
; break;
61 g_assert_not_reached ();
68 * \param flag indicating whether to enable or disable the use of MAP_JIT in mmap
70 * Call this method to enable or disable the use of MAP_JIT to create the pages
71 * for the JIT to use. This is only needed for scenarios where Mono is bundled
75 mono_setmmapjit (int flag
)
77 /* Ignored on HOST_WIN32 */
81 mono_valloc (void *addr
, size_t length
, int flags
, MonoMemAccountType type
)
83 if (!mono_valloc_can_alloc (length
))
87 int mflags
= MEM_RESERVE
|MEM_COMMIT
;
88 int prot
= mono_mmap_win_prot_from_flags (flags
);
89 /* translate the flags */
91 ptr
= VirtualAlloc (addr
, length
, mflags
, prot
);
93 mono_account_mem (type
, (ssize_t
)length
);
99 mono_valloc_aligned (size_t length
, size_t alignment
, int flags
, MonoMemAccountType type
)
101 int prot
= mono_mmap_win_prot_from_flags (flags
);
102 char *mem
= (char*)VirtualAlloc (NULL
, length
+ alignment
, MEM_RESERVE
, prot
);
108 if (!mono_valloc_can_alloc (length
))
111 aligned
= mono_aligned_address (mem
, length
, alignment
);
113 aligned
= (char*)VirtualAlloc (aligned
, length
, MEM_COMMIT
, prot
);
116 mono_account_mem (type
, (ssize_t
)length
);
122 mono_vfree (void *addr
, size_t length
, MonoMemAccountType type
)
124 MEMORY_BASIC_INFORMATION mbi
;
125 SIZE_T query_result
= VirtualQuery (addr
, &mbi
, sizeof (mbi
));
128 g_assert (query_result
);
130 res
= VirtualFree (mbi
.AllocationBase
, 0, MEM_RELEASE
);
134 mono_account_mem (type
, -(ssize_t
)length
);
139 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) || G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
142 remove_trailing_whitespace_utf16 (wchar_t *s
)
144 gsize length
= wcslen (s
);
145 gsize
const original_length
= length
;
146 while (length
> 0 && iswspace (s
[length
- 1]))
148 if (length
!= original_length
)
153 mono_file_map_error (size_t length
, int flags
, int fd
, guint64 offset
, void **ret_handle
,
154 const char *filepath
, char **error_message
)
157 HANDLE mapping
= NULL
;
158 int const prot
= mono_mmap_win_prot_from_flags (flags
);
159 /* translate the flags */
160 /*if (flags & MONO_MMAP_PRIVATE)
161 mflags |= MAP_PRIVATE;
162 if (flags & MONO_MMAP_SHARED)
163 mflags |= MAP_SHARED;
164 if (flags & MONO_MMAP_ANON)
165 mflags |= MAP_ANONYMOUS;
166 if (flags & MONO_MMAP_FIXED)
168 if (flags & MONO_MMAP_32BIT)
169 mflags |= MAP_32BIT;*/
170 int const mflags
= (flags
& MONO_MMAP_WRITE
) ? FILE_MAP_COPY
: FILE_MAP_READ
;
171 HANDLE
const file
= (HANDLE
)_get_osfhandle (fd
);
172 const char *failed_function
= NULL
;
174 // The size of the mapping is the maximum file offset to map.
176 // It is not, as you might expect, the maximum view size to be mapped from it.
178 // If it were the maximum view size, the size parameter would have just
179 // been one DWORD in 32bit Windows, expanded to SIZE_T in 64bit Windows.
180 // It is 64bits even on 32bit Windows to allow large files.
182 // See https://docs.microsoft.com/en-us/windows/desktop/Memory/creating-a-file-mapping-object.
183 const guint64 mapping_length
= offset
+ length
;
185 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
187 failed_function
= "CreateFileMapping";
188 mapping
= CreateFileMappingW (file
, NULL
, prot
, (DWORD
)(mapping_length
>> 32), (DWORD
)mapping_length
, NULL
);
192 failed_function
= "MapViewOfFile";
193 ptr
= MapViewOfFile (mapping
, mflags
, (DWORD
)(offset
>> 32), (DWORD
)offset
, length
);
197 #elif G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
199 failed_function
= "CreateFileMappingFromApp";
200 mapping
= CreateFileMappingFromApp (file
, NULL
, prot
, mapping_length
, NULL
);
204 failed_function
= "MapViewOfFileFromApp";
205 ptr
= MapViewOfFileFromApp (mapping
, mflags
, offset
, length
);
210 #error unknown Windows variant
214 if (!ptr
&& (mapping
|| error_message
)) {
215 int const win32_error
= GetLastError ();
217 CloseHandle (mapping
);
219 WCHAR win32_error_string
[100] = { 0 }; // FIXME LocalFree not initially in UWP but it is now.
220 FormatMessageW (FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_SYSTEM
,
221 0, win32_error
, 0, win32_error_string
, 99, NULL
);
222 // Win32 error messages end with an unsightly newline.
223 remove_trailing_whitespace_utf16 (win32_error_string
);
224 *error_message
= g_strdup_printf ("%s failed file:%s length:0x%IX offset:0x%I64X function:%s error:%ls(0x%X)\n",
225 __func__
, filepath
? filepath
: "", length
, offset
, failed_function
, win32_error_string
, win32_error
);
227 SetLastError (win32_error
);
229 *ret_handle
= mapping
;
234 mono_file_map (size_t length
, int flags
, int fd
, guint64 offset
, void **ret_handle
)
236 return mono_file_map_error (length
, flags
, fd
, offset
, ret_handle
, NULL
, NULL
);
240 mono_file_unmap (void *addr
, void *handle
)
242 UnmapViewOfFile (addr
);
243 CloseHandle (handle
);
247 #endif // G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) || G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
250 mono_mprotect (void *addr
, size_t length
, int flags
)
253 int prot
= mono_mmap_win_prot_from_flags (flags
);
255 if (flags
& MONO_MMAP_DISCARD
) {
256 VirtualFree (addr
, length
, MEM_DECOMMIT
);
257 VirtualAlloc (addr
, length
, MEM_COMMIT
, prot
);
260 return VirtualProtect (addr
, length
, prot
, &oldprot
) == 0;
264 mono_shared_area (void)
266 if (!malloced_shared_area
)
267 malloced_shared_area
= mono_malloc_shared_area (0);
268 /* get the pid here */
269 return malloced_shared_area
;
273 mono_shared_area_remove (void)
275 if (malloced_shared_area
)
276 g_free (malloced_shared_area
);
277 malloced_shared_area
= NULL
;
281 mono_shared_area_for_pid (void *pid
)
287 mono_shared_area_unload (void *area
)
292 mono_shared_area_instances (void **array
, int count
)