Commit 410ae4f3 authored by Alexandre Julliard's avatar Alexandre Julliard

Debugger is now called by exception handling.

Added 'pass' command to pass exceptions to the app.
parent 1eeed685
...@@ -482,7 +482,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) ...@@ -482,7 +482,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
* If we are about to stop, then print out the source line if we * If we are about to stop, then print out the source line if we
* have it. * have it.
*/ */
if( (mode != EXEC_CONT && mode != EXEC_FINISH) ) if ((mode != EXEC_CONT && mode != EXEC_PASS && mode != EXEC_FINISH))
{ {
DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list); DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
if( list.sourcefile != NULL ) if( list.sourcefile != NULL )
...@@ -497,7 +497,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) ...@@ -497,7 +497,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
EIP_reg(&DEBUG_context)++; EIP_reg(&DEBUG_context)++;
/* no breakpoint, continue if in continuous mode */ /* no breakpoint, continue if in continuous mode */
return (mode == EXEC_CONT || mode == EXEC_FINISH); return (mode == EXEC_CONT || mode == EXEC_PASS || mode == EXEC_FINISH);
} }
...@@ -612,6 +612,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) ...@@ -612,6 +612,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
switch(mode) switch(mode)
{ {
case EXEC_CONT: /* Continuous execution */ case EXEC_CONT: /* Continuous execution */
case EXEC_PASS: /* Continue, passing exception */
EFL_reg(&DEBUG_context) &= ~STEP_FLAG; EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
DEBUG_SetBreakpoints( TRUE ); DEBUG_SetBreakpoints( TRUE );
break; break;
......
...@@ -70,7 +70,7 @@ extern void VIRTUAL_Dump(void); /* memory/virtual.c */ ...@@ -70,7 +70,7 @@ extern void VIRTUAL_Dump(void); /* memory/virtual.c */
struct datatype * type; struct datatype * type;
} }
%token tCONT tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN %token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
%token tENABLE tDISABLE tBREAK tDELETE tSET tMODE tPRINT tEXAM tABORT tDEBUGMSG %token tENABLE tDISABLE tBREAK tDELETE tSET tMODE tPRINT tEXAM tABORT tDEBUGMSG
%token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL %token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
%token tPROCESS tMODREF %token tPROCESS tMODREF
...@@ -128,6 +128,8 @@ command: ...@@ -128,6 +128,8 @@ command:
| tHELP tINFO tEOL { DEBUG_HelpInfo(); } | tHELP tINFO tEOL { DEBUG_HelpInfo(); }
| tCONT tEOL { dbg_exec_count = 1; | tCONT tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_CONT; return 0; } dbg_exec_mode = EXEC_CONT; return 0; }
| tPASS tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_PASS; return 0; }
| tCONT tNUM tEOL { dbg_exec_count = $2; | tCONT tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_CONT; return 0; } dbg_exec_mode = EXEC_CONT; return 0; }
| tSTEP tEOL { dbg_exec_count = 1; | tSTEP tEOL { dbg_exec_count = 1;
...@@ -435,7 +437,7 @@ void mode_command(int newmode) ...@@ -435,7 +437,7 @@ void mode_command(int newmode)
* *
* Debugger main loop. * Debugger main loop.
*/ */
static void DEBUG_Main( int signal ) static void DEBUG_Main( BOOL is_debug )
{ {
static int loaded_symbols = 0; static int loaded_symbols = 0;
static BOOL frozen = FALSE; static BOOL frozen = FALSE;
...@@ -449,7 +451,7 @@ static void DEBUG_Main( int signal ) ...@@ -449,7 +451,7 @@ static void DEBUG_Main( int signal )
if (in_debugger) if (in_debugger)
{ {
fprintf( stderr, "Segmentation fault inside debugger, exiting.\n" ); fprintf( stderr, " inside debugger, exiting.\n" );
exit(1); exit(1);
} }
in_debugger = TRUE; in_debugger = TRUE;
...@@ -457,6 +459,15 @@ static void DEBUG_Main( int signal ) ...@@ -457,6 +459,15 @@ static void DEBUG_Main( int signal )
DEBUG_SetBreakpoints( FALSE ); DEBUG_SetBreakpoints( FALSE );
if (!is_debug)
{
if (IS_SELECTOR_SYSTEM(CS_reg(&DEBUG_context)))
fprintf( stderr, " in 32-bit code (0x%08lx).\n", EIP_reg(&DEBUG_context));
else
fprintf( stderr, " in 16-bit code (%04x:%04lx).\n",
(WORD)CS_reg(&DEBUG_context), EIP_reg(&DEBUG_context) );
}
if (!loaded_symbols) if (!loaded_symbols)
{ {
loaded_symbols++; loaded_symbols++;
...@@ -516,8 +527,7 @@ static void DEBUG_Main( int signal ) ...@@ -516,8 +527,7 @@ static void DEBUG_Main( int signal )
sleep(1); sleep(1);
#endif #endif
if ((signal != SIGTRAP) || !DEBUG_ShouldContinue( dbg_exec_mode, if (!is_debug || !DEBUG_ShouldContinue( dbg_exec_mode, &dbg_exec_count ))
&dbg_exec_count ))
{ {
DBG_ADDR addr; DBG_ADDR addr;
TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() ); TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() );
...@@ -548,7 +558,7 @@ static void DEBUG_Main( int signal ) ...@@ -548,7 +558,7 @@ static void DEBUG_Main( int signal )
DEBUG_DoDisplay(); DEBUG_DoDisplay();
if (signal != SIGTRAP) /* This is a real crash, dump some info */ if (!is_debug) /* This is a real crash, dump some info */
{ {
DEBUG_InfoRegisters(); DEBUG_InfoRegisters();
DEBUG_InfoStack(); DEBUG_InfoStack();
...@@ -558,6 +568,7 @@ static void DEBUG_Main( int signal ) ...@@ -558,6 +568,7 @@ static void DEBUG_Main( int signal )
if (ES_reg(&DEBUG_context) != DS_reg(&DEBUG_context)) if (ES_reg(&DEBUG_context) != DS_reg(&DEBUG_context))
LDT_Print( SELECTOR_TO_ENTRY(ES_reg(&DEBUG_context)), 1 ); LDT_Print( SELECTOR_TO_ENTRY(ES_reg(&DEBUG_context)), 1 );
} }
LDT_Print( SELECTOR_TO_ENTRY(FS_reg(&DEBUG_context)), 1 );
DEBUG_BackTrace(); DEBUG_BackTrace();
} }
else else
...@@ -569,7 +580,7 @@ static void DEBUG_Main( int signal ) ...@@ -569,7 +580,7 @@ static void DEBUG_Main( int signal )
DEBUG_SilentBackTrace(); DEBUG_SilentBackTrace();
} }
if ((signal != SIGTRAP) || if (!is_debug ||
(dbg_exec_mode == EXEC_STEPI_OVER) || (dbg_exec_mode == EXEC_STEPI_OVER) ||
(dbg_exec_mode == EXEC_STEPI_INSTR)) (dbg_exec_mode == EXEC_STEPI_INSTR))
{ {
...@@ -604,7 +615,7 @@ static void DEBUG_Main( int signal ) ...@@ -604,7 +615,7 @@ static void DEBUG_Main( int signal )
* if it was used. Otherwise it would have been ignored. * if it was used. Otherwise it would have been ignored.
* In any case, we don't mess with it any more. * In any case, we don't mess with it any more.
*/ */
if( dbg_exec_mode == EXEC_CONT ) if ((dbg_exec_mode == EXEC_CONT) || (dbg_exec_mode == EXEC_PASS))
{ {
dbg_exec_count = 0; dbg_exec_count = 0;
...@@ -621,44 +632,72 @@ static void DEBUG_Main( int signal ) ...@@ -621,44 +632,72 @@ static void DEBUG_Main( int signal )
} }
DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
/***********************************************************************
* DebugBreak (KERNEL.203) (KERNEL32.181)
*/
void DebugBreak16( CONTEXT *regs )
{ {
char module[10]; BOOL is_debug = FALSE;
if (!GetModuleName16( GetCurrentTask(), module, sizeof(module) ))
strcpy( module, "???" );
fprintf( stderr, "%s called DebugBreak\n", module );
DEBUG_context = *regs;
DEBUG_Main( SIGTRAP );
}
if (first_chance && !Options.debug) return 0; /* pass to app first */
void ctx_debug( int signal, CONTEXT *regs ) switch(rec->ExceptionCode)
{ {
DEBUG_context = *regs; case EXCEPTION_BREAKPOINT:
DEBUG_Main( signal ); case EXCEPTION_SINGLE_STEP:
*regs = DEBUG_context; is_debug = TRUE;
} break;
case CONTROL_C_EXIT:
if (!Options.debug) exit(0);
break;
}
void wine_debug( int signal, SIGCONTEXT *regs ) if (!is_debug)
{ {
#if 0 /* print some infos */
DWORD *stack = (DWORD *)ESP_sig(regs); fprintf( stderr, "%s: ",
*(--stack) = 0; first_chance ? "First chance exception" : "Unhandled exception" );
*(--stack) = 0; switch(rec->ExceptionCode)
*(--stack) = EH_NONCONTINUABLE; {
*(--stack) = EXCEPTION_ACCESS_VIOLATION; case EXCEPTION_INT_DIVIDE_BY_ZERO:
*(--stack) = EIP_sig(regs); fprintf( stderr, "divide by zero" );
ESP_sig(regs) = (DWORD)stack; break;
EIP_sig(regs) = (DWORD)RaiseException; case EXCEPTION_INT_OVERFLOW:
#else fprintf( stderr, "overflow" );
DEBUG_SetSigContext( regs ); break;
DEBUG_Main( signal ); case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
DEBUG_GetSigContext( regs ); fprintf( stderr, "array bounds " );
#endif break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
fprintf( stderr, "illegal instruction" );
break;
case EXCEPTION_STACK_OVERFLOW:
fprintf( stderr, "stack overflow" );
break;
case EXCEPTION_PRIV_INSTRUCTION:
fprintf( stderr, "priviledged instruction" );
break;
case EXCEPTION_ACCESS_VIOLATION:
if (rec->NumberParameters == 2)
fprintf( stderr, "page fault on %s access to 0x%08lx",
rec->ExceptionInformation[0] ? "write" : "read",
rec->ExceptionInformation[1] );
else
fprintf( stderr, "page fault" );
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
fprintf( stderr, "Alignment" );
break;
case CONTROL_C_EXIT:
fprintf( stderr, "^C" );
break;
default:
fprintf( stderr, "%08lx", rec->ExceptionCode );
break;
}
}
DEBUG_context = *context;
DEBUG_Main( is_debug );
*context = DEBUG_context;
return (dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE;
} }
int yyerror(char * s) int yyerror(char * s)
......
...@@ -135,6 +135,7 @@ $gs { yylval.reg = REG_GS; return tREG; } ...@@ -135,6 +135,7 @@ $gs { yylval.reg = REG_GS; return tREG; }
<INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; } <INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
<INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; } <INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; }
<INITIAL>pass|pas|pa { BEGIN(NOCMD); return tPASS; }
<INITIAL>condition|conditio|conditi|condit|condi|cond { BEGIN(NOCMD); return tCOND; } <INITIAL>condition|conditio|conditi|condit|condi|cond { BEGIN(NOCMD); return tCOND; }
<INITIAL>step|ste|st|s { BEGIN(NOCMD); return tSTEP; } <INITIAL>step|ste|st|s { BEGIN(NOCMD); return tSTEP; }
<INITIAL>next|nex|ne|n { BEGIN(NOCMD); return tNEXT; } <INITIAL>next|nex|ne|n { BEGIN(NOCMD); return tNEXT; }
......
...@@ -124,11 +124,10 @@ void DEBUG_Help(void) ...@@ -124,11 +124,10 @@ void DEBUG_Help(void)
"The commands accepted by the Wine debugger are a reasonable", "The commands accepted by the Wine debugger are a reasonable",
"subset of the commands that gdb accepts.", "subset of the commands that gdb accepts.",
"The commands currently are:", "The commands currently are:",
" help quit",
" break [*<addr>] delete break bpnum", " break [*<addr>] delete break bpnum",
" disable bpnum enable bpnum", " disable bpnum enable bpnum",
" condition <bpnum> [<expr>]", " condition <bpnum> [<expr>] pass",
" help quit",
" bt cont [N]", " bt cont [N]",
" step [N] next [N]", " step [N] next [N]",
" stepi [N] nexti [N]", " stepi [N] nexti [N]",
...@@ -140,8 +139,6 @@ void DEBUG_Help(void) ...@@ -140,8 +139,6 @@ void DEBUG_Help(void)
" show dir dir <path>", " show dir dir <path>",
" display <expr> undisplay <disnum>", " display <expr> undisplay <disnum>",
" delete display <disnum> debugmsg <class>[-+]<type>\n", " delete display <disnum> debugmsg <class>[-+]<type>\n",
"Wine-specific commands:",
" mode [16,32] walk [wnd,class,queue,module,", " mode [16,32] walk [wnd,class,queue,module,",
" process,modref <pid>]", " process,modref <pid>]",
" info (see 'help info' for options)\n", " info (see 'help info' for options)\n",
......
...@@ -127,77 +127,6 @@ int DEBUG_GetRegister( enum debug_regs reg ) ...@@ -127,77 +127,6 @@ int DEBUG_GetRegister( enum debug_regs reg )
/*********************************************************************** /***********************************************************************
* DEBUG_SetSigContext
*
* Set the register values from a sigcontext.
*/
void DEBUG_SetSigContext( const SIGCONTEXT *sigcontext )
{
EAX_reg(&DEBUG_context) = EAX_sig(sigcontext);
EBX_reg(&DEBUG_context) = EBX_sig(sigcontext);
ECX_reg(&DEBUG_context) = ECX_sig(sigcontext);
EDX_reg(&DEBUG_context) = EDX_sig(sigcontext);
ESI_reg(&DEBUG_context) = ESI_sig(sigcontext);
EDI_reg(&DEBUG_context) = EDI_sig(sigcontext);
EBP_reg(&DEBUG_context) = EBP_sig(sigcontext);
EFL_reg(&DEBUG_context) = EFL_sig(sigcontext);
EIP_reg(&DEBUG_context) = EIP_sig(sigcontext);
ESP_reg(&DEBUG_context) = ESP_sig(sigcontext);
CS_reg(&DEBUG_context) = LOWORD(CS_sig(sigcontext));
DS_reg(&DEBUG_context) = LOWORD(DS_sig(sigcontext));
ES_reg(&DEBUG_context) = LOWORD(ES_sig(sigcontext));
SS_reg(&DEBUG_context) = LOWORD(SS_sig(sigcontext));
#ifdef FS_sig
FS_reg(&DEBUG_context) = LOWORD(FS_sig(sigcontext));
#else
GET_FS( FS_reg(&DEBUG_context) );
FS_reg(&DEBUG_context) &= 0xffff;
#endif
#ifdef GS_sig
GS_reg(&DEBUG_context) = LOWORD(GS_sig(sigcontext));
#else
GET_GS( GS_reg(&DEBUG_context) );
GS_reg(&DEBUG_context) &= 0xffff;
#endif
if (ISV86(&DEBUG_context))
V86BASE(&DEBUG_context) = (DWORD) DOSMEM_MemoryBase(0);
}
/***********************************************************************
* DEBUG_GetSigContext
*
* Build a sigcontext from the register values.
*/
void DEBUG_GetSigContext( SIGCONTEXT *sigcontext )
{
EAX_sig(sigcontext) = EAX_reg(&DEBUG_context);
EBX_sig(sigcontext) = EBX_reg(&DEBUG_context);
ECX_sig(sigcontext) = ECX_reg(&DEBUG_context);
EDX_sig(sigcontext) = EDX_reg(&DEBUG_context);
ESI_sig(sigcontext) = ESI_reg(&DEBUG_context);
EDI_sig(sigcontext) = EDI_reg(&DEBUG_context);
EBP_sig(sigcontext) = EBP_reg(&DEBUG_context);
EFL_sig(sigcontext) = EFL_reg(&DEBUG_context);
EIP_sig(sigcontext) = EIP_reg(&DEBUG_context);
ESP_sig(sigcontext) = ESP_reg(&DEBUG_context);
CS_sig(sigcontext) = CS_reg(&DEBUG_context);
DS_sig(sigcontext) = DS_reg(&DEBUG_context);
ES_sig(sigcontext) = ES_reg(&DEBUG_context);
SS_sig(sigcontext) = SS_reg(&DEBUG_context);
#ifdef FS_sig
FS_sig(sigcontext) = FS_reg(&DEBUG_context);
#else
SET_FS( FS_reg(&DEBUG_context) );
#endif
#ifdef GS_sig
GS_sig(sigcontext) = GS_reg(&DEBUG_context);
#else
SET_GS( GS_reg(&DEBUG_context) );
#endif
}
/***********************************************************************
* DEBUG_Flags * DEBUG_Flags
* *
* Return Flag String. * Return Flag String.
......
...@@ -129,6 +129,7 @@ enum debug_regs ...@@ -129,6 +129,7 @@ enum debug_regs
enum exec_mode enum exec_mode
{ {
EXEC_CONT, /* Continuous execution */ EXEC_CONT, /* Continuous execution */
EXEC_PASS, /* Continue, passing exception to app */
EXEC_STEP_OVER, /* Stepping over a call to next source line */ EXEC_STEP_OVER, /* Stepping over a call to next source line */
EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */ EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */
EXEC_STEPI_OVER, /* Stepping over a call */ EXEC_STEPI_OVER, /* Stepping over a call */
...@@ -255,8 +256,6 @@ extern void DEBUG_SetRegister( enum debug_regs reg, int val ); ...@@ -255,8 +256,6 @@ extern void DEBUG_SetRegister( enum debug_regs reg, int val );
extern int DEBUG_GetRegister( enum debug_regs reg ); extern int DEBUG_GetRegister( enum debug_regs reg );
extern void DEBUG_InfoRegisters(void); extern void DEBUG_InfoRegisters(void);
extern BOOL DEBUG_ValidateRegisters(void); extern BOOL DEBUG_ValidateRegisters(void);
extern void DEBUG_SetSigContext( const SIGCONTEXT *sigcontext );
extern void DEBUG_GetSigContext( SIGCONTEXT *sigcontext );
extern int DEBUG_PrintRegister(enum debug_regs reg); extern int DEBUG_PrintRegister(enum debug_regs reg);
/* debugger/stack.c */ /* debugger/stack.c */
...@@ -318,16 +317,7 @@ extern void DEBUG_NukePath(void); ...@@ -318,16 +317,7 @@ extern void DEBUG_NukePath(void);
extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset ); extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset );
/* debugger/dbg.y */ /* debugger/dbg.y */
extern void ctx_debug( int signal, CONTEXT *regs ); extern DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
extern void wine_debug( int signal, SIGCONTEXT *regs );
/* miscemu/instr.c */
extern BOOL INSTR_EmulateInstruction( SIGCONTEXT* );
/* loader/signal.c */
extern void (*fnWINE_Debugger)(int,SIGCONTEXT*);
extern void (*ctx_debug_call)( int, CONTEXT* );
extern BOOL (*fnINSTR_EmulateInstruction)( SIGCONTEXT* );
/* Choose your allocator! */ /* Choose your allocator! */
#if 1 #if 1
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "thread.h" #include "thread.h"
#include "task.h" #include "task.h"
#include "stackframe.h" #include "stackframe.h"
#include "wine/exception.h"
#include "debug.h" #include "debug.h"
static int MAIN_argc; static int MAIN_argc;
...@@ -139,10 +140,8 @@ int main( int argc, char *argv[] ) ...@@ -139,10 +140,8 @@ int main( int argc, char *argv[] )
if (!MAIN_WineInit( &argc, argv )) return 1; if (!MAIN_WineInit( &argc, argv )) return 1;
MAIN_argc = argc; MAIN_argv = argv; MAIN_argc = argc; MAIN_argv = argv;
/* Set up debugger/instruction emulation callback routines */ /* Set up debugger hook */
ctx_debug_call = ctx_debug; EXC_SetDebugEventHook( wine_debugger );
fnWINE_Debugger = wine_debug;
fnINSTR_EmulateInstruction = INSTR_EmulateInstruction;
if (Options.debug) if (Options.debug)
TASK_AddTaskEntryBreakpoint = DEBUG_AddTaskEntryBreakpoint; TASK_AddTaskEntryBreakpoint = DEBUG_AddTaskEntryBreakpoint;
......
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