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