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