source: trunk/nom/src/nomgc.c@ 286

Last change on this file since 286 was 286, checked in by cinc, 18 years ago

Fixed DLL registering with the GC. See ticket #7.

File size: 10.3 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2005-2006
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34
35/*
36 This file contains functions for working with the garbage collector.
37 */
38
39#define INCL_DOS
40#define INCL_DOSERRORS
41#define INCL_DOSMEMMGR
42#include <os2.h>
43
44#include <stdio.h>
45#include <string.h>
46#include <stdlib.h>
47
48/* For nomToken etc. */
49#include <nom.h>
50#include "nomtk.h"
51#include "nomgc.h"
52
53/* Garbage collector */
54#include <gc.h>
55
56gboolean bUseGC=FALSE; /* Mark if we use the garbage collector */
57GTree* treeRegisteredDLL;
58
59static gpointer gcMalloc(gulong ulBytes)
60{
61 //printf("Hi there...\n");
62 // return malloc(ulBytes);
63 return (gpointer) GC_malloc(ulBytes);
64}
65
66static gpointer gcRealloc(gpointer mem, gulong ulBytes)
67{
68 // printf("...and here\n");
69 // return realloc(mem, ulBytes);
70 return (gpointer) GC_realloc(mem, ulBytes);
71}
72
73static void gcFree(gpointer mem)
74{
75 // printf("free(): %x\n", mem);
76 return;
77 GC_free(mem);
78}
79
80
81/*
82 This is called from the EMX wrapper to set the garbage collector
83 memory functions as the GLIB default allocation function.
84 */
85void _System nomInitGarbageCollection(void* pMemInExe)
86{
87 GMemVTable vtbl={0};
88
89 /* Init the garbage collector */
90 GC_init();
91
92 vtbl.malloc=(gpointer)gcMalloc;
93 vtbl.realloc=(gpointer)gcRealloc;
94 vtbl.free=(gpointer)gcFree;
95
96 g_mem_set_vtable(&vtbl);
97 /* fprintf(stderr, " GC memory functions set for GLIB. (%s: %d)\n", __FILE__, __LINE__); */
98
99 /* Cretea tree holding the already registered DLLs */
100 treeRegisteredDLL=g_tree_new((GCompareFunc)stricmp);
101
102 bUseGC=TRUE;
103}
104
105
106void test()
107{
108 gulong ulObj, ulOffset;
109 gchar thePath[CCHMAXPATH];
110 HMODULE hModule;
111
112 if(DosQueryModFromEIP( &hModule, &ulObj, CCHMAXPATH, thePath, &ulOffset, (ULONG)test)!=0) {
113 hModule=0;
114 return ; /* Error */
115 }
116
117}
118
119NOMEXTERN void NOMLINK nomRegisterDataAreaForGC(char* pStart, char* pEnd)
120{
121 GC_add_roots(pStart, pEnd);
122}
123
124static void qsAddDLLToList(HREGDLL hReg, qsLrec_t* rec)
125{
126 if(NULLHANDLE==g_slist_find(hReg->dllList, rec))
127 hReg->dllList=g_slist_append(hReg->dllList, rec);
128}
129
130#if 0
131static void qsPrintDLLList(HREGDLL hReg)
132{
133 GSList* lTemp;
134 int a=0;
135
136 lTemp=hReg->dllList;
137 while(lTemp)
138 {
139 qsLrec_t* rec;
140 rec=(qsLrec_t*)lTemp->data;
141 a++;
142 g_message(" %d: %s", a, rec->pName);
143 lTemp=g_slist_next(lTemp);
144 }
145}
146#endif
147
148/**
149 Find a library record in the buffer filled by DosQuerySysState(). This function
150 searches in the list of all known libs, not in the process libs list.
151 */
152static qsLrec_t* qsFindModuleRec(const qsPtrRec_t * hRegisterDLL, USHORT hMod){
153 qsLrec_t * pModRec;
154 int a=0;
155
156 pModRec=hRegisterDLL->pLibRec;
157 while(NULL!=pModRec)
158 {
159 a++;
160 /* g_message("%d Checking: %x -> %04X (%s)", a, pModRec, pModRec->hmte, pModRec->pName); */
161
162 if (NULLHANDLE==pModRec->pObjInfo && pModRec->ctObj > 0)
163 {
164 pModRec->pObjInfo = (qsLObjrec_t*)((char*)pModRec
165 + ((sizeof(qsLrec_t)
166 + pModRec->ctImpMod * sizeof(short)
167 + strlen((char*)pModRec->pName) + 1 /* filename */
168 + 3) & ~3));
169 pModRec->pNextRec = (void*)((char*)pModRec->pObjInfo
170 + sizeof(qsLObjrec_t) * pModRec->ctObj);
171 }
172 if(pModRec->hmte==hMod)
173 break;
174
175 pModRec=(qsLrec_t *)pModRec->pNextRec;
176 }
177
178 return pModRec;
179}
180
181/**
182 Get the info about the current DLLs from OS/2. Go over all found
183 DLLs and insert them in a list. For all found DLLs go over the imports
184 of them and add them to the list etc. Duplicates are ignored.
185 */
186#define BUFSIZE 1024*1024
187NOMEXTERN HREGDLL NOMLINK nomBeginRegisterDLLWithGC(void)
188{
189 ULONG rc;
190 HREGDLL hReg=NULLHANDLE;
191 PTIB ptib;
192 PPIB ppib;
193 char * buf;
194 HREGDLL pRegDLL=NULLHANDLE;
195
196 rc = DosGetInfoBlocks(&ptib, &ppib);
197 if (rc!=NO_ERROR)
198 return NULLHANDLE;
199
200 buf = malloc(BUFSIZE);
201 if(!buf)
202 return NULLHANDLE;
203
204 pRegDLL =(HREGDLL) malloc(sizeof(REGDLL));
205 if(!pRegDLL){
206 free(buf);
207 return NULLHANDLE;
208 }
209 pRegDLL->dllList=NULLHANDLE;
210
211 memset(buf,0,BUFSIZE);
212
213 rc = DosQuerySysState(QS_PROCESS | QS_SEMAPHORE | QS_MTE | QS_FILESYS | QS_SHMEMORY ,
214 QS_MTE, /*0x96*/ ppib->pib_ulpid , 1UL, (PCHAR)buf, BUFSIZE);
215 if (rc==NO_ERROR) {
216 qsPrec_t * p;
217 GSList* lTemp;
218
219 pRegDLL->pMainAnchor=(qsPtrRec_t*) buf;
220
221 /* Pointer to process information */
222 p=pRegDLL->pMainAnchor->pProcRec;
223
224 while(p && p->RecType == 1)
225 {
226 qsLrec_t * pModRec; /* Info about a DLL */
227
228 /* Get record for executable */
229 pModRec=qsFindModuleRec(pRegDLL->pMainAnchor, p->hMte);
230 if(pModRec){
231 //if(pModRec->pName)
232 //g_message("exe) %s", pModRec->pName);
233 qsAddDLLToList(pRegDLL, pModRec);
234 }
235
236 if (p->cLib) { /* Number of lib imports */
237 int i;
238
239 for (i=0; i<p->cLib; i++){
240 pModRec=qsFindModuleRec(pRegDLL->pMainAnchor, p->pLibRec[i]);
241
242 if(pModRec){
243 //if(pModRec->pName)
244 //g_message("a) %s", pModRec->pName);
245 qsAddDLLToList(pRegDLL, pModRec);
246 }
247 }/* for() */
248 }/* if(p->clib) */
249 break;
250 };/* while() */
251
252 /* Ok, got directly imported DLLs. Now go over these and check them for additional imports.
253 Every import is added to the end of the list (except duplicates). So while going over
254 the list we touch every DLL and check every import. Import cycles are no problem, because
255 later duplicates are ignored. */
256 //g_message("\n\n");
257 lTemp=pRegDLL->dllList;
258 while(lTemp)
259 {
260 qsLrec_t* rec;
261
262 rec=(qsLrec_t*)lTemp->data;
263
264 /* Check the imports of this DLL if any */
265 if(rec->ctImpMod >0)
266 {
267 int iImps;
268 PUSHORT pImpHmte;
269
270 pImpHmte=(PUSHORT)((void*)rec + sizeof(qsLrec_t));
271 for(iImps=0; iImps < rec->ctImpMod; iImps++)
272 {
273 qsLrec_t * pModImp;
274
275 pModImp=qsFindModuleRec(pRegDLL->pMainAnchor, pImpHmte[iImps]);
276 if(pModImp){
277 //if(pModImp->pName)
278 //g_message("b) %s", pModImp->pName);
279 qsAddDLLToList(pRegDLL, pModImp);
280 }
281 }/* for()*/
282 }/* if() */
283 lTemp=g_slist_next(lTemp);
284 };/* while() */
285 // qsPrintDLLList();
286 hReg=pRegDLL;
287 }
288 else{
289 free(pRegDLL);
290 free(buf);
291 }
292 return hReg;
293}
294
295NOMEXTERN void NOMLINK nomEndRegisterDLLWithGC(const HREGDLL hRegisterDLL )
296{
297 g_slist_free(hRegisterDLL->dllList);
298 free((char*)hRegisterDLL->pMainAnchor);
299 free((char*)hRegisterDLL);
300}
301
302#define OBJREAD 0x0001L
303#define OBJWRITE 0x0002L
304#define OBJINVALID 0x0080L
305NOMEXTERN BOOL NOMLINK nomRegisterDLLByName(const HREGDLL hRegisterDLL, const char* chrDLLName)
306{
307 GSList* lTemp;
308
309 //g_message("Trying to register DLL %s", chrDLLName);
310 lTemp=hRegisterDLL->dllList;
311 while(lTemp)
312 {
313 qsLrec_t* pModRec;
314
315 pModRec=(qsLrec_t*)lTemp->data;
316 if(pModRec){
317 // g_message("DLL name: %s", pModRec->pName);
318 if(pModRec->pName && (NULLHANDLE!=strstr( pModRec->pName, chrDLLName)))
319 {
320 qsLObjrec_t *pObjInfo;
321 //g_message(" --> Found DLL %s", pModRec->pName);
322 pObjInfo=pModRec->pObjInfo;
323 if(NULLHANDLE!=pObjInfo)
324 {
325 int iObj;
326 for(iObj=0; iObj<pModRec->ctObj ;iObj++)
327 {
328 if (!(pObjInfo[iObj].oflags & OBJWRITE)) continue;
329 if (!(pObjInfo[iObj].oflags & OBJREAD)) continue;
330 if ((pObjInfo[iObj].oflags & OBJINVALID)) continue;
331 //g_message(" #%d: %04lX, size: %04lX %04lX",
332 // iObj, pObjInfo[iObj].oaddr, pObjInfo[iObj].osize, pObjInfo[iObj].oflags);
333 nomRegisterDataAreaForGC((char*)pObjInfo[iObj].oaddr,
334 (char*)(pObjInfo[iObj].oaddr+pObjInfo[iObj].osize));
335 g_tree_insert(treeRegisteredDLL, g_strdup(chrDLLName), GUINT_TO_POINTER((guint)pModRec->hmte));
336 }
337 }
338 return TRUE;
339 }
340 }
341 lTemp=g_slist_next(lTemp);
342 };/* while() */
343 return FALSE;
344}
345
346
347NOMEXTERN BOOL NOMLINK nomQueryUsingNameIsDLLRegistered(const gchar *chrName)
348{
349 if(NULLHANDLE!=g_tree_lookup(treeRegisteredDLL, chrName))
350 return TRUE;
351
352 return FALSE;
353}
Note: See TracBrowser for help on using the repository browser.