1 /* Wine internal debugger
2 * Interface to Windows debugger API
3 * Copyright 2000-2004 Eric Pouech
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "wine/port.h"
29 #include "wine/exception.h"
30 #include "wine/library.h"
32 #include "wine/debug.h"
37 * + allow winedbg in automatic mode to create a minidump (or add another option
39 * + set a mode where winedbg would start (postmortem debugging) from a minidump
41 * + we always assume the stack grows as on i386 (ie downwards)
43 * + enable back the limited output (depth of structure printing and number of
45 * + make the output as close as possible to what gdb does
46 * - symbol management:
47 * + symbol table loading is broken
48 * + in symbol_get_lvalue, we don't do any scoping (as C does) between local and
49 * global vars (we may need this to force some display for example). A solution
50 * would be always to return arrays with: local vars, global vars, thunks
52 * + some bits of internal types are missing (like type casts and the address
54 * + the type for an enum's value is always inferred as int (winedbg & dbghelp)
55 * + most of the code implies that sizeof(void*) = sizeof(int)
56 * + all computations should be made on long long
57 * o expr computations are in int:s
58 * o bitfield size is on a 4-bytes
59 * + array_index and deref should be the same function (or should share the same
62 * + set a better fix for gdb (proxy mode) than the step-mode hack
63 * + implement function call in debuggee
64 * + trampoline management is broken when getting 16 <=> 32 thunk destination
66 * + thunking of delayed imports doesn't work as expected (ie, when stepping,
67 * it currently stops at first insn with line number during the library
68 * loading). We should identify this (__wine_delay_import) and set a
69 * breakpoint instead of single stepping the library loading.
70 * + it's wrong to copy thread->step_over_bp into process->bp[0] (when
71 * we have a multi-thread debuggee). complete fix must include storing all
72 * thread's step-over bp in process-wide bp array, and not to handle bp
73 * when we have the wrong thread running into that bp
74 * + code in CREATE_PROCESS debug event doesn't work on Windows, as we cannot
75 * get the name of the main module this way. We should rewrite all this code
76 * and store in struct dbg_process as early as possible (before process
77 * creation or attachment), the name of the main module
79 * + define a better way to enable the wine extensions (either DBG SDK function
80 * in dbghelp, or TLS variable, or environment variable or ...)
81 * + audit all files to ensure that we check all potential return values from
82 * every function call to catch the errors
83 * + BTW check also whether the exception mechanism is the best way to return
84 * errors (or find a proper fix for MinGW port)
85 * + use Wine standard list mechanism for all list handling
88 WINE_DEFAULT_DEBUG_CHANNEL(winedbg
);
90 struct dbg_process
* dbg_curr_process
= NULL
;
91 struct dbg_thread
* dbg_curr_thread
= NULL
;
95 BOOL dbg_interactiveP
= FALSE
;
96 static char* dbg_last_cmd_line
= NULL
;
98 static struct dbg_process
* dbg_process_list
= NULL
;
99 static enum {none_mode
= 0, winedbg_mode
, automatic_mode
, gdb_mode
} dbg_action_mode
;
101 struct dbg_internal_var dbg_internal_vars
[DBG_IV_LAST
];
102 const struct dbg_internal_var
* dbg_context_vars
;
103 static HANDLE dbg_houtput
;
105 void dbg_outputA(const char* buffer
, int len
)
107 static char line_buff
[4096];
108 static unsigned int line_pos
;
114 unsigned int count
= min( len
, sizeof(line_buff
) - line_pos
);
115 memcpy( line_buff
+ line_pos
, buffer
, count
);
119 for (i
= line_pos
; i
> 0; i
--) if (line_buff
[i
-1] == '\n') break;
120 if (!i
) /* no newline found */
122 if (len
> 0) i
= line_pos
; /* buffer is full, flush anyway */
125 WriteFile(dbg_houtput
, line_buff
, i
, &w
, NULL
);
126 memmove( line_buff
, line_buff
+ i
, line_pos
- i
);
131 void dbg_outputW(const WCHAR
* buffer
, int len
)
136 /* do a serious Unicode to ANSI conversion
137 * FIXME: should CP_ACP be GetConsoleCP()?
139 newlen
= WideCharToMultiByte(CP_ACP
, 0, buffer
, len
, NULL
, 0, NULL
, NULL
);
142 if (!(ansi
= HeapAlloc(GetProcessHeap(), 0, newlen
))) return;
143 WideCharToMultiByte(CP_ACP
, 0, buffer
, len
, ansi
, newlen
, NULL
, NULL
);
144 dbg_outputA(ansi
, newlen
);
145 HeapFree(GetProcessHeap(), 0, ansi
);
149 int dbg_printf(const char* format
, ...)
151 static char buf
[4*1024];
155 va_start(valist
, format
);
156 len
= vsnprintf(buf
, sizeof(buf
), format
, valist
);
159 if (len
<= -1 || len
>= sizeof(buf
))
161 len
= sizeof(buf
) - 1;
163 buf
[len
- 1] = buf
[len
- 2] = buf
[len
- 3] = '.';
165 dbg_outputA(buf
, len
);
169 static unsigned dbg_load_internal_vars(void)
172 DWORD type
= REG_DWORD
;
174 DWORD count
= sizeof(val
);
176 struct dbg_internal_var
* div
= dbg_internal_vars
;
178 /* initializes internal vars table */
179 #define INTERNAL_VAR(_var,_val,_ref,_tid) \
180 div->val = _val; div->name = #_var; div->pval = _ref; \
181 div->typeid = _tid; div++;
185 /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
186 if (RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\WineDbg", &hkey
))
188 WINE_ERR("Cannot create WineDbg key in registry\n");
192 for (i
= 0; i
< DBG_IV_LAST
; i
++)
194 if (!dbg_internal_vars
[i
].pval
)
196 if (!RegQueryValueEx(hkey
, dbg_internal_vars
[i
].name
, 0,
197 &type
, (LPBYTE
)&val
, &count
))
198 dbg_internal_vars
[i
].val
= val
;
199 dbg_internal_vars
[i
].pval
= &dbg_internal_vars
[i
].val
;
203 /* set up the debug variables for the CPU context */
204 dbg_context_vars
= be_cpu
->init_registers(&dbg_context
);
208 static unsigned dbg_save_internal_vars(void)
213 /* @@ Wine registry key: HKCU\Software\Wine\WineDbg */
214 if (RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\WineDbg", &hkey
))
216 WINE_ERR("Cannot create WineDbg key in registry\n");
220 for (i
= 0; i
< DBG_IV_LAST
; i
++)
222 /* FIXME: type should be infered from basic type -if any- of intvar */
223 if (dbg_internal_vars
[i
].pval
== &dbg_internal_vars
[i
].val
)
224 RegSetValueEx(hkey
, dbg_internal_vars
[i
].name
, 0,
225 REG_DWORD
, (const void*)dbg_internal_vars
[i
].pval
,
226 sizeof(*dbg_internal_vars
[i
].pval
));
232 const struct dbg_internal_var
* dbg_get_internal_var(const char* name
)
234 const struct dbg_internal_var
* div
;
236 for (div
= &dbg_internal_vars
[DBG_IV_LAST
- 1]; div
>= dbg_internal_vars
; div
--)
238 if (!strcmp(div
->name
, name
)) return div
;
240 for (div
= dbg_context_vars
; div
->name
; div
++)
242 if (!strcasecmp(div
->name
, name
)) return div
;
248 struct dbg_process
* dbg_get_process(DWORD pid
)
250 struct dbg_process
* p
;
252 for (p
= dbg_process_list
; p
; p
= p
->next
)
253 if (p
->pid
== pid
) break;
257 struct dbg_process
* dbg_add_process(DWORD pid
, HANDLE h
)
259 /* FIXME: temporary */
260 extern struct be_process_io be_process_active_io
;
262 struct dbg_process
* p
;
264 if ((p
= dbg_get_process(pid
)))
268 WINE_ERR("Process (%lu) is already defined\n", pid
);
278 if (!(p
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_process
)))) return NULL
;
281 p
->process_io
= &be_process_active_io
;
284 p
->continue_on_first_exception
= FALSE
;
285 p
->next_bp
= 1; /* breakpoint 0 is reserved for step-over */
286 memset(p
->bp
, 0, sizeof(p
->bp
));
287 p
->delayed_bp
= NULL
;
288 p
->num_delayed_bp
= 0;
290 p
->next
= dbg_process_list
;
292 if (dbg_process_list
) dbg_process_list
->prev
= p
;
293 dbg_process_list
= p
;
297 void dbg_set_process_name(struct dbg_process
* p
, const char* imageName
)
299 assert(p
->imageName
== NULL
);
302 char* tmp
= HeapAlloc(GetProcessHeap(), 0, strlen(imageName
) + 1);
303 if (tmp
) p
->imageName
= strcpy(tmp
, imageName
);
307 void dbg_del_process(struct dbg_process
* p
)
311 while (p
->threads
) dbg_del_thread(p
->threads
);
313 for (i
= 0; i
< p
->num_delayed_bp
; i
++)
314 if (p
->delayed_bp
[i
].is_symbol
)
315 HeapFree(GetProcessHeap(), 0, p
->delayed_bp
[i
].u
.symbol
.name
);
317 HeapFree(GetProcessHeap(), 0, p
->delayed_bp
);
318 if (p
->prev
) p
->prev
->next
= p
->next
;
319 if (p
->next
) p
->next
->prev
= p
->prev
;
320 if (p
== dbg_process_list
) dbg_process_list
= p
->next
;
321 if (p
== dbg_curr_process
) dbg_curr_process
= NULL
;
322 HeapFree(GetProcessHeap(), 0, (char*)p
->imageName
);
323 HeapFree(GetProcessHeap(), 0, p
);
326 static void dbg_init_current_process(void)
330 struct mod_loader_info
333 IMAGEHLP_MODULE
* imh_mod
;
336 static BOOL CALLBACK
mod_loader_cb(PSTR mod_name
, DWORD base
, void* ctx
)
338 struct mod_loader_info
* mli
= (struct mod_loader_info
*)ctx
;
340 if (!strcmp(mod_name
, "<wine-loader>"))
342 if (SymGetModuleInfo(mli
->handle
, base
, mli
->imh_mod
))
343 return FALSE
; /* stop enum */
348 BOOL
dbg_get_debuggee_info(HANDLE hProcess
, IMAGEHLP_MODULE
* imh_mod
)
350 struct mod_loader_info mli
;
353 /* this will resynchronize builtin dbghelp's internal ELF module list */
354 SymLoadModule(hProcess
, 0, 0, 0, 0, 0);
355 mli
.handle
= hProcess
;
356 mli
.imh_mod
= imh_mod
;
357 imh_mod
->SizeOfStruct
= sizeof(*imh_mod
);
358 imh_mod
->BaseOfImage
= 0;
359 /* this is a wine specific options to return also ELF modules in the
362 SymSetOptions((opt
= SymGetOptions()) | 0x40000000);
363 SymEnumerateModules(hProcess
, mod_loader_cb
, (void*)&mli
);
366 return imh_mod
->BaseOfImage
!= 0;
369 struct dbg_thread
* dbg_get_thread(struct dbg_process
* p
, DWORD tid
)
371 struct dbg_thread
* t
;
374 for (t
= p
->threads
; t
; t
= t
->next
)
375 if (t
->tid
== tid
) break;
379 struct dbg_thread
* dbg_add_thread(struct dbg_process
* p
, DWORD tid
,
382 struct dbg_thread
* t
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct dbg_thread
));
391 t
->exec_mode
= dbg_exec_cont
;
393 t
->step_over_bp
.enabled
= FALSE
;
394 t
->step_over_bp
.refcount
= 0;
395 t
->stopped_xpoint
= -1;
396 t
->in_exception
= FALSE
;
401 snprintf(t
->name
, sizeof(t
->name
), "0x%08lx", tid
);
403 t
->next
= p
->threads
;
405 if (p
->threads
) p
->threads
->prev
= t
;
411 static void dbg_init_current_thread(void* start
)
415 if (dbg_curr_process
->threads
&&
416 !dbg_curr_process
->threads
->next
&& /* first thread ? */
417 DBG_IVAR(BreakAllThreadsStartup
))
421 break_set_xpoints(FALSE
);
422 addr
.Mode
= AddrModeFlat
;
423 addr
.Offset
= (DWORD
)start
;
424 break_add_break(&addr
, TRUE
, TRUE
);
425 break_set_xpoints(TRUE
);
430 void dbg_del_thread(struct dbg_thread
* t
)
432 HeapFree(GetProcessHeap(), 0, t
->frames
);
433 if (t
->prev
) t
->prev
->next
= t
->next
;
434 if (t
->next
) t
->next
->prev
= t
->prev
;
435 if (t
== t
->process
->threads
) t
->process
->threads
= t
->next
;
436 if (t
== dbg_curr_thread
) dbg_curr_thread
= NULL
;
437 HeapFree(GetProcessHeap(), 0, t
);
440 static unsigned dbg_handle_debug_event(DEBUG_EVENT
* de
);
442 /******************************************************************
443 * dbg_attach_debuggee
445 * Sets the debuggee to <pid>
446 * cofe instructs winedbg what to do when first exception is received
447 * (break=FALSE, continue=TRUE)
448 * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
449 * until the first exception is received (aka: attach to an already running process)
451 BOOL
dbg_attach_debuggee(DWORD pid
, BOOL cofe
, BOOL wfe
)
455 if (!(dbg_curr_process
= dbg_add_process(pid
, 0))) return FALSE
;
457 if (!DebugActiveProcess(pid
))
459 dbg_printf("Can't attach process %lx: error %ld\n", pid
, GetLastError());
460 dbg_del_process(dbg_curr_process
);
463 dbg_curr_process
->continue_on_first_exception
= cofe
;
465 if (wfe
) /* shall we proceed all debug events until we get an exception ? */
467 dbg_interactiveP
= FALSE
;
468 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
470 if (dbg_handle_debug_event(&de
)) break;
472 if (dbg_curr_process
) dbg_interactiveP
= TRUE
;
477 BOOL
dbg_detach_debuggee(void)
479 /* remove all set breakpoints in debuggee code */
480 break_set_xpoints(FALSE
);
481 /* needed for single stepping (ugly).
482 * should this be handled inside the server ???
484 be_cpu
->single_step(&dbg_context
, FALSE
);
485 SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
);
486 if (dbg_curr_thread
->in_exception
)
487 ContinueDebugEvent(dbg_curr_pid
, dbg_curr_tid
, DBG_CONTINUE
);
488 if (!DebugActiveProcessStop(dbg_curr_pid
)) return FALSE
;
489 dbg_del_process(dbg_curr_process
);
494 static unsigned dbg_fetch_context(void)
496 dbg_context
.ContextFlags
= CONTEXT_CONTROL
498 #ifdef CONTEXT_SEGMENTS
501 #ifdef CONTEXT_DEBUG_REGISTERS
502 | CONTEXT_DEBUG_REGISTERS
505 if (!GetThreadContext(dbg_curr_thread
->handle
, &dbg_context
))
507 WINE_WARN("Can't get thread's context\n");
513 static unsigned dbg_exception_prolog(BOOL is_debug
, const EXCEPTION_RECORD
* rec
)
518 memory_get_current_pc(&addr
);
519 break_suspend_execution();
520 dbg_curr_thread
->excpt_record
= *rec
;
521 dbg_curr_thread
->in_exception
= TRUE
;
527 case AddrModeFlat
: dbg_printf(" in 32-bit code (0x%08lx)", addr
.Offset
); break;
528 case AddrModeReal
: dbg_printf(" in vm86 code (%04x:%04lx)", addr
.Segment
, addr
.Offset
); break;
529 case AddrMode1616
: dbg_printf(" in 16-bit code (%04x:%04lx)", addr
.Segment
, addr
.Offset
); break;
530 case AddrMode1632
: dbg_printf(" in 32-bit code (%04x:%08lx)", addr
.Segment
, addr
.Offset
); break;
531 default: dbg_printf(" bad address");
536 /* this will resynchronize builtin dbghelp's internal ELF module list */
537 SymLoadModule(dbg_curr_process
->handle
, 0, 0, 0, 0, 0);
540 * Do a quiet backtrace so that we have an idea of what the situation
541 * is WRT the source files.
543 stack_fetch_frames();
545 break_should_continue(&addr
, rec
->ExceptionCode
, &dbg_curr_thread
->exec_count
, &is_break
))
548 if (addr
.Mode
!= dbg_curr_thread
->addr_mode
)
550 const char* name
= NULL
;
554 case AddrMode1616
: name
= "16 bit"; break;
555 case AddrMode1632
: name
= "32 bit"; break;
556 case AddrModeReal
: name
= "vm86"; break;
557 case AddrModeFlat
: name
= "32 bit"; break;
560 dbg_printf("In %s mode.\n", name
);
561 dbg_curr_thread
->addr_mode
= addr
.Mode
;
567 /* This is a real crash, dump some info */
568 be_cpu
->print_context(dbg_curr_thread
->handle
, &dbg_context
);
570 be_cpu
->print_segment_info(dbg_curr_thread
->handle
, &dbg_context
);
571 stack_backtrace(dbg_curr_tid
);
575 static char* last_name
;
576 static char* last_file
;
578 char buffer
[sizeof(SYMBOL_INFO
) + 256];
579 SYMBOL_INFO
* si
= (SYMBOL_INFO
*)buffer
;
580 void* lin
= memory_to_linear_addr(&addr
);
585 si
->SizeOfStruct
= sizeof(*si
);
586 si
->MaxNameLen
= 256;
587 il
.SizeOfStruct
= sizeof(il
);
588 if (SymFromAddr(dbg_curr_process
->handle
, (DWORD_PTR
)lin
, &disp64
, si
) &&
589 SymGetLineFromAddr(dbg_curr_process
->handle
, (DWORD_PTR
)lin
, &disp
, &il
))
591 if ((!last_name
|| strcmp(last_name
, si
->Name
)) ||
592 (!last_file
|| strcmp(last_file
, il
.FileName
)))
594 HeapFree(GetProcessHeap(), 0, last_name
);
595 HeapFree(GetProcessHeap(), 0, last_file
);
596 last_name
= strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si
->Name
) + 1), si
->Name
);
597 last_file
= strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il
.FileName
) + 1), il
.FileName
);
598 dbg_printf("%s () at %s:%ld\n", last_name
, last_file
, il
.LineNumber
);
602 if (!is_debug
|| is_break
||
603 dbg_curr_thread
->exec_mode
== dbg_exec_step_over_insn
||
604 dbg_curr_thread
->exec_mode
== dbg_exec_step_into_insn
)
607 /* Show where we crashed */
608 memory_disasm_one_insn(&tmp
);
610 source_list_from_addr(&addr
, 0);
615 static void dbg_exception_epilog(void)
617 break_restart_execution(dbg_curr_thread
->exec_count
);
619 * This will have gotten absorbed into the breakpoint info
620 * if it was used. Otherwise it would have been ignored.
621 * In any case, we don't mess with it any more.
623 if (dbg_curr_thread
->exec_mode
== dbg_exec_cont
)
624 dbg_curr_thread
->exec_count
= 0;
625 dbg_curr_thread
->in_exception
= FALSE
;
628 static DWORD
dbg_handle_exception(const EXCEPTION_RECORD
* rec
, BOOL first_chance
)
630 BOOL is_debug
= FALSE
;
631 THREADNAME_INFO
* pThreadName
;
632 struct dbg_thread
* pThread
;
634 assert(dbg_curr_thread
);
636 WINE_TRACE("exception=%lx first_chance=%c\n",
637 rec
->ExceptionCode
, first_chance
? 'Y' : 'N');
639 switch (rec
->ExceptionCode
)
641 case EXCEPTION_BREAKPOINT
:
642 case EXCEPTION_SINGLE_STEP
:
645 case EXCEPTION_NAME_THREAD
:
646 pThreadName
= (THREADNAME_INFO
*)(rec
->ExceptionInformation
);
647 if (pThreadName
->dwThreadID
== -1)
648 pThread
= dbg_curr_thread
;
650 pThread
= dbg_get_thread(dbg_curr_process
, pThreadName
->dwThreadID
);
652 if (dbg_read_memory(pThreadName
->szName
, pThread
->name
, 9))
653 dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
654 pThread
->tid
, pThread
->name
);
658 if (first_chance
&& !is_debug
&& !DBG_IVAR(BreakOnFirstChance
) &&
659 !(rec
->ExceptionFlags
& EH_STACK_INVALID
))
661 /* pass exception to program except for debug exceptions */
662 return DBG_EXCEPTION_NOT_HANDLED
;
667 /* print some infos */
669 first_chance
? "First chance exception" : "Unhandled exception");
670 switch (rec
->ExceptionCode
)
672 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
673 dbg_printf("divide by zero");
675 case EXCEPTION_INT_OVERFLOW
:
676 dbg_printf("overflow");
678 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
679 dbg_printf("array bounds");
681 case EXCEPTION_ILLEGAL_INSTRUCTION
:
682 dbg_printf("illegal instruction");
684 case EXCEPTION_STACK_OVERFLOW
:
685 dbg_printf("stack overflow");
687 case EXCEPTION_PRIV_INSTRUCTION
:
688 dbg_printf("privileged instruction");
690 case EXCEPTION_ACCESS_VIOLATION
:
691 if (rec
->NumberParameters
== 2)
692 dbg_printf("page fault on %s access to 0x%08lx",
693 rec
->ExceptionInformation
[0] ? "write" : "read",
694 rec
->ExceptionInformation
[1]);
696 dbg_printf("page fault");
698 case EXCEPTION_DATATYPE_MISALIGNMENT
:
699 dbg_printf("Alignment");
707 case STATUS_POSSIBLE_DEADLOCK
:
711 addr
.Mode
= AddrModeFlat
;
712 addr
.Offset
= rec
->ExceptionInformation
[0];
714 dbg_printf("wait failed on critical section ");
715 print_address(&addr
, FALSE
);
717 if (!DBG_IVAR(BreakOnCritSectTimeOut
))
720 return DBG_EXCEPTION_NOT_HANDLED
;
723 case EXCEPTION_WINE_STUB
:
725 char dll
[32], name
[64];
726 memory_get_string(dbg_curr_process
,
727 (void*)rec
->ExceptionInformation
[0], TRUE
, FALSE
,
729 if (HIWORD(rec
->ExceptionInformation
[1]))
730 memory_get_string(dbg_curr_process
,
731 (void*)rec
->ExceptionInformation
[1], TRUE
, FALSE
,
734 sprintf( name
, "%ld", rec
->ExceptionInformation
[1] );
735 dbg_printf("unimplemented function %s.%s called", dll
, name
);
738 case EXCEPTION_WINE_ASSERTION
:
739 dbg_printf("assertion failed");
741 case EXCEPTION_VM86_INTx
:
742 dbg_printf("interrupt %02lx in vm86 mode", rec
->ExceptionInformation
[0]);
744 case EXCEPTION_VM86_STI
:
745 dbg_printf("sti in vm86 mode");
747 case EXCEPTION_VM86_PICRETURN
:
748 dbg_printf("PIC return in vm86 mode");
750 case EXCEPTION_FLT_DENORMAL_OPERAND
:
751 dbg_printf("denormal float operand");
753 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
754 dbg_printf("divide by zero");
756 case EXCEPTION_FLT_INEXACT_RESULT
:
757 dbg_printf("inexact float result");
759 case EXCEPTION_FLT_INVALID_OPERATION
:
760 dbg_printf("invalid float operation");
762 case EXCEPTION_FLT_OVERFLOW
:
763 dbg_printf("floating pointer overflow");
765 case EXCEPTION_FLT_UNDERFLOW
:
766 dbg_printf("floating pointer underflow");
768 case EXCEPTION_FLT_STACK_CHECK
:
769 dbg_printf("floating point stack check");
772 dbg_printf("0x%08lx", rec
->ExceptionCode
);
776 if( (rec
->ExceptionFlags
& EH_STACK_INVALID
) ) {
777 dbg_printf( ", invalid program stack" );
780 if (dbg_action_mode
== automatic_mode
)
782 dbg_exception_prolog(is_debug
, rec
);
783 dbg_exception_epilog();
784 return 0; /* terminate execution */
787 if (dbg_exception_prolog(is_debug
, rec
))
789 dbg_interactiveP
= TRUE
;
792 dbg_exception_epilog();
797 static unsigned dbg_handle_debug_event(DEBUG_EVENT
* de
)
800 DWORD cont
= DBG_CONTINUE
;
802 dbg_curr_pid
= de
->dwProcessId
;
803 dbg_curr_tid
= de
->dwThreadId
;
805 if ((dbg_curr_process
= dbg_get_process(de
->dwProcessId
)) != NULL
)
806 dbg_curr_thread
= dbg_get_thread(dbg_curr_process
, de
->dwThreadId
);
808 dbg_curr_thread
= NULL
;
810 switch (de
->dwDebugEventCode
)
812 case EXCEPTION_DEBUG_EVENT
:
813 if (!dbg_curr_thread
)
815 WINE_ERR("%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
816 de
->dwProcessId
, de
->dwThreadId
);
820 WINE_TRACE("%08lx:%08lx: exception code=%08lx\n",
821 de
->dwProcessId
, de
->dwThreadId
,
822 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
824 if (dbg_curr_process
->continue_on_first_exception
)
826 dbg_curr_process
->continue_on_first_exception
= FALSE
;
827 if (!DBG_IVAR(BreakOnAttach
)) break;
829 if (dbg_fetch_context())
831 cont
= dbg_handle_exception(&de
->u
.Exception
.ExceptionRecord
,
832 de
->u
.Exception
.dwFirstChance
);
833 if (cont
&& dbg_curr_thread
)
835 SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
);
840 case CREATE_PROCESS_DEBUG_EVENT
:
841 dbg_curr_process
= dbg_add_process(de
->dwProcessId
,
842 de
->u
.CreateProcessInfo
.hProcess
);
843 if (dbg_curr_process
== NULL
)
845 WINE_ERR("Couldn't create process\n");
848 memory_get_string_indirect(dbg_curr_process
,
849 de
->u
.CreateProcessInfo
.lpImageName
,
850 de
->u
.CreateProcessInfo
.fUnicode
,
851 buffer
, sizeof(buffer
));
852 if (!buffer
[0]) strcpy(buffer
, "<Debugged Process>");
854 WINE_TRACE("%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
855 de
->dwProcessId
, de
->dwThreadId
,
856 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
857 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
,
858 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
859 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
860 dbg_set_process_name(dbg_curr_process
, buffer
);
862 if (!SymInitialize(dbg_curr_process
->handle
, NULL
, TRUE
))
863 dbg_printf("Couldn't initiate DbgHelp\n");
865 WINE_TRACE("%08lx:%08lx: create thread I @%08lx\n",
866 de
->dwProcessId
, de
->dwThreadId
,
867 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
);
869 dbg_curr_thread
= dbg_add_thread(dbg_curr_process
,
871 de
->u
.CreateProcessInfo
.hThread
,
872 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
873 if (!dbg_curr_thread
)
875 WINE_ERR("Couldn't create thread\n");
878 dbg_init_current_process();
879 dbg_init_current_thread(de
->u
.CreateProcessInfo
.lpStartAddress
);
882 case EXIT_PROCESS_DEBUG_EVENT
:
883 WINE_TRACE("%08lx:%08lx: exit process (%ld)\n",
884 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
886 if (dbg_curr_process
== NULL
)
888 WINE_ERR("Unknown process\n");
891 if (!SymCleanup(dbg_curr_process
->handle
))
892 dbg_printf("Couldn't initiate DbgHelp\n");
894 break_set_xpoints(FALSE
);
895 /* kill last thread */
896 dbg_del_thread(dbg_curr_process
->threads
);
897 dbg_del_process(dbg_curr_process
);
899 dbg_printf("Process of pid=0x%08lx has terminated\n", dbg_curr_pid
);
902 case CREATE_THREAD_DEBUG_EVENT
:
903 WINE_TRACE("%08lx:%08lx: create thread D @%08lx\n",
904 de
->dwProcessId
, de
->dwThreadId
,
905 (unsigned long)(void*)de
->u
.CreateThread
.lpStartAddress
);
907 if (dbg_curr_process
== NULL
)
909 WINE_ERR("Unknown process\n");
912 if (dbg_get_thread(dbg_curr_process
, de
->dwThreadId
) != NULL
)
914 WINE_TRACE("Thread already listed, skipping\n");
918 dbg_curr_thread
= dbg_add_thread(dbg_curr_process
,
920 de
->u
.CreateThread
.hThread
,
921 de
->u
.CreateThread
.lpThreadLocalBase
);
922 if (!dbg_curr_thread
)
924 WINE_ERR("Couldn't create thread\n");
927 dbg_init_current_thread(de
->u
.CreateThread
.lpStartAddress
);
930 case EXIT_THREAD_DEBUG_EVENT
:
931 WINE_TRACE("%08lx:%08lx: exit thread (%ld)\n",
932 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
934 if (dbg_curr_thread
== NULL
)
936 WINE_ERR("Unknown thread\n");
939 /* FIXME: remove break point set on thread startup */
940 dbg_del_thread(dbg_curr_thread
);
943 case LOAD_DLL_DEBUG_EVENT
:
944 if (dbg_curr_thread
== NULL
)
946 WINE_ERR("Unknown thread\n");
949 memory_get_string_indirect(dbg_curr_process
,
950 de
->u
.LoadDll
.lpImageName
,
951 de
->u
.LoadDll
.fUnicode
,
952 buffer
, sizeof(buffer
));
954 WINE_TRACE("%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
955 de
->dwProcessId
, de
->dwThreadId
,
956 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
,
957 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
958 de
->u
.LoadDll
.nDebugInfoSize
);
959 SymLoadModule(dbg_curr_process
->handle
, de
->u
.LoadDll
.hFile
, buffer
, NULL
,
960 (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
, 0);
961 break_set_xpoints(FALSE
);
962 break_check_delayed_bp();
963 break_set_xpoints(TRUE
);
964 if (DBG_IVAR(BreakOnDllLoad
))
966 dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
967 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
);
968 if (dbg_fetch_context()) cont
= 0;
972 case UNLOAD_DLL_DEBUG_EVENT
:
973 WINE_TRACE("%08lx:%08lx: unload DLL @%08lx\n",
974 de
->dwProcessId
, de
->dwThreadId
,
975 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
976 break_delete_xpoints_from_module((unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
977 SymUnloadModule(dbg_curr_process
->handle
,
978 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
981 case OUTPUT_DEBUG_STRING_EVENT
:
982 if (dbg_curr_thread
== NULL
)
984 WINE_ERR("Unknown thread\n");
988 memory_get_string(dbg_curr_process
,
989 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
990 de
->u
.DebugString
.fUnicode
, buffer
, sizeof(buffer
));
991 WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
992 de
->dwProcessId
, de
->dwThreadId
, buffer
);
996 WINE_TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
997 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
998 de
->u
.RipInfo
.dwType
);
1002 WINE_TRACE("%08lx:%08lx: unknown event (%ld)\n",
1003 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
1005 if (!cont
) return TRUE
; /* stop execution */
1006 ContinueDebugEvent(de
->dwProcessId
, de
->dwThreadId
, cont
);
1007 return FALSE
; /* continue execution */
1010 static void dbg_resume_debuggee(DWORD cont
)
1012 if (dbg_curr_thread
->in_exception
)
1016 dbg_exception_epilog();
1017 memory_get_current_pc(&addr
);
1018 WINE_TRACE("Exiting debugger PC=0x%lx mode=%d count=%d\n",
1019 addr
.Offset
, dbg_curr_thread
->exec_mode
,
1020 dbg_curr_thread
->exec_count
);
1021 if (dbg_curr_thread
)
1023 if (!SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
))
1024 dbg_printf("Cannot set ctx on %lu\n", dbg_curr_tid
);
1027 dbg_interactiveP
= FALSE
;
1028 if (!ContinueDebugEvent(dbg_curr_pid
, dbg_curr_tid
, cont
))
1029 dbg_printf("Cannot continue on %lu (%lu)\n", dbg_curr_tid
, cont
);
1032 void dbg_wait_next_exception(DWORD cont
, int count
, int mode
)
1037 if (cont
== DBG_CONTINUE
)
1039 dbg_curr_thread
->exec_count
= count
;
1040 dbg_curr_thread
->exec_mode
= mode
;
1042 dbg_resume_debuggee(cont
);
1044 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
1046 if (dbg_handle_debug_event(&de
)) break;
1048 if (!dbg_curr_process
) return;
1049 dbg_interactiveP
= TRUE
;
1051 memory_get_current_pc(&addr
);
1052 WINE_TRACE("Entering debugger PC=0x%lx mode=%d count=%d\n",
1053 addr
.Offset
, dbg_curr_thread
->exec_mode
,
1054 dbg_curr_thread
->exec_count
);
1057 static unsigned dbg_main_loop(HANDLE hFile
)
1061 if (dbg_curr_process
)
1062 dbg_printf("WineDbg starting on pid 0x%lx\n", dbg_curr_pid
);
1064 /* wait for first exception */
1065 while (WaitForDebugEvent(&de
, INFINITE
))
1067 if (dbg_handle_debug_event(&de
)) break;
1069 switch (dbg_action_mode
)
1071 case automatic_mode
:
1072 /* print some extra information */
1073 dbg_printf("Modules:\n");
1074 info_win32_module(0); /* print all modules */
1075 dbg_printf("Threads:\n");
1076 info_win32_threads();
1079 dbg_interactiveP
= TRUE
;
1080 parser_handle(hFile
);
1082 dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid
);
1087 static unsigned dbg_start_debuggee(LPSTR cmdLine
)
1089 PROCESS_INFORMATION info
;
1090 STARTUPINFOA startup
;
1092 memset(&startup
, 0, sizeof(startup
));
1093 startup
.cb
= sizeof(startup
);
1094 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
1095 startup
.wShowWindow
= SW_SHOWNORMAL
;
1097 /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
1100 if (!CreateProcess(NULL
, cmdLine
, NULL
, NULL
,
1102 DEBUG_PROCESS
|DEBUG_ONLY_THIS_PROCESS
|CREATE_NEW_CONSOLE
,
1103 NULL
, NULL
, &startup
, &info
))
1105 dbg_printf("Couldn't start process '%s'\n", cmdLine
);
1108 if (!info
.dwProcessId
)
1110 /* this happens when the program being run is not a Wine binary
1111 * (for example, a shell wrapper around a WineLib app)
1113 /* Current fix: list running processes and let the user attach
1114 * to one of them (sic)
1115 * FIXME: implement a real fix => grab the process (from the
1116 * running processes) from its name
1118 dbg_printf("Debuggee has been started (%s)\n"
1119 "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
1120 "Try to attach to one of those processes:\n", cmdLine
);
1121 /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
1123 info_win32_processes();
1126 dbg_curr_pid
= info
.dwProcessId
;
1127 if (!(dbg_curr_process
= dbg_add_process(dbg_curr_pid
, 0))) return FALSE
;
1132 void dbg_run_debuggee(const char* args
)
1136 WINE_FIXME("Re-running current program with %s as args is broken\n", args
);
1143 if (!dbg_last_cmd_line
)
1145 dbg_printf("Cannot find previously used command line.\n");
1148 dbg_start_debuggee(dbg_last_cmd_line
);
1149 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
1151 if (dbg_handle_debug_event(&de
)) break;
1153 source_list_from_addr(NULL
, 0);
1157 BOOL
dbg_interrupt_debuggee(void)
1159 if (!dbg_process_list
) return FALSE
;
1160 /* FIXME: since we likely have a single process, signal the first process
1163 if (dbg_process_list
->next
) dbg_printf("Ctrl-C: only stopping the first process\n");
1164 else dbg_printf("Ctrl-C: stopping debuggee\n");
1165 dbg_process_list
->continue_on_first_exception
= FALSE
;
1166 return DebugBreakProcess(dbg_process_list
->handle
);
1169 static BOOL WINAPI
ctrl_c_handler(DWORD dwCtrlType
)
1171 if (dwCtrlType
== CTRL_C_EVENT
)
1173 return dbg_interrupt_debuggee();
1178 static void dbg_init_console(void)
1180 /* set our control-C handler */
1181 SetConsoleCtrlHandler(ctrl_c_handler
, TRUE
);
1183 /* set our own title */
1184 SetConsoleTitle("Wine Debugger");
1187 static int dbg_winedbg_usage(void)
1189 dbg_printf("Usage: winedbg [--command cmd|--file file|--auto] [--gdb [--no-start] [--with-xterm]] cmdline\n");
1193 struct backend_cpu
* be_cpu
;
1195 extern struct backend_cpu be_i386
;
1197 extern struct backend_cpu be_ppc
;
1199 extern struct backend_cpu be_alpha
;
1204 int main(int argc
, char** argv
)
1207 unsigned gdb_flags
= 0;
1208 HANDLE hFile
= INVALID_HANDLE_VALUE
;
1219 /* Initialize the output */
1220 dbg_houtput
= GetStdHandle(STD_OUTPUT_HANDLE
);
1222 /* Initialize internal vars */
1223 if (!dbg_load_internal_vars()) return -1;
1226 while (argc
> 1 && argv
[1][0] == '-')
1228 if (!strcmp(argv
[1], "--command"))
1230 char path
[MAX_PATH
], file
[MAX_PATH
];
1233 GetTempPath(sizeof(path
), path
);
1234 GetTempFileName(path
, "WD", 0, file
);
1236 hFile
= CreateFileA(file
, GENERIC_READ
|GENERIC_WRITE
|DELETE
, FILE_SHARE_DELETE
,
1237 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
1238 if (hFile
== INVALID_HANDLE_VALUE
)
1240 dbg_printf("Couldn't open temp file %s (%lu)\n", file
, GetLastError());
1243 WriteFile(hFile
, argv
[1], strlen(argv
[1]), &w
, 0);
1244 WriteFile(hFile
, "\nquit\n", 6, &w
, 0);
1245 SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
);
1250 if (!strcmp(argv
[1], "--file"))
1253 hFile
= CreateFileA(argv
[1], GENERIC_READ
|DELETE
, 0,
1254 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0);
1255 if (hFile
== INVALID_HANDLE_VALUE
)
1257 dbg_printf("Couldn't open file %s (%lu)\n", argv
[1], GetLastError());
1263 if (!strcmp(argv
[1], "--auto"))
1265 if (dbg_action_mode
!= none_mode
) return dbg_winedbg_usage();
1266 dbg_action_mode
= automatic_mode
;
1267 /* force some internal variables */
1268 DBG_IVAR(BreakOnDllLoad
) = 0;
1270 dbg_houtput
= GetStdHandle(STD_ERROR_HANDLE
);
1273 if (!strcmp(argv
[1], "--gdb"))
1275 if (dbg_action_mode
!= none_mode
) return dbg_winedbg_usage();
1276 dbg_action_mode
= gdb_mode
;
1280 if (strcmp(argv
[1], "--no-start") == 0 && dbg_action_mode
== gdb_mode
)
1283 argc
--; argv
++; /* as we don't use argv[0] */
1286 if (strcmp(argv
[1], "--with-xterm") == 0 && dbg_action_mode
== gdb_mode
)
1289 argc
--; argv
++; /* as we don't use argv[0] */
1292 return dbg_winedbg_usage();
1295 if (dbg_action_mode
== none_mode
) dbg_action_mode
= winedbg_mode
;
1297 /* try the form <myself> pid */
1298 if (dbg_curr_pid
== 0 && argc
== 2)
1302 dbg_curr_pid
= strtol(argv
[1], &ptr
, 10);
1303 if (dbg_curr_pid
== 0 || ptr
!= argv
[1] + strlen(argv
[1]) ||
1304 !dbg_attach_debuggee(dbg_curr_pid
, FALSE
, FALSE
))
1308 /* try the form <myself> pid evt (Win32 JIT debugger) */
1309 if (dbg_curr_pid
== 0 && argc
== 3)
1315 if ((pid
= strtol(argv
[1], &ptr
, 10)) != 0 && ptr
!= NULL
&&
1316 (hEvent
= (HANDLE
)strtol(argv
[2], &ptr
, 10)) != 0 && ptr
!= NULL
)
1318 if (!dbg_attach_debuggee(pid
, TRUE
, FALSE
))
1320 /* don't care about result */
1324 if (!SetEvent(hEvent
))
1326 WINE_ERR("Invalid event handle: %p\n", hEvent
);
1329 CloseHandle(hEvent
);
1334 if (dbg_curr_pid
== 0 && argc
> 1)
1339 if (!(cmdLine
= HeapAlloc(GetProcessHeap(), 0, len
= 1))) goto oom_leave
;
1342 for (i
= 1; i
< argc
; i
++)
1344 len
+= strlen(argv
[i
]) + 1;
1345 if (!(cmdLine
= HeapReAlloc(GetProcessHeap(), 0, cmdLine
, len
)))
1347 strcat(cmdLine
, argv
[i
]);
1348 cmdLine
[len
- 2] = ' ';
1349 cmdLine
[len
- 1] = '\0';
1352 if (!dbg_start_debuggee(cmdLine
))
1354 dbg_printf("Couldn't start process '%s'\n", cmdLine
);
1357 dbg_last_cmd_line
= cmdLine
;
1359 /* don't save local vars in gdb mode */
1360 if (dbg_action_mode
== gdb_mode
&& dbg_curr_pid
)
1361 return gdb_remote(gdb_flags
);
1365 SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME
)) |
1366 SYMOPT_LOAD_LINES
| SYMOPT_DEFERRED_LOADS
| SYMOPT_AUTO_PUBLICS
);
1368 retv
= dbg_main_loop(hFile
);
1369 /* don't save modified variables in auto mode */
1370 if (dbg_action_mode
!= automatic_mode
) dbg_save_internal_vars();
1376 dbg_printf("Out of memory\n");