From 2602dec603ae83318622f6ffefb4e5f307f6baae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 7 Apr 2003 23:10:08 +0000 Subject: [PATCH] Improve (hardware) exception handling and reporting svn path=/trunk/; revision=4514 --- reactos/lib/kernel32/process/create.c | 43 +++++---- reactos/lib/ntdll/rtl/exception.c | 4 +- reactos/ntoskrnl/kd/gdbstub.c | 39 ++++---- reactos/ntoskrnl/ke/bug.c | 10 +- reactos/ntoskrnl/ke/catch.c | 128 +++++++++++++------------- reactos/ntoskrnl/ke/i386/exp.c | 3 + reactos/ntoskrnl/ke/i386/usertrap.c | 3 + 7 files changed, 118 insertions(+), 112 deletions(-) diff --git a/reactos/lib/kernel32/process/create.c b/reactos/lib/kernel32/process/create.c index 3cde7480699..4ce65fa8a25 100644 --- a/reactos/lib/kernel32/process/create.c +++ b/reactos/lib/kernel32/process/create.c @@ -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 * PROJECT: ReactOS system libraries @@ -171,29 +171,32 @@ _except_handler( struct _CONTEXT *ContextRecord, void * DispatcherContext ) { - DPRINT("Process terminated abnormally...\n"); + DPRINT1("Process terminated abnormally due to unhandled exception\n"); - if (++_except_recursion_trap > 3) { - DPRINT("_except_handler(...) appears to be recursing.\n"); - DPRINT("Process HALTED.\n"); - for (;;) {} - } - - if (/* FIXME: */ TRUE) /* Not a service */ + if (3 < ++_except_recursion_trap) + { + DPRINT1("_except_handler(...) appears to be recursing.\n"); + DPRINT1("Process HALTED.\n"); + for (;;) { - 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"); - /* We should not get to here */ - return ExceptionContinueSearch; + 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); + } + + DPRINT1(" We should not get to here !!!\n"); + /* We should not get to here */ + return ExceptionContinueSearch; } VOID STDCALL diff --git a/reactos/lib/ntdll/rtl/exception.c b/reactos/lib/ntdll/rtl/exception.c index 441987b19c8..6f3538f3b55 100644 --- a/reactos/lib/ntdll/rtl/exception.c +++ b/reactos/lib/ntdll/rtl/exception.c @@ -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 * PROJECT: ReactOS kernel @@ -58,7 +58,7 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, VOID STDCALL RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) { - DbgPrint("RtlRaiseException()"); + DPRINT("RtlRaiseException()\n"); } VOID STDCALL diff --git a/reactos/ntoskrnl/kd/gdbstub.c b/reactos/ntoskrnl/kd/gdbstub.c index f32992a005b..c1a9ee0ba63 100644 --- a/reactos/ntoskrnl/kd/gdbstub.c +++ b/reactos/ntoskrnl/kd/gdbstub.c @@ -90,7 +90,7 @@ #include #include -#undef NDEBUG +#define NDEBUG #include extern LIST_ENTRY PiThreadListHead; @@ -354,7 +354,7 @@ GspPutPacketNoWait (PCHAR Buffer) /* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an error. */ 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 */ @@ -370,6 +370,12 @@ GspMem2Hex (PCHAR Address, ULONG i; CHAR ch; + if (NULL == Address && MayFault) + { + GspMemoryError = TRUE; + return Buffer; + } + for (i = 0; i < (ULONG) Count; i++) { if (MayFault) @@ -457,14 +463,12 @@ GspComputeSignal (NTSTATUS ExceptionCode) SigVal = 8; break; /* divide by zero */ case STATUS_SINGLE_STEP: - SigVal = 5; - break; /* debug exception */ + /* debug exception */ case STATUS_BREAKPOINT: SigVal = 5; break; /* breakpoint */ case STATUS_INTEGER_OVERFLOW: - SigVal = 16; - break; /* into instruction (overflow) */ + /* into instruction (overflow) */ case STATUS_ARRAY_BOUNDS_EXCEEDED: SigVal = 16; break; /* bound instruction */ @@ -477,11 +481,12 @@ GspComputeSignal (NTSTATUS ExceptionCode) break; /* coprocessor not available */ #endif case STATUS_STACK_OVERFLOW: - SigVal = 11; - break; /* stack exception */ + /* stack exception */ case STATUS_DATATYPE_MISALIGNMENT: - SigVal = 11; - break; /* page fault */ + /* page fault */ + case STATUS_ACCESS_VIOLATION: + SigVal = 11; /* access violation */ + break; default: SigVal = 7; /* "software generated" */ } @@ -746,7 +751,6 @@ GspQuery(PCHAR Request) ETHREAD, Tcb.ThreadListEntry); Value = (ULONG) GspEnumThread->Cid.UniqueThread; GspLong2Hex (&ptr, Value); -DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread); } else if (strncmp (Command, "sThreadInfo", 11) == 0) { @@ -760,12 +764,10 @@ DPRINT("fThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread); GspOutBuffer[0] = 'm'; Value = (ULONG) GspEnumThread->Cid.UniqueThread; GspLong2Hex (&ptr, Value); -DPRINT("sThreadInfo 0x%08x\n", (ULONG) GspEnumThread->Cid.UniqueThread); } else { GspOutBuffer[0] = 'l'; -DPRINT("End of threads\n"); } } else if (strncmp (Command, "ThreadExtraInfo", 15) == 0) @@ -983,13 +985,15 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, /* Disable hardware debugging while we are inside the stub */ __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); - if (NULL != GspAccessLocation && + if (STATUS_ACCESS_VIOLATION == ExceptionRecord->ExceptionCode && + NULL != GspAccessLocation && (ULONG_PTR) GspAccessLocation == (ULONG_PTR) ExceptionRecord->ExceptionInformation[1]) { GspAccessLocation = NULL; GspMemoryError = TRUE; TrapFrame->Eip += 2; + ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NONCONTINUABLE; } else { @@ -1044,16 +1048,9 @@ KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, break; case 'g': /* return the value of the CPU Registers */ if (GspDbgThread) -{ -DPRINT("GspDbgThread active\n"); GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame); -/*GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);*/ -} else -{ -DPRINT("GspDbgThread not active\n"); GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame); -} break; case 'G': /* set the value of the CPU Registers - return OK */ if (GspDbgThread) diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index c77e5898dff..c324558acd7 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * FILE: ntoskrnl/ke/bug.c @@ -158,14 +158,18 @@ KeBugCheckEx(ULONG BugCheckCode, MmDumpToPagingFile(BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4, NULL); - + if (KdDebuggerEnabled) { __asm__("sti\n\t"); DbgBreakPoint(); + __asm__("cli\n\t"); } - for(;;); + for (;;) + { + __asm__("hlt\n\t"); + } } VOID STDCALL diff --git a/reactos/ntoskrnl/ke/catch.c b/reactos/ntoskrnl/ke/catch.c index 135ad00f512..3e83f224111 100644 --- a/reactos/ntoskrnl/ke/catch.c +++ b/reactos/ntoskrnl/ke/catch.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * FILE: ntoskrnl/ke/catch.c @@ -53,6 +53,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, { EXCEPTION_DISPOSITION Value; CONTEXT TContext; + KD_CONTINUE_TYPE Action = kdContinue; DPRINT("KiDispatchException() called\n"); @@ -77,69 +78,65 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, Context->Eip--; } #endif - if (PreviousMode == UserMode) - { - if (SearchFrames) - { - 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); + if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) + { + Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf); } - else - { - KD_CONTINUE_TYPE Action = kdContinue; - - /* PreviousMode == KernelMode */ - - if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) - { - Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf); - } #ifdef KDBG - else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB) - { - Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf); - } + else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB) + { + Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf); + } #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); DPRINT("RtlpDispatchException() returned with 0x%X\n", Value); @@ -147,17 +144,16 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, * If RtlpDispatchException() does not handle the exception then * bugcheck */ -#ifdef TODO - if (Value != ExceptionContinueExecution) -#endif + if (Value != ExceptionContinueExecution || + 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) { KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED); } } - else - { - KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame); - } + } + else + { + KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame); } } diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index a5918d8d7c5..cd9d7ff6fb2 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -181,6 +181,9 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) Er.NumberParameters = 0; } + Er.ExceptionFlags = (STATUS_SINGLE_STEP == Er.ExceptionCode || STATUS_BREAKPOINT == Er.ExceptionCode ? + 0 : EXCEPTION_NONCONTINUABLE); + KiDispatchException(&Er, 0, Tf, KernelMode, TRUE); return(0); diff --git a/reactos/ntoskrnl/ke/i386/usertrap.c b/reactos/ntoskrnl/ke/i386/usertrap.c index 19a300baeb5..67e5b54cd27 100644 --- a/reactos/ntoskrnl/ke/i386/usertrap.c +++ b/reactos/ntoskrnl/ke/i386/usertrap.c @@ -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); return(0); }