Added magic comments to all Wine-specific registry accesses to make
[wine] / programs / winedbg / winedbg.c
1 /* Wine internal debugger
2  * Interface to Windows debugger API
3  * Copyright 2000-2004 Eric Pouech
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "debugger.h"
27
28 #include "winternl.h"
29 #include "wine/exception.h"
30 #include "wine/library.h"
31
32 #include "wine/debug.h"
33
34 /* TODO list:
35  *
36  * - minidump
37  *      + allow winedbg in automatic mode to create a minidump (or add another option
38  *        for that)
39  *      + set a mode where winedbg would start (postmortem debugging) from a minidump
40  * - CPU adherence
41  *      + we always assume the stack grows has an i386 (ie downwards)
42  * - UI
43  *      + enable back the limited output (depth of structure printing and number of 
44  *        lines)
45  *      + make the output as close as possible to what gdb does
46  * - symbol management:
47  *      + symbol table loading is broken
48  *      + in symbol_get_lvalue, we don't do any scoping (as C does) between local and
49  *        global vars (we may need this to force some display for example). A solution
50  *        would be always to return arrays with: local vars, global vars, thunks
51  * - type management:
52  *      + some bits of internal types are missing (like type casts and the address
53  *        operator)
54  *      + the type for an enum's value is always inferred as int (winedbg & dbghelp)
55  *      + most of the code implies that sizeof(void*) = sizeof(int)
56  *      + all computations should be made on long long
57  *              o expr computations are in int:s
58  *              o bitfield size is on a 4-bytes
59  * - execution:
60  *      + set a better fix for gdb (proxy mode) than the step-mode hack
61  *      + implement function call in debuggee
62  *      + trampoline management is broken when getting 16 <=> 32 thunk destination
63  *        address
64  *      + thunking of delayed imports doesn't work as expected (ie, when stepping,
65  *        it currently stops at first insn with line number during the library 
66  *        loading). We should identify this (__wine_delay_import) and set a
67  *        breakpoint instead of single stepping the library loading.
68  *      + it's wrong to copy thread->step_over_bp into process->bp[0] (when 
69  *        we have a multi-thread debuggee). complete fix must include storing all
70  *        thread's step-over bp in process-wide bp array, and not to handle bp
71  *        when we have the wrong thread running into that bp
72  */
73
74 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
75
76 struct dbg_process*     dbg_curr_process = NULL;
77 struct dbg_thread*      dbg_curr_thread = NULL;
78 DWORD                   dbg_curr_tid;
79 DWORD                   dbg_curr_pid;
80 CONTEXT                 dbg_context;
81 int                     dbg_curr_frame = 0;
82 BOOL                    dbg_interactiveP = FALSE;
83 static char*            dbg_last_cmd_line = NULL;
84
85 static struct dbg_process*      dbg_process_list = NULL;
86 static enum {none_mode = 0, winedbg_mode, automatic_mode, gdb_mode} dbg_action_mode;
87
88 struct dbg_internal_var         dbg_internal_vars[DBG_IV_LAST];
89 const struct dbg_internal_var*  dbg_context_vars;
90 static HANDLE                   dbg_houtput;
91
92 void    dbg_outputA(const char* buffer, int len)
93 {
94     static char line_buff[4096];
95     static unsigned int line_pos;
96
97     DWORD w, i;
98
99     while (len > 0)
100     {
101         unsigned int count = min( len, sizeof(line_buff) - line_pos );
102         memcpy( line_buff + line_pos, buffer, count );
103         buffer += count;
104         len -= count;
105         line_pos += count;
106         for (i = line_pos; i > 0; i--) if (line_buff[i-1] == '\n') break;
107         if (!i)  /* no newline found */
108         {
109             if (len > 0) i = line_pos;  /* buffer is full, flush anyway */
110             else break;
111         }
112         WriteFile(dbg_houtput, line_buff, i, &w, NULL);
113         memmove( line_buff, line_buff + i, line_pos - i );
114         line_pos -= i;
115     }
116 }
117
118 void    dbg_outputW(const WCHAR* buffer, int len)
119 {
120     char* ansi = NULL;
121     int newlen;
122         
123     /* do a serious Unicode to ANSI conversion
124      * FIXME: should CP_ACP be GetConsoleCP()?
125      */
126     newlen = WideCharToMultiByte(CP_ACP, 0, buffer, len, NULL, 0, NULL, NULL);
127     if (newlen)
128     {
129         if (!(ansi = HeapAlloc(GetProcessHeap(), 0, newlen))) return;
130         WideCharToMultiByte(CP_ACP, 0, buffer, len, ansi, newlen, NULL, NULL);
131         dbg_outputA(ansi, newlen);
132         HeapFree(GetProcessHeap(), 0, ansi);
133     }
134 }
135
136 int     dbg_printf(const char* format, ...)
137 {
138     static    char      buf[4*1024];
139     va_list     valist;
140     int         len;
141
142     va_start(valist, format);
143     len = vsnprintf(buf, sizeof(buf), format, valist);
144     va_end(valist);
145
146     if (len <= -1 || len >= sizeof(buf)) 
147     {
148         len = sizeof(buf) - 1;
149         buf[len] = 0;
150         buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
151     }
152     dbg_outputA(buf, len);
153     return len;
154 }
155
156 static  unsigned dbg_load_internal_vars(void)
157 {
158     HKEY                        hkey;
159     DWORD                       type = REG_DWORD;
160     DWORD                       val;
161     DWORD                       count = sizeof(val);
162     int                         i;
163     struct dbg_internal_var*    div = dbg_internal_vars;
164
165 /* initializes internal vars table */
166 #define  INTERNAL_VAR(_var,_val,_ref,_tid)                      \
167         div->val = _val; div->name = #_var; div->pval = _ref;   \
168         div->typeid = _tid; div++;
169 #include "intvar.h"
170 #undef   INTERNAL_VAR
171
172     /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
173     if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) 
174     {
175         WINE_ERR("Cannot create WineDbg key in registry\n");
176         return FALSE;
177     }
178
179     for (i = 0; i < DBG_IV_LAST; i++) 
180     {
181         if (!dbg_internal_vars[i].pval) 
182         {
183             if (!RegQueryValueEx(hkey, dbg_internal_vars[i].name, 0,
184                                  &type, (LPSTR)&val, &count))
185                 dbg_internal_vars[i].val = val;
186             dbg_internal_vars[i].pval = &dbg_internal_vars[i].val;
187         }
188     }
189     RegCloseKey(hkey);
190     /* set up the debug variables for the CPU context */
191     dbg_context_vars = be_cpu->init_registers(&dbg_context);
192     return TRUE;
193 }
194
195 static  unsigned dbg_save_internal_vars(void)
196 {
197     HKEY                        hkey;
198     int                         i;
199
200     /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
201     if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) 
202     {
203         WINE_ERR("Cannot create WineDbg key in registry\n");
204         return FALSE;
205     }
206
207     for (i = 0; i < DBG_IV_LAST; i++) 
208     {
209         /* FIXME: type should be infered from basic type -if any- of intvar */
210         if (dbg_internal_vars[i].pval == &dbg_internal_vars[i].val)
211             RegSetValueEx(hkey, dbg_internal_vars[i].name, 0,
212                           REG_DWORD, (const void*)dbg_internal_vars[i].pval, 
213                           sizeof(*dbg_internal_vars[i].pval));
214     }
215     RegCloseKey(hkey);
216     return TRUE;
217 }
218
219 const struct dbg_internal_var* dbg_get_internal_var(const char* name)
220 {
221     const struct dbg_internal_var*      div;
222
223     for (div = &dbg_internal_vars[DBG_IV_LAST - 1]; div >= dbg_internal_vars; div--)
224     {
225         if (!strcmp(div->name, name)) return div;
226     }
227     for (div = dbg_context_vars; div->name; div++)
228     {
229         if (!strcasecmp(div->name, name)) return div;
230     }
231
232     return NULL;
233 }
234
235 struct dbg_process*     dbg_get_process(DWORD pid)
236 {
237     struct dbg_process* p;
238
239     for (p = dbg_process_list; p; p = p->next)
240         if (p->pid == pid) break;
241     return p;
242 }
243
244 struct dbg_process*     dbg_add_process(DWORD pid, HANDLE h)
245 {
246     /* FIXME: temporary */
247     extern struct be_process_io be_process_active_io;
248
249     struct dbg_process* p;
250
251     if ((p = dbg_get_process(pid)))
252     {
253         if (p->handle != 0)
254         {
255             WINE_ERR("Process (%lu) is already defined\n", pid);
256         }
257         else
258         {
259             p->handle = h;
260             p->imageName = NULL;
261         }
262         return p;
263     }
264
265     if (!(p = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_process)))) return NULL;
266     p->handle = h;
267     p->pid = pid;
268     p->process_io = &be_process_active_io;
269     p->imageName = NULL;
270     p->threads = NULL;
271     p->continue_on_first_exception = FALSE;
272     p->next_bp = 1;  /* breakpoint 0 is reserved for step-over */
273     memset(p->bp, 0, sizeof(p->bp));
274     p->delayed_bp = NULL;
275     p->num_delayed_bp = 0;
276
277     p->next = dbg_process_list;
278     p->prev = NULL;
279     if (dbg_process_list) dbg_process_list->prev = p;
280     dbg_process_list = p;
281     return p;
282 }
283
284 void dbg_set_process_name(struct dbg_process* p, const char* imageName)
285 {
286     assert(p->imageName == NULL);
287     if (imageName)
288     {
289         char* tmp = HeapAlloc(GetProcessHeap(), 0, strlen(imageName) + 1);
290         if (tmp) p->imageName = strcpy(tmp, imageName);
291     }
292 }
293
294 void dbg_del_process(struct dbg_process* p)
295 {
296     int i;
297
298     while (p->threads) dbg_del_thread(p->threads);
299
300     for (i = 0; i < p->num_delayed_bp; i++)
301         if (p->delayed_bp[i].is_symbol)
302             HeapFree(GetProcessHeap(), 0, p->delayed_bp[i].u.symbol.name);
303
304     HeapFree(GetProcessHeap(), 0, p->delayed_bp);
305     if (p->prev) p->prev->next = p->next;
306     if (p->next) p->next->prev = p->prev;
307     if (p == dbg_process_list) dbg_process_list = p->next;
308     if (p == dbg_curr_process) dbg_curr_process = NULL;
309     HeapFree(GetProcessHeap(), 0, (char*)p->imageName);
310     HeapFree(GetProcessHeap(), 0, p);
311 }
312
313 static void dbg_init_current_process(void)
314 {
315 }
316
317 struct mod_loader_info
318 {
319     HANDLE              handle;
320     IMAGEHLP_MODULE*    imh_mod;
321 };
322
323 static BOOL CALLBACK mod_loader_cb(PSTR mod_name, DWORD base, void* ctx)
324 {
325     struct mod_loader_info*     mli = (struct mod_loader_info*)ctx;
326
327     if (!strcmp(mod_name, "<wine-loader>"))
328     {
329         if (SymGetModuleInfo(mli->handle, base, mli->imh_mod))
330             return FALSE; /* stop enum */
331     }
332     return TRUE;
333 }
334
335 BOOL dbg_get_debuggee_info(HANDLE hProcess, IMAGEHLP_MODULE* imh_mod)
336 {
337     struct mod_loader_info  mli;
338     DWORD                   opt;
339
340     /* this will resynchronize builtin dbghelp's internal ELF module list */
341     SymLoadModule(hProcess, 0, 0, 0, 0, 0);
342     mli.handle  = hProcess;
343     mli.imh_mod = imh_mod;
344     imh_mod->SizeOfStruct = sizeof(*imh_mod);
345     imh_mod->BaseOfImage = 0;
346     /* this is a wine specific options to return also ELF modules in the
347      * enumeration
348      */
349     SymSetOptions((opt = SymGetOptions()) | 0x40000000);
350     SymEnumerateModules(hProcess, mod_loader_cb, (void*)&mli);
351     SymSetOptions(opt);
352
353     return imh_mod->BaseOfImage != 0;
354 }
355
356 struct dbg_thread* dbg_get_thread(struct dbg_process* p, DWORD tid)
357 {
358     struct dbg_thread*  t;
359
360     if (!p) return NULL;
361     for (t = p->threads; t; t = t->next)
362         if (t->tid == tid) break;
363     return t;
364 }
365
366 struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid,
367                                   HANDLE h, void* teb)
368 {
369     struct dbg_thread*  t = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_thread));
370
371     if (!t)
372         return NULL;
373
374     t->handle = h;
375     t->tid = tid;
376     t->teb = teb;
377     t->process = p;
378     t->exec_mode = dbg_exec_cont;
379     t->exec_count = 0;
380     t->step_over_bp.enabled = FALSE;
381     t->step_over_bp.refcount = 0;
382     t->in_exception = FALSE;
383
384     snprintf(t->name, sizeof(t->name), "0x%08lx", tid);
385
386     t->next = p->threads;
387     t->prev = NULL;
388     if (p->threads) p->threads->prev = t;
389     p->threads = t;
390
391     return t;
392 }
393
394 static void dbg_init_current_thread(void* start)
395 {
396     if (start)
397     {
398         if (dbg_curr_process->threads && 
399             !dbg_curr_process->threads->next && /* first thread ? */
400             DBG_IVAR(BreakAllThreadsStartup)) 
401         {
402             ADDRESS     addr;
403
404             break_set_xpoints(FALSE);
405             addr.Mode   = AddrModeFlat;
406             addr.Offset = (DWORD)start;
407             break_add_break(&addr, TRUE);
408             break_set_xpoints(TRUE);
409         }
410     } 
411 }
412
413 void dbg_del_thread(struct dbg_thread* t)
414 {
415     if (t->prev) t->prev->next = t->next;
416     if (t->next) t->next->prev = t->prev;
417     if (t == t->process->threads) t->process->threads = t->next;
418     if (t == dbg_curr_thread) dbg_curr_thread = NULL;
419     HeapFree(GetProcessHeap(), 0, t);
420 }
421
422 static unsigned dbg_handle_debug_event(DEBUG_EVENT* de);
423
424 /******************************************************************
425  *              dbg_attach_debuggee
426  *
427  * Sets the debuggee to <pid>
428  * cofe instructs winedbg what to do when first exception is received 
429  * (break=FALSE, continue=TRUE)
430  * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
431  * until the first exception is received (aka: attach to an already running process)
432  */
433 BOOL dbg_attach_debuggee(DWORD pid, BOOL cofe, BOOL wfe)
434 {
435     DEBUG_EVENT         de;
436
437     if (!(dbg_curr_process = dbg_add_process(pid, 0))) return FALSE;
438
439     if (!DebugActiveProcess(pid)) 
440     {
441         dbg_printf("Can't attach process %lx: error %ld\n", pid, GetLastError());
442         dbg_del_process(dbg_curr_process);
443         return FALSE;
444     }
445     dbg_curr_process->continue_on_first_exception = cofe;
446
447     if (wfe) /* shall we proceed all debug events until we get an exception ? */
448     {
449         dbg_interactiveP = FALSE;
450         while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
451         {
452             if (dbg_handle_debug_event(&de)) break;
453         }
454         if (dbg_curr_process) dbg_interactiveP = TRUE;
455     }
456     return TRUE;
457 }
458
459 BOOL dbg_detach_debuggee(void)
460 {
461     /* remove all set breakpoints in debuggee code */
462     break_set_xpoints(FALSE);
463     /* needed for single stepping (ugly).
464      * should this be handled inside the server ??? 
465      */
466     be_cpu->single_step(&dbg_context, FALSE);
467     SetThreadContext(dbg_curr_thread->handle, &dbg_context);
468     if (dbg_curr_thread->in_exception)
469         ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
470     if (!DebugActiveProcessStop(dbg_curr_pid)) return FALSE;
471     dbg_del_process(dbg_curr_process);
472
473     return TRUE;
474 }
475
476 static unsigned dbg_fetch_context(void)
477 {
478     dbg_context.ContextFlags = CONTEXT_CONTROL
479         | CONTEXT_INTEGER
480 #ifdef CONTEXT_SEGMENTS
481         | CONTEXT_SEGMENTS
482 #endif
483 #ifdef CONTEXT_DEBUG_REGISTERS
484         | CONTEXT_DEBUG_REGISTERS
485 #endif
486         ;
487     if (!GetThreadContext(dbg_curr_thread->handle, &dbg_context))
488     {
489         WINE_WARN("Can't get thread's context\n");
490         return FALSE;
491     }
492     return TRUE;
493 }
494
495 static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
496 {
497     ADDRESS     addr;
498     BOOL        is_break;
499
500     memory_get_current_pc(&addr);
501     break_suspend_execution();
502     dbg_curr_thread->excpt_record = *rec;
503     dbg_curr_thread->in_exception = TRUE;
504
505     if (!is_debug)
506     {
507         switch (addr.Mode)
508         {
509         case AddrModeFlat: dbg_printf(" in 32-bit code (0x%08lx)", addr.Offset); break;
510         case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04lx)", addr.Segment, addr.Offset); break;
511         case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04lx)", addr.Segment, addr.Offset); break;
512         case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, addr.Offset); break;
513         default: dbg_printf(" bad address");
514         }
515         dbg_printf(".\n");
516     }
517
518     /* this will resynchronize builtin dbghelp's internal ELF module list */
519     SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
520
521     /*
522      * Do a quiet backtrace so that we have an idea of what the situation
523      * is WRT the source files.
524      */
525     stack_backtrace(dbg_curr_tid, FALSE);
526     if (is_debug &&
527         break_should_continue(&addr, rec->ExceptionCode, &dbg_curr_thread->exec_count, &is_break))
528         return FALSE;
529
530     if (addr.Mode != dbg_curr_thread->addr_mode)
531     {
532         const char* name = NULL;
533         
534         switch (addr.Mode)
535         {
536         case AddrMode1616: name = "16 bit";     break;
537         case AddrMode1632: name = "32 bit";     break;
538         case AddrModeReal: name = "vm86";       break;
539         case AddrModeFlat: name = "32 bit";     break;
540         }
541         
542         dbg_printf("In %s mode.\n", name);
543         dbg_curr_thread->addr_mode = addr.Mode;
544     }
545     display_print();
546
547     if (!is_debug)
548     {
549         /* This is a real crash, dump some info */
550         be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
551         stack_info();
552         be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
553         stack_backtrace(dbg_curr_tid, TRUE);
554     }
555     if (!is_debug || is_break ||
556         dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
557         dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
558     {
559         ADDRESS tmp = addr;
560         /* Show where we crashed */
561         dbg_curr_frame = 0;
562         memory_disasm_one_insn(&tmp);
563     }
564     source_list_from_addr(&addr, 0);
565
566     return TRUE;
567 }
568
569 static void dbg_exception_epilog(void)
570 {
571     break_restart_execution(dbg_curr_thread->exec_count);
572     /*
573      * This will have gotten absorbed into the breakpoint info
574      * if it was used.  Otherwise it would have been ignored.
575      * In any case, we don't mess with it any more.
576      */
577     if (dbg_curr_thread->exec_mode == dbg_exec_cont)
578         dbg_curr_thread->exec_count = 0;
579     dbg_curr_thread->in_exception = FALSE;
580 }
581
582 static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
583 {
584     BOOL                is_debug = FALSE;
585     THREADNAME_INFO*    pThreadName;
586     struct dbg_thread*  pThread;
587
588     assert(dbg_curr_thread);
589
590     WINE_TRACE("exception=%lx first_chance=%c\n",
591                rec->ExceptionCode, first_chance ? 'Y' : 'N');
592
593     switch (rec->ExceptionCode)
594     {
595     case EXCEPTION_BREAKPOINT:
596     case EXCEPTION_SINGLE_STEP:
597         is_debug = TRUE;
598         break;
599     case EXCEPTION_NAME_THREAD:
600         pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
601         if (pThreadName->dwThreadID == -1)
602             pThread = dbg_curr_thread;
603         else
604             pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
605
606         if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
607             dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
608                        pThread->tid, pThread->name);
609         return DBG_CONTINUE;
610     }
611
612     if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance))
613     {
614         /* pass exception to program except for debug exceptions */
615         return DBG_EXCEPTION_NOT_HANDLED;
616     }
617
618     if (!is_debug)
619     {
620         /* print some infos */
621         dbg_printf("%s: ",
622                    first_chance ? "First chance exception" : "Unhandled exception");
623         switch (rec->ExceptionCode)
624         {
625         case EXCEPTION_INT_DIVIDE_BY_ZERO:
626             dbg_printf("divide by zero");
627             break;
628         case EXCEPTION_INT_OVERFLOW:
629             dbg_printf("overflow");
630             break;
631         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
632             dbg_printf("array bounds");
633             break;
634         case EXCEPTION_ILLEGAL_INSTRUCTION:
635             dbg_printf("illegal instruction");
636             break;
637         case EXCEPTION_STACK_OVERFLOW:
638             dbg_printf("stack overflow");
639             break;
640         case EXCEPTION_PRIV_INSTRUCTION:
641             dbg_printf("privileged instruction");
642             break;
643         case EXCEPTION_ACCESS_VIOLATION:
644             if (rec->NumberParameters == 2)
645                 dbg_printf("page fault on %s access to 0x%08lx",
646                            rec->ExceptionInformation[0] ? "write" : "read",
647                            rec->ExceptionInformation[1]);
648             else
649                 dbg_printf("page fault");
650             break;
651         case EXCEPTION_DATATYPE_MISALIGNMENT:
652             dbg_printf("Alignment");
653             break;
654         case DBG_CONTROL_C:
655             dbg_printf("^C");
656             break;
657         case CONTROL_C_EXIT:
658             dbg_printf("^C");
659             break;
660         case STATUS_POSSIBLE_DEADLOCK:
661         {
662             ADDRESS         addr;
663
664             addr.Mode   = AddrModeFlat;
665             addr.Offset = rec->ExceptionInformation[0];
666
667             dbg_printf("wait failed on critical section ");
668             print_address(&addr, FALSE);
669         }
670         if (!DBG_IVAR(BreakOnCritSectTimeOut))
671         {
672             dbg_printf("\n");
673             return DBG_EXCEPTION_NOT_HANDLED;
674         }
675         break;
676         case EXCEPTION_WINE_STUB:
677         {
678             char dll[32], name[64];
679             memory_get_string(dbg_curr_process,
680                               (void*)rec->ExceptionInformation[0], TRUE, FALSE,
681                               dll, sizeof(dll));
682             if (HIWORD(rec->ExceptionInformation[1]))
683                 memory_get_string(dbg_curr_process,
684                                   (void*)rec->ExceptionInformation[1], TRUE, FALSE,
685                                   name, sizeof(name));
686             else
687                 sprintf( name, "%ld", rec->ExceptionInformation[1] );
688             dbg_printf("unimplemented function %s.%s called", dll, name);
689         }
690         break;
691         case EXCEPTION_WINE_ASSERTION:
692             dbg_printf("assertion failed");
693             break;
694         case EXCEPTION_VM86_INTx:
695             dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
696             break;
697         case EXCEPTION_VM86_STI:
698             dbg_printf("sti in vm86 mode");
699             break;
700         case EXCEPTION_VM86_PICRETURN:
701             dbg_printf("PIC return in vm86 mode");
702             break;
703         case EXCEPTION_FLT_DENORMAL_OPERAND:
704             dbg_printf("denormal float operand");
705             break;
706         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
707             dbg_printf("divide by zero");
708             break;
709         case EXCEPTION_FLT_INEXACT_RESULT:
710             dbg_printf("inexact float result");
711             break;
712         case EXCEPTION_FLT_INVALID_OPERATION:
713             dbg_printf("invalid float operation");
714             break;
715         case EXCEPTION_FLT_OVERFLOW:
716             dbg_printf("floating pointer overflow");
717             break;
718         case EXCEPTION_FLT_UNDERFLOW:
719             dbg_printf("floating pointer underflow");
720             break;
721         case EXCEPTION_FLT_STACK_CHECK:
722             dbg_printf("floating point stack check");
723             break;
724         default:
725             dbg_printf("0x%08lx", rec->ExceptionCode);
726             break;
727         }
728     }
729
730     if (dbg_action_mode == automatic_mode)
731     {
732         dbg_exception_prolog(is_debug, rec);
733         dbg_exception_epilog();
734         return 0;  /* terminate execution */
735     }
736
737     if (dbg_exception_prolog(is_debug, rec))
738     {
739         dbg_interactiveP = TRUE;
740         return 0;
741     }
742     dbg_exception_epilog();
743
744     return DBG_CONTINUE;
745 }
746
747 static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
748 {
749     char        buffer[256];
750     DWORD       cont = DBG_CONTINUE;
751
752     dbg_curr_pid = de->dwProcessId;
753     dbg_curr_tid = de->dwThreadId;
754
755     if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
756         dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
757     else
758         dbg_curr_thread = NULL;
759
760     switch (de->dwDebugEventCode)
761     {
762     case EXCEPTION_DEBUG_EVENT:
763         if (!dbg_curr_thread)
764         {
765             WINE_ERR("%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
766                      de->dwProcessId, de->dwThreadId);
767             break;
768         }
769
770         WINE_TRACE("%08lx:%08lx: exception code=%08lx\n",
771                    de->dwProcessId, de->dwThreadId,
772                    de->u.Exception.ExceptionRecord.ExceptionCode);
773
774         if (dbg_curr_process->continue_on_first_exception)
775         {
776             dbg_curr_process->continue_on_first_exception = FALSE;
777             if (!DBG_IVAR(BreakOnAttach)) break;
778         }
779         if (dbg_fetch_context())
780         {
781             cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
782                                         de->u.Exception.dwFirstChance);
783             if (cont && dbg_curr_thread)
784             {
785                 SetThreadContext(dbg_curr_thread->handle, &dbg_context);
786             }
787         }
788         break;
789
790     case CREATE_PROCESS_DEBUG_EVENT:
791         dbg_curr_process = dbg_add_process(de->dwProcessId,
792                                            de->u.CreateProcessInfo.hProcess);
793         if (dbg_curr_process == NULL)
794         {
795             WINE_ERR("Couldn't create process\n");
796             break;
797         }
798         memory_get_string_indirect(dbg_curr_process,
799                                    de->u.CreateProcessInfo.lpImageName,
800                                    de->u.CreateProcessInfo.fUnicode,
801                                    buffer, sizeof(buffer));
802         if (!buffer[0]) strcpy(buffer, "<Debugged Process>");
803
804         WINE_TRACE("%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
805                    de->dwProcessId, de->dwThreadId,
806                    buffer, de->u.CreateProcessInfo.lpImageName,
807                    (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
808                    de->u.CreateProcessInfo.dwDebugInfoFileOffset,
809                    de->u.CreateProcessInfo.nDebugInfoSize);
810         dbg_set_process_name(dbg_curr_process, buffer);
811
812         if (!SymInitialize(dbg_curr_process->handle, NULL, TRUE))
813             dbg_printf("Couldn't initiate DbgHelp\n");
814
815         WINE_TRACE("%08lx:%08lx: create thread I @%08lx\n",
816                    de->dwProcessId, de->dwThreadId,
817                    (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
818
819         dbg_curr_thread = dbg_add_thread(dbg_curr_process,
820                                          de->dwThreadId,
821                                          de->u.CreateProcessInfo.hThread,
822                                          de->u.CreateProcessInfo.lpThreadLocalBase);
823         if (!dbg_curr_thread)
824         {
825             WINE_ERR("Couldn't create thread\n");
826             break;
827         }
828         dbg_init_current_process();
829         dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
830         break;
831
832     case EXIT_PROCESS_DEBUG_EVENT:
833         WINE_TRACE("%08lx:%08lx: exit process (%ld)\n",
834                    de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
835
836         if (dbg_curr_process == NULL)
837         {
838             WINE_ERR("Unknown process\n");
839             break;
840         }
841         if (!SymCleanup(dbg_curr_process->handle))
842             dbg_printf("Couldn't initiate DbgHelp\n");
843         /* just in case */
844         break_set_xpoints(FALSE);
845         /* kill last thread */
846         dbg_del_thread(dbg_curr_process->threads);
847         dbg_del_process(dbg_curr_process);
848
849         dbg_printf("Process of pid=0x%08lx has terminated\n", dbg_curr_pid);
850         break;
851
852     case CREATE_THREAD_DEBUG_EVENT:
853         WINE_TRACE("%08lx:%08lx: create thread D @%08lx\n",
854                    de->dwProcessId, de->dwThreadId,
855                    (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
856
857         if (dbg_curr_process == NULL)
858         {
859             WINE_ERR("Unknown process\n");
860             break;
861         }
862         if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
863         {
864             WINE_TRACE("Thread already listed, skipping\n");
865             break;
866         }
867
868         dbg_curr_thread = dbg_add_thread(dbg_curr_process,
869                                          de->dwThreadId,
870                                          de->u.CreateThread.hThread,
871                                          de->u.CreateThread.lpThreadLocalBase);
872         if (!dbg_curr_thread)
873         {
874             WINE_ERR("Couldn't create thread\n");
875             break;
876         }
877         dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
878         break;
879
880     case EXIT_THREAD_DEBUG_EVENT:
881         WINE_TRACE("%08lx:%08lx: exit thread (%ld)\n",
882                    de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
883
884         if (dbg_curr_thread == NULL)
885         {
886             WINE_ERR("Unknown thread\n");
887             break;
888         }
889         /* FIXME: remove break point set on thread startup */
890         dbg_del_thread(dbg_curr_thread);
891         break;
892
893     case LOAD_DLL_DEBUG_EVENT:
894         if (dbg_curr_thread == NULL)
895         {
896             WINE_ERR("Unknown thread\n");
897             break;
898         }
899         memory_get_string_indirect(dbg_curr_process, 
900                                    de->u.LoadDll.lpImageName,
901                                    de->u.LoadDll.fUnicode,
902                                    buffer, sizeof(buffer));
903
904         WINE_TRACE("%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
905                    de->dwProcessId, de->dwThreadId,
906                    buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
907                    de->u.LoadDll.dwDebugInfoFileOffset,
908                    de->u.LoadDll.nDebugInfoSize);
909         _strupr(buffer);
910         SymLoadModule(dbg_curr_process->handle, de->u.LoadDll.hFile, buffer, NULL,
911                       (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
912         break_set_xpoints(FALSE);
913         break_check_delayed_bp();
914         break_set_xpoints(TRUE);
915         if (DBG_IVAR(BreakOnDllLoad))
916         {
917             dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
918                        buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
919             if (dbg_fetch_context()) cont = 0;
920         }
921         break;
922
923     case UNLOAD_DLL_DEBUG_EVENT:
924         WINE_TRACE("%08lx:%08lx: unload DLL @%08lx\n", 
925                    de->dwProcessId, de->dwThreadId,
926                    (unsigned long)de->u.UnloadDll.lpBaseOfDll);
927         break_delete_xpoints_from_module((unsigned long)de->u.UnloadDll.lpBaseOfDll);
928         SymUnloadModule(dbg_curr_process->handle, 
929                         (unsigned long)de->u.UnloadDll.lpBaseOfDll);
930         break;
931
932     case OUTPUT_DEBUG_STRING_EVENT:
933         if (dbg_curr_thread == NULL)
934         {
935             WINE_ERR("Unknown thread\n");
936             break;
937         }
938
939         memory_get_string(dbg_curr_process,
940                           de->u.DebugString.lpDebugStringData, TRUE,
941                           de->u.DebugString.fUnicode, buffer, sizeof(buffer));
942         WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
943                    de->dwProcessId, de->dwThreadId, buffer);
944         break;
945
946     case RIP_EVENT:
947         WINE_TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
948                    de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
949                    de->u.RipInfo.dwType);
950         break;
951
952     default:
953         WINE_TRACE("%08lx:%08lx: unknown event (%ld)\n",
954                    de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
955     }
956     if (!cont) return TRUE;  /* stop execution */
957     ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
958     return FALSE;  /* continue execution */
959 }
960
961 static void dbg_resume_debuggee(DWORD cont)
962 {
963     if (dbg_curr_thread->in_exception)
964     {
965         ADDRESS         addr;
966
967         dbg_exception_epilog();
968         memory_get_current_pc(&addr);
969         WINE_TRACE("Exiting debugger      PC=0x%lx mode=%d count=%d\n",
970                    addr.Offset, dbg_curr_thread->exec_mode,
971                    dbg_curr_thread->exec_count);
972         if (dbg_curr_thread)
973         {
974             if (!SetThreadContext(dbg_curr_thread->handle, &dbg_context))
975                 dbg_printf("Cannot set ctx on %lu\n", dbg_curr_tid);
976         }
977     }
978     dbg_interactiveP = FALSE;
979     if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
980         dbg_printf("Cannot continue on %lu (%lu)\n", dbg_curr_tid, cont);
981 }
982
983 void dbg_wait_next_exception(DWORD cont, int count, int mode)
984 {
985     DEBUG_EVENT         de;
986     ADDRESS             addr;
987
988     if (cont == DBG_CONTINUE)
989     {
990         dbg_curr_thread->exec_count = count;
991         dbg_curr_thread->exec_mode = mode;
992     }
993     dbg_resume_debuggee(cont);
994
995     while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
996     {
997         if (dbg_handle_debug_event(&de)) break;
998     }
999     if (!dbg_curr_process) return;
1000     dbg_interactiveP = TRUE;
1001
1002     memory_get_current_pc(&addr);
1003     WINE_TRACE("Entering debugger     PC=0x%lx mode=%d count=%d\n",
1004                addr.Offset, dbg_curr_thread->exec_mode,
1005                dbg_curr_thread->exec_count);
1006 }
1007
1008 static  unsigned        dbg_main_loop(void)
1009 {
1010     DEBUG_EVENT         de;
1011
1012     if (dbg_curr_process)
1013         dbg_printf("WineDbg starting on pid 0x%lx\n", dbg_curr_pid);
1014
1015     /* wait for first exception */
1016     while (WaitForDebugEvent(&de, INFINITE))
1017     {
1018         if (dbg_handle_debug_event(&de)) break;
1019     }
1020     switch (dbg_action_mode)
1021     {
1022     case automatic_mode:
1023         /* print some extra information */
1024         dbg_printf("Modules:\n");
1025         info_win32_module(0); /* print all modules */
1026         dbg_printf("Threads:\n");
1027         info_win32_threads();
1028         break;
1029     default:
1030         dbg_interactiveP = TRUE;
1031         parser(NULL);
1032     }
1033     dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid);
1034
1035     return 0;
1036 }
1037
1038 static  unsigned dbg_start_debuggee(LPSTR cmdLine)
1039 {
1040     PROCESS_INFORMATION info;
1041     STARTUPINFOA        startup;
1042
1043     memset(&startup, 0, sizeof(startup));
1044     startup.cb = sizeof(startup);
1045     startup.dwFlags = STARTF_USESHOWWINDOW;
1046     startup.wShowWindow = SW_SHOWNORMAL;
1047
1048     /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
1049      * while GUI:s don't
1050      */
1051     if (!CreateProcess(NULL, cmdLine, NULL, NULL,
1052                        FALSE, 
1053                        DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,
1054                        NULL, NULL, &startup, &info))
1055     {
1056         dbg_printf("Couldn't start process '%s'\n", cmdLine);
1057         return FALSE;
1058     }
1059     if (!info.dwProcessId)
1060     {
1061         /* this happens when the program being run is not a Wine binary
1062          * (for example, a shell wrapper around a WineLib app)
1063          */
1064         /* Current fix: list running processes and let the user attach
1065          * to one of them (sic)
1066          * FIXME: implement a real fix => grab the process (from the
1067          * running processes) from its name
1068          */
1069         dbg_printf("Debuggee has been started (%s)\n"
1070                    "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
1071                    "Try to attach to one of those processes:\n", cmdLine);
1072         /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
1073         Sleep(100);
1074         info_win32_processes();
1075         return TRUE;
1076     }
1077     dbg_curr_pid = info.dwProcessId;
1078     if (!(dbg_curr_process = dbg_add_process(dbg_curr_pid, 0))) return FALSE;
1079
1080     return TRUE;
1081 }
1082
1083 void    dbg_run_debuggee(const char* args)
1084 {
1085     if (args)
1086     {
1087         WINE_FIXME("Re-running current program with %s as args is broken\n", args);
1088         return;
1089     }
1090     else 
1091     {
1092         DEBUG_EVENT     de;
1093
1094         if (!dbg_last_cmd_line)
1095         {
1096             dbg_printf("Cannot find previously used command line.\n");
1097             return;
1098         }
1099         dbg_start_debuggee(dbg_last_cmd_line);
1100         while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
1101         {
1102             if (dbg_handle_debug_event(&de)) break;
1103         }
1104         source_list_from_addr(NULL, 0);
1105     }
1106 }
1107
1108 BOOL dbg_interrupt_debuggee(void)
1109 {
1110     if (!dbg_process_list) return FALSE;
1111     /* FIXME: since we likely have a single process, signal the first process
1112      * in list
1113      */
1114     if (dbg_process_list->next) dbg_printf("Ctrl-C: only stopping the first process\n");
1115     else dbg_printf("Ctrl-C: stopping debuggee\n");
1116     dbg_process_list->continue_on_first_exception = FALSE;
1117     return DebugBreakProcess(dbg_process_list->handle);
1118 }
1119
1120 static BOOL WINAPI ctrl_c_handler(DWORD dwCtrlType)
1121 {
1122     if (dwCtrlType == CTRL_C_EVENT)
1123     {
1124         return dbg_interrupt_debuggee();
1125     }
1126     return FALSE;
1127 }
1128
1129 static void dbg_init_console(void)
1130 {
1131     /* set our control-C handler */
1132     SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
1133
1134     /* set our own title */
1135     SetConsoleTitle("Wine Debugger");
1136 }
1137
1138 static int dbg_winedbg_usage(void)
1139 {
1140     dbg_printf("Usage: winedbg [--auto] [--gdb] cmdline\n");
1141     return 1;
1142 }
1143
1144 struct backend_cpu* be_cpu;
1145 #ifdef __i386__
1146 extern struct backend_cpu be_i386;
1147 #elif __powerpc__
1148 extern struct backend_cpu be_ppc;
1149 #elif __ALPHA__
1150 extern struct backend_cpu be_alpha;
1151 #else
1152 # error CPU unknown
1153 #endif
1154
1155 int main(int argc, char** argv)
1156 {
1157     DWORD       retv = 0;
1158     unsigned    gdb_flags = 0;
1159
1160 #ifdef __i386__
1161     be_cpu = &be_i386;
1162 #elif __powerpc__
1163     be_cpu = &be_ppc;
1164 #elif __ALPHA__
1165     be_cpu = &be_alpha;
1166 #else
1167 # error CPU unknown
1168 #endif
1169     /* Initialize the output */
1170     dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE);
1171
1172     /* Initialize internal vars */
1173     if (!dbg_load_internal_vars()) return -1;
1174
1175     /* parse options */
1176     while (argc > 1 && argv[1][0] == '-')
1177     {
1178         if (!strcmp(argv[1], "--command"))
1179         {
1180             argc--; argv++;
1181             arg_command = HeapAlloc(GetProcessHeap(), 0, strlen(argv[1])+2);
1182             strcpy(arg_command, argv[1]);
1183             strcat(arg_command, "\n");
1184             argc--; argv++;
1185             continue;
1186         }
1187         if (!strcmp(argv[1], "--auto"))
1188         {
1189             if (dbg_action_mode != none_mode) return dbg_winedbg_usage();
1190             dbg_action_mode = automatic_mode;
1191             /* force some internal variables */
1192             DBG_IVAR(BreakOnDllLoad) = 0;
1193             argc--; argv++;
1194             dbg_houtput = GetStdHandle(STD_ERROR_HANDLE);
1195             continue;
1196         }
1197         if (!strcmp(argv[1], "--gdb"))
1198         {
1199             if (dbg_action_mode != none_mode) return dbg_winedbg_usage();
1200             dbg_action_mode = gdb_mode;
1201             argc--; argv++;
1202             continue;
1203         }
1204         if (strcmp(argv[1], "--no-start") == 0 && dbg_action_mode == gdb_mode)
1205         {
1206             gdb_flags |= 1;
1207             argc--; argv++; /* as we don't use argv[0] */
1208             continue;
1209         }
1210         if (strcmp(argv[1], "--with-xterm") == 0 && dbg_action_mode == gdb_mode)
1211         {
1212             gdb_flags |= 2;
1213             argc--; argv++; /* as we don't use argv[0] */
1214             continue;
1215         }
1216         return dbg_winedbg_usage();
1217     }
1218
1219     if (dbg_action_mode == none_mode) dbg_action_mode = winedbg_mode;
1220
1221     /* try the form <myself> pid */
1222     if (dbg_curr_pid == 0 && argc == 2)
1223     {
1224         char*   ptr;
1225
1226         dbg_curr_pid = strtol(argv[1], &ptr, 10);
1227         if (dbg_curr_pid == 0 || ptr != argv[1] + strlen(argv[1]) ||
1228             !dbg_attach_debuggee(dbg_curr_pid, dbg_action_mode != gdb_mode, FALSE))
1229             dbg_curr_pid = 0;
1230     }
1231
1232     /* try the form <myself> pid evt (Win32 JIT debugger) */
1233     if (dbg_curr_pid == 0 && argc == 3)
1234     {
1235         HANDLE  hEvent;
1236         DWORD   pid;
1237         char*   ptr;
1238
1239         if ((pid = strtol(argv[1], &ptr, 10)) != 0 && ptr != NULL &&
1240             (hEvent = (HANDLE)strtol(argv[2], &ptr, 10)) != 0 && ptr != NULL)
1241         {
1242             if (!dbg_attach_debuggee(pid, TRUE, FALSE))
1243             {
1244                 /* don't care about result */
1245                 SetEvent(hEvent);
1246                 goto leave;
1247             }
1248             if (!SetEvent(hEvent))
1249             {
1250                 WINE_ERR("Invalid event handle: %p\n", hEvent);
1251                 goto leave;
1252             }
1253             CloseHandle(hEvent);
1254             dbg_curr_pid = pid;
1255         }
1256     }
1257
1258     if (dbg_curr_pid == 0 && argc > 1)
1259     {
1260         int     i, len;
1261         LPSTR   cmdLine;
1262
1263         if (!(cmdLine = HeapAlloc(GetProcessHeap(), 0, len = 1))) goto oom_leave;
1264         cmdLine[0] = '\0';
1265
1266         for (i = 1; i < argc; i++)
1267         {
1268             len += strlen(argv[i]) + 1;
1269             if (!(cmdLine = HeapReAlloc(GetProcessHeap(), 0, cmdLine, len)))
1270                 goto oom_leave;
1271             strcat(cmdLine, argv[i]);
1272             cmdLine[len - 2] = ' ';
1273             cmdLine[len - 1] = '\0';
1274         }
1275
1276         if (!dbg_start_debuggee(cmdLine))
1277         {
1278             dbg_printf("Couldn't start process '%s'\n", cmdLine);
1279             goto leave;
1280         }
1281         dbg_last_cmd_line = cmdLine;
1282     }
1283     /* don't save local vars in gdb mode */
1284     if (dbg_action_mode == gdb_mode && dbg_curr_pid)
1285         return gdb_remote(gdb_flags);
1286
1287     dbg_init_console();
1288
1289     SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) |
1290                   SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS);
1291
1292     retv = dbg_main_loop();
1293     /* don't save modified variables in auto mode */
1294     if (dbg_action_mode != automatic_mode) dbg_save_internal_vars();
1295
1296 leave:
1297     return retv;
1298
1299 oom_leave:
1300     dbg_printf("Out of memory\n");
1301     return retv;
1302 }