/** * \file * Windows support for mapping code into the process address space * * Author: * Mono Team (mono-list@lists.ximian.com) * * Copyright 2001-2008 Novell, Inc. * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include #include #if defined(HOST_WIN32) #include #include "mono/utils/mono-mmap-windows-internals.h" #include #include static void *malloced_shared_area = NULL; int mono_pagesize (void) { SYSTEM_INFO info; static int saved_pagesize = 0; if (saved_pagesize) return saved_pagesize; GetSystemInfo (&info); saved_pagesize = info.dwPageSize; return saved_pagesize; } int mono_valloc_granule (void) { SYSTEM_INFO info; static int saved_valloc_granule = 0; if (saved_valloc_granule) return saved_valloc_granule; GetSystemInfo (&info); saved_valloc_granule = info.dwAllocationGranularity; return saved_valloc_granule; } int mono_mmap_win_prot_from_flags (int flags) { int prot = flags & (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC); switch (prot) { case 0: prot = PAGE_NOACCESS; break; case MONO_MMAP_READ: prot = PAGE_READONLY; break; case MONO_MMAP_READ|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READ; break; case MONO_MMAP_READ|MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; case MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; case MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; case MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; case MONO_MMAP_EXEC: prot = PAGE_EXECUTE; break; default: g_assert_not_reached (); } return prot; } void* mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type) { void *ptr; int mflags = MEM_RESERVE|MEM_COMMIT; int prot = mono_mmap_win_prot_from_flags (flags); /* translate the flags */ if (!mono_valloc_can_alloc (length)) return NULL; ptr = VirtualAlloc (addr, length, mflags, prot); account_mem (type, (ssize_t)length); return ptr; } void* mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type) { int prot = mono_mmap_win_prot_from_flags (flags); char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot); char *aligned; if (!mem) return NULL; if (!mono_valloc_can_alloc (length)) return NULL; aligned = aligned_address (mem, length, alignment); aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot); g_assert (aligned); account_mem (type, (ssize_t)length); return aligned; } int mono_vfree (void *addr, size_t length, MonoMemAccountType type) { MEMORY_BASIC_INFORMATION mbi; SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi)); BOOL res; g_assert (query_result); res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE); g_assert (res); account_mem (type, -(ssize_t)length); return 0; } #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) void* mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle) { void *ptr; int mflags = 0; HANDLE file, mapping; int prot = mono_mmap_win_prot_from_flags (flags); /* translate the flags */ /*if (flags & MONO_MMAP_PRIVATE) mflags |= MAP_PRIVATE; if (flags & MONO_MMAP_SHARED) mflags |= MAP_SHARED; if (flags & MONO_MMAP_ANON) mflags |= MAP_ANONYMOUS; if (flags & MONO_MMAP_FIXED) mflags |= MAP_FIXED; if (flags & MONO_MMAP_32BIT) mflags |= MAP_32BIT;*/ mflags = FILE_MAP_READ; if (flags & MONO_MMAP_WRITE) mflags = FILE_MAP_COPY; file = (HANDLE) _get_osfhandle (fd); mapping = CreateFileMapping (file, NULL, prot, 0, 0, NULL); if (mapping == NULL) return NULL; ptr = MapViewOfFile (mapping, mflags, 0, offset, length); if (ptr == NULL) { CloseHandle (mapping); return NULL; } *ret_handle = (void*)mapping; return ptr; } int mono_file_unmap (void *addr, void *handle) { UnmapViewOfFile (addr); CloseHandle ((HANDLE)handle); return 0; } #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ int mono_mprotect (void *addr, size_t length, int flags) { DWORD oldprot; int prot = mono_mmap_win_prot_from_flags (flags); if (flags & MONO_MMAP_DISCARD) { VirtualFree (addr, length, MEM_DECOMMIT); VirtualAlloc (addr, length, MEM_COMMIT, prot); return 0; } return VirtualProtect (addr, length, prot, &oldprot) == 0; } void* mono_shared_area (void) { if (!malloced_shared_area) malloced_shared_area = malloc_shared_area (0); /* get the pid here */ return malloced_shared_area; } void mono_shared_area_remove (void) { if (malloced_shared_area) g_free (malloced_shared_area); malloced_shared_area = NULL; } void* mono_shared_area_for_pid (void *pid) { return NULL; } void mono_shared_area_unload (void *area) { } int mono_shared_area_instances (void **array, int count) { return 0; } #endif