Commit a5612755 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- now storing exception info (if any) in thread structure

- added minidump function in winedbg (write only)
parent 5c819a98
...@@ -21,6 +21,7 @@ C_SRCS = \ ...@@ -21,6 +21,7 @@ C_SRCS = \
source.c \ source.c \
symbol.c \ symbol.c \
stack.c \ stack.c \
tgt_minidump.c \
types.c \ types.c \
winedbg.c winedbg.c
......
...@@ -57,7 +57,8 @@ int yyerror(const char*); ...@@ -57,7 +57,8 @@ int yyerror(const char*);
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
%token <string> tPATH tIDENTIFIER tSTRING tDEBUGSTR tINTVAR %token <string> tPATH tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
%token <integer> tNUM tFORMAT %token <integer> tNUM tFORMAT
%token tSYMBOLFILE tRUN tATTACH tDETACH tNOPROCESS tMAINTENANCE tTYPE %token tSYMBOLFILE tRUN tATTACH tDETACH tMAINTENANCE tTYPE tMINIDUMP
%token tNOPROCESS
%token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED %token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED
%token tSTRUCT tUNION tENUM %token tSTRUCT tUNION tENUM
...@@ -138,6 +139,7 @@ command: ...@@ -138,6 +139,7 @@ command:
| tWHATIS expr_lvalue { types_print_type(&$2.type, FALSE); dbg_printf("\n"); } | tWHATIS expr_lvalue { types_print_type(&$2.type, FALSE); dbg_printf("\n"); }
| tATTACH tNUM { dbg_attach_debuggee($2, FALSE, TRUE); } | tATTACH tNUM { dbg_attach_debuggee($2, FALSE, TRUE); }
| tDETACH { dbg_detach_debuggee(); } | tDETACH { dbg_detach_debuggee(); }
| tMINIDUMP pathname { minidump_write($2, (dbg_curr_thread && dbg_curr_thread->in_exception) ? &dbg_curr_thread->excpt_record : NULL);}
| run_command | run_command
| list_command | list_command
| disassemble_command | disassemble_command
......
...@@ -174,6 +174,7 @@ STRING \"[^\n"]+\" ...@@ -174,6 +174,7 @@ STRING \"[^\n"]+\"
<INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;} <INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;}
<INITIAL>detach|detac|deta|det { BEGIN(NOCMD); return tDETACH; } <INITIAL>detach|detac|deta|det { BEGIN(NOCMD); return tDETACH; }
<INITIAL>maintenance|maint { BEGIN(MAINT_CMD); return tMAINTENANCE; } <INITIAL>maintenance|maint { BEGIN(MAINT_CMD); return tMAINTENANCE; }
<INITIAL>minidump|mdmp { BEGIN(PATH_EXPECTED); return tMINIDUMP; }
<NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; } <NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; }
<INFO_CMD>share|shar|sha { return tSHARE; } <INFO_CMD>share|shar|sha { return tSHARE; }
<INFO_CMD>locals|local|loca|loc { return tLOCAL; } <INFO_CMD>locals|local|loca|loc { return tLOCAL; }
......
...@@ -168,6 +168,8 @@ struct dbg_thread ...@@ -168,6 +168,8 @@ struct dbg_thread
char name[9]; char name[9];
struct dbg_thread* next; struct dbg_thread* next;
struct dbg_thread* prev; struct dbg_thread* prev;
BOOL in_exception; /* TRUE if thread stopped with an exception */
EXCEPTION_RECORD excpt_record; /* only valid when in_exception is TRUE */
}; };
struct dbg_delayed_bp struct dbg_delayed_bp
...@@ -343,6 +345,9 @@ extern void symbol_info(const char* str); ...@@ -343,6 +345,9 @@ extern void symbol_info(const char* str);
extern int symbol_info_locals(void); extern int symbol_info_locals(void);
extern BOOL symbol_is_local(const char* name); extern BOOL symbol_is_local(const char* name);
/* tgt_minidump.c */
extern void minidump_write(const char*, const EXCEPTION_RECORD*);
/* types.c */ /* types.c */
extern void print_value(const struct dbg_lvalue* addr, char format, int level); extern void print_value(const struct dbg_lvalue* addr, char format, int level);
extern int types_print_type(const struct dbg_type*, BOOL details); extern int types_print_type(const struct dbg_type*, BOOL details);
......
/*
* Wine debugger - minidump handling
*
* Copyright 2005 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "debugger.h"
#include "wingdi.h"
#include "winuser.h"
#include "tlhelp32.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
void minidump_write(const char* file, const EXCEPTION_RECORD* rec)
{
HANDLE hFile;
MINIDUMP_EXCEPTION_INFORMATION mei;
EXCEPTION_POINTERS ep;
DWORD wine_opt;
hFile = CreateFile(file, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return;
if (rec)
{
mei.ThreadId = dbg_curr_thread->tid;
mei.ExceptionPointers = &ep;
ep.ExceptionRecord = (EXCEPTION_RECORD*)rec;
ep.ContextRecord = &dbg_context;
mei.ClientPointers = FALSE;
}
/* this is a wine specific options to return also ELF modules in the
* dumping
*/
SymSetOptions((wine_opt = SymGetOptions()) | 0x40000000);
MiniDumpWriteDump(dbg_curr_process->handle, dbg_curr_process->pid,
hFile, MiniDumpNormal/*|MiniDumpWithDataSegs*/,
rec ? &mei : NULL, NULL, NULL);
SymSetOptions(wine_opt);
CloseHandle(hFile);
}
...@@ -80,7 +80,6 @@ DWORD dbg_curr_pid; ...@@ -80,7 +80,6 @@ DWORD dbg_curr_pid;
CONTEXT dbg_context; CONTEXT dbg_context;
int dbg_curr_frame = 0; int dbg_curr_frame = 0;
BOOL dbg_interactiveP = FALSE; BOOL dbg_interactiveP = FALSE;
static unsigned dbg_in_exception = FALSE;
static char* dbg_last_cmd_line = NULL; static char* dbg_last_cmd_line = NULL;
static struct dbg_process* dbg_process_list = NULL; static struct dbg_process* dbg_process_list = NULL;
...@@ -364,6 +363,7 @@ struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid, ...@@ -364,6 +363,7 @@ struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid,
t->exec_count = 0; t->exec_count = 0;
t->step_over_bp.enabled = FALSE; t->step_over_bp.enabled = FALSE;
t->step_over_bp.refcount = 0; t->step_over_bp.refcount = 0;
t->in_exception = FALSE;
snprintf(t->name, sizeof(t->name), "0x%08lx", tid); snprintf(t->name, sizeof(t->name), "0x%08lx", tid);
...@@ -449,7 +449,7 @@ BOOL dbg_detach_debuggee(void) ...@@ -449,7 +449,7 @@ BOOL dbg_detach_debuggee(void)
*/ */
be_cpu->single_step(&dbg_context, FALSE); be_cpu->single_step(&dbg_context, FALSE);
SetThreadContext(dbg_curr_thread->handle, &dbg_context); SetThreadContext(dbg_curr_thread->handle, &dbg_context);
if (dbg_in_exception) if (dbg_curr_thread->in_exception)
ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE); ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
if (!DebugActiveProcessStop(dbg_curr_pid)) return FALSE; if (!DebugActiveProcessStop(dbg_curr_pid)) return FALSE;
dbg_del_process(dbg_curr_process); dbg_del_process(dbg_curr_process);
...@@ -476,14 +476,15 @@ static unsigned dbg_fetch_context(void) ...@@ -476,14 +476,15 @@ static unsigned dbg_fetch_context(void)
return TRUE; return TRUE;
} }
static unsigned dbg_exception_prolog(BOOL is_debug, DWORD code) static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
{ {
ADDRESS addr; ADDRESS addr;
BOOL is_break; BOOL is_break;
dbg_in_exception = TRUE;
memory_get_current_pc(&addr); memory_get_current_pc(&addr);
break_suspend_execution(); break_suspend_execution();
dbg_curr_thread->excpt_record = *rec;
dbg_curr_thread->in_exception = TRUE;
if (!is_debug) if (!is_debug)
{ {
...@@ -507,7 +508,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, DWORD code) ...@@ -507,7 +508,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, DWORD code)
*/ */
stack_backtrace(dbg_curr_tid, FALSE); stack_backtrace(dbg_curr_tid, FALSE);
if (is_debug && if (is_debug &&
break_should_continue(&addr, code, &dbg_curr_thread->exec_count, &is_break)) break_should_continue(&addr, rec->ExceptionCode, &dbg_curr_thread->exec_count, &is_break))
return FALSE; return FALSE;
if (addr.Mode != dbg_curr_thread->addr_mode) if (addr.Mode != dbg_curr_thread->addr_mode)
...@@ -559,10 +560,10 @@ static void dbg_exception_epilog(void) ...@@ -559,10 +560,10 @@ static void dbg_exception_epilog(void)
*/ */
if (dbg_curr_thread->exec_mode == dbg_exec_cont) if (dbg_curr_thread->exec_mode == dbg_exec_cont)
dbg_curr_thread->exec_count = 0; dbg_curr_thread->exec_count = 0;
dbg_in_exception = FALSE; dbg_curr_thread->in_exception = FALSE;
} }
static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance) static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
{ {
BOOL is_debug = FALSE; BOOL is_debug = FALSE;
THREADNAME_INFO* pThreadName; THREADNAME_INFO* pThreadName;
...@@ -712,12 +713,12 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance) ...@@ -712,12 +713,12 @@ static DWORD dbg_handle_exception(EXCEPTION_RECORD* rec, BOOL first_chance)
if (dbg_action_mode == automatic_mode) if (dbg_action_mode == automatic_mode)
{ {
dbg_exception_prolog(is_debug, rec->ExceptionCode); dbg_exception_prolog(is_debug, rec);
dbg_exception_epilog(); dbg_exception_epilog();
return 0; /* terminate execution */ return 0; /* terminate execution */
} }
if (dbg_exception_prolog(is_debug, rec->ExceptionCode)) if (dbg_exception_prolog(is_debug, rec))
{ {
dbg_interactiveP = TRUE; dbg_interactiveP = TRUE;
return 0; return 0;
...@@ -941,7 +942,7 @@ static unsigned dbg_handle_debug_event(DEBUG_EVENT* de) ...@@ -941,7 +942,7 @@ static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
static void dbg_resume_debuggee(DWORD cont) static void dbg_resume_debuggee(DWORD cont)
{ {
if (dbg_in_exception) if (dbg_curr_thread->in_exception)
{ {
ADDRESS addr; ADDRESS addr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment