Debugger is now called by exception handling.
Added 'pass' command to pass exceptions to the app.
This commit is contained in:
parent
1eeed68514
commit
410ae4f3e7
|
@ -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
|
||||
* 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);
|
||||
if( list.sourcefile != NULL )
|
||||
|
@ -497,7 +497,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
|
|||
EIP_reg(&DEBUG_context)++;
|
||||
|
||||
/* 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 )
|
|||
switch(mode)
|
||||
{
|
||||
case EXEC_CONT: /* Continuous execution */
|
||||
case EXEC_PASS: /* Continue, passing exception */
|
||||
EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
|
||||
DEBUG_SetBreakpoints( TRUE );
|
||||
break;
|
||||
|
|
123
debugger/dbg.y
123
debugger/dbg.y
|
@ -70,7 +70,7 @@ extern void VIRTUAL_Dump(void); /* memory/virtual.c */
|
|||
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 tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
|
||||
%token tPROCESS tMODREF
|
||||
|
@ -128,6 +128,8 @@ command:
|
|||
| tHELP tINFO tEOL { DEBUG_HelpInfo(); }
|
||||
| tCONT tEOL { dbg_exec_count = 1;
|
||||
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;
|
||||
dbg_exec_mode = EXEC_CONT; return 0; }
|
||||
| tSTEP tEOL { dbg_exec_count = 1;
|
||||
|
@ -435,7 +437,7 @@ void mode_command(int newmode)
|
|||
*
|
||||
* Debugger main loop.
|
||||
*/
|
||||
static void DEBUG_Main( int signal )
|
||||
static void DEBUG_Main( BOOL is_debug )
|
||||
{
|
||||
static int loaded_symbols = 0;
|
||||
static BOOL frozen = FALSE;
|
||||
|
@ -449,7 +451,7 @@ static void DEBUG_Main( int signal )
|
|||
|
||||
if (in_debugger)
|
||||
{
|
||||
fprintf( stderr, "Segmentation fault inside debugger, exiting.\n" );
|
||||
fprintf( stderr, " inside debugger, exiting.\n" );
|
||||
exit(1);
|
||||
}
|
||||
in_debugger = TRUE;
|
||||
|
@ -457,6 +459,15 @@ static void DEBUG_Main( int signal )
|
|||
|
||||
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)
|
||||
{
|
||||
loaded_symbols++;
|
||||
|
@ -516,8 +527,7 @@ static void DEBUG_Main( int signal )
|
|||
sleep(1);
|
||||
#endif
|
||||
|
||||
if ((signal != SIGTRAP) || !DEBUG_ShouldContinue( dbg_exec_mode,
|
||||
&dbg_exec_count ))
|
||||
if (!is_debug || !DEBUG_ShouldContinue( dbg_exec_mode, &dbg_exec_count ))
|
||||
{
|
||||
DBG_ADDR addr;
|
||||
TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() );
|
||||
|
@ -548,7 +558,7 @@ static void DEBUG_Main( int signal )
|
|||
|
||||
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_InfoStack();
|
||||
|
@ -558,6 +568,7 @@ static void DEBUG_Main( int signal )
|
|||
if (ES_reg(&DEBUG_context) != DS_reg(&DEBUG_context))
|
||||
LDT_Print( SELECTOR_TO_ENTRY(ES_reg(&DEBUG_context)), 1 );
|
||||
}
|
||||
LDT_Print( SELECTOR_TO_ENTRY(FS_reg(&DEBUG_context)), 1 );
|
||||
DEBUG_BackTrace();
|
||||
}
|
||||
else
|
||||
|
@ -569,7 +580,7 @@ static void DEBUG_Main( int signal )
|
|||
DEBUG_SilentBackTrace();
|
||||
}
|
||||
|
||||
if ((signal != SIGTRAP) ||
|
||||
if (!is_debug ||
|
||||
(dbg_exec_mode == EXEC_STEPI_OVER) ||
|
||||
(dbg_exec_mode == EXEC_STEPI_INSTR))
|
||||
{
|
||||
|
@ -604,7 +615,7 @@ static void DEBUG_Main( int signal )
|
|||
* if it was used. Otherwise it would have been ignored.
|
||||
* 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;
|
||||
|
||||
|
@ -621,44 +632,72 @@ static void DEBUG_Main( int signal )
|
|||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DebugBreak (KERNEL.203) (KERNEL32.181)
|
||||
*/
|
||||
void DebugBreak16( CONTEXT *regs )
|
||||
DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
char module[10];
|
||||
if (!GetModuleName16( GetCurrentTask(), module, sizeof(module) ))
|
||||
strcpy( module, "???" );
|
||||
fprintf( stderr, "%s called DebugBreak\n", module );
|
||||
DEBUG_context = *regs;
|
||||
DEBUG_Main( SIGTRAP );
|
||||
}
|
||||
BOOL is_debug = FALSE;
|
||||
|
||||
if (first_chance && !Options.debug) return 0; /* pass to app first */
|
||||
|
||||
void ctx_debug( int signal, CONTEXT *regs )
|
||||
{
|
||||
DEBUG_context = *regs;
|
||||
DEBUG_Main( signal );
|
||||
*regs = DEBUG_context;
|
||||
}
|
||||
switch(rec->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
case EXCEPTION_SINGLE_STEP:
|
||||
is_debug = TRUE;
|
||||
break;
|
||||
case CONTROL_C_EXIT:
|
||||
if (!Options.debug) exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
void wine_debug( int signal, SIGCONTEXT *regs )
|
||||
{
|
||||
#if 0
|
||||
DWORD *stack = (DWORD *)ESP_sig(regs);
|
||||
*(--stack) = 0;
|
||||
*(--stack) = 0;
|
||||
*(--stack) = EH_NONCONTINUABLE;
|
||||
*(--stack) = EXCEPTION_ACCESS_VIOLATION;
|
||||
*(--stack) = EIP_sig(regs);
|
||||
ESP_sig(regs) = (DWORD)stack;
|
||||
EIP_sig(regs) = (DWORD)RaiseException;
|
||||
#else
|
||||
DEBUG_SetSigContext( regs );
|
||||
DEBUG_Main( signal );
|
||||
DEBUG_GetSigContext( regs );
|
||||
#endif
|
||||
if (!is_debug)
|
||||
{
|
||||
/* print some infos */
|
||||
fprintf( stderr, "%s: ",
|
||||
first_chance ? "First chance exception" : "Unhandled exception" );
|
||||
switch(rec->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
fprintf( stderr, "divide by zero" );
|
||||
break;
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
fprintf( stderr, "overflow" );
|
||||
break;
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
fprintf( stderr, "array bounds " );
|
||||
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)
|
||||
|
|
|
@ -135,6 +135,7 @@ $gs { yylval.reg = REG_GS; return tREG; }
|
|||
<INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
|
||||
|
||||
<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>step|ste|st|s { BEGIN(NOCMD); return tSTEP; }
|
||||
<INITIAL>next|nex|ne|n { BEGIN(NOCMD); return tNEXT; }
|
||||
|
|
|
@ -124,11 +124,10 @@ void DEBUG_Help(void)
|
|||
"The commands accepted by the Wine debugger are a reasonable",
|
||||
"subset of the commands that gdb accepts.",
|
||||
"The commands currently are:",
|
||||
" help quit",
|
||||
" break [*<addr>] delete break bpnum",
|
||||
" disable bpnum enable bpnum",
|
||||
" condition <bpnum> [<expr>]",
|
||||
|
||||
" help quit",
|
||||
" condition <bpnum> [<expr>] pass",
|
||||
" bt cont [N]",
|
||||
" step [N] next [N]",
|
||||
" stepi [N] nexti [N]",
|
||||
|
@ -140,8 +139,6 @@ void DEBUG_Help(void)
|
|||
" show dir dir <path>",
|
||||
" display <expr> undisplay <disnum>",
|
||||
" delete display <disnum> debugmsg <class>[-+]<type>\n",
|
||||
|
||||
"Wine-specific commands:",
|
||||
" mode [16,32] walk [wnd,class,queue,module,",
|
||||
" process,modref <pid>]",
|
||||
" info (see 'help info' for options)\n",
|
||||
|
|
|
@ -126,77 +126,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
|
||||
*
|
||||
|
|
|
@ -129,6 +129,7 @@ enum debug_regs
|
|||
enum exec_mode
|
||||
{
|
||||
EXEC_CONT, /* Continuous execution */
|
||||
EXEC_PASS, /* Continue, passing exception to app */
|
||||
EXEC_STEP_OVER, /* Stepping over a call to next source line */
|
||||
EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */
|
||||
EXEC_STEPI_OVER, /* Stepping over a call */
|
||||
|
@ -255,8 +256,6 @@ extern void DEBUG_SetRegister( enum debug_regs reg, int val );
|
|||
extern int DEBUG_GetRegister( enum debug_regs reg );
|
||||
extern void DEBUG_InfoRegisters(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);
|
||||
|
||||
/* debugger/stack.c */
|
||||
|
@ -318,16 +317,7 @@ extern void DEBUG_NukePath(void);
|
|||
extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset );
|
||||
|
||||
/* debugger/dbg.y */
|
||||
extern void ctx_debug( int signal, CONTEXT *regs );
|
||||
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* );
|
||||
extern DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
|
||||
|
||||
/* Choose your allocator! */
|
||||
#if 1
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "thread.h"
|
||||
#include "task.h"
|
||||
#include "stackframe.h"
|
||||
#include "wine/exception.h"
|
||||
#include "debug.h"
|
||||
|
||||
static int MAIN_argc;
|
||||
|
@ -139,10 +140,8 @@ int main( int argc, char *argv[] )
|
|||
if (!MAIN_WineInit( &argc, argv )) return 1;
|
||||
MAIN_argc = argc; MAIN_argv = argv;
|
||||
|
||||
/* Set up debugger/instruction emulation callback routines */
|
||||
ctx_debug_call = ctx_debug;
|
||||
fnWINE_Debugger = wine_debug;
|
||||
fnINSTR_EmulateInstruction = INSTR_EmulateInstruction;
|
||||
/* Set up debugger hook */
|
||||
EXC_SetDebugEventHook( wine_debugger );
|
||||
|
||||
if (Options.debug)
|
||||
TASK_AddTaskEntryBreakpoint = DEBUG_AddTaskEntryBreakpoint;
|
||||
|
|
Loading…
Reference in New Issue