VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win32/alloc-win32.cpp@ 4015

Last change on this file since 4015 was 2981, checked in by vboxsync, 17 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1/* $Id: alloc-win32.cpp 2981 2007-06-01 16:01:28Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Memory Allocation, Win32.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP RTLOGGROUP_MEM
27#include <Windows.h>
28
29#include <iprt/alloc.h>
30#include <iprt/assert.h>
31#include <iprt/param.h>
32#include <iprt/string.h>
33#include <iprt/err.h>
34
35#ifndef USE_VIRTUAL_ALLOC
36# include <malloc.h>
37#endif
38
39
40/**
41 * Allocates memory which may contain code.
42 *
43 * @returns Pointer to the allocated memory.
44 * @returns NULL on failure.
45 * @param cb Size in bytes of the memory block to allocate.
46 */
47RTDECL(void *) RTMemExecAlloc(size_t cb)
48{
49 /*
50 * Allocate first.
51 */
52 AssertMsg(cb, ("Allocating ZERO bytes is really not a good idea! Good luck with the next assertion!\n"));
53 cb = RT_ALIGN_Z(cb, 32);
54 void *pv = malloc(cb);
55 AssertMsg(pv, ("malloc(%d) failed!!!\n", cb));
56 if (pv)
57 {
58 /*
59 * Add PROT_EXEC flag to the page.
60 *
61 * This is in violation of the SuS where I think it saith that mprotect() shall
62 * only be used with mmap()'ed memory. Works on linux and OS/2 LIBC v0.6.
63 */
64 memset(pv, 0xcc, cb);
65 void *pvProt = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
66 size_t cbProt = ((uintptr_t)pv & PAGE_OFFSET_MASK) + cb;
67 cbProt = RT_ALIGN_Z(cbProt, PAGE_SIZE);
68 DWORD fFlags = 0;
69 if (!VirtualProtect(pvProt, cbProt, PAGE_EXECUTE_READWRITE, &fFlags))
70 {
71 AssertMsgFailed(("VirtualProtect(%p, %#x,,) -> lasterr=%d\n", pvProt, cbProt, GetLastError()));
72 free(pv);
73 pv = NULL;
74 }
75 }
76 return pv;
77}
78
79
80/**
81 * Free executable/read/write memory allocated by RTMemExecAlloc().
82 *
83 * @param pv Pointer to memory block.
84 */
85RTDECL(void) RTMemExecFree(void *pv)
86{
87 if (pv)
88 free(pv);
89}
90
91
92/**
93 * Allocate page aligned memory.
94 *
95 * @returns Pointer to the allocated memory.
96 * @returns NULL if we're out of memory.
97 * @param cb Size of the memory block. Will be rounded up to page size.
98 */
99RTDECL(void *) RTMemPageAlloc(size_t cb)
100{
101#ifdef USE_VIRTUAL_ALLOC
102 void *pv = VirtualAlloc(NULL, RT_ALIGN_Z(cb, PAGE_SIZE), MEM_COMMIT, PAGE_READWRITE);
103#else
104 void *pv = _aligned_malloc(cb, PAGE_SIZE);
105#endif
106 AssertMsg(pv, ("cb=%d lasterr=%d\n", cb, GetLastError()));
107 return pv;
108}
109
110
111/**
112 * Allocate zero'ed page aligned memory.
113 *
114 * @returns Pointer to the allocated memory.
115 * @returns NULL if we're out of memory.
116 * @param cb Size of the memory block. Will be rounded up to page size.
117 */
118RTDECL(void *) RTMemPageAllocZ(size_t cb)
119{
120#ifdef USE_VIRTUAL_ALLOC
121 void *pv = VirtualAlloc(NULL, RT_ALIGN_Z(cb, PAGE_SIZE), MEM_COMMIT, PAGE_READWRITE);
122#else
123 void *pv = _aligned_malloc(cb, PAGE_SIZE);
124#endif
125 if (pv)
126 {
127 memset(pv, 0, RT_ALIGN_Z(cb, PAGE_SIZE));
128 return pv;
129 }
130 AssertMsgFailed(("cb=%d lasterr=%d\n", cb, GetLastError()));
131 return NULL;
132}
133
134
135/**
136 * Free a memory block allocated with RTMemPageAlloc() or RTMemPageAllocZ().
137 *
138 * @param pv Pointer to the block as it was returned by the allocation function.
139 * NULL will be ignored.
140 */
141RTDECL(void) RTMemPageFree(void *pv)
142{
143 if (pv)
144 {
145#ifdef USE_VIRTUAL_ALLOC
146 if (!VirtualFree(pv, 0, MEM_RELEASE))
147 AssertMsgFailed(("pv=%p lasterr=%d\n", pv, GetLastError()));
148#else
149 _aligned_free(pv);
150#endif
151 }
152}
153
154
155/**
156 * Change the page level protection of a memory region.
157 *
158 * @returns iprt status code.
159 * @param pv Start of the region. Will be rounded down to nearest page boundary.
160 * @param cb Size of the region. Will be rounded up to the nearest page boundary.
161 * @param fProtect The new protection, a combination of the RTMEM_PROT_* defines.
162 */
163RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect)
164{
165 /*
166 * Validate input.
167 */
168 if (cb == 0)
169 {
170 AssertMsgFailed(("!cb\n"));
171 return VERR_INVALID_PARAMETER;
172 }
173 if (fProtect & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC))
174 {
175 AssertMsgFailed(("fProtect=%#x\n", fProtect));
176 return VERR_INVALID_PARAMETER;
177 }
178
179 /*
180 * Convert the flags.
181 */
182 int fProt;
183 Assert(!RTMEM_PROT_NONE);
184 switch (fProtect & (RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC))
185 {
186 case RTMEM_PROT_NONE:
187 fProt = PAGE_NOACCESS;
188 break;
189
190 case RTMEM_PROT_READ:
191 fProt = PAGE_READONLY;
192 break;
193
194 case RTMEM_PROT_READ | RTMEM_PROT_WRITE:
195 fProt = PAGE_READWRITE;
196 break;
197
198 case RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC:
199 fProt = PAGE_EXECUTE_READWRITE;
200 break;
201
202 case RTMEM_PROT_READ | RTMEM_PROT_EXEC:
203 fProt = PAGE_EXECUTE_READWRITE;
204 break;
205
206 case RTMEM_PROT_WRITE:
207 fProt = PAGE_READWRITE;
208 break;
209
210 case RTMEM_PROT_WRITE | RTMEM_PROT_EXEC:
211 fProt = PAGE_EXECUTE_READWRITE;
212 break;
213
214 case RTMEM_PROT_EXEC:
215 fProt = PAGE_EXECUTE_READWRITE;
216 break;
217
218 /* If the compiler had any brains it would warn about this case. */
219 default:
220 AssertMsgFailed(("fProtect=%#x\n", fProtect));
221 return VERR_INTERNAL_ERROR;
222 }
223
224 /*
225 * Align the request.
226 */
227 cb += (uintptr_t)pv & PAGE_OFFSET_MASK;
228 pv = (void *)((uintptr_t)pv & ~PAGE_OFFSET_MASK);
229
230 /*
231 * Change the page attributes.
232 */
233 DWORD fFlags = 0;
234 if (VirtualProtect(pv, cb, fProt, &fFlags))
235 return VINF_SUCCESS;
236 return RTErrConvertFromWin32(GetLastError());
237}
238
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette