source: trunk/src/kernel32/oslibdebug.cpp@ 6975

Last change on this file since 6975 was 6975, checked in by sandervl, 24 years ago

Image header page must be readonly + disabled high memory usage for heap

File size: 14.5 KB
Line 
1/* $Id: oslibdebug.cpp,v 1.6 2001-10-09 20:25:20 sandervl Exp $ */
2
3/*
4 * OS/2 debug apis
5 *
6 * Copyright 2000 Sander van Leeuwen
7 * Copyright 2000 Edgar Buerkle
8 * Copyright 2000 Michal Necasek
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_DOSPROCESS
14#define INCL_DOSSEMAPHORES
15#define INCL_DOSQUEUES
16#define INCL_DOSMODULEMGR
17#define INCL_DOSEXCEPTIONS
18#define INCL_DOSERRORS
19#include <os2wrap.h>
20#include <process.h>
21#include <os2sel.h>
22#include <stdlib.h>
23#include <string.h>
24#include <misc.h>
25#include <windllbase.h>
26#include <winconst.h>
27#include "oslibdebug.h"
28
29#define DBG_LOCALLOG DBG_oslibdebug
30#include "dbglocal.h"
31
32#define DEBUG_QUEUENAME "\\QUEUES\\ODINTRACE\\"
33#define DEBUG_QSEMNAME "\\SEM32\\ODINTRACEQ\\"
34#define DEBUG_SEMNAME "\\SEM32\\ODINTRACE\\"
35
36//******************************************************************************
37//******************************************************************************
38VOID _Optlink DebugThread(VOID *argpid)
39{
40 BOOL fTerminate = FALSE;
41 CHAR QueueName[30] = DEBUG_QUEUENAME;
42 CHAR SemName[30] = DEBUG_SEMNAME;
43 CHAR QSemName[30] = DEBUG_QSEMNAME;
44 HQUEUE QueueHandle = 0;
45 HEV hevSem = 0,
46 hevQSem = 0;
47 uDB_t DbgBuf = {0};
48 int rc;
49 char path[CCHMAXPATH];
50 Win32DllBase *winmod;
51 LPDEBUG_EVENT lpde;
52 ULONG *pid = (ULONG*)argpid;
53 ULONG staticPid = *pid;
54 char tmp[12];
55
56 dprintf(("KERNEL32: DebugThread pid:%d", *pid));
57
58 strcat(QueueName, itoa(getpid(), tmp, 10));
59 rc = DosCreateQueue( &QueueHandle , QUE_FIFO, QueueName);
60 if(rc != 0)
61 {
62 dprintf(("DebugThread: Could not create queue:%s rc:%d", QueueName, rc));
63 return;
64 }
65 strcat(SemName, itoa(getpid(), tmp, 10));
66 rc = DosCreateEventSem(SemName, &hevSem, 0, TRUE);
67 if(rc != 0)
68 {
69 dprintf(("DebugThread: Could not create event sem:%s rc:%d", SemName, rc));
70 DosCloseQueue(QueueHandle);
71 return;
72 }
73 strcat(QSemName, itoa(getpid(), tmp, 10));
74 rc = DosCreateEventSem(QSemName, &hevQSem, 0, FALSE);
75 if(rc != 0)
76 {
77 dprintf(("DebugThread: Could not create event sem:%s rc:%d", QSemName, rc));
78 DosCloseEventSem(hevSem);
79 DosCloseQueue(QueueHandle);
80 return;
81 }
82
83 // connect to debuggee
84 DbgBuf.Cmd = DBG_C_Connect;
85 DbgBuf.Pid = *pid;
86 DbgBuf.Tid = 0;
87 DbgBuf.Value = DBG_L_386;
88 DbgBuf.Addr = 1;
89 rc = DosDebug(&DbgBuf);
90 if (rc != 0)
91 {
92 dprintf(("DosDebug error: rc = %d error:%d", rc, DbgBuf.Value));
93 DosCloseQueue(QueueHandle);
94 DosCloseEventSem(hevSem);
95 return;
96 }
97
98 while (rc == 0)
99 {
100 DosWaitEventSem(hevSem, SEM_INDEFINITE_WAIT);
101
102 DosDebug_GO:
103 DbgBuf.Cmd = DBG_C_Go;
104 DbgBuf.Pid = *pid;
105
106 DebugApi:
107 rc = DosDebug(&DbgBuf);
108 if (rc != 0)
109 dprintf(("DosDebug error: rc = %d", rc));
110
111 if (fTerminate) // break out of the while loop
112 break;
113
114 switch (DbgBuf.Cmd)
115 {
116 case DBG_N_Success:
117 dprintf(("DosDebug: GO ok"));
118 goto DosDebug_GO;
119
120 case DBG_N_Error:
121 dprintf(("DosDebug: Error %d", DbgBuf.Value));
122 // if(DbgBuf.Value == ERROR_INVALID_PROCID) connect ?
123 if(DbgBuf.Value == ERROR_EXCL_SEM_ALREADY_OWNED)
124 {
125 rc = 0; // continue
126 goto DosDebug_GO;
127 }
128 break; // end thread !!!
129
130 case DBG_N_ProcTerm:
131 dprintf(("DosDebug: Process terminated with rc %d\n", DbgBuf.Value));
132 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
133 lpde->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT_W;
134 lpde->dwProcessId = *pid;
135 lpde->dwThreadId = 0;
136 lpde->u.ExitThread.dwExitCode = DbgBuf.Value;
137 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
138 // We should now fire final DBG_C_Go and end processing. We shouldn't
139 // get any more debug events.
140 fTerminate = TRUE;
141 // goto DosDebug_GO; *pid is invalid?!?
142 DbgBuf.Cmd = DBG_C_Go;
143 DbgBuf.Pid = staticPid;
144 goto DebugApi;
145 break;
146
147 case DBG_N_Exception:
148 dprintf(("DosDebug: Exception"));
149 // lpde = malloc(sizeof(DEBUG_EVENT));
150 // TODO: fill union
151 // DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
152 // break;
153 DbgBuf.Cmd = DBG_C_Continue;
154 DbgBuf.Value = XCPT_CONTINUE_SEARCH;
155 goto DebugApi;
156
157 case DBG_N_ModuleLoad:
158 DosQueryModuleName(DbgBuf.Value, CCHMAXPATH, path);
159 dprintf(("DosDebug: module loaded [%s]", path));
160
161 winmod = Win32DllBase::findModule(path);
162 // only odin32(win32) modules, hide OS/2 ones
163 if(!winmod)
164 {
165 dprintf(("DosDebug: os/2 module [%s], suppress", path));
166 goto DosDebug_GO;
167 }
168 dprintf(("DosDebug: win32 module [%s], inform", path));
169 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
170 lpde->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT_W;
171 lpde->dwProcessId = *pid;
172 lpde->dwThreadId = 0;
173 lpde->u.LoadDll.hFile = 0;
174 // TODO: make a pe fakeheader in our DLL's (kernel32,...)
175 lpde->u.LoadDll.lpBaseOfDll = (PVOID)winmod->getInstanceHandle();
176 lpde->u.LoadDll.dwDebugInfoFileOffset = 0;
177 lpde->u.LoadDll.nDebugInfoSize = 0;
178 lpde->u.LoadDll.lpImageName = path;
179 lpde->u.LoadDll.fUnicode = FALSE;
180 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
181 break;
182
183 case DBG_N_CoError:
184 dprintf(("DosDebug: Coprocessor Error"));
185 // TODO: create an exception ?
186 goto DosDebug_GO;
187 break;
188
189 case DBG_N_ThreadTerm:
190 dprintf(("DosDebug: Thread %d terminated with rc %d", DbgBuf.Tid,DbgBuf.Value));
191 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
192 lpde->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT_W;
193 lpde->dwProcessId = *pid;
194 lpde->dwThreadId = DbgBuf.Tid;
195 lpde->u.ExitThread.dwExitCode = DbgBuf.Value;
196 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
197 break;
198
199 case DBG_N_AsyncStop:
200 dprintf(("DosDebug: Async stop"));
201 goto DosDebug_GO;
202 break;
203
204 case DBG_N_NewProc:
205 dprintf(("DosDebug: Debuggee started new Pid %d",DbgBuf.Value));
206 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
207 lpde->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT_W;
208 lpde->dwProcessId = *pid;
209 lpde->dwThreadId = 0;
210 //TODO: fill union
211 lpde->u.CreateProcessInfo.hFile = 0;
212 lpde->u.CreateProcessInfo.hProcess = 0;
213 lpde->u.CreateProcessInfo.hThread = 0;
214 lpde->u.CreateProcessInfo.lpBaseOfImage = NULL;
215 lpde->u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
216 lpde->u.CreateProcessInfo.nDebugInfoSize = 0;
217 lpde->u.CreateProcessInfo.lpThreadLocalBase = NULL;
218 lpde->u.CreateProcessInfo.lpStartAddress = NULL;
219 lpde->u.CreateProcessInfo.lpImageName = NULL;
220 lpde->u.CreateProcessInfo.fUnicode = FALSE;
221 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
222 break;
223
224 case DBG_N_AliasFree:
225 dprintf(("DosDebug: AliasFree"));
226 goto DosDebug_GO;
227 break;
228
229 case DBG_N_Watchpoint:
230 dprintf(("DosDebug: WatchPoint"));
231 goto DosDebug_GO;
232 break;
233
234 case DBG_N_ThreadCreate:
235 // Note: Win32 debuggers expect a process creation event first!
236 dprintf(("DosDebug: Thread %d created",DbgBuf.Tid));
237
238 if (DbgBuf.Tid == 1) { // Is this the first thread of a process?
239 // If so, fake a process creation event
240 dprintf(("DosDebug: Faking process creation event"));
241 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
242 lpde->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT_W;
243 lpde->dwProcessId = *pid;
244 lpde->dwThreadId = 0;
245 //TODO: fill union
246 lpde->u.CreateProcessInfo.hFile = 0;
247 lpde->u.CreateProcessInfo.hProcess = 0;
248 lpde->u.CreateProcessInfo.hThread = 0;
249 lpde->u.CreateProcessInfo.lpBaseOfImage = NULL;
250 lpde->u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
251 lpde->u.CreateProcessInfo.nDebugInfoSize = 0;
252 lpde->u.CreateProcessInfo.lpThreadLocalBase = NULL;
253 lpde->u.CreateProcessInfo.lpStartAddress = NULL;
254 lpde->u.CreateProcessInfo.lpImageName = NULL;
255 lpde->u.CreateProcessInfo.fUnicode = FALSE;
256 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
257 }
258 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
259 lpde->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT_W;
260 lpde->dwProcessId = *pid;
261 lpde->dwThreadId = DbgBuf.Tid;
262 //TODO: fill union
263 lpde->u.CreateThread.hThread = 0;
264 lpde->u.CreateThread.lpThreadLocalBase = NULL;
265 lpde->u.CreateThread.lpStartAddress = NULL;
266 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
267 break;
268
269 case DBG_N_ModuleFree:
270 DosQueryModuleName(DbgBuf.Value, CCHMAXPATH, path);
271 dprintf(("DosDebug: ModuleFree [%s]", path));
272 winmod = Win32DllBase::findModule(path);
273 // only odin32(win32) modules, hide OS/2 ones
274 if(!winmod)
275 {
276 dprintf(("DosDebug: os/2 module [%s], suppress", path));
277 break;
278 }
279 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
280 lpde->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT_W;
281 lpde->dwProcessId = *pid;
282 lpde->dwThreadId = 0;
283 lpde->u.UnloadDll.lpBaseOfDll = (PVOID)winmod->getInstanceHandle();
284 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
285 break;
286
287 case DBG_N_RangeStep:
288 dprintf(("DosDebug: RangeStep"));
289 goto DosDebug_GO;
290 break;
291
292 default:
293 dprintf(("DosDebug: Unkown Notify %d", DbgBuf.Cmd));
294 goto DosDebug_GO;
295 break;
296 }
297 }
298
299 dprintf(("DosDebug - ending the service thread"));
300 DosCloseQueue(QueueHandle);
301 DosCloseEventSem(hevSem);
302 DosCloseEventSem(hevQSem);
303// *pid = 0; No can do - for some reason *pid is invalid by now
304}
305
306//******************************************************************************
307//******************************************************************************
308BOOL OSLibWaitForDebugEvent(LPDEBUG_EVENT lpde, DWORD dwTimeout)
309{
310 CHAR QueueName[30]=DEBUG_QUEUENAME;
311 CHAR SemName[30]=DEBUG_QSEMNAME;
312 LPDEBUG_EVENT lpde_queue;
313 int rc, req;
314 PID pidOwner;
315 HQUEUE QueueHandle=0;
316 REQUESTDATA Request = {0};
317 ULONG len;
318 BYTE prio;
319 HEV hevQSem=0;
320 char tmp[12];
321 USHORT sel = RestoreOS2FS();
322
323 strcat(SemName, itoa(getpid(),tmp, 10));
324 rc = DosOpenEventSem(SemName, &hevQSem);
325 if(rc != 0)
326 goto fail;
327
328 // get a DebugEvent from our DebugThread
329 strcat(QueueName, itoa(getpid(), tmp, 10));
330 rc = DosOpenQueue(&pidOwner, &QueueHandle, QueueName);
331 Request.pid = pidOwner;
332 rc = DosReadQueue(QueueHandle, &Request, &len, (PPVOID) &lpde_queue, 0, DCWW_NOWAIT,
333 &prio, hevQSem);
334 if(rc == ERROR_QUE_EMPTY)
335 {
336 if(DosWaitEventSem(hevQSem, dwTimeout) == 0)
337 rc = DosReadQueue(QueueHandle, &Request, &len, (PPVOID) &lpde_queue, 0, DCWW_NOWAIT,
338 &prio, hevQSem);
339 }
340 if(rc != 0)
341 goto fail;
342
343 // copy DebugEvent to user space and free queue pointer
344 memcpy(lpde, lpde_queue, len);
345 free(lpde_queue);
346 // DosCloseEventSem(hevSem);
347 SetFS(sel);
348 return TRUE;
349
350fail:
351 // DosCloseEventSem(hevSem);
352 SetFS(sel);
353 return FALSE;
354}
355//******************************************************************************
356//******************************************************************************
357BOOL OSLibContinueDebugEvent(DWORD dwProcessId, DWORD dwThreadId, DWORD dwContinueStatus)
358{
359 CHAR SemName[30]=DEBUG_SEMNAME;
360 CHAR QueueName[30]=DEBUG_QUEUENAME;
361 PID pidOwner;
362 HQUEUE QueueHandle=0;
363 HEV hev=0;
364 int rc;
365 char tmp[12];
366 ULONG QEntries=0;
367 USHORT sel = RestoreOS2FS();
368
369 // only continue DebugThread, if queue is empty
370 strcat(QueueName, itoa(getpid(), tmp, 10));
371 rc = DosOpenQueue(&pidOwner, &QueueHandle, QueueName);
372 rc = DosQueryQueue(QueueHandle, &QEntries);
373 if(QEntries > 0) {
374 SetFS(sel);
375 return TRUE;
376 }
377 // continue DebugThread
378 strcat(SemName, itoa(getpid(), tmp, 10));
379 rc = DosOpenEventSem(SemName, &hev);
380 rc = DosPostEventSem(hev);
381 // DosCloseEventSem(hev);
382 SetFS(sel);
383 return (rc == 0) ? TRUE : FALSE;
384}
385//******************************************************************************
386//******************************************************************************
387BOOL OSLibAddModuleDebugEvent(char *name, BOOL fLoad)
388{
389 Win32DllBase *winmod;
390 LPDEBUG_EVENT lpde;
391 int rc;
392 CHAR QueueName[30]=DEBUG_QUEUENAME;
393 PID pidOwner;
394 HQUEUE QueueHandle=0;
395 char tmp[12];
396 USHORT sel = RestoreOS2FS();
397
398 winmod = Win32DllBase::findModule(name);
399 if(!winmod)
400 {
401 dprintf(("OSLibAddModuleDebugEvent: ERROR could not find module [%s]", name));
402 SetFS(sel);
403 return FALSE;
404 }
405
406// strcat(QueueName, itoa(getDebuggerPID(), tmp, 10));
407 rc = DosOpenQueue(&pidOwner, &QueueHandle, QueueName);
408
409 if(fLoad == TRUE)
410 {
411 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
412 lpde->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT_W;
413 lpde->dwProcessId = getpid(); // debuggee pid
414 lpde->dwThreadId = 0;
415 lpde->u.LoadDll.hFile = 0;
416 lpde->u.LoadDll.lpBaseOfDll = (PVOID)winmod->getInstanceHandle();
417 lpde->u.LoadDll.dwDebugInfoFileOffset = 0;
418 lpde->u.LoadDll.nDebugInfoSize = 0;
419 lpde->u.LoadDll.lpImageName = name;
420 lpde->u.LoadDll.fUnicode = FALSE;
421 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
422 }
423 else
424 {
425 lpde = (LPDEBUG_EVENT) malloc(sizeof(DEBUG_EVENT));
426 lpde->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT_W;
427 lpde->dwProcessId = getpid(); // debuggee pid
428 lpde->dwThreadId = 0;
429 lpde->u.UnloadDll.lpBaseOfDll = (PVOID)winmod->getInstanceHandle();
430 DosWriteQueue(QueueHandle, 0, sizeof(DEBUG_EVENT), lpde, 0);
431 }
432 SetFS(sel);
433 return TRUE;
434}
435//******************************************************************************
436//******************************************************************************
437VOID OSLibStartDebugger(ULONG *pid)
438{
439 USHORT sel = RestoreOS2FS();
440 TID tid;
441
442 tid = _beginthread(DebugThread, NULL, 1024, (PVOID) pid);
443 if (tid == 0)
444 {
445 dprintf(("OSLibStartDebugger: Could not create debug thread!"));
446 SetFS(sel);
447 return;
448 }
449 DosSleep(128);
450 SetFS(sel);
451}
452//******************************************************************************
453//******************************************************************************
Note: See TracBrowser for help on using the repository browser.