winedbg: Remove an unused debug channel.
[wine] / programs / winedbg / tgt_active.c
1 /*
2  * Wine debugger - back-end for an active target
3  *
4  * Copyright 2000-2006 Eric Pouech
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdarg.h>
27
28 #include "debugger.h"
29 #include "psapi.h"
30 #include "resource.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
33 #include "wine/exception.h"
34 #include "wine/unicode.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
37
38 static char*            dbg_last_cmd_line;
39 static struct be_process_io be_process_active_io;
40
41 static void dbg_init_current_process(void)
42 {
43 }
44
45 static void dbg_init_current_thread(void* start)
46 {
47     if (start)
48     {
49         if (dbg_curr_process->threads &&
50             !dbg_curr_process->threads->next && /* first thread ? */
51             DBG_IVAR(BreakAllThreadsStartup))
52         {
53             ADDRESS64   addr;
54
55             break_set_xpoints(FALSE);
56             addr.Mode   = AddrModeFlat;
57             addr.Offset = (DWORD_PTR)start;
58             break_add_break(&addr, TRUE, TRUE);
59             break_set_xpoints(TRUE);
60         }
61     } 
62 }
63
64 static unsigned dbg_handle_debug_event(DEBUG_EVENT* de);
65
66 /******************************************************************
67  *              dbg_attach_debuggee
68  *
69  * Sets the debuggee to <pid>
70  * cofe instructs winedbg what to do when first exception is received 
71  * (break=FALSE, continue=TRUE)
72  * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
73  * until the first exception is received (aka: attach to an already running process)
74  */
75 BOOL dbg_attach_debuggee(DWORD pid, BOOL cofe)
76 {
77     if (!(dbg_curr_process = dbg_add_process(&be_process_active_io, pid, 0))) return FALSE;
78
79     if (!DebugActiveProcess(pid)) 
80     {
81         dbg_printf("Can't attach process %04x: error %u\n", pid, GetLastError());
82         dbg_del_process(dbg_curr_process);
83         return FALSE;
84     }
85     dbg_curr_process->continue_on_first_exception = cofe;
86
87     SetEnvironmentVariableA("DBGHELP_NOLIVE", NULL);
88
89     dbg_curr_process->active_debuggee = TRUE;
90     return TRUE;
91 }
92
93 static unsigned dbg_fetch_context(void)
94 {
95     dbg_context.ContextFlags = CONTEXT_CONTROL
96         | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT
97 #ifdef CONTEXT_SEGMENTS
98         | CONTEXT_SEGMENTS
99 #endif
100 #ifdef CONTEXT_DEBUG_REGISTERS
101         | CONTEXT_DEBUG_REGISTERS
102 #endif
103         ;
104     if (!GetThreadContext(dbg_curr_thread->handle, &dbg_context))
105     {
106         WINE_WARN("Can't get thread's context\n");
107         return FALSE;
108     }
109     return TRUE;
110 }
111
112 /***********************************************************************
113  *              dbg_exception_prolog
114  *
115  * Examine exception and decide if interactive mode is entered(return TRUE)
116  * or exception is silently continued(return FALSE)
117  * is_debug means the exception is a breakpoint or single step exception
118  */
119 static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec)
120 {
121     ADDRESS64   addr;
122     BOOL        is_break;
123     char        hexbuf[MAX_OFFSET_TO_STR_LEN];
124
125     memory_get_current_pc(&addr);
126     break_suspend_execution();
127     dbg_curr_thread->excpt_record = *rec;
128     dbg_curr_thread->in_exception = TRUE;
129
130     if (!is_debug)
131     {
132         switch (addr.Mode)
133         {
134         case AddrModeFlat:
135             dbg_printf(" in 32-bit code (%s)",
136                        memory_offset_to_string(hexbuf, addr.Offset, 0));
137             break;
138         case AddrModeReal:
139             dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
140             break;
141         case AddrMode1616:
142             dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
143             break;
144         case AddrMode1632:
145             dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset);
146             break;
147         default: dbg_printf(" bad address");
148         }
149         dbg_printf(".\n");
150     }
151
152     /* this will resynchronize builtin dbghelp's internal ELF module list */
153     SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
154
155     if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break);
156     /*
157      * Do a quiet backtrace so that we have an idea of what the situation
158      * is WRT the source files.
159      */
160     stack_fetch_frames();
161
162     if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode))
163         return FALSE;
164
165     if (addr.Mode != dbg_curr_thread->addr_mode)
166     {
167         const char* name = NULL;
168         
169         switch (addr.Mode)
170         {
171         case AddrMode1616: name = "16 bit";     break;
172         case AddrMode1632: name = "32 bit";     break;
173         case AddrModeReal: name = "vm86";       break;
174         case AddrModeFlat: name = "32 bit";     break;
175         }
176         
177         dbg_printf("In %s mode.\n", name);
178         dbg_curr_thread->addr_mode = addr.Mode;
179     }
180     display_print();
181
182     if (!is_debug)
183     {
184         /* This is a real crash, dump some info */
185         be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
186         stack_info();
187         be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
188         stack_backtrace(dbg_curr_tid);
189     }
190     else
191     {
192         static char*        last_name;
193         static char*        last_file;
194
195         char                buffer[sizeof(SYMBOL_INFO) + 256];
196         SYMBOL_INFO*        si = (SYMBOL_INFO*)buffer;
197         void*               lin = memory_to_linear_addr(&addr);
198         DWORD64             disp64;
199         IMAGEHLP_LINE       il;
200         DWORD               disp;
201
202         si->SizeOfStruct = sizeof(*si);
203         si->MaxNameLen   = 256;
204         il.SizeOfStruct = sizeof(il);
205         if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) &&
206             SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il))
207         {
208             if ((!last_name || strcmp(last_name, si->Name)) ||
209                 (!last_file || strcmp(last_file, il.FileName)))
210             {
211                 HeapFree(GetProcessHeap(), 0, last_name);
212                 HeapFree(GetProcessHeap(), 0, last_file);
213                 last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name);
214                 last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName);
215                 dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber);
216             }
217         }
218     }
219     if (!is_debug || is_break ||
220         dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
221         dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
222     {
223         ADDRESS64 tmp = addr;
224         /* Show where we crashed */
225         memory_disasm_one_insn(&tmp);
226     }
227     source_list_from_addr(&addr, 0);
228
229     return TRUE;
230 }
231
232 static void dbg_exception_epilog(void)
233 {
234     break_restart_execution(dbg_curr_thread->exec_count);
235     /*
236      * This will have gotten absorbed into the breakpoint info
237      * if it was used.  Otherwise it would have been ignored.
238      * In any case, we don't mess with it any more.
239      */
240     if (dbg_curr_thread->exec_mode == dbg_exec_cont)
241         dbg_curr_thread->exec_count = 0;
242     dbg_curr_thread->in_exception = FALSE;
243 }
244
245 static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
246 {
247     BOOL                is_debug = FALSE;
248     THREADNAME_INFO*    pThreadName;
249     struct dbg_thread*  pThread;
250
251     assert(dbg_curr_thread);
252
253     WINE_TRACE("exception=%x first_chance=%c\n",
254                rec->ExceptionCode, first_chance ? 'Y' : 'N');
255
256     switch (rec->ExceptionCode)
257     {
258     case EXCEPTION_BREAKPOINT:
259     case EXCEPTION_SINGLE_STEP:
260         is_debug = TRUE;
261         break;
262     case EXCEPTION_NAME_THREAD:
263         pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
264         if (pThreadName->dwThreadID == -1)
265             pThread = dbg_curr_thread;
266         else
267             pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
268         if(!pThread)
269         {
270             dbg_printf("Thread ID=%04x not in our list of threads -> can't rename\n", pThreadName->dwThreadID);
271             return DBG_CONTINUE;
272         }
273         if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
274             dbg_printf("Thread ID=%04x renamed using MS VC6 extension (name==\"%s\")\n",
275                        pThread->tid, pThread->name);
276         return DBG_CONTINUE;
277     }
278
279     if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance) &&
280         !(rec->ExceptionFlags & EH_STACK_INVALID))
281     {
282         /* pass exception to program except for debug exceptions */
283         return DBG_EXCEPTION_NOT_HANDLED;
284     }
285
286     if (!is_debug)
287     {
288         /* print some infos */
289         dbg_printf("%s: ",
290                    first_chance ? "First chance exception" : "Unhandled exception");
291         switch (rec->ExceptionCode)
292         {
293         case EXCEPTION_INT_DIVIDE_BY_ZERO:
294             dbg_printf("divide by zero");
295             break;
296         case EXCEPTION_INT_OVERFLOW:
297             dbg_printf("overflow");
298             break;
299         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
300             dbg_printf("array bounds");
301             break;
302         case EXCEPTION_ILLEGAL_INSTRUCTION:
303             dbg_printf("illegal instruction");
304             break;
305         case EXCEPTION_STACK_OVERFLOW:
306             dbg_printf("stack overflow");
307             break;
308         case EXCEPTION_PRIV_INSTRUCTION:
309             dbg_printf("privileged instruction");
310             break;
311         case EXCEPTION_ACCESS_VIOLATION:
312             if (rec->NumberParameters == 2)
313                 dbg_printf("page fault on %s access to 0x%08lx",
314                            rec->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT ? "write" :
315                            rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ? "execute" : "read",
316                            rec->ExceptionInformation[1]);
317             else
318                 dbg_printf("page fault");
319             break;
320         case EXCEPTION_DATATYPE_MISALIGNMENT:
321             dbg_printf("Alignment");
322             break;
323         case DBG_CONTROL_C:
324             dbg_printf("^C");
325             break;
326         case CONTROL_C_EXIT:
327             dbg_printf("^C");
328             break;
329         case STATUS_POSSIBLE_DEADLOCK:
330         {
331             ADDRESS64       addr;
332
333             addr.Mode   = AddrModeFlat;
334             addr.Offset = rec->ExceptionInformation[0];
335
336             dbg_printf("wait failed on critical section ");
337             print_address(&addr, FALSE);
338         }
339         if (!DBG_IVAR(BreakOnCritSectTimeOut))
340         {
341             dbg_printf("\n");
342             return DBG_EXCEPTION_NOT_HANDLED;
343         }
344         break;
345         case EXCEPTION_WINE_STUB:
346         {
347             char dll[32], name[64];
348             memory_get_string(dbg_curr_process,
349                               (void*)rec->ExceptionInformation[0], TRUE, FALSE,
350                               dll, sizeof(dll));
351             if (HIWORD(rec->ExceptionInformation[1]))
352                 memory_get_string(dbg_curr_process,
353                                   (void*)rec->ExceptionInformation[1], TRUE, FALSE,
354                                   name, sizeof(name));
355             else
356                 sprintf( name, "%ld", rec->ExceptionInformation[1] );
357             dbg_printf("unimplemented function %s.%s called", dll, name);
358         }
359         break;
360         case EXCEPTION_WINE_ASSERTION:
361             dbg_printf("assertion failed");
362             break;
363         case EXCEPTION_VM86_INTx:
364             dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
365             break;
366         case EXCEPTION_VM86_STI:
367             dbg_printf("sti in vm86 mode");
368             break;
369         case EXCEPTION_VM86_PICRETURN:
370             dbg_printf("PIC return in vm86 mode");
371             break;
372         case EXCEPTION_FLT_DENORMAL_OPERAND:
373             dbg_printf("denormal float operand");
374             break;
375         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
376             dbg_printf("divide by zero");
377             break;
378         case EXCEPTION_FLT_INEXACT_RESULT:
379             dbg_printf("inexact float result");
380             break;
381         case EXCEPTION_FLT_INVALID_OPERATION:
382             dbg_printf("invalid float operation");
383             break;
384         case EXCEPTION_FLT_OVERFLOW:
385             dbg_printf("floating point overflow");
386             break;
387         case EXCEPTION_FLT_UNDERFLOW:
388             dbg_printf("floating point underflow");
389             break;
390         case EXCEPTION_FLT_STACK_CHECK:
391             dbg_printf("floating point stack check");
392             break;
393         case CXX_EXCEPTION:
394             if(rec->NumberParameters == 3 && rec->ExceptionInformation[0] == CXX_FRAME_MAGIC)
395                 dbg_printf("C++ exception(object = 0x%08lx, type = 0x%08lx)",
396                            rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
397             else
398                 dbg_printf("C++ exception with strange parameter count %d or magic 0x%08lx",
399                            rec->NumberParameters, rec->ExceptionInformation[0]);
400             break;
401         default:
402             dbg_printf("0x%08x", rec->ExceptionCode);
403             break;
404         }
405     }
406     if( (rec->ExceptionFlags & EH_STACK_INVALID) ) {
407         dbg_printf( ", invalid program stack" );
408     }
409
410     if (dbg_exception_prolog(is_debug, first_chance, rec))
411     {
412         dbg_interactiveP = TRUE;
413         return 0;
414     }
415     dbg_exception_epilog();
416
417     return DBG_CONTINUE;
418 }
419
420 static BOOL tgt_process_active_close_process(struct dbg_process* pcs, BOOL kill);
421
422 static void fetch_module_name(void* name_addr, BOOL unicode, void* mod_addr,
423                               WCHAR* buffer, size_t bufsz, BOOL is_pcs)
424 {
425     static WCHAR        pcspid[] = {'P','r','o','c','e','s','s','_','%','0','8','x',0};
426     static WCHAR        dlladdr[] = {'D','L','L','_','%','0','8','l','x',0};
427
428     memory_get_string_indirect(dbg_curr_process, name_addr, unicode, buffer, bufsz);
429     if (!buffer[0] &&
430         !GetModuleFileNameExW(dbg_curr_process->handle, mod_addr, buffer, bufsz))
431     {
432         if (is_pcs)
433         {
434             HMODULE h;
435             WORD (WINAPI *gpif)(HANDLE, LPWSTR, DWORD);
436
437             /* On Windows, when we get the process creation debug event for a process
438              * created by winedbg, the modules' list is not initialized yet. Hence,
439              * GetModuleFileNameExA (on the main module) will generate an error.
440              * Psapi (starting on XP) provides GetProcessImageFileName() which should
441              * give us the expected result
442              */
443             if (!(h = GetModuleHandleA("psapi")) ||
444                 !(gpif = (void*)GetProcAddress(h, "GetProcessImageFileNameW")) ||
445                 !(gpif)(dbg_curr_process->handle, buffer, bufsz))
446                 snprintfW(buffer, bufsz, pcspid, dbg_curr_pid);
447         }
448         else
449             snprintfW(buffer, bufsz, dlladdr, (unsigned long)mod_addr);
450     }
451 }
452
453 static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
454 {
455     union {
456         char    bufferA[256];
457         WCHAR   buffer[256];
458     } u;
459     DWORD       cont = DBG_CONTINUE;
460
461     dbg_curr_pid = de->dwProcessId;
462     dbg_curr_tid = de->dwThreadId;
463
464     if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
465         dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
466     else
467         dbg_curr_thread = NULL;
468
469     switch (de->dwDebugEventCode)
470     {
471     case EXCEPTION_DEBUG_EVENT:
472         if (!dbg_curr_thread)
473         {
474             WINE_ERR("%04x:%04x: not a registered process or thread (perhaps a 16 bit one ?)\n",
475                      de->dwProcessId, de->dwThreadId);
476             break;
477         }
478
479         WINE_TRACE("%04x:%04x: exception code=%08x\n",
480                    de->dwProcessId, de->dwThreadId,
481                    de->u.Exception.ExceptionRecord.ExceptionCode);
482
483         if (dbg_curr_process->continue_on_first_exception)
484         {
485             dbg_curr_process->continue_on_first_exception = FALSE;
486             if (!DBG_IVAR(BreakOnAttach)) break;
487         }
488         if (dbg_fetch_context())
489         {
490             cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
491                                         de->u.Exception.dwFirstChance);
492             if (cont && dbg_curr_thread)
493             {
494                 SetThreadContext(dbg_curr_thread->handle, &dbg_context);
495             }
496         }
497         break;
498
499     case CREATE_PROCESS_DEBUG_EVENT:
500         dbg_curr_process = dbg_add_process(&be_process_active_io, de->dwProcessId,
501                                            de->u.CreateProcessInfo.hProcess);
502         if (dbg_curr_process == NULL)
503         {
504             WINE_ERR("Couldn't create process\n");
505             break;
506         }
507         fetch_module_name(de->u.CreateProcessInfo.lpImageName,
508                           de->u.CreateProcessInfo.fUnicode,
509                           de->u.CreateProcessInfo.lpBaseOfImage,
510                           u.buffer, sizeof(u.buffer) / sizeof(WCHAR), TRUE);
511
512         WINE_TRACE("%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
513                    de->dwProcessId, de->dwThreadId,
514                    wine_dbgstr_w(u.buffer),
515                    de->u.CreateProcessInfo.lpImageName,
516                    de->u.CreateProcessInfo.lpStartAddress,
517                    de->u.CreateProcessInfo.dwDebugInfoFileOffset,
518                    de->u.CreateProcessInfo.nDebugInfoSize);
519         dbg_set_process_name(dbg_curr_process, u.buffer);
520
521         if (!dbg_init(dbg_curr_process->handle, u.buffer, FALSE))
522             dbg_printf("Couldn't initiate DbgHelp\n");
523         if (!dbg_load_module(dbg_curr_process->handle, de->u.CreateProcessInfo.hFile, u.buffer,
524                              (DWORD_PTR)de->u.CreateProcessInfo.lpBaseOfImage, 0))
525             dbg_printf("couldn't load main module (%u)\n", GetLastError());
526
527         WINE_TRACE("%04x:%04x: create thread I @%p\n",
528                    de->dwProcessId, de->dwThreadId, de->u.CreateProcessInfo.lpStartAddress);
529
530         dbg_curr_thread = dbg_add_thread(dbg_curr_process,
531                                          de->dwThreadId,
532                                          de->u.CreateProcessInfo.hThread,
533                                          de->u.CreateProcessInfo.lpThreadLocalBase);
534         if (!dbg_curr_thread)
535         {
536             WINE_ERR("Couldn't create thread\n");
537             break;
538         }
539         dbg_init_current_process();
540         dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
541         break;
542
543     case EXIT_PROCESS_DEBUG_EVENT:
544         WINE_TRACE("%04x:%04x: exit process (%d)\n",
545                    de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
546
547         if (dbg_curr_process == NULL)
548         {
549             WINE_ERR("Unknown process\n");
550             break;
551         }
552         tgt_process_active_close_process(dbg_curr_process, FALSE);
553         dbg_printf("Process of pid=%04x has terminated\n", de->dwProcessId);
554         break;
555
556     case CREATE_THREAD_DEBUG_EVENT:
557         WINE_TRACE("%04x:%04x: create thread D @%p\n",
558                    de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);
559
560         if (dbg_curr_process == NULL)
561         {
562             WINE_ERR("Unknown process\n");
563             break;
564         }
565         if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
566         {
567             WINE_TRACE("Thread already listed, skipping\n");
568             break;
569         }
570
571         dbg_curr_thread = dbg_add_thread(dbg_curr_process,
572                                          de->dwThreadId,
573                                          de->u.CreateThread.hThread,
574                                          de->u.CreateThread.lpThreadLocalBase);
575         if (!dbg_curr_thread)
576         {
577             WINE_ERR("Couldn't create thread\n");
578             break;
579         }
580         dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
581         break;
582
583     case EXIT_THREAD_DEBUG_EVENT:
584         WINE_TRACE("%04x:%04x: exit thread (%d)\n",
585                    de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
586
587         if (dbg_curr_thread == NULL)
588         {
589             WINE_ERR("Unknown thread\n");
590             break;
591         }
592         /* FIXME: remove break point set on thread startup */
593         dbg_del_thread(dbg_curr_thread);
594         break;
595
596     case LOAD_DLL_DEBUG_EVENT:
597         if (dbg_curr_thread == NULL)
598         {
599             WINE_ERR("Unknown thread\n");
600             break;
601         }
602         fetch_module_name(de->u.LoadDll.lpImageName,
603                           de->u.LoadDll.fUnicode,
604                           de->u.LoadDll.lpBaseOfDll,
605                           u.buffer, sizeof(u.buffer) / sizeof(WCHAR), FALSE);
606
607         WINE_TRACE("%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
608                    de->dwProcessId, de->dwThreadId,
609                    wine_dbgstr_w(u.buffer), de->u.LoadDll.lpBaseOfDll,
610                    de->u.LoadDll.dwDebugInfoFileOffset,
611                    de->u.LoadDll.nDebugInfoSize);
612         dbg_load_module(dbg_curr_process->handle, de->u.LoadDll.hFile, u.buffer,
613                         (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
614         break_set_xpoints(FALSE);
615         break_check_delayed_bp();
616         break_set_xpoints(TRUE);
617         if (DBG_IVAR(BreakOnDllLoad))
618         {
619             dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
620                        dbg_W2A(u.buffer, -1), (unsigned long)de->u.LoadDll.lpBaseOfDll);
621             if (dbg_fetch_context()) cont = 0;
622         }
623         break;
624
625     case UNLOAD_DLL_DEBUG_EVENT:
626         WINE_TRACE("%04x:%04x: unload DLL @%p\n",
627                    de->dwProcessId, de->dwThreadId,
628                    de->u.UnloadDll.lpBaseOfDll);
629         break_delete_xpoints_from_module((unsigned long)de->u.UnloadDll.lpBaseOfDll);
630         SymUnloadModule(dbg_curr_process->handle, 
631                         (unsigned long)de->u.UnloadDll.lpBaseOfDll);
632         break;
633
634     case OUTPUT_DEBUG_STRING_EVENT:
635         if (dbg_curr_thread == NULL)
636         {
637             WINE_ERR("Unknown thread\n");
638             break;
639         }
640
641         memory_get_string(dbg_curr_process,
642                           de->u.DebugString.lpDebugStringData, TRUE,
643                           de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
644         WINE_TRACE("%04x:%04x: output debug string (%s)\n",
645                    de->dwProcessId, de->dwThreadId, u.bufferA);
646         break;
647
648     case RIP_EVENT:
649         WINE_TRACE("%04x:%04x: rip error=%u type=%u\n",
650                    de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
651                    de->u.RipInfo.dwType);
652         break;
653
654     default:
655         WINE_TRACE("%04x:%04x: unknown event (%x)\n",
656                    de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
657     }
658     if (!cont) return TRUE;  /* stop execution */
659     ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
660     return FALSE;  /* continue execution */
661 }
662
663 static void dbg_resume_debuggee(DWORD cont)
664 {
665     if (dbg_curr_thread->in_exception)
666     {
667         ADDRESS64       addr;
668         char            hexbuf[MAX_OFFSET_TO_STR_LEN];
669
670         dbg_exception_epilog();
671         memory_get_current_pc(&addr);
672         WINE_TRACE("Exiting debugger      PC=%s mode=%d count=%d\n",
673                    memory_offset_to_string(hexbuf, addr.Offset, 0),
674                    dbg_curr_thread->exec_mode,
675                    dbg_curr_thread->exec_count);
676         if (dbg_curr_thread)
677         {
678             if (!SetThreadContext(dbg_curr_thread->handle, &dbg_context))
679                 dbg_printf("Cannot set ctx on %04x\n", dbg_curr_tid);
680         }
681     }
682     dbg_interactiveP = FALSE;
683     if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
684         dbg_printf("Cannot continue on %04x (%08x)\n", dbg_curr_tid, cont);
685 }
686
687 static void wait_exception(void)
688 {
689     DEBUG_EVENT         de;
690
691     while (dbg_num_processes() && WaitForDebugEvent(&de, INFINITE))
692     {
693         if (dbg_handle_debug_event(&de)) break;
694     }
695     dbg_interactiveP = TRUE;
696 }
697
698 void dbg_wait_next_exception(DWORD cont, int count, int mode)
699 {
700     ADDRESS64           addr;
701     char                hexbuf[MAX_OFFSET_TO_STR_LEN];
702
703     if (cont == DBG_CONTINUE)
704     {
705         dbg_curr_thread->exec_count = count;
706         dbg_curr_thread->exec_mode = mode;
707     }
708     dbg_resume_debuggee(cont);
709
710     wait_exception();
711     if (!dbg_curr_process) return;
712
713     memory_get_current_pc(&addr);
714     WINE_TRACE("Entering debugger     PC=%s mode=%d count=%d\n",
715                memory_offset_to_string(hexbuf, addr.Offset, 0),
716                dbg_curr_thread->exec_mode,
717                dbg_curr_thread->exec_count);
718 }
719
720 void     dbg_active_wait_for_first_exception(void)
721 {
722     dbg_interactiveP = FALSE;
723     /* wait for first exception */
724     wait_exception();
725 }
726
727 static  unsigned dbg_start_debuggee(LPSTR cmdLine)
728 {
729     PROCESS_INFORMATION info;
730     STARTUPINFOA        startup, current;
731     DWORD               flags;
732
733     GetStartupInfoA(&current);
734
735     memset(&startup, 0, sizeof(startup));
736     startup.cb = sizeof(startup);
737     startup.dwFlags = STARTF_USESHOWWINDOW;
738
739     startup.wShowWindow = (current.dwFlags & STARTF_USESHOWWINDOW) ?
740         current.wShowWindow : SW_SHOWNORMAL;
741
742     /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
743      * while GUI:s don't
744      */
745     flags = DEBUG_PROCESS | CREATE_NEW_CONSOLE;
746     if (!DBG_IVAR(AlsoDebugProcChild)) flags |= DEBUG_ONLY_THIS_PROCESS;
747
748     if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, flags,
749                        NULL, NULL, &startup, &info))
750     {
751         dbg_printf("Couldn't start process '%s'\n", cmdLine);
752         return FALSE;
753     }
754     if (!info.dwProcessId)
755     {
756         /* this happens when the program being run is not a Wine binary
757          * (for example, a shell wrapper around a WineLib app)
758          */
759         /* Current fix: list running processes and let the user attach
760          * to one of them (sic)
761          * FIXME: implement a real fix => grab the process (from the
762          * running processes) from its name
763          */
764         dbg_printf("Debuggee has been started (%s)\n"
765                    "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
766                    "Try to attach to one of those processes:\n", cmdLine);
767         /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
768         Sleep(100);
769         info_win32_processes();
770         return TRUE;
771     }
772     dbg_curr_pid = info.dwProcessId;
773     if (!(dbg_curr_process = dbg_add_process(&be_process_active_io, dbg_curr_pid, 0))) return FALSE;
774     dbg_curr_process->active_debuggee = TRUE;
775
776     return TRUE;
777 }
778
779 void    dbg_run_debuggee(const char* args)
780 {
781     if (args)
782     {
783         WINE_FIXME("Re-running current program with %s as args is broken\n", args);
784         return;
785     }
786     else 
787     {
788         if (!dbg_last_cmd_line)
789         {
790             dbg_printf("Cannot find previously used command line.\n");
791             return;
792         }
793         dbg_start_debuggee(dbg_last_cmd_line);
794         dbg_active_wait_for_first_exception();
795         source_list_from_addr(NULL, 0);
796     }
797 }
798
799 static BOOL     str2int(const char* str, DWORD* val)
800 {
801     char*   ptr;
802
803     *val = strtol(str, &ptr, 10);
804     return str < ptr && !*ptr;
805 }
806
807
808 /******************************************************************
809  *              dbg_active_attach
810  *
811  * Tries to attach to a running process
812  * Handles the <pid> or <pid> <evt> forms
813  */
814 enum dbg_start  dbg_active_attach(int argc, char* argv[])
815 {
816     DWORD       pid, evt;
817
818     /* try the form <myself> pid */
819     if (argc == 1 && str2int(argv[0], &pid) && pid != 0)
820     {
821         if (!dbg_attach_debuggee(pid, FALSE))
822             return start_error_init;
823     }
824     /* try the form <myself> pid evt (Win32 JIT debugger) */
825     else if (argc == 2 && str2int(argv[0], &pid) && pid != 0 &&
826              str2int(argv[1], &evt) && evt != 0)
827     {
828         if (!dbg_attach_debuggee(pid, TRUE))
829         {
830             /* don't care about result */
831             SetEvent((HANDLE)evt);
832             return start_error_init;
833         }
834         if (!SetEvent((HANDLE)evt))
835         {
836             WINE_ERR("Invalid event handle: %x\n", evt);
837             return start_error_init;
838         }
839         CloseHandle((HANDLE)evt);
840     }
841     else return start_error_parse;
842
843     dbg_curr_pid = pid;
844     return start_ok;
845 }
846
847 /******************************************************************
848  *              dbg_active_launch
849  *
850  * Launches a debuggee (with its arguments) from argc/argv
851  */
852 enum dbg_start    dbg_active_launch(int argc, char* argv[])
853 {
854     int         i, len;
855     LPSTR       cmd_line;
856
857     if (argc == 0) return start_error_parse;
858
859     if (!(cmd_line = HeapAlloc(GetProcessHeap(), 0, len = 1)))
860     {
861     oom_leave:
862         dbg_printf("Out of memory\n");
863         return start_error_init;
864     }
865     cmd_line[0] = '\0';
866
867     for (i = 0; i < argc; i++)
868     {
869         len += strlen(argv[i]) + 1;
870         if (!(cmd_line = HeapReAlloc(GetProcessHeap(), 0, cmd_line, len)))
871             goto oom_leave;
872         strcat(cmd_line, argv[i]);
873         cmd_line[len - 2] = ' ';
874         cmd_line[len - 1] = '\0';
875     }
876
877     if (!dbg_start_debuggee(cmd_line))
878     {
879         HeapFree(GetProcessHeap(), 0, cmd_line);
880         return start_error_init;
881     }
882     HeapFree(GetProcessHeap(), 0, dbg_last_cmd_line);
883     dbg_last_cmd_line = cmd_line;
884     return start_ok;
885 }
886
887 /******************************************************************
888  *              dbg_active_auto
889  *
890  * Starts (<pid> or <pid> <evt>) in automatic mode
891  */
892 enum dbg_start dbg_active_auto(int argc, char* argv[])
893 {
894     HANDLE              hFile;
895     enum dbg_start      ds = start_error_parse;
896
897     if (!strcmp(argv[0], "--auto"))
898     {
899         /* auto mode */
900         argc--; argv++;
901         ds = dbg_active_attach(argc, argv);
902         if (ds != start_ok) {
903             msgbox_res_id(NULL, IDS_INVALID_PARAMS, IDS_AUTO_CAPTION, MB_OK);
904             return ds;
905         }
906         if (!display_crash_dialog()) {
907             dbg_init_console();
908             dbg_start_interactive(INVALID_HANDLE_VALUE);
909             return start_ok;
910         }
911
912         hFile = parser_generate_command_file("echo Modules:", "info share",
913                                              "echo Threads:", "info threads",
914                                              "backtrace", "detach", NULL);
915     }
916     else if (!strcmp(argv[0], "--minidump"))
917     {
918         const char*     file = NULL;
919         char            tmp[8 + 1 + MAX_PATH]; /* minidump <file> */
920
921         argc--; argv++;
922         /* hard stuff now ; we can get things like:
923          * --minidump <pid>                     1 arg
924          * --minidump <pid> <evt>               2 args
925          * --minidump <file> <pid>              2 args
926          * --minidump <file> <pid> <evt>        3 args
927          */
928         switch (argc)
929         {
930         case 1:
931             ds = dbg_active_attach(argc, argv);
932             break;
933         case 2:
934             if ((ds = dbg_active_attach(argc, argv)) != start_ok)
935             {
936                 file = argv[0];
937                 ds = dbg_active_attach(argc - 1, argv + 1);
938             }
939             break;
940         case 3:
941             file = argv[0];
942             ds = dbg_active_attach(argc - 1, argv + 1);
943             break;
944         default:
945             return start_error_parse;
946         }
947         if (ds != start_ok) return ds;
948         memcpy(tmp, "minidump \"", 10);
949         if (!file)
950         {
951             char        path[MAX_PATH];
952
953             GetTempPath(sizeof(path), path);
954             GetTempFileName(path, "WD", 0, tmp + 10);
955         }
956         else strcpy(tmp + 10, file);
957         strcat(tmp, "\"");
958         if (!file)
959         {
960             /* FIXME: should generate unix name as well */
961             dbg_printf("Capturing program state in %s\n", tmp + 9);
962         }
963         hFile = parser_generate_command_file(tmp, "detach", NULL);
964     }
965     else return start_error_parse;
966     if (hFile == INVALID_HANDLE_VALUE) return start_error_parse;
967
968     if (dbg_curr_process->active_debuggee)
969         dbg_active_wait_for_first_exception();
970
971     dbg_interactiveP = TRUE;
972     parser_handle(hFile);
973
974     return start_ok;
975 }
976
977 static BOOL tgt_process_active_close_process(struct dbg_process* pcs, BOOL kill)
978 {
979     if (pcs == dbg_curr_process)
980     {
981         /* remove all set breakpoints in debuggee code */
982         break_set_xpoints(FALSE);
983         /* needed for single stepping (ugly).
984          * should this be handled inside the server ??? 
985          */
986         be_cpu->single_step(&dbg_context, FALSE);
987         if (dbg_curr_thread->in_exception)
988         {
989             SetThreadContext(dbg_curr_thread->handle, &dbg_context);
990             ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
991         }
992     }
993     if (kill)
994     {
995         TerminateProcess(pcs->handle, 0);
996     }
997     else
998     {
999         if (!DebugActiveProcessStop(pcs->pid)) return FALSE;
1000     }
1001     SymCleanup(pcs->handle);
1002     dbg_del_process(pcs);
1003
1004     return TRUE;
1005 }
1006
1007 static struct be_process_io be_process_active_io =
1008 {
1009     tgt_process_active_close_process,
1010     ReadProcessMemory,
1011     WriteProcessMemory,
1012     GetThreadSelectorEntry,
1013 };