Fixed stabs parsing for GCC 3.0 (default types).
[wine] / debugger / winedbg.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /* Wine internal debugger
4  * Interface to Windows debugger API
5  * Eric Pouech (c) 2000
6  */
7
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "debugger.h"
13
14 #include "ntddk.h"
15 #include "thread.h"
16 #include "wincon.h"
17 #include "wingdi.h"
18 #include "winuser.h"
19
20 #include "winreg.h"
21
22 DBG_PROCESS*    DEBUG_CurrProcess = NULL;
23 DBG_THREAD*     DEBUG_CurrThread = NULL;
24 DWORD           DEBUG_CurrTid;
25 DWORD           DEBUG_CurrPid;
26 CONTEXT         DEBUG_context;
27 BOOL            DEBUG_interactiveP = FALSE;
28 int             curr_frame = 0;
29 static char*    DEBUG_LastCmdLine = NULL;
30
31 static DBG_PROCESS* DEBUG_ProcessList = NULL;
32 static int automatic_mode;
33 DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
34
35 void    DEBUG_Output(int chn, const char* buffer, int len)
36 {
37     if (DBG_IVAR(ConChannelMask) & chn)
38         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL);
39     if (DBG_IVAR(StdChannelMask) & chn)
40         fwrite(buffer, len, 1, stderr);
41 }
42
43 int     DEBUG_Printf(int chn, const char* format, ...)
44 {
45 static    char  buf[4*1024];
46     va_list     valist;
47     int         len;
48
49     va_start(valist, format);
50     len = vsnprintf(buf, sizeof(buf), format, valist);
51     va_end(valist);
52
53     if (len <= -1) {
54         len = sizeof(buf) - 1;
55         buf[len] = 0;
56         buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
57     }
58     DEBUG_Output(chn, buf, len);
59     return len;
60 }
61
62 static  BOOL DEBUG_IntVarsRW(int read)
63 {
64     HKEY        hkey;
65     DWORD       type = REG_DWORD;
66     DWORD       val;
67     DWORD       count = sizeof(val);
68     int         i;
69     DBG_INTVAR* div = DEBUG_IntVars;
70
71     if (read) {
72 /* initializes internal vars table */
73 #define  INTERNAL_VAR(_var,_val,_ref,_typ)                      \
74         div->val = _val; div->name = #_var; div->pval = _ref;   \
75         div->type = DEBUG_GetBasicType(_typ); div++;
76 #include "intvar.h"
77 #undef   INTERNAL_VAR
78     }
79
80     if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) {
81         /* since the IVars are not yet setup, DEBUG_Printf doesn't work,
82          * so don't use it */
83         fprintf(stderr, "Cannot create WineDbg key in registry\n");
84         return FALSE;
85     }
86
87     for (i = 0; i < DBG_IV_LAST; i++) {
88         if (read) {
89             if (!DEBUG_IntVars[i].pval) {
90                 if (!RegQueryValueEx(hkey, DEBUG_IntVars[i].name, 0, 
91                                      &type, (LPSTR)&val, &count))
92                     DEBUG_IntVars[i].val = val;
93                 DEBUG_IntVars[i].pval = &DEBUG_IntVars[i].val;
94             } else {
95                 *DEBUG_IntVars[i].pval = 0;
96             }
97         } else {
98             /* FIXME: type should be infered from basic type -if any- of intvar */
99             if (DEBUG_IntVars[i].pval == &DEBUG_IntVars[i].val)
100                 RegSetValueEx(hkey, DEBUG_IntVars[i].name, 0, 
101                               type, (LPCVOID)DEBUG_IntVars[i].pval, count);
102         }
103     }
104     RegCloseKey(hkey);
105     return TRUE;
106 }
107
108 DBG_INTVAR*     DEBUG_GetIntVar(const char* name)
109 {
110     int         i;
111
112     for (i = 0; i < DBG_IV_LAST; i++) {
113         if (!strcmp(DEBUG_IntVars[i].name, name))
114             return &DEBUG_IntVars[i];
115     }
116     return NULL;
117 }
118                        
119 static WINE_EXCEPTION_FILTER(wine_dbg)
120 {
121     DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg: Exception (%lx) inside debugger, continuing...\n", GetExceptionCode());
122     DEBUG_ExternalDebugger();
123     return EXCEPTION_EXECUTE_HANDLER;
124 }
125
126 DBG_PROCESS*    DEBUG_GetProcess(DWORD pid)
127 {
128     DBG_PROCESS*        p;
129     
130     for (p = DEBUG_ProcessList; p; p = p->next)
131         if (p->pid == pid) break;
132     return p;
133 }
134
135 static  DBG_PROCESS*    DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
136 {
137     DBG_PROCESS*        p = DBG_alloc(sizeof(DBG_PROCESS));
138     if (!p)
139         return NULL;
140     p->handle = h;
141     p->pid = pid;
142     p->imageName = imageName ? DBG_strdup(imageName) : NULL;
143     p->threads = NULL;
144     p->num_threads = 0;
145     p->continue_on_first_exception = FALSE;
146     p->modules = NULL;
147     p->num_modules = 0;
148     p->next_index = 0;
149     p->dbg_hdr_addr = 0;
150     p->delayed_bp = NULL;
151     p->num_delayed_bp = 0;
152
153     p->next = DEBUG_ProcessList;
154     p->prev = NULL;
155     if (DEBUG_ProcessList) DEBUG_ProcessList->prev = p;
156     DEBUG_ProcessList = p;
157     return p;
158 }
159
160 static  void                    DEBUG_DelThread(DBG_THREAD* p);
161
162 static  void                    DEBUG_DelProcess(DBG_PROCESS* p)
163 {
164     int i;
165
166     if (p->threads != NULL) {
167         DEBUG_Printf(DBG_CHN_ERR, "Shouldn't happen\n");
168         while (p->threads) DEBUG_DelThread(p->threads);
169     }
170     for (i = 0; i < p->num_delayed_bp; i++) {
171         DBG_free(p->delayed_bp[i].name);
172     }
173     DBG_free(p->delayed_bp);
174     if (p->prev) p->prev->next = p->next;
175     if (p->next) p->next->prev = p->prev;
176     if (p == DEBUG_ProcessList) DEBUG_ProcessList = p->next;
177     if (p == DEBUG_CurrProcess) DEBUG_CurrProcess = NULL;
178     DBG_free((char*)p->imageName);
179     DBG_free(p);
180 }
181
182 static  void                    DEBUG_InitCurrProcess(void)
183 {
184 }
185
186 static BOOL DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr)
187 {
188     DWORD sz;
189     *(WCHAR*)buffer = 0;
190     return (addr && ReadProcessMemory(hp, addr, buffer, size, &sz));
191 }
192
193 static BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr)
194 {
195     LPVOID      ad;
196     DWORD       sz;
197     
198     if (   addr 
199         && ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz) 
200         && sz == sizeof(ad) 
201         && ad 
202         && ReadProcessMemory(hp, ad, buffer, size, &sz))
203         return TRUE;
204     *(WCHAR*)buffer = 0;
205     return FALSE;
206 }
207
208 DBG_THREAD*     DEBUG_GetThread(DBG_PROCESS* p, DWORD tid)
209 {
210     DBG_THREAD* t;
211     
212     for (t = p->threads; t; t = t->next)
213         if (t->tid == tid) break;
214     return t;
215 }
216
217 static  DBG_THREAD*     DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, 
218                                         HANDLE h, LPVOID start, LPVOID teb)
219 {
220     DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD));
221     if (!t)
222         return NULL;
223     
224     t->handle = h;
225     t->tid = tid;
226     t->start = start;
227     t->teb = teb;
228     t->process = p;
229     t->wait_for_first_exception = 0;
230     t->dbg_exec_mode = EXEC_CONT;
231     t->dbg_exec_count = 0;
232     sprintf(t->name, "%08lx", tid);
233
234     p->num_threads++;
235     t->next = p->threads;
236     t->prev = NULL;
237     if (p->threads) p->threads->prev = t;
238     p->threads = t;
239
240     return t;
241 }
242
243 static  void                    DEBUG_InitCurrThread(void)
244 {
245     if (DEBUG_CurrThread->start) {
246         if (DEBUG_CurrThread->process->num_threads == 1 || 
247             DBG_IVAR(BreakAllThreadsStartup)) {
248             DBG_VALUE   value;
249             
250             DEBUG_SetBreakpoints(FALSE);
251             value.type = NULL;
252             value.cookie = DV_TARGET;
253             value.addr.seg = 0;
254             value.addr.off = (DWORD)DEBUG_CurrThread->start;
255             DEBUG_AddBreakpoint(&value, NULL);
256             DEBUG_SetBreakpoints(TRUE);
257         }
258     } else {
259         DEBUG_CurrThread->wait_for_first_exception = 1;
260     }
261 }
262
263 static  void                    DEBUG_DelThread(DBG_THREAD* t)
264 {
265     if (t->prev) t->prev->next = t->next;
266     if (t->next) t->next->prev = t->prev;
267     if (t == t->process->threads) t->process->threads = t->next;
268     t->process->num_threads--;
269     if (t == DEBUG_CurrThread) DEBUG_CurrThread = NULL;
270     DBG_free(t);
271 }
272
273 BOOL                            DEBUG_Attach(DWORD pid, BOOL cofe)
274 {
275     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0, NULL))) return FALSE;
276
277     if (!DebugActiveProcess(pid)) {
278         DEBUG_Printf(DBG_CHN_MESG, "Can't attach process %lx: error %ld\n", pid, GetLastError());
279         DEBUG_DelProcess(DEBUG_CurrProcess);
280         DEBUG_CurrProcess = NULL;
281         return FALSE;
282     }
283     DEBUG_CurrProcess->continue_on_first_exception = cofe;
284     return TRUE;
285 }
286
287 static  BOOL    DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
288 {
289     DBG_ADDR    addr;
290     int         newmode;
291
292     DEBUG_GetCurrentAddress(&addr);
293     DEBUG_SuspendExecution();
294
295     if (!is_debug) {
296         if (!addr.seg)
297             DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off);
298         else
299             switch(DEBUG_GetSelectorType(addr.seg))
300             {
301             case MODE_32:
302                 DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (%04lx:%08lx)", addr.seg, addr.off);
303                 break;
304             case MODE_16:
305                 DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04lx:%04lx)", addr.seg, addr.off);
306                 break;
307             case MODE_VM86:
308                 DEBUG_Printf(DBG_CHN_MESG, " in vm86 code (%04lx:%04lx)", addr.seg, addr.off);
309                 break;
310             case MODE_INVALID:
311                 DEBUG_Printf(DBG_CHN_MESG, " bad CS (%lx)", addr.seg);
312                 break;
313         }
314         DEBUG_Printf(DBG_CHN_MESG, ".\n");
315     }
316  
317     DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
318
319     if (!force && is_debug && 
320         DEBUG_ShouldContinue(&addr,
321                              code, 
322                              DEBUG_CurrThread->dbg_exec_mode, 
323                              &DEBUG_CurrThread->dbg_exec_count))
324         return FALSE;
325
326     if ((newmode = DEBUG_GetSelectorType(addr.seg)) == MODE_INVALID) newmode = MODE_32;
327     if (newmode != DEBUG_CurrThread->dbg_mode)
328     {
329         static const char * const names[] = { "???", "16-bit", "32-bit", "vm86" };
330         DEBUG_Printf(DBG_CHN_MESG,"In %s mode.\n", names[newmode] );
331         DEBUG_CurrThread->dbg_mode = newmode;
332     }
333
334     DEBUG_DoDisplay();
335
336     if (is_debug || force) {
337         /*
338          * Do a quiet backtrace so that we have an idea of what the situation
339          * is WRT the source files.
340          */
341         DEBUG_BackTrace(DEBUG_CurrTid, FALSE);
342     } else {
343         /* This is a real crash, dump some info */
344         DEBUG_InfoRegisters();
345         DEBUG_InfoStack();
346 #ifdef __i386__
347         if (DEBUG_CurrThread->dbg_mode == MODE_16) {
348             DEBUG_InfoSegments(DEBUG_context.SegDs >> 3, 1);
349             if (DEBUG_context.SegEs != DEBUG_context.SegDs)
350                 DEBUG_InfoSegments(DEBUG_context.SegEs >> 3, 1);
351         }
352         DEBUG_InfoSegments(DEBUG_context.SegFs >> 3, 1);
353 #endif
354         DEBUG_BackTrace(DEBUG_CurrTid, TRUE);
355     }
356
357     if (!is_debug ||
358         (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
359         (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR)) {
360
361         struct list_id list;
362
363         /* Show where we crashed */
364         curr_frame = 0;
365         DEBUG_DisassembleInstruction(&addr);
366
367         /* resets list internal arguments so we can look at source code when needed */
368         DEBUG_FindNearestSymbol(&addr, TRUE, NULL, 0, &list); 
369         if (list.sourcefile) DEBUG_List(&list, NULL, 0);
370     }
371     return TRUE;
372 }
373
374 static  DWORD   DEBUG_ExceptionEpilog(void)
375 {
376     DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution(DEBUG_CurrThread->dbg_exec_mode, 
377                                                              DEBUG_CurrThread->dbg_exec_count);
378     /*
379      * This will have gotten absorbed into the breakpoint info
380      * if it was used.  Otherwise it would have been ignored.
381      * In any case, we don't mess with it any more.
382      */
383     if (DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT || DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)
384         DEBUG_CurrThread->dbg_exec_count = 0;
385     
386     return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
387 }
388
389 static  BOOL    DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force, LPDWORD cont)
390 {
391     BOOL             is_debug = FALSE;
392     BOOL             ret = TRUE;
393     THREADNAME_INFO *pThreadName;
394     DBG_THREAD      *pThread;
395
396
397     *cont = DBG_CONTINUE;
398
399     switch (rec->ExceptionCode)
400     {
401     case EXCEPTION_BREAKPOINT:
402     case EXCEPTION_SINGLE_STEP:
403         is_debug = TRUE;
404         break;
405     case EXCEPTION_NAME_THREAD:
406         pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
407         if (pThreadName->dwThreadID == -1)
408             pThread = DEBUG_CurrThread;
409         else
410             pThread = DEBUG_GetThread(DEBUG_CurrProcess, pThreadName->dwThreadID);
411
412         if (ReadProcessMemory(DEBUG_CurrThread->process->handle, pThreadName->szName,
413                               pThread->name, 9, NULL))
414             DEBUG_Printf (DBG_CHN_MESG,
415                           "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
416                           pThread->tid, pThread->name);
417         return TRUE;
418     }
419
420     if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance))
421     {
422         /* pass exception to program except for debug exceptions */
423         *cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED;
424         return TRUE;
425     }
426
427     if (!is_debug)
428     {
429         /* print some infos */
430         DEBUG_Printf(DBG_CHN_MESG, "%s: ",
431                       first_chance ? "First chance exception" : "Unhandled exception");
432         switch (rec->ExceptionCode)
433         {
434         case EXCEPTION_INT_DIVIDE_BY_ZERO:
435             DEBUG_Printf(DBG_CHN_MESG, "divide by zero");
436             break;
437         case EXCEPTION_INT_OVERFLOW:
438             DEBUG_Printf(DBG_CHN_MESG, "overflow");
439             break;
440         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
441             DEBUG_Printf(DBG_CHN_MESG, "array bounds ");
442             break;
443         case EXCEPTION_ILLEGAL_INSTRUCTION:
444             DEBUG_Printf(DBG_CHN_MESG, "illegal instruction");
445             break;
446         case EXCEPTION_STACK_OVERFLOW:
447             DEBUG_Printf(DBG_CHN_MESG, "stack overflow");
448             break;
449         case EXCEPTION_PRIV_INSTRUCTION:
450             DEBUG_Printf(DBG_CHN_MESG, "privileged instruction");
451             break;
452         case EXCEPTION_ACCESS_VIOLATION:
453             if (rec->NumberParameters == 2)
454                 DEBUG_Printf(DBG_CHN_MESG, "page fault on %s access to 0x%08lx", 
455                               rec->ExceptionInformation[0] ? "write" : "read",
456                               rec->ExceptionInformation[1]);
457             else
458                 DEBUG_Printf(DBG_CHN_MESG, "page fault");
459             break;
460         case EXCEPTION_DATATYPE_MISALIGNMENT:
461             DEBUG_Printf(DBG_CHN_MESG, "Alignment");
462             break;
463         case DBG_CONTROL_C:
464             DEBUG_Printf(DBG_CHN_MESG, "^C");
465             break;
466         case CONTROL_C_EXIT:
467             DEBUG_Printf(DBG_CHN_MESG, "^C");
468             break;
469         case EXCEPTION_CRITICAL_SECTION_WAIT:
470             {
471                 DBG_ADDR        addr;
472
473                 addr.seg = 0;
474                 addr.off = rec->ExceptionInformation[0];
475
476                 DEBUG_Printf(DBG_CHN_MESG, "wait failed on critical section ");
477                 DEBUG_PrintAddress(&addr, DEBUG_CurrThread->dbg_mode, FALSE);
478             }
479             if (!DBG_IVAR(BreakOnCritSectTimeOut))
480             {
481                 DEBUG_Printf(DBG_CHN_MESG, "\n");
482                 return TRUE;
483             }
484             break;
485         case EXCEPTION_WINE_STUB:
486             {
487                 char dll[32], name[64];
488                 DEBUG_ProcessGetString( dll, sizeof(dll), DEBUG_CurrThread->process->handle,
489                                         (char *)rec->ExceptionInformation[0] );
490                 DEBUG_ProcessGetString( name, sizeof(name), DEBUG_CurrThread->process->handle,
491                                         (char *)rec->ExceptionInformation[1] );
492                 DEBUG_Printf(DBG_CHN_MESG, "unimplemented function %s.%s called", dll, name );
493             }
494             break;
495         case EXCEPTION_VM86_INTx:
496             DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
497                          rec->ExceptionInformation[0]);
498             break;
499         case EXCEPTION_VM86_STI:
500             DEBUG_Printf(DBG_CHN_MESG, "sti in vm86 mode");
501             break;
502         case EXCEPTION_VM86_PICRETURN:
503             DEBUG_Printf(DBG_CHN_MESG, "PIC return in vm86 mode");
504             break;
505         default:
506             DEBUG_Printf(DBG_CHN_MESG, "%08lx", rec->ExceptionCode);
507             break;
508         }
509     }
510
511 #if 0
512     DEBUG_Printf(DBG_CHN_TRACE, 
513                  "Entering debugger     PC=%lx EFL=%08lx mode=%d count=%d\n",
514 #ifdef __i386__
515                  DEBUG_context.Eip, DEBUG_context.EFlags, 
516 #else
517                  0L, 0L,
518 #endif
519                  DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
520 #endif
521
522     if (automatic_mode)
523     {
524         DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode);
525         return FALSE;  /* terminate execution */
526     }
527
528     if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) {
529         DEBUG_interactiveP = TRUE;
530         while ((ret = DEBUG_Parser())) {
531             if (DEBUG_ValidateRegisters()) {
532                 if (DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance)
533                     break;
534                 DEBUG_Printf(DBG_CHN_MESG, "Cannot pass on last chance exception. You must use cont\n");
535             }
536         }
537         DEBUG_interactiveP = FALSE;
538     }
539     *cont = DEBUG_ExceptionEpilog();
540
541 #if 0
542     DEBUG_Printf(DBG_CHN_TRACE, 
543                  "Exiting debugger      PC=%lx EFL=%08lx mode=%d count=%d\n",
544 #ifdef __i386__
545                  DEBUG_context.Eip, DEBUG_context.EFlags, 
546 #else
547                  0L, 0L,
548 #endif
549                  DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
550 #endif
551
552     return ret;
553 }
554
555 static  BOOL    DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
556 {
557     char                buffer[256];
558     BOOL                ret;
559
560     DEBUG_CurrPid = de->dwProcessId;
561     DEBUG_CurrTid = de->dwThreadId;
562
563     __TRY {
564         ret = TRUE;
565         *cont = 0L;
566         
567         if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
568             DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
569         else 
570             DEBUG_CurrThread = NULL;
571         
572         switch (de->dwDebugEventCode) {
573         case EXCEPTION_DEBUG_EVENT:
574             if (!DEBUG_CurrThread) {
575                 DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
576                              de->dwProcessId, de->dwThreadId);
577                 break;
578             }
579             
580             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n", 
581                          de->dwProcessId, de->dwThreadId, 
582                          de->u.Exception.ExceptionRecord.ExceptionCode);
583
584             if (DEBUG_CurrProcess->continue_on_first_exception) {
585                 DEBUG_CurrProcess->continue_on_first_exception = FALSE;
586                 if (!DBG_IVAR(BreakOnAttach)) {
587                     *cont = DBG_CONTINUE;
588                     break;
589                 }
590             }
591
592             DEBUG_context.ContextFlags =  CONTEXT_CONTROL
593                                         | CONTEXT_INTEGER
594 #ifdef CONTEXT_SEGMENTS
595                                         | CONTEXT_SEGMENTS
596 #endif
597 #ifdef CONTEXT_DEBUG_REGISTERS
598                                         | CONTEXT_DEBUG_REGISTERS
599 #endif
600                                         ;
601
602             if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
603                 DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
604                 break;
605             }
606             
607             ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord, 
608                                         de->u.Exception.dwFirstChance, 
609                                         DEBUG_CurrThread->wait_for_first_exception,
610                                         cont);
611             if (DEBUG_CurrThread) {
612                 DEBUG_CurrThread->wait_for_first_exception = 0;
613                 SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
614             }
615             break;
616             
617         case CREATE_THREAD_DEBUG_EVENT:
618             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId, 
619                          (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
620             
621             if (DEBUG_CurrProcess == NULL) {
622                 DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
623                 break;
624             }
625             if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) {
626                 DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
627                 break;
628             }
629             
630             DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, 
631                                                de->dwThreadId, 
632                                                de->u.CreateThread.hThread, 
633                                                de->u.CreateThread.lpStartAddress, 
634                                                de->u.CreateThread.lpThreadLocalBase);
635             if (!DEBUG_CurrThread) {
636                 DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
637                 break;
638             }
639             DEBUG_InitCurrThread();
640             break;
641             
642         case CREATE_PROCESS_DEBUG_EVENT:
643             DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
644                                            de->u.CreateProcessInfo.hProcess, 
645                                            de->u.CreateProcessInfo.lpImageName);
646
647             /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
648             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n", 
649                          de->dwProcessId, de->dwThreadId, 
650                          buffer, de->u.CreateProcessInfo.lpImageName,
651                          (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
652                          de->u.CreateProcessInfo.dwDebugInfoFileOffset,
653                          de->u.CreateProcessInfo.nDebugInfoSize);
654             
655             if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) {
656                 if (DEBUG_CurrProcess->handle) {
657                     DEBUG_Printf(DBG_CHN_ERR, "Skipping already defined process\n");
658                     break;
659                 }
660                 DEBUG_CurrProcess->handle = de->u.CreateProcessInfo.hProcess;
661                 if (DEBUG_CurrProcess->imageName == NULL)
662                     DEBUG_CurrProcess->imageName = DBG_strdup(buffer[0] ? buffer : "<Debugged Process>");
663
664             } else {
665                 DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
666                                                      de->u.CreateProcessInfo.hProcess,
667                                                      buffer[0] ? buffer : "<Debugged Process>");
668                 if (DEBUG_CurrProcess == NULL) {
669                     DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
670                     break;
671                 }
672             }
673             
674             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n", 
675                          de->dwProcessId, de->dwThreadId, 
676                          (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
677             
678             DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,       
679                                                de->dwThreadId, 
680                                                de->u.CreateProcessInfo.hThread, 
681                                                de->u.CreateProcessInfo.lpStartAddress, 
682                                                de->u.CreateProcessInfo.lpThreadLocalBase);
683             if (!DEBUG_CurrThread) {
684                 DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
685                 break;
686             }
687             
688             DEBUG_InitCurrProcess();
689             DEBUG_InitCurrThread();
690
691             DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile, 
692                                (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
693
694             if (buffer[0])  /* we got a process name */
695             {
696                 DWORD type;
697                 if (!GetBinaryTypeA( buffer, &type ))
698                 {
699                     /* not a Windows binary, assume it's a Unix executable then */
700                     char unixname[MAX_PATH];
701                     /* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
702                     if (wine_get_unix_file_name( buffer, unixname, sizeof(unixname) ))
703                     {
704                         DEBUG_ReadExecutableDbgInfo( unixname );
705                         break;
706                     }
707                 }
708             }
709             /* if it is a Windows binary, or an invalid or missing file name,
710              * we use wine itself as the main executable */
711             DEBUG_ReadExecutableDbgInfo( "wine" );
712             break;
713             
714         case EXIT_THREAD_DEBUG_EVENT:
715             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n", 
716                          de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
717             
718             if (DEBUG_CurrThread == NULL) {
719                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
720                 break;
721             }
722             /* FIXME: remove break point set on thread startup */
723             DEBUG_DelThread(DEBUG_CurrThread);
724             break;
725             
726         case EXIT_PROCESS_DEBUG_EVENT:
727             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n", 
728                          de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
729             
730             if (DEBUG_CurrProcess == NULL) {
731                 DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
732                 break;
733             }
734             /* just in case */
735             DEBUG_SetBreakpoints(FALSE);
736             /* kill last thread */
737             DEBUG_DelThread(DEBUG_CurrProcess->threads);
738             DEBUG_DelProcess(DEBUG_CurrProcess);
739
740             DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
741             break;
742             
743         case LOAD_DLL_DEBUG_EVENT:
744             if (DEBUG_CurrThread == NULL) {
745                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
746                 break;
747             }
748             DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
749                                            DEBUG_CurrThread->process->handle, 
750                                            de->u.LoadDll.lpImageName);
751             
752             /* FIXME unicode: de->u.LoadDll.fUnicode */
753             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n", 
754                          de->dwProcessId, de->dwThreadId, 
755                          buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
756                          de->u.LoadDll.dwDebugInfoFileOffset,
757                          de->u.LoadDll.nDebugInfoSize);
758             _strupr(buffer);
759             DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, (DWORD)de->u.LoadDll.lpBaseOfDll);
760             DEBUG_CheckDelayedBP();
761             if (DBG_IVAR(BreakOnDllLoad)) {
762                 DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n", 
763                              buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
764                 ret = DEBUG_Parser();
765             }
766             break;
767             
768         case UNLOAD_DLL_DEBUG_EVENT:
769             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId, 
770                          (unsigned long)de->u.UnloadDll.lpBaseOfDll);
771             break;
772             
773         case OUTPUT_DEBUG_STRING_EVENT:
774             if (DEBUG_CurrThread == NULL) {
775                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
776                 break;
777             }
778             
779             DEBUG_ProcessGetString(buffer, sizeof(buffer), 
780                                    DEBUG_CurrThread->process->handle, 
781                                    de->u.DebugString.lpDebugStringData);
782             
783             /* fixme unicode de->u.DebugString.fUnicode ? */
784             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n", 
785                          de->dwProcessId, de->dwThreadId, buffer);
786             break;
787             
788         case RIP_EVENT:
789             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n", 
790                          de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, 
791                          de->u.RipInfo.dwType);
792             break;
793             
794         default:
795             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n", 
796                          de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
797         }
798         
799     } __EXCEPT(wine_dbg) {
800         *cont = 0;
801         ret = TRUE;
802     }
803     __ENDTRY;
804     return ret;
805 }
806
807 static  DWORD   DEBUG_MainLoop(void)
808 {
809     DEBUG_EVENT         de;
810     DWORD               cont;
811     BOOL                ret;
812
813     DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
814     
815     for (ret = TRUE; ret; ) {
816         /* wait until we get at least one loaded process */
817         while (!DEBUG_ProcessList && (ret = DEBUG_Parser()));
818         if (!ret) break;
819
820         while (ret && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) {
821             ret = DEBUG_HandleDebugEvent(&de, &cont);
822             ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
823         }
824     };
825     
826     DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
827
828     return 0;
829 }
830
831 static DWORD DEBUG_AutoMode(void)
832 {
833     DEBUG_EVENT de;
834     DWORD cont;
835     BOOL ret = TRUE;
836
837     DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
838
839     while (ret && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE))
840     {
841         ret = DEBUG_HandleDebugEvent(&de, &cont);
842         ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
843     }
844     /* print some extra information */
845     DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
846     DEBUG_WalkModules();
847     DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
848     DEBUG_WalkThreads();
849
850     DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
851     return 0;
852 }
853
854 static  BOOL    DEBUG_Start(LPSTR cmdLine)
855 {
856     PROCESS_INFORMATION info;
857     STARTUPINFOA        startup;
858
859     memset(&startup, 0, sizeof(startup));
860     startup.cb = sizeof(startup);
861     startup.dwFlags = STARTF_USESHOWWINDOW;
862     startup.wShowWindow = SW_SHOWNORMAL;
863     
864     if (!CreateProcess(NULL, cmdLine, NULL, NULL, 
865                        FALSE, DEBUG_PROCESS|DETACHED_PROCESS, NULL, NULL, &startup, &info)) {
866         DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
867         return FALSE;
868     }
869     DEBUG_CurrPid = info.dwProcessId;
870     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(DEBUG_CurrPid, 0, NULL))) return FALSE;
871
872     return TRUE;
873 }
874
875 void    DEBUG_Run(const char* args)
876 {
877     DBG_MODULE* wmod = DEBUG_GetProcessMainModule(DEBUG_CurrProcess);
878     const char* pgm = (wmod) ? wmod->module_name : "none";
879
880     if (args) {
881         DEBUG_Printf(DBG_CHN_MESG, "Run (%s) with '%s'\n", pgm, args);
882     } else {
883         if (!DEBUG_LastCmdLine) {
884             DEBUG_Printf(DBG_CHN_MESG, "Cannot find previously used command line.\n");
885             return;
886         }
887         DEBUG_Start(DEBUG_LastCmdLine);
888     }
889 }
890
891 static void DEBUG_InitConsole(void)
892 {
893     COORD       c;
894     SMALL_RECT  sr;
895     DWORD       mode;
896
897     /* keep it as a cuiexe for now, so that Wine won't touch the Unix stdin, 
898      * stdout and stderr streams
899      */
900     if (DBG_IVAR(UseXTerm)) 
901     {
902         FreeConsole();
903         AllocConsole();
904     }
905     /* this would be nicer for output */
906     c.X = 132;
907     c.Y = 500;
908     SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), c);
909
910     /* sets the console's window width accordingly */
911     sr.Left   = 0;
912     sr.Top    = 0;
913     sr.Right  = c.X - 1;
914     sr.Bottom = 50;
915     SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &sr);
916
917     /* put the line editing mode with the nice emacs features (FIXME: could be triggered by a IVAR) */
918     if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode))
919         SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | WINE_ENABLE_LINE_INPUT_EMACS);
920 }
921
922 int DEBUG_main(int argc, char** argv)
923 {
924     DWORD       retv = 0;
925
926     /* Initialize the type handling stuff. */
927     DEBUG_InitTypes();
928     DEBUG_InitCVDataTypes();    
929
930     /* Initialize internal vars (types must have been initialized before) */
931     if (!DEBUG_IntVarsRW(TRUE)) return -1;
932
933     if (argc > 1 && !strcmp( argv[1], "--auto" ))
934     {
935         argc--;
936         argv++;
937         automatic_mode = 1;
938         /* force some internal variables */
939         DBG_IVAR(UseXTerm) = 0;
940         DBG_IVAR(BreakOnDllLoad) = 0;
941         DBG_IVAR(ConChannelMask) = 0;
942         DBG_IVAR(StdChannelMask) = DBG_CHN_MESG;
943     }
944
945     DEBUG_InitConsole();
946     
947     DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting... ");
948         
949     if (argc == 3) {
950         HANDLE  hEvent;
951         DWORD   pid;
952
953         if ((pid = atoi(argv[1])) != 0 && (hEvent = (HANDLE)atoi(argv[2])) != 0) {
954             if (!DEBUG_Attach(pid, TRUE)) {
955                 /* don't care about result */
956                 SetEvent(hEvent);
957                 goto leave;
958             }
959             if (!SetEvent(hEvent)) {
960                 DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent);
961                 goto leave;
962             }
963             CloseHandle(hEvent);
964             DEBUG_CurrPid = pid;
965         }
966     }
967         
968     if (DEBUG_CurrPid == 0 && argc > 1) {
969         int     i, len;
970         LPSTR   cmdLine;
971                 
972         if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
973         cmdLine[0] = '\0';
974
975         for (i = 1; i < argc; i++) {
976             len += strlen(argv[i]) + 1;
977             if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
978             strcat(cmdLine, argv[i]);
979             cmdLine[len - 2] = ' ';
980             cmdLine[len - 1] = '\0';
981         }
982
983         if (!DEBUG_Start(cmdLine)) {
984             DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
985             goto leave;
986         }
987         DBG_free(DEBUG_LastCmdLine);
988         DEBUG_LastCmdLine = cmdLine;
989     }
990
991     if (automatic_mode)
992     {
993         retv = DEBUG_AutoMode();
994         /* don't save modified variables in auto mode */
995     }
996     else
997     {
998         retv = DEBUG_MainLoop();
999         /* saves modified variables */
1000         DEBUG_IntVarsRW(FALSE);
1001     }
1002
1003  leave:
1004     return retv;
1005
1006  oom_leave:
1007     DEBUG_Printf(DBG_CHN_MESG, "Out of memory\n");
1008     goto leave;
1009 }