source: trunk/kLdr/kLdrHlpMem.c@ 3232

Last change on this file since 3232 was 2944, checked in by bird, 19 years ago

split up kLdrHlp.c and kLdr.c to make it more flexible (like using the module interpreters without the dynamic loader bit and similar).

  • Property svn:keywords set to Id
File size: 8.0 KB
RevLine 
[2944]1/* $Id: kLdrHlpMem.c 2944 2007-01-13 15:55:40Z 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 <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 size_t 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(KLDRPROT enmProt)
67{
68 switch (enmProt)
69 {
70 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
71 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ;
72 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
73 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
74 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
75 case KLDRPROT_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(KLDRPROT enmProt)
83{
84 switch (enmProt)
85 {
86 case KLDRPROT_NOACCESS: return PAGE_NOACCESS;
87 case KLDRPROT_READONLY: return PAGE_READONLY;
88 case KLDRPROT_READWRITE: return PAGE_READWRITE;
89 case KLDRPROT_EXECUTE: return PAGE_EXECUTE;
90 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
91 case KLDRPROT_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, size_t cb, KLDRPROT 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, size_t cb, KLDRPROT 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 *)((uintptr_t)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, size_t cb)
218{
219#ifdef __OS2__
220 APIRET rc;
221
222 /*
223 * Deal with any portion overlapping with the stub.
224 */
225 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
226 if (offStub < g_cbStub)
227 {
228 /* decommit the pages in the stub. */
229 size_t cbStub = KLDR_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 *)((uintptr_t)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 *)((uintptr_t)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.