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