source: trunk/kStuff/kLdr/kLdrHlpMem.c@ 3571

Last change on this file since 3571 was 3571, checked in by bird, 18 years ago

Eliminated KLDRPROT.

  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1/* $Id: kLdrHlpMem.c 3571 2007-08-31 02:39:26Z bird $ */
2/** @file
3 *
4 * kLdr - The Dynamic Loader, Memory Helper Functions.
5 *
6 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifdef __OS2__
32# define INCL_BASE
33# define INCL_ERRORS
34# include <os2.h>
35#elif defined(__WIN__)
36# include <Windows.h>
37#else
38# error "port me"
39#endif
40
41#include <k/kLdr.h>
42#include "kLdrHlp.h"
43
44
45/*******************************************************************************
46* Global Variables *
47*******************************************************************************/
48#ifdef __OS2__
49/** The base of the stub object.
50 * The OS/2 exe stub consists of a single data object. When allocating memory
51 * for an executable, we'll have to reuse this. */
52static void *g_pvStub = NULL;
53/** The size of the stub object - 0 if no stub. */
54static KSIZE g_cbStub = 0;
55
56#elif defined(__WIN__)
57/** The system info. */
58static SYSTEM_INFO g_SystemInfo;
59#else
60# error "port me"
61#endif
62
63
64
65#ifdef __OS2__
66static ULONG kldrHlpPageProtToNative(KPROT enmProt)
67{
68 switch (enmProt)
69 {
70 case KPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
71 case KPROT_READONLY: return PAG_COMMIT | PAG_READ;
72 case KPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
73 case KPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
74 case KPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
75 case KPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
76 default:
77 kldrHlpAssert(0);
78 return ~0U;
79 }
80}
81#elif defined(__WIN__)
82static DWORD kldrHlpPageProtToNative(KPROT enmProt)
83{
84 switch (enmProt)
85 {
86 case KPROT_NOACCESS: return PAGE_NOACCESS;
87 case KPROT_READONLY: return PAGE_READONLY;
88 case KPROT_READWRITE: return PAGE_READWRITE;
89 case KPROT_EXECUTE: return PAGE_EXECUTE;
90 case KPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
91 case KPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
92 default:
93 kldrHlpAssert(0);
94 return ~0U;
95 }
96}
97#endif
98
99
100/**
101 * Allocate a chunk of memory with page granularity.
102 *
103 * @returns 0 on success, non-zero OS status code on failure.
104 * @param ppv Where to store the address of the allocated memory.
105 * If fFixed is set, *ppv will on entry contain the desired address (page aligned).
106 * @param cb Number of bytes. Page aligned.
107 * @param enmProt The new protection. Copy-on-write is invalid.
108 */
109int kldrHlpPageAlloc(void **ppv, KSIZE cb, KPROT enmProt, unsigned fFixed)
110{
111#ifdef __OS2__
112 APIRET rc;
113 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
114
115 if (!fFixed)
116 {
117 /* simple */
118 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
119 if (rc == ERROR_INVALID_PARAMETER)
120 rc = DosAllocMem(ppv, cb, fFlags);
121 }
122 else
123 {
124 /* not so simple. */
125 /** @todo I've got code for this in libc somewhere. */
126 rc = -1;
127 }
128 if (!rc)
129 return 0;
130 kldrHlpAssert(0);
131 return rc;
132
133#elif defined(__WIN__)
134 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
135 int rc;
136 DWORD fProt = kldrHlpPageProtToNative(enmProt);
137
138 if (!g_SystemInfo.dwPageSize)
139 GetSystemInfo(&g_SystemInfo);
140
141 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
142 if (*ppv != NULL)
143 return 0;
144 rc = GetLastError();
145 kldrHlpAssert(0);
146 return rc;
147
148#else
149# error "port me"
150#endif
151}
152
153
154/**
155 * Change the protection of one or more pages in an allocation.
156 *
157 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
158 *
159 * @returns 0 on success, non-zero OS status code on failure.
160 * @param pv First page. Page aligned.
161 * @param cb Number of bytes. Page aligned.
162 * @param enmProt The new protection. Copy-on-write is invalid.
163 */
164int kldrHlpPageProtect(void *pv, KSIZE cb, KPROT enmProt)
165{
166#ifdef __OS2__
167 APIRET rc;
168 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
169
170 /*
171 * The non-stub pages.
172 */
173 rc = DosSetMem(pv, cb, fFlags);
174 if (rc && fFlags != PAG_DECOMMIT)
175 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
176 if (rc)
177 {
178 /* Try page by page. */
179 while (cb > 0)
180 {
181 rc = DosSetMem(pv, 0x1000, fFlags);
182 if (rc && fFlags != PAG_DECOMMIT)
183 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
184 if (rc)
185 return rc;
186 pv = (void *)((KUPTR)pv + 0x1000);
187 cb -= 0x1000;
188 }
189 }
190 kldrHlpAssert(!rc);
191 return rc;
192
193#elif defined(__WIN__)
194 DWORD fOldProt = 0;
195 DWORD fProt = kldrHlpPageProtToNative(enmProt);
196 int rc = 0;
197
198 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
199 {
200 rc = GetLastError();
201 kldrHlpAssert(0);
202 }
203 return rc;
204#else
205# error "port me"
206#endif
207}
208
209
210/**
211 * Free memory allocated by kldrHlpPageAlloc().
212 *
213 * @returns 0 on success, non-zero OS status code on failure.
214 * @param pv The address returned by kldrHlpPageAlloc().
215 * @param cb The byte count requested from kldrHlpPageAlloc().
216 */
217int kldrHlpPageFree(void *pv, KSIZE cb)
218{
219#ifdef __OS2__
220 APIRET rc;
221
222 /*
223 * Deal with any portion overlapping with the stub.
224 */
225 KUPTR offStub = (KUPTR)pv - (KUPTR)g_pvStub;
226 if (offStub < g_cbStub)
227 {
228 /* decommit the pages in the stub. */
229 KSIZE cbStub = K_MIN(g_cbStub - offStub, cb);
230 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
231 if (rc)
232 {
233 /* Page by page, ignoring errors after the first success. */
234 while (cbStub > 0)
235 {
236 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
237 rc = 0;
238 pv = (void *)((KUPTR)pv + 0x1000);
239 cbStub -= 0x1000;
240 cb -= 0x1000;
241 }
242 if (rc)
243 {
244 kldrHlpAssert(!rc);
245 return rc;
246 }
247 }
248 else
249 {
250 cb -= cbStub;
251 if (!cb)
252 return 0;
253 pv = (void *)((KUPTR)pv + cbStub);
254 }
255 }
256
257 /*
258 * Free the object.
259 */
260 rc = DosFreeMem(pv);
261 kldrHlpAssert(!rc);
262 return rc;
263
264#elif defined(__WIN__)
265 /*
266 * Free the object.
267 */
268 int rc = 0;
269 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
270 {
271 rc = GetLastError();
272 kldrHlpAssert(0);
273 }
274 return rc;
275
276#else
277# error "port me"
278#endif
279}
280
Note: See TracBrowser for help on using the repository browser.