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