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
;
400 t
->addr_mode
= AddrModeFlat
;
402 snprintf(t
->name
, sizeof(t
->name
), "0x%08lx", tid
);
404 t
->next
= p
->threads
;
406 if (p
->threads
) p
->threads
->prev
= t
;
412 static void dbg_init_current_thread(void* start
)
416 if (dbg_curr_process
->threads
&&
417 !dbg_curr_process
->threads
->next
&& /* first thread ? */
418 DBG_IVAR(BreakAllThreadsStartup
))
422 break_set_xpoints(FALSE
);
423 addr
.Mode
= AddrModeFlat
;
424 addr
.Offset
= (DWORD
)start
;
425 break_add_break(&addr
, TRUE
, TRUE
);
426 break_set_xpoints(TRUE
);
431 void dbg_del_thread(struct dbg_thread
* t
)
433 HeapFree(GetProcessHeap(), 0, t
->frames
);
434 if (t
->prev
) t
->prev
->next
= t
->next
;
435 if (t
->next
) t
->next
->prev
= t
->prev
;
436 if (t
== t
->process
->threads
) t
->process
->threads
= t
->next
;
437 if (t
== dbg_curr_thread
) dbg_curr_thread
= NULL
;
438 HeapFree(GetProcessHeap(), 0, t
);
441 static unsigned dbg_handle_debug_event(DEBUG_EVENT
* de
);
443 /******************************************************************
444 * dbg_attach_debuggee
446 * Sets the debuggee to <pid>
447 * cofe instructs winedbg what to do when first exception is received
448 * (break=FALSE, continue=TRUE)
449 * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
450 * until the first exception is received (aka: attach to an already running process)
452 BOOL
dbg_attach_debuggee(DWORD pid
, BOOL cofe
, BOOL wfe
)
456 if (!(dbg_curr_process
= dbg_add_process(pid
, 0))) return FALSE
;
458 if (!DebugActiveProcess(pid
))
460 dbg_printf("Can't attach process %lx: error %ld\n", pid
, GetLastError());
461 dbg_del_process(dbg_curr_process
);
464 dbg_curr_process
->continue_on_first_exception
= cofe
;
466 if (wfe
) /* shall we proceed all debug events until we get an exception ? */
468 dbg_interactiveP
= FALSE
;
469 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
471 if (dbg_handle_debug_event(&de
)) break;
473 if (dbg_curr_process
) dbg_interactiveP
= TRUE
;
478 BOOL
dbg_detach_debuggee(void)
480 /* remove all set breakpoints in debuggee code */
481 break_set_xpoints(FALSE
);
482 /* needed for single stepping (ugly).
483 * should this be handled inside the server ???
485 be_cpu
->single_step(&dbg_context
, FALSE
);
486 SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
);
487 if (dbg_curr_thread
->in_exception
)
488 ContinueDebugEvent(dbg_curr_pid
, dbg_curr_tid
, DBG_CONTINUE
);
489 if (!DebugActiveProcessStop(dbg_curr_pid
)) return FALSE
;
490 dbg_del_process(dbg_curr_process
);
495 static unsigned dbg_fetch_context(void)
497 dbg_context
.ContextFlags
= CONTEXT_CONTROL
499 #ifdef CONTEXT_SEGMENTS
502 #ifdef CONTEXT_DEBUG_REGISTERS
503 | CONTEXT_DEBUG_REGISTERS
506 if (!GetThreadContext(dbg_curr_thread
->handle
, &dbg_context
))
508 WINE_WARN("Can't get thread's context\n");
514 static unsigned dbg_exception_prolog(BOOL is_debug
, const EXCEPTION_RECORD
* rec
)
519 memory_get_current_pc(&addr
);
520 break_suspend_execution();
521 dbg_curr_thread
->excpt_record
= *rec
;
522 dbg_curr_thread
->in_exception
= TRUE
;
528 case AddrModeFlat
: dbg_printf(" in 32-bit code (0x%08lx)", addr
.Offset
); break;
529 case AddrModeReal
: dbg_printf(" in vm86 code (%04x:%04lx)", addr
.Segment
, addr
.Offset
); break;
530 case AddrMode1616
: dbg_printf(" in 16-bit code (%04x:%04lx)", addr
.Segment
, addr
.Offset
); break;
531 case AddrMode1632
: dbg_printf(" in 32-bit code (%04x:%08lx)", addr
.Segment
, addr
.Offset
); break;
532 default: dbg_printf(" bad address");
537 /* this will resynchronize builtin dbghelp's internal ELF module list */
538 SymLoadModule(dbg_curr_process
->handle
, 0, 0, 0, 0, 0);
541 * Do a quiet backtrace so that we have an idea of what the situation
542 * is WRT the source files.
544 stack_fetch_frames();
546 break_should_continue(&addr
, rec
->ExceptionCode
, &dbg_curr_thread
->exec_count
, &is_break
))
549 if (addr
.Mode
!= dbg_curr_thread
->addr_mode
)
551 const char* name
= NULL
;
555 case AddrMode1616
: name
= "16 bit"; break;
556 case AddrMode1632
: name
= "32 bit"; break;
557 case AddrModeReal
: name
= "vm86"; break;
558 case AddrModeFlat
: name
= "32 bit"; break;
561 dbg_printf("In %s mode.\n", name
);
562 dbg_curr_thread
->addr_mode
= addr
.Mode
;
568 /* This is a real crash, dump some info */
569 be_cpu
->print_context(dbg_curr_thread
->handle
, &dbg_context
);
571 be_cpu
->print_segment_info(dbg_curr_thread
->handle
, &dbg_context
);
572 stack_backtrace(dbg_curr_tid
);
576 static char* last_name
;
577 static char* last_file
;
579 char buffer
[sizeof(SYMBOL_INFO
) + 256];
580 SYMBOL_INFO
* si
= (SYMBOL_INFO
*)buffer
;
581 void* lin
= memory_to_linear_addr(&addr
);
586 si
->SizeOfStruct
= sizeof(*si
);
587 si
->MaxNameLen
= 256;
588 il
.SizeOfStruct
= sizeof(il
);
589 if (SymFromAddr(dbg_curr_process
->handle
, (DWORD_PTR
)lin
, &disp64
, si
) &&
590 SymGetLineFromAddr(dbg_curr_process
->handle
, (DWORD_PTR
)lin
, &disp
, &il
))
592 if ((!last_name
|| strcmp(last_name
, si
->Name
)) ||
593 (!last_file
|| strcmp(last_file
, il
.FileName
)))
595 HeapFree(GetProcessHeap(), 0, last_name
);
596 HeapFree(GetProcessHeap(), 0, last_file
);
597 last_name
= strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si
->Name
) + 1), si
->Name
);
598 last_file
= strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il
.FileName
) + 1), il
.FileName
);
599 dbg_printf("%s () at %s:%ld\n", last_name
, last_file
, il
.LineNumber
);
603 if (!is_debug
|| is_break
||
604 dbg_curr_thread
->exec_mode
== dbg_exec_step_over_insn
||
605 dbg_curr_thread
->exec_mode
== dbg_exec_step_into_insn
)
608 /* Show where we crashed */
609 memory_disasm_one_insn(&tmp
);
611 source_list_from_addr(&addr
, 0);
616 static void dbg_exception_epilog(void)
618 break_restart_execution(dbg_curr_thread
->exec_count
);
620 * This will have gotten absorbed into the breakpoint info
621 * if it was used. Otherwise it would have been ignored.
622 * In any case, we don't mess with it any more.
624 if (dbg_curr_thread
->exec_mode
== dbg_exec_cont
)
625 dbg_curr_thread
->exec_count
= 0;
626 dbg_curr_thread
->in_exception
= FALSE
;
629 static DWORD
dbg_handle_exception(const EXCEPTION_RECORD
* rec
, BOOL first_chance
)
631 BOOL is_debug
= FALSE
;
632 THREADNAME_INFO
* pThreadName
;
633 struct dbg_thread
* pThread
;
635 assert(dbg_curr_thread
);
637 WINE_TRACE("exception=%lx first_chance=%c\n",
638 rec
->ExceptionCode
, first_chance
? 'Y' : 'N');
640 switch (rec
->ExceptionCode
)
642 case EXCEPTION_BREAKPOINT
:
643 case EXCEPTION_SINGLE_STEP
:
646 case EXCEPTION_NAME_THREAD
:
647 pThreadName
= (THREADNAME_INFO
*)(rec
->ExceptionInformation
);
648 if (pThreadName
->dwThreadID
== -1)
649 pThread
= dbg_curr_thread
;
651 pThread
= dbg_get_thread(dbg_curr_process
, pThreadName
->dwThreadID
);
653 if (dbg_read_memory(pThreadName
->szName
, pThread
->name
, 9))
654 dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
655 pThread
->tid
, pThread
->name
);
659 if (first_chance
&& !is_debug
&& !DBG_IVAR(BreakOnFirstChance
) &&
660 !(rec
->ExceptionFlags
& EH_STACK_INVALID
))
662 /* pass exception to program except for debug exceptions */
663 return DBG_EXCEPTION_NOT_HANDLED
;
668 /* print some infos */
670 first_chance
? "First chance exception" : "Unhandled exception");
671 switch (rec
->ExceptionCode
)
673 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
674 dbg_printf("divide by zero");
676 case EXCEPTION_INT_OVERFLOW
:
677 dbg_printf("overflow");
679 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
680 dbg_printf("array bounds");
682 case EXCEPTION_ILLEGAL_INSTRUCTION
:
683 dbg_printf("illegal instruction");
685 case EXCEPTION_STACK_OVERFLOW
:
686 dbg_printf("stack overflow");
688 case EXCEPTION_PRIV_INSTRUCTION
:
689 dbg_printf("privileged instruction");
691 case EXCEPTION_ACCESS_VIOLATION
:
692 if (rec
->NumberParameters
== 2)
693 dbg_printf("page fault on %s access to 0x%08lx",
694 rec
->ExceptionInformation
[0] ? "write" : "read",
695 rec
->ExceptionInformation
[1]);
697 dbg_printf("page fault");
699 case EXCEPTION_DATATYPE_MISALIGNMENT
:
700 dbg_printf("Alignment");
708 case STATUS_POSSIBLE_DEADLOCK
:
712 addr
.Mode
= AddrModeFlat
;
713 addr
.Offset
= rec
->ExceptionInformation
[0];
715 dbg_printf("wait failed on critical section ");
716 print_address(&addr
, FALSE
);
718 if (!DBG_IVAR(BreakOnCritSectTimeOut
))
721 return DBG_EXCEPTION_NOT_HANDLED
;
724 case EXCEPTION_WINE_STUB
:
726 char dll
[32], name
[64];
727 memory_get_string(dbg_curr_process
,
728 (void*)rec
->ExceptionInformation
[0], TRUE
, FALSE
,
730 if (HIWORD(rec
->ExceptionInformation
[1]))
731 memory_get_string(dbg_curr_process
,
732 (void*)rec
->ExceptionInformation
[1], TRUE
, FALSE
,
735 sprintf( name
, "%ld", rec
->ExceptionInformation
[1] );
736 dbg_printf("unimplemented function %s.%s called", dll
, name
);
739 case EXCEPTION_WINE_ASSERTION
:
740 dbg_printf("assertion failed");
742 case EXCEPTION_VM86_INTx
:
743 dbg_printf("interrupt %02lx in vm86 mode", rec
->ExceptionInformation
[0]);
745 case EXCEPTION_VM86_STI
:
746 dbg_printf("sti in vm86 mode");
748 case EXCEPTION_VM86_PICRETURN
:
749 dbg_printf("PIC return in vm86 mode");
751 case EXCEPTION_FLT_DENORMAL_OPERAND
:
752 dbg_printf("denormal float operand");
754 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
755 dbg_printf("divide by zero");
757 case EXCEPTION_FLT_INEXACT_RESULT
:
758 dbg_printf("inexact float result");
760 case EXCEPTION_FLT_INVALID_OPERATION
:
761 dbg_printf("invalid float operation");
763 case EXCEPTION_FLT_OVERFLOW
:
764 dbg_printf("floating pointer overflow");
766 case EXCEPTION_FLT_UNDERFLOW
:
767 dbg_printf("floating pointer underflow");
769 case EXCEPTION_FLT_STACK_CHECK
:
770 dbg_printf("floating point stack check");
773 dbg_printf("0x%08lx", rec
->ExceptionCode
);
777 if( (rec
->ExceptionFlags
& EH_STACK_INVALID
) ) {
778 dbg_printf( ", invalid program stack" );
781 if (dbg_action_mode
== automatic_mode
)
783 dbg_exception_prolog(is_debug
, rec
);
784 dbg_exception_epilog();
785 return 0; /* terminate execution */
788 if (dbg_exception_prolog(is_debug
, rec
))
790 dbg_interactiveP
= TRUE
;
793 dbg_exception_epilog();
798 static unsigned dbg_handle_debug_event(DEBUG_EVENT
* de
)
801 DWORD cont
= DBG_CONTINUE
;
803 dbg_curr_pid
= de
->dwProcessId
;
804 dbg_curr_tid
= de
->dwThreadId
;
806 if ((dbg_curr_process
= dbg_get_process(de
->dwProcessId
)) != NULL
)
807 dbg_curr_thread
= dbg_get_thread(dbg_curr_process
, de
->dwThreadId
);
809 dbg_curr_thread
= NULL
;
811 switch (de
->dwDebugEventCode
)
813 case EXCEPTION_DEBUG_EVENT
:
814 if (!dbg_curr_thread
)
816 WINE_ERR("%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
817 de
->dwProcessId
, de
->dwThreadId
);
821 WINE_TRACE("%08lx:%08lx: exception code=%08lx\n",
822 de
->dwProcessId
, de
->dwThreadId
,
823 de
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
825 if (dbg_curr_process
->continue_on_first_exception
)
827 dbg_curr_process
->continue_on_first_exception
= FALSE
;
828 if (!DBG_IVAR(BreakOnAttach
)) break;
830 if (dbg_fetch_context())
832 cont
= dbg_handle_exception(&de
->u
.Exception
.ExceptionRecord
,
833 de
->u
.Exception
.dwFirstChance
);
834 if (cont
&& dbg_curr_thread
)
836 SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
);
841 case CREATE_PROCESS_DEBUG_EVENT
:
842 dbg_curr_process
= dbg_add_process(de
->dwProcessId
,
843 de
->u
.CreateProcessInfo
.hProcess
);
844 if (dbg_curr_process
== NULL
)
846 WINE_ERR("Couldn't create process\n");
849 memory_get_string_indirect(dbg_curr_process
,
850 de
->u
.CreateProcessInfo
.lpImageName
,
851 de
->u
.CreateProcessInfo
.fUnicode
,
852 buffer
, sizeof(buffer
));
853 if (!buffer
[0]) strcpy(buffer
, "<Debugged Process>");
855 WINE_TRACE("%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
856 de
->dwProcessId
, de
->dwThreadId
,
857 buffer
, de
->u
.CreateProcessInfo
.lpImageName
,
858 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
,
859 de
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
,
860 de
->u
.CreateProcessInfo
.nDebugInfoSize
);
861 dbg_set_process_name(dbg_curr_process
, buffer
);
863 if (!SymInitialize(dbg_curr_process
->handle
, NULL
, TRUE
))
864 dbg_printf("Couldn't initiate DbgHelp\n");
866 WINE_TRACE("%08lx:%08lx: create thread I @%08lx\n",
867 de
->dwProcessId
, de
->dwThreadId
,
868 (unsigned long)(void*)de
->u
.CreateProcessInfo
.lpStartAddress
);
870 dbg_curr_thread
= dbg_add_thread(dbg_curr_process
,
872 de
->u
.CreateProcessInfo
.hThread
,
873 de
->u
.CreateProcessInfo
.lpThreadLocalBase
);
874 if (!dbg_curr_thread
)
876 WINE_ERR("Couldn't create thread\n");
879 dbg_init_current_process();
880 dbg_init_current_thread(de
->u
.CreateProcessInfo
.lpStartAddress
);
883 case EXIT_PROCESS_DEBUG_EVENT
:
884 WINE_TRACE("%08lx:%08lx: exit process (%ld)\n",
885 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitProcess
.dwExitCode
);
887 if (dbg_curr_process
== NULL
)
889 WINE_ERR("Unknown process\n");
892 if (!SymCleanup(dbg_curr_process
->handle
))
893 dbg_printf("Couldn't initiate DbgHelp\n");
895 break_set_xpoints(FALSE
);
896 /* kill last thread */
897 dbg_del_thread(dbg_curr_process
->threads
);
898 dbg_del_process(dbg_curr_process
);
900 dbg_printf("Process of pid=0x%08lx has terminated\n", dbg_curr_pid
);
903 case CREATE_THREAD_DEBUG_EVENT
:
904 WINE_TRACE("%08lx:%08lx: create thread D @%08lx\n",
905 de
->dwProcessId
, de
->dwThreadId
,
906 (unsigned long)(void*)de
->u
.CreateThread
.lpStartAddress
);
908 if (dbg_curr_process
== NULL
)
910 WINE_ERR("Unknown process\n");
913 if (dbg_get_thread(dbg_curr_process
, de
->dwThreadId
) != NULL
)
915 WINE_TRACE("Thread already listed, skipping\n");
919 dbg_curr_thread
= dbg_add_thread(dbg_curr_process
,
921 de
->u
.CreateThread
.hThread
,
922 de
->u
.CreateThread
.lpThreadLocalBase
);
923 if (!dbg_curr_thread
)
925 WINE_ERR("Couldn't create thread\n");
928 dbg_init_current_thread(de
->u
.CreateThread
.lpStartAddress
);
931 case EXIT_THREAD_DEBUG_EVENT
:
932 WINE_TRACE("%08lx:%08lx: exit thread (%ld)\n",
933 de
->dwProcessId
, de
->dwThreadId
, de
->u
.ExitThread
.dwExitCode
);
935 if (dbg_curr_thread
== NULL
)
937 WINE_ERR("Unknown thread\n");
940 /* FIXME: remove break point set on thread startup */
941 dbg_del_thread(dbg_curr_thread
);
944 case LOAD_DLL_DEBUG_EVENT
:
945 if (dbg_curr_thread
== NULL
)
947 WINE_ERR("Unknown thread\n");
950 memory_get_string_indirect(dbg_curr_process
,
951 de
->u
.LoadDll
.lpImageName
,
952 de
->u
.LoadDll
.fUnicode
,
953 buffer
, sizeof(buffer
));
955 WINE_TRACE("%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
956 de
->dwProcessId
, de
->dwThreadId
,
957 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
,
958 de
->u
.LoadDll
.dwDebugInfoFileOffset
,
959 de
->u
.LoadDll
.nDebugInfoSize
);
960 SymLoadModule(dbg_curr_process
->handle
, de
->u
.LoadDll
.hFile
, buffer
, NULL
,
961 (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
, 0);
962 break_set_xpoints(FALSE
);
963 break_check_delayed_bp();
964 break_set_xpoints(TRUE
);
965 if (DBG_IVAR(BreakOnDllLoad
))
967 dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
968 buffer
, (unsigned long)de
->u
.LoadDll
.lpBaseOfDll
);
969 if (dbg_fetch_context()) cont
= 0;
973 case UNLOAD_DLL_DEBUG_EVENT
:
974 WINE_TRACE("%08lx:%08lx: unload DLL @%08lx\n",
975 de
->dwProcessId
, de
->dwThreadId
,
976 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
977 break_delete_xpoints_from_module((unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
978 SymUnloadModule(dbg_curr_process
->handle
,
979 (unsigned long)de
->u
.UnloadDll
.lpBaseOfDll
);
982 case OUTPUT_DEBUG_STRING_EVENT
:
983 if (dbg_curr_thread
== NULL
)
985 WINE_ERR("Unknown thread\n");
989 memory_get_string(dbg_curr_process
,
990 de
->u
.DebugString
.lpDebugStringData
, TRUE
,
991 de
->u
.DebugString
.fUnicode
, buffer
, sizeof(buffer
));
992 WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
993 de
->dwProcessId
, de
->dwThreadId
, buffer
);
997 WINE_TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
998 de
->dwProcessId
, de
->dwThreadId
, de
->u
.RipInfo
.dwError
,
999 de
->u
.RipInfo
.dwType
);
1003 WINE_TRACE("%08lx:%08lx: unknown event (%ld)\n",
1004 de
->dwProcessId
, de
->dwThreadId
, de
->dwDebugEventCode
);
1006 if (!cont
) return TRUE
; /* stop execution */
1007 ContinueDebugEvent(de
->dwProcessId
, de
->dwThreadId
, cont
);
1008 return FALSE
; /* continue execution */
1011 static void dbg_resume_debuggee(DWORD cont
)
1013 if (dbg_curr_thread
->in_exception
)
1017 dbg_exception_epilog();
1018 memory_get_current_pc(&addr
);
1019 WINE_TRACE("Exiting debugger PC=0x%lx mode=%d count=%d\n",
1020 addr
.Offset
, dbg_curr_thread
->exec_mode
,
1021 dbg_curr_thread
->exec_count
);
1022 if (dbg_curr_thread
)
1024 if (!SetThreadContext(dbg_curr_thread
->handle
, &dbg_context
))
1025 dbg_printf("Cannot set ctx on %lu\n", dbg_curr_tid
);
1028 dbg_interactiveP
= FALSE
;
1029 if (!ContinueDebugEvent(dbg_curr_pid
, dbg_curr_tid
, cont
))
1030 dbg_printf("Cannot continue on %lu (%lu)\n", dbg_curr_tid
, cont
);
1033 void dbg_wait_next_exception(DWORD cont
, int count
, int mode
)
1038 if (cont
== DBG_CONTINUE
)
1040 dbg_curr_thread
->exec_count
= count
;
1041 dbg_curr_thread
->exec_mode
= mode
;
1043 dbg_resume_debuggee(cont
);
1045 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
1047 if (dbg_handle_debug_event(&de
)) break;
1049 if (!dbg_curr_process
) return;
1050 dbg_interactiveP
= TRUE
;
1052 memory_get_current_pc(&addr
);
1053 WINE_TRACE("Entering debugger PC=0x%lx mode=%d count=%d\n",
1054 addr
.Offset
, dbg_curr_thread
->exec_mode
,
1055 dbg_curr_thread
->exec_count
);
1058 static unsigned dbg_main_loop(HANDLE hFile
)
1062 if (dbg_curr_process
)
1063 dbg_printf("WineDbg starting on pid 0x%lx\n", dbg_curr_pid
);
1065 /* wait for first exception */
1066 while (WaitForDebugEvent(&de
, INFINITE
))
1068 if (dbg_handle_debug_event(&de
)) break;
1070 switch (dbg_action_mode
)
1072 case automatic_mode
:
1073 /* print some extra information */
1074 dbg_printf("Modules:\n");
1075 info_win32_module(0); /* print all modules */
1076 dbg_printf("Threads:\n");
1077 info_win32_threads();
1080 dbg_interactiveP
= TRUE
;
1081 parser_handle(hFile
);
1083 dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid
);
1088 static unsigned dbg_start_debuggee(LPSTR cmdLine
)
1090 PROCESS_INFORMATION info
;
1091 STARTUPINFOA startup
;
1093 memset(&startup
, 0, sizeof(startup
));
1094 startup
.cb
= sizeof(startup
);
1095 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
1096 startup
.wShowWindow
= SW_SHOWNORMAL
;
1098 /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
1101 if (!CreateProcess(NULL
, cmdLine
, NULL
, NULL
,
1103 DEBUG_PROCESS
|DEBUG_ONLY_THIS_PROCESS
|CREATE_NEW_CONSOLE
,
1104 NULL
, NULL
, &startup
, &info
))
1106 dbg_printf("Couldn't start process '%s'\n", cmdLine
);
1109 if (!info
.dwProcessId
)
1111 /* this happens when the program being run is not a Wine binary
1112 * (for example, a shell wrapper around a WineLib app)
1114 /* Current fix: list running processes and let the user attach
1115 * to one of them (sic)
1116 * FIXME: implement a real fix => grab the process (from the
1117 * running processes) from its name
1119 dbg_printf("Debuggee has been started (%s)\n"
1120 "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
1121 "Try to attach to one of those processes:\n", cmdLine
);
1122 /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
1124 info_win32_processes();
1127 dbg_curr_pid
= info
.dwProcessId
;
1128 if (!(dbg_curr_process
= dbg_add_process(dbg_curr_pid
, 0))) return FALSE
;
1133 void dbg_run_debuggee(const char* args
)
1137 WINE_FIXME("Re-running current program with %s as args is broken\n", args
);
1144 if (!dbg_last_cmd_line
)
1146 dbg_printf("Cannot find previously used command line.\n");
1149 dbg_start_debuggee(dbg_last_cmd_line
);
1150 while (dbg_curr_process
&& WaitForDebugEvent(&de
, INFINITE
))
1152 if (dbg_handle_debug_event(&de
)) break;
1154 source_list_from_addr(NULL
, 0);
1158 BOOL
dbg_interrupt_debuggee(void)
1160 if (!dbg_process_list
) return FALSE
;
1161 /* FIXME: since we likely have a single process, signal the first process
1164 if (dbg_process_list
->next
) dbg_printf("Ctrl-C: only stopping the first process\n");
1165 else dbg_printf("Ctrl-C: stopping debuggee\n");
1166 dbg_process_list
->continue_on_first_exception
= FALSE
;
1167 return DebugBreakProcess(dbg_process_list
->handle
);
1170 static BOOL WINAPI
ctrl_c_handler(DWORD dwCtrlType
)
1172 if (dwCtrlType
== CTRL_C_EVENT
)
1174 return dbg_interrupt_debuggee();
1179 static void dbg_init_console(void)
1181 /* set our control-C handler */
1182 SetConsoleCtrlHandler(ctrl_c_handler
, TRUE
);
1184 /* set our own title */
1185 SetConsoleTitle("Wine Debugger");
1188 static int dbg_winedbg_usage(void)
1190 dbg_printf("Usage: winedbg [--command cmd|--file file|--auto] [--gdb [--no-start] [--with-xterm]] cmdline\n");
1194 struct backend_cpu
* be_cpu
;
1196 extern struct backend_cpu be_i386
;
1198 extern struct backend_cpu be_ppc
;
1200 extern struct backend_cpu be_alpha
;
1205 int main(int argc
, char** argv
)
1208 unsigned gdb_flags
= 0;
1209 HANDLE hFile
= INVALID_HANDLE_VALUE
;
1220 /* Initialize the output */
1221 dbg_houtput
= GetStdHandle(STD_OUTPUT_HANDLE
);
1223 /* Initialize internal vars */
1224 if (!dbg_load_internal_vars()) return -1;
1227 while (argc
> 1 && argv
[1][0] == '-')
1229 if (!strcmp(argv
[1], "--command"))
1231 char path
[MAX_PATH
], file
[MAX_PATH
];
1234 GetTempPath(sizeof(path
), path
);
1235 GetTempFileName(path
, "WD", 0, file
);
1237 hFile
= CreateFileA(file
, GENERIC_READ
|GENERIC_WRITE
|DELETE
, FILE_SHARE_DELETE
,
1238 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, 0);
1239 if (hFile
== INVALID_HANDLE_VALUE
)
1241 dbg_printf("Couldn't open temp file %s (%lu)\n", file
, GetLastError());
1244 WriteFile(hFile
, argv
[1], strlen(argv
[1]), &w
, 0);
1245 WriteFile(hFile
, "\nquit\n", 6, &w
, 0);
1246 SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
);
1251 if (!strcmp(argv
[1], "--file"))
1254 hFile
= CreateFileA(argv
[1], GENERIC_READ
|DELETE
, 0,
1255 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0);
1256 if (hFile
== INVALID_HANDLE_VALUE
)
1258 dbg_printf("Couldn't open file %s (%lu)\n", argv
[1], GetLastError());
1264 if (!strcmp(argv
[1], "--auto"))
1266 if (dbg_action_mode
!= none_mode
) return dbg_winedbg_usage();
1267 dbg_action_mode
= automatic_mode
;
1268 /* force some internal variables */
1269 DBG_IVAR(BreakOnDllLoad
) = 0;
1271 dbg_houtput
= GetStdHandle(STD_ERROR_HANDLE
);
1274 if (!strcmp(argv
[1], "--gdb"))
1276 if (dbg_action_mode
!= none_mode
) return dbg_winedbg_usage();
1277 dbg_action_mode
= gdb_mode
;
1281 if (strcmp(argv
[1], "--no-start") == 0 && dbg_action_mode
== gdb_mode
)
1284 argc
--; argv
++; /* as we don't use argv[0] */
1287 if (strcmp(argv
[1], "--with-xterm") == 0 && dbg_action_mode
== gdb_mode
)
1290 argc
--; argv
++; /* as we don't use argv[0] */
1293 return dbg_winedbg_usage();
1296 if (dbg_action_mode
== none_mode
) dbg_action_mode
= winedbg_mode
;
1298 /* try the form <myself> pid */
1299 if (dbg_curr_pid
== 0 && argc
== 2)
1303 dbg_curr_pid
= strtol(argv
[1], &ptr
, 10);
1304 if (dbg_curr_pid
== 0 || ptr
!= argv
[1] + strlen(argv
[1]) ||
1305 !dbg_attach_debuggee(dbg_curr_pid
, FALSE
, FALSE
))
1309 /* try the form <myself> pid evt (Win32 JIT debugger) */
1310 if (dbg_curr_pid
== 0 && argc
== 3)
1316 if ((pid
= strtol(argv
[1], &ptr
, 10)) != 0 && ptr
!= NULL
&&
1317 (hEvent
= (HANDLE
)strtol(argv
[2], &ptr
, 10)) != 0 && ptr
!= NULL
)
1319 if (!dbg_attach_debuggee(pid
, TRUE
, FALSE
))
1321 /* don't care about result */
1325 if (!SetEvent(hEvent
))
1327 WINE_ERR("Invalid event handle: %p\n", hEvent
);
1330 CloseHandle(hEvent
);
1335 if (dbg_curr_pid
== 0 && argc
> 1)
1340 if (!(cmdLine
= HeapAlloc(GetProcessHeap(), 0, len
= 1))) goto oom_leave
;
1343 for (i
= 1; i
< argc
; i
++)
1345 len
+= strlen(argv
[i
]) + 1;
1346 if (!(cmdLine
= HeapReAlloc(GetProcessHeap(), 0, cmdLine
, len
)))
1348 strcat(cmdLine
, argv
[i
]);
1349 cmdLine
[len
- 2] = ' ';
1350 cmdLine
[len
- 1] = '\0';
1353 if (!dbg_start_debuggee(cmdLine
))
1355 dbg_printf("Couldn't start process '%s'\n", cmdLine
);
1358 dbg_last_cmd_line
= cmdLine
;
1360 /* don't save local vars in gdb mode */
1361 if (dbg_action_mode
== gdb_mode
&& dbg_curr_pid
)
1362 return gdb_remote(gdb_flags
);
1366 SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME
)) |
1367 SYMOPT_LOAD_LINES
| SYMOPT_DEFERRED_LOADS
| SYMOPT_AUTO_PUBLICS
);
1369 retv
= dbg_main_loop(hFile
);
1370 /* don't save modified variables in auto mode */
1371 if (dbg_action_mode
!= automatic_mode
) dbg_save_internal_vars();
1377 dbg_printf("Out of memory\n");