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