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