Improve (hardware) exception handling and reporting

svn path=/trunk/; revision=4514
This commit is contained in:
Gé van Geldorp 2003-04-07 23:10:08 +00:00
parent e81de9962d
commit 2602dec603
7 changed files with 118 additions and 112 deletions

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.64 2003/03/26 22:11:27 hbirr Exp $ /* $Id: create.c,v 1.65 2003/04/07 23:10:07 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -171,29 +171,32 @@ _except_handler(
struct _CONTEXT *ContextRecord, struct _CONTEXT *ContextRecord,
void * DispatcherContext ) void * DispatcherContext )
{ {
DPRINT("Process terminated abnormally...\n"); DPRINT1("Process terminated abnormally due to unhandled exception\n");
if (++_except_recursion_trap > 3) { if (3 < ++_except_recursion_trap)
DPRINT("_except_handler(...) appears to be recursing.\n"); {
DPRINT("Process HALTED.\n"); DPRINT1("_except_handler(...) appears to be recursing.\n");
for (;;) {} DPRINT1("Process HALTED.\n");
} for (;;)
if (/* FIXME: */ TRUE) /* Not a service */
{ {
DPRINT(" calling ExitProcess(0) no, lets try ExitThread . . .\n");
//ExitProcess(0);
ExitThread(0);
}
else
{
DPRINT(" calling ExitThread(0) . . .\n");
ExitThread(0);
} }
}
DPRINT(" We should not get to here !!!\n"); if (/* FIXME: */ TRUE) /* Not a service */
/* We should not get to here */ {
return ExceptionContinueSearch; DPRINT(" calling ExitProcess(0) no, lets try ExitThread . . .\n");
/* ExitProcess(0); */
ExitThread(0);
}
else
{
DPRINT(" calling ExitThread(0) . . .\n");
ExitThread(0);
}
DPRINT1(" We should not get to here !!!\n");
/* We should not get to here */
return ExceptionContinueSearch;
} }
VOID STDCALL VOID STDCALL

View file

@ -1,4 +1,4 @@
/* $Id: exception.c,v 1.12 2003/03/16 14:16:54 chorns Exp $ /* $Id: exception.c,v 1.13 2003/04/07 23:10:08 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -58,7 +58,7 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
VOID STDCALL VOID STDCALL
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
{ {
DbgPrint("RtlRaiseException()"); DPRINT("RtlRaiseException()\n");
} }
VOID STDCALL VOID STDCALL

View file

@ -90,7 +90,7 @@
#include <internal/module.h> #include <internal/module.h>
#include <internal/ldr.h> #include <internal/ldr.h>
#undef NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
extern LIST_ENTRY PiThreadListHead; extern LIST_ENTRY PiThreadListHead;
@ -354,7 +354,7 @@ GspPutPacketNoWait (PCHAR Buffer)
/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
error. */ error. */
static volatile BOOLEAN GspMemoryError = FALSE; static volatile BOOLEAN GspMemoryError = FALSE;
static void *GspAccessLocation = NULL; static volatile void *GspAccessLocation = NULL;
/* Convert the memory pointed to by Address into hex, placing result in Buffer */ /* Convert the memory pointed to by Address into hex, placing result in Buffer */
@ -370,6 +370,12 @@ GspMem2Hex (PCHAR Address,
ULONG i; ULONG i;
CHAR ch; CHAR ch;
if (NULL == Address && MayFault)
{
GspMemoryError = TRUE;
return Buffer;
}
for (i = 0; i < (ULONG) Count; i++) for (i = 0; i < (ULONG) Count; i++)
{ {
if (MayFault) if (MayFault)
@ -457,14 +463,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
SigVal = 8; SigVal = 8;
break; /* divide by zero */ break; /* divide by zero */
case STATUS_SINGLE_STEP: case STATUS_SINGLE_STEP:
SigVal = 5; /* debug exception */
break; /* debug exception */
case STATUS_BREAKPOINT: case STATUS_BREAKPOINT:
SigVal = 5; SigVal = 5;
break; /* breakpoint */ break; /* breakpoint */
case STATUS_INTEGER_OVERFLOW: case STATUS_INTEGER_OVERFLOW:
SigVal = 16; /* into instruction (overflow) */
break; /* into instruction (overflow) */
case STATUS_ARRAY_BOUNDS_EXCEEDED: case STATUS_ARRAY_BOUNDS_EXCEEDED:
SigVal = 16; SigVal = 16;
break; /* bound instruction */ break; /* bound instruction */
@ -477,11 +481,12 @@ GspComputeSignal (NTSTATUS ExceptionCode)
break; /* coprocessor not available */ break; /* coprocessor not available */
#endif #endif
case STATUS_STACK_OVERFLOW: case STATUS_STACK_OVERFLOW:
SigVal = 11; /* stack exception */
break; /* stack exception */
case STATUS_DATATYPE_MISALIGNMENT: case STATUS_DATATYPE_MISALIGNMENT:
SigVal = 11; /* page fault */
break; /* page fault */ case STATUS_ACCESS_VIOLATION:
SigVal = 11; /* access violation */
break;
default: default:
SigVal = 7; /* "software generated" */ SigVal = 7; /* "software generated" */
} }
@ -746,7 +751,6 @@ GspQuery(PCHAR Request)
ETHREAD, Tcb.ThreadListEntry); ETHREAD, Tcb.ThreadListEntry);
Value = (ULONG) GspEnumThread->Cid.UniqueThread; Value = (ULONG) GspEnumThread->Cid.UniqueThread;
GspLong2Hex (&ptr, Value); GspLong2Hex (&ptr, Value);
DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
} }
else if (strncmp (Command, "sThreadInfo", 11) == 0) else if (strncmp (Command, "sThreadInfo", 11) == 0)
{ {
@ -760,12 +764,10 @@ DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
GspOutBuffer[0] = 'm'; GspOutBuffer[0] = 'm';
Value = (ULONG) GspEnumThread->Cid.UniqueThread; Value = (ULONG) GspEnumThread->Cid.UniqueThread;
GspLong2Hex (&ptr, Value); GspLong2Hex (&ptr, Value);
DPRINT("sThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread);
} }
else else
{ {
GspOutBuffer[0] = 'l'; GspOutBuffer[0] = 'l';
DPRINT("End of threads\n");
} }
} }
else if (strncmp (Command, "ThreadExtraInfo", 15) == 0) else if (strncmp (Command, "ThreadExtraInfo", 15) == 0)
@ -983,13 +985,15 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
/* Disable hardware debugging while we are inside the stub */ /* Disable hardware debugging while we are inside the stub */
__asm__("movl %0,%%db7" : /* no output */ : "r" (0)); __asm__("movl %0,%%db7" : /* no output */ : "r" (0));
if (NULL != GspAccessLocation && if (STATUS_ACCESS_VIOLATION == ExceptionRecord->ExceptionCode &&
NULL != GspAccessLocation &&
(ULONG_PTR) GspAccessLocation == (ULONG_PTR) GspAccessLocation ==
(ULONG_PTR) ExceptionRecord->ExceptionInformation[1]) (ULONG_PTR) ExceptionRecord->ExceptionInformation[1])
{ {
GspAccessLocation = NULL; GspAccessLocation = NULL;
GspMemoryError = TRUE; GspMemoryError = TRUE;
TrapFrame->Eip += 2; TrapFrame->Eip += 2;
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NONCONTINUABLE;
} }
else else
{ {
@ -1044,16 +1048,9 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
break; break;
case 'g': /* return the value of the CPU Registers */ case 'g': /* return the value of the CPU Registers */
if (GspDbgThread) if (GspDbgThread)
{
DPRINT("GspDbgThread active\n");
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame); GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
/*GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);*/
}
else else
{
DPRINT("GspDbgThread not active\n");
GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame); GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
}
break; break;
case 'G': /* set the value of the CPU Registers - return OK */ case 'G': /* set the value of the CPU Registers - return OK */
if (GspDbgThread) if (GspDbgThread)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: bug.c,v 1.27 2002/09/08 10:23:28 chorns Exp $ /* $Id: bug.c,v 1.28 2003/04/07 23:10:08 gvg Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/bug.c * FILE: ntoskrnl/ke/bug.c
@ -163,9 +163,13 @@ KeBugCheckEx(ULONG BugCheckCode,
{ {
__asm__("sti\n\t"); __asm__("sti\n\t");
DbgBreakPoint(); DbgBreakPoint();
__asm__("cli\n\t");
} }
for(;;); for (;;)
{
__asm__("hlt\n\t");
}
} }
VOID STDCALL VOID STDCALL

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: catch.c,v 1.29 2003/03/06 23:57:02 gvg Exp $ /* $Id: catch.c,v 1.30 2003/04/07 23:10:08 gvg Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c * FILE: ntoskrnl/ke/catch.c
@ -53,6 +53,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
{ {
EXCEPTION_DISPOSITION Value; EXCEPTION_DISPOSITION Value;
CONTEXT TContext; CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdContinue;
DPRINT("KiDispatchException() called\n"); DPRINT("KiDispatchException() called\n");
@ -77,69 +78,65 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
Context->Eip--; Context->Eip--;
} }
#endif #endif
if (PreviousMode == UserMode)
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
{ {
if (SearchFrames) Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
{
PULONG Stack;
ULONG CDest;
/* FIXME: Give the kernel debugger a chance */
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Check user mode stack for enough space */
/*
* Let usermode try and handle the exception
*/
Tf->Esp = Tf->Esp -
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
Stack = (PULONG)Tf->Esp;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&Stack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&Stack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
/* Terminate the offending thread */
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
/* If that fails then bugcheck */
DbgPrint("Could not terminate thread\n");
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
} }
else
{
KD_CONTINUE_TYPE Action = kdContinue;
/* PreviousMode == KernelMode */
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
{
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
#ifdef KDBG #ifdef KDBG
else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB) else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
{ {
Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf); Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
} }
#endif /* KDBG */ #endif /* KDBG */
if (Action != kdHandleException) if (Action != kdHandleException)
{
if (PreviousMode == UserMode)
{ {
if (SearchFrames)
{
PULONG Stack;
ULONG CDest;
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Check user mode stack for enough space */
/*
* Let usermode try and handle the exception
*/
Tf->Esp = Tf->Esp -
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
Stack = (PULONG)Tf->Esp;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&Stack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&Stack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
/* If that fails then bugcheck */
DPRINT1("Could not terminate thread\n");
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
else
{
/* PreviousMode == KernelMode */
Value = RtlpDispatchException (ExceptionRecord, Context); Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value); DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
@ -147,17 +144,16 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
* If RtlpDispatchException() does not handle the exception then * If RtlpDispatchException() does not handle the exception then
* bugcheck * bugcheck
*/ */
#ifdef TODO if (Value != ExceptionContinueExecution ||
if (Value != ExceptionContinueExecution) 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
#endif
{ {
KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED); KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);
} }
} }
else }
{ else
KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame); {
} KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
} }
} }

View file

@ -181,6 +181,9 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
Er.NumberParameters = 0; Er.NumberParameters = 0;
} }
Er.ExceptionFlags = (STATUS_SINGLE_STEP == Er.ExceptionCode || STATUS_BREAKPOINT == Er.ExceptionCode ?
0 : EXCEPTION_NONCONTINUABLE);
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE); KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
return(0); return(0);

View file

@ -144,6 +144,9 @@ KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
} }
Er.ExceptionFlags = (STATUS_SINGLE_STEP == Er.ExceptionCode || STATUS_BREAKPOINT == Er.ExceptionCode ?
0 : EXCEPTION_NONCONTINUABLE);
KiDispatchException(&Er, 0, Tf, UserMode, TRUE); KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
return(0); return(0);
} }