diff --git a/reactos/ChangeLog b/reactos/ChangeLog index e9fbbed12a6..76389d834c6 100644 --- a/reactos/ChangeLog +++ b/reactos/ChangeLog @@ -1,3 +1,37 @@ +2002-10-26 Casper S. Hornstrup + + * lib/msvcrt/Makefile (OBJECTS_EXCEPT): Add except/seh.o; Remove + except/exhand3.o. + * lib/msvcrt/except/exhand2.c (MsvcrtDebug): New function. + * lib/msvcrt/except/unwind.c (PEXCEPTION_FRAME): Remove. + (_global_unwind2): Correct prototype. + * lib/ntdll/makefile (RTL_I386_OBJECTS, ARCH_OBJECTS): New groups. + (TARGET_OBJECTS): Add ARCH_OBJECTS group. + * lib/ntdll/rtl/exception.c (KiUserExceptionDispatcher): Set + NumberParameters in exception record. + (RtlRaiseStatus): Remove. + * ntoskrnl/Makefile (OBJECTS_RTL): Remove rtl/seh.o. + (OBJECTS_RTL_I386): Add rtl/i386/except.o, rtl/i386/exception.o, and + rtl/i386/seh.o. + * ntoskrnl/ke/catch.c (RtlpExecuteHandlerForException, + RtlpDumpExceptionRegistrations, RtlpDispatchException, + RtlpExecuteHandler, RtlpExceptionHandler, RtlpUnwindHandler, + RtlpExecuteHandlerForException, RtlpExecuteHandlerForUnwind, + RtlUnwind): Remove. + (RtlpDispatchException): Add prototype. + * ntoskrnl/ke/i386/usertrap.c (ExceptionTypeStrings): Remove. + * ntoskrnl/ps/create.c (PsCreateTeb): Mark end of exception + registration list. + * tools/helper.mk (TARGET_ASFLAGS): Add -g if DBG = 1. + * lib/msvcrt/except/exhand3.c: Remove. + * ntoskrnl/rtl/seh.c: Ditto. + * lib/msvcrt/except/seh.s: New file. + * lib/ntdll/rtl/i386/except.s: Ditto. + * lib/ntdll/rtl/i386/exception.c: Ditto. + * ntoskrnl/rtl/i386/except.s: Ditto. + * ntoskrnl/rtl/i386/exception.c: Ditto. + * ntoskrnl/rtl/i386/seh.s: Ditto. + 2002-10-26 Casper S. Hornstrup * lib/kernel32/process/create.c (_except_handler): New function. diff --git a/reactos/lib/msvcrt/Makefile b/reactos/lib/msvcrt/Makefile index 03e18551549..51c1c7221d0 100644 --- a/reactos/lib/msvcrt/Makefile +++ b/reactos/lib/msvcrt/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.23 2002/09/08 10:22:46 chorns Exp $ +# $Id: Makefile,v 1.24 2002/10/26 00:32:17 chorns Exp $ PATH_TO_TOP = ../.. @@ -73,9 +73,9 @@ OBJECTS_DIRECT = \ direct/rmdir.o OBJECTS_EXCEPT = \ + except/seh.o \ except/abnorter.o \ except/exhand2.o \ - except/exhand3.o \ except/matherr.o \ except/unwind.o \ except/xcptfil.o diff --git a/reactos/lib/msvcrt/except/exhand2.c b/reactos/lib/msvcrt/except/exhand2.c index 406aeeff7d0..7bd2a7230a0 100644 --- a/reactos/lib/msvcrt/except/exhand2.c +++ b/reactos/lib/msvcrt/except/exhand2.c @@ -1,5 +1,11 @@ #include +VOID STDCALL +MsvcrtDebug(ULONG Value) +{ + DbgPrint("MsvcrtDebug 0x%.08x\n", Value); +} + EXCEPTION_DISPOSITION _except_handler2( struct _EXCEPTION_RECORD *ExceptionRecord, diff --git a/reactos/lib/msvcrt/except/exhand3.c b/reactos/lib/msvcrt/except/exhand3.c deleted file mode 100644 index d17bacf1fd3..00000000000 --- a/reactos/lib/msvcrt/except/exhand3.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -EXCEPTION_DISPOSITION -_except_handler3( -struct _EXCEPTION_RECORD *ExceptionRecord, -void *Frame, -struct _CONTEXT *ContextRecord, -void *DispatcherContext) -{ - printf("_except_handler3()\n"); -} diff --git a/reactos/lib/msvcrt/except/seh.s b/reactos/lib/msvcrt/except/seh.s new file mode 100755 index 00000000000..9b1999eda03 --- /dev/null +++ b/reactos/lib/msvcrt/except/seh.s @@ -0,0 +1,366 @@ +/* $Id: seh.s,v 1.1 2002/10/26 00:32:17 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS MSVCRT Runtime Library + * PURPOSE: Runtime library exception support for IA-32 + * FILE: lib/msvcrt/except/seh.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s. + * Please keep them in sync. + */ + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +#define EXCEPTION_NONCONTINUABLE 0x01 +#define EXCEPTION_UNWINDING 0x02 +#define EXCEPTION_EXIT_UNWIND 0x04 +#define EXCEPTION_STACK_INVALID 0x08 +#define EXCEPTION_NESTED_CALL 0x10 +#define EXCEPTION_TARGET_UNWIND 0x20 +#define EXCEPTION_COLLIDED_UNWIND 0x40 + +#define EXCEPTION_UNWIND_MODE \ +( EXCEPTION_UNWINDING \ + | EXCEPTION_EXIT_UNWIND \ + | EXCEPTION_TARGET_UNWIND \ + | EXCEPTION_COLLIDED_UNWIND) + +#define EREC_CODE 0x00 +#define EREC_FLAGS 0x04 +#define EREC_RECORD 0x08 +#define EREC_ADDRESS 0x0C +#define EREC_NUMPARAMS 0x10 +#define EREC_INFO 0x14 + +#define TRYLEVEL_NONE -1 +#define TRYLEVEL_INVALID -2 + +#define ER_STANDARDESP -0x08 +#define ER_EPOINTERS -0x04 +#define ER_PREVFRAME 0x00 +#define ER_HANDLER 0x04 +#define ER_SCOPETABLE 0x08 +#define ER_TRYLEVEL 0x0C +#define ER_EBP 0x10 + +#define ST_TRYLEVEL 0x00 +#define ST_FILTER 0x04 +#define ST_HANDLER 0x08 + +#define CONTEXT_EDI 0x9C +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EIP 0xB8 + +.globl __local_unwind2 +.globl __except_handler3 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _MsvcrtDebug@4 + popal + ret + +#define LU2_TRYLEVEL 0x08 +#define LU2_REGFRAME 0x04 + +// +// void +// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame, +// LONG TryLevel) +// +// Parameters: +// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EDX+04h] - LONG TryLevel +// Registers: +// EBP - EBP of call frame we are unwinding +// Returns: +// Nothing +// Notes: +// Run all termination handlers for a call frame from the current +// try-level up to (but not including) the given stop try-level. +__local_unwind2: + // Setup our call frame so we can access parameters using EDX + //pushl %ebp + movl %esp, %edx + + // FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the + // unwinding in case something goes wrong + +.lu2_next_scope: + + // Keep a pointer to the exception registration in EBX + movl LU2_REGFRAME(%edx), %ebx + + // If we have reached the end of the chain or we're asked to stop here + // by the caller then exit + movl ER_TRYLEVEL(%ebx), %eax + + cmpl $-1, %eax + je .lu2_done + + cmpl LU2_TRYLEVEL(%edx), %eax + je .lu2_done + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable that describes + // the scope that is to be unwound. Put the offset in EDI. + movl ST_TRYLEVEL(%esi), %edi + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // If this is not a termination handler then skip it + cmpl $0, ST_FILTER(%edi) + jne .lu2_next_scope + + // Save the previous try-level in the exception registration structure + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + + // Fetch the address of the termination handler + movl ST_HANDLER(%edi), %eax + + // Termination handlers may trash all registers so save the + // important ones and then call the handler + pushl %edx + call *%eax + + // Get our base pointer back + popl %edx + + jmp .lu2_next_scope + +.lu2_done: + + // FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect + // the unwinding + + //movl %esi, %esp + //popl %ebp + ret + +#define EH3_DISPCONTEXT 0x14 +#define EH3_CONTEXT 0x10 +#define EH3_REGFRAME 0x0C +#define EH3_ERECORD 0x08 + +// Parameters: +// [ESP+14h] - PVOID DispatcherContext +// [ESP+10h] - PCONTEXT Context +// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord +// Registers: +// Unknown +// Returns: +// EXCEPTION_DISPOSITION - How this handler handled the exception +// Notes: +// Try to find an exception handler that will handle the exception. +// Traverse the entries in the scopetable that is associated with the +// exception registration passed as a parameter to this function. +// If an exception handler that will handle the exception is found, it +// is called and this function never returns +__except_handler3: + // Setup our call frame so we can access parameters using EBP + pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION) + movl %esp, %ebp + + // Don't trust the direction flag to be cleared + cld + + // Either we're called to handle an exception or we're called to unwind + movl EH3_ERECORD(%ebp), %eax + testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax) + jnz .eh3_unwind + + // Keep a pointer to the exception registration in EBX + movl EH3_REGFRAME(%ebp), %ebx + + // Build an EXCEPTION_POINTERS structure on the stack and store it's + // address in the EXCEPTION_REGISTRATION structure + movl EH3_CONTEXT(%esp), %eax + pushl %ebx // Registration frame + pushl %eax // Context + movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack + + // Keep current try-level in EDI + movl ER_TRYLEVEL(%ebx), %edi + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + +.eh3_next_scope: + + // If we have reached the end of the chain then exit + cmpl $-1, %edi + je .eh3_search + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EAX + lea (%edi, %edi, 2), %eax + shll $2, %eax + addl %esi, %eax + + // Fetch the address of the filter routine + movl ST_FILTER(%eax), %eax + + // If this is a termination handler then skip it + cmpl $0, %eax + je .eh3_continue + + // Filter routines may trash all registers so save the important + // ones before restoring the call frame ebp and calling the handler + pushl %ebp + pushl %edi // Stop try-level + lea ER_EBP(%ebx), %ebp + call *%eax + popl %edi // Stop try-level + popl %ebp + + // Reload EBX with registration frame address + movl EH3_REGFRAME(%ebp), %ebx + + // Be more flexible here by checking if the return value is less than + // zero, equal to zero, or larger than zero instead of the defined + // values: + // -1 (EXCEPTION_CONTINUE_EXECUTION) + // 0 (EXCEPTION_CONTINUE_SEARCH) + // +1 (EXCEPTION_EXECUTE_HANDLER) + orl %eax, %eax + jz .eh3_continue + js .eh3_dismiss + + // Filter returned: EXCEPTION_EXECUTE_HANDLER + + // Ask the OS to perform global unwinding. + pushl %edi // Save stop try-level + pushl %ebx // Save registration frame address + pushl %ebx // Registration frame address + call __global_unwind2 + popl %eax // Remove parameter to __global_unwind2 + popl %ebx // Restore registration frame address + popl %edi // Restore stop try-level + + // Change the context structure so _except_finish is called in the + // correct context since we return ExceptionContinueExecution. + movl EH3_CONTEXT(%ebp), %eax + + movl %edi, CONTEXT_EDI(%eax) // Stop try-level + movl %ebx, CONTEXT_EBX(%eax) // Registration frame address + movl $_except_finish, CONTEXT_EIP(%eax) + + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Filter returned: EXCEPTION_CONTINUE_SEARCH +.eh3_continue: + + // Reload ESI because the filter routine may have trashed it + movl ER_SCOPETABLE(%ebx), %esi + + // Go one try-level closer to the top + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + movl ST_TRYLEVEL(%edi), %edi + + jmp .eh3_next_scope + + // Filter returned: EXCEPTION_CONTINUE_EXECUTION + // Continue execution like nothing happened +.eh3_dismiss: + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Tell the OS to search for another handler that will handle the exception +.eh3_search: + + movl $ExceptionContinueSearch, %eax + jmp .eh3_return + + // Perform local unwinding +.eh3_unwind: + + movl $ExceptionContinueSearch, %eax + testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax) + jnz .eh3_return + + // Save some important registers + pushl %ebp + + lea ER_EBP(%ebx), %ebp + pushl $-1 + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %ebp + + movl $ExceptionContinueSearch, %eax + + // Get me out of here +.eh3_return: + + movl %ebp, %esp + popl %ebp + ret + +// Parameters: +// None +// Registers: +// EBX - Pointer to exception registration structure +// EDI - Stop try-level +// Returns: +// - +// Notes: +// - +_except_finish: + + // Setup EBP for the exception handler. By doing this the exception + // handler can access local variables as normal + lea ER_EBP(%ebx), %ebp + + // Save some important registers + pushl %ebp + pushl %ebx + pushl %edi + + // Stop try-level + pushl %edi + + // Pointer to exception registration structure + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %edi + popl %ebx + popl %ebp + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EDI + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // Set the current try-level to the previous try-level and call + // the exception handler + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + movl ST_HANDLER(%edi), %eax + + call *%eax + + // We should never get here + ret diff --git a/reactos/lib/msvcrt/except/unwind.c b/reactos/lib/msvcrt/except/unwind.c index 1cdf65a8c7a..b4dc5553d3a 100644 --- a/reactos/lib/msvcrt/except/unwind.c +++ b/reactos/lib/msvcrt/except/unwind.c @@ -1,13 +1,10 @@ #include -#define PEXCEPTION_FRAME void* -void _global_unwind2( PEXCEPTION_FRAME frame ) +void __cdecl +_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame) { - //RtlUnwind( frame, 0, NULL, 0 ); -} - -void _local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr ) -{ - //TRACE(crtdll,"(%p,%ld)\n",endframe,nr); + RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0); +__ret_label: + // return is important return; } diff --git a/reactos/lib/ntdll/makefile b/reactos/lib/ntdll/makefile index 245bab0e7dc..94cb7ea56aa 100644 --- a/reactos/lib/ntdll/makefile +++ b/reactos/lib/ntdll/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.74 2002/09/08 10:23:02 chorns Exp $ +# $Id: makefile,v 1.75 2002/10/26 00:32:18 chorns Exp $ PATH_TO_TOP = ../.. @@ -24,6 +24,10 @@ CSR_OBJECTS = csr/lpc.o csr/capture.o csr/probe.o csr/thread.o DBG_OBJECTS = dbg/brkpoint.o dbg/debug.o dbg/print.o dbg/winedbg.o +RTL_I386_OBJECTS = \ + rtl/i386/exception.o \ + rtl/i386/except.o + RTL_OBJECTS = rtl/critical.o rtl/error.o rtl/heap.o rtl/largeint.o \ rtl/math.o rtl/mem.o rtl/nls.o rtl/process.o rtl/sd.o \ rtl/thread.o rtl/unicode.o rtl/env.o rtl/path.o rtl/ppb.o \ @@ -51,9 +55,13 @@ STRING_OBJECTS = string/ctype.o string/memccpy.o string/memchr.o \ string/strpbrk.o string/strrchr.o string/strspn.o \ string/strstr.o string/strupr.o string/wstring.o +ARCH_OBJECTS = \ + $(RTL_I386_OBJECTS) + TARGET_OBJECTS = \ napi.o \ ldr/startup.o \ + $(ARCH_OBJECTS) \ $(DBG_OBJECTS) \ $(RTL_OBJECTS) \ $(STDIO_OBJECTS) \ diff --git a/reactos/lib/ntdll/rtl/exception.c b/reactos/lib/ntdll/rtl/exception.c index 7ea159d303e..41f884c3d8a 100644 --- a/reactos/lib/ntdll/rtl/exception.c +++ b/reactos/lib/ntdll/rtl/exception.c @@ -1,4 +1,4 @@ -/* $Id: exception.c,v 1.10 2002/09/08 10:23:05 chorns Exp $ +/* $Id: exception.c,v 1.11 2002/10/26 00:32:18 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -13,31 +13,14 @@ #include #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ -VOID STDCALL -RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) -{ -#if 0 - CONTEXT Context; - - /* FIXME: fill in the CONTEXT */ - NtRaiseException ( - ExceptionRecord, - & Context, - TRUE - ); - /* FIXME: ExceptionRecord */ - RtlRaiseException (ExceptionRecord); -#endif -} - ULONG -RtlDispatchException(PEXCEPTION_RECORD ExceptionRecord, - PCONTEXT Context) -{ - -} +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); VOID STDCALL KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, @@ -46,42 +29,29 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, EXCEPTION_RECORD NestedExceptionRecord; NTSTATUS Status; - if (RtlDispatchException(ExceptionRecord, Context) == 1) + DPRINT("KiUserExceptionDispatcher()\n"); + + if (RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution) { - Status = ZwContinue(Context, FALSE); + Status = NtContinue(Context, FALSE); } else { - Status = ZwRaiseException(ExceptionRecord, Context, FALSE); + Status = NtRaiseException(ExceptionRecord, Context, FALSE); } NestedExceptionRecord.ExceptionCode = Status; NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; NestedExceptionRecord.ExceptionRecord = ExceptionRecord; + NestedExceptionRecord.NumberParameters = Status; RtlRaiseException(&NestedExceptionRecord); } VOID STDCALL -RtlRaiseStatus(NTSTATUS Status) +RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) { - EXCEPTION_RECORD ExceptionRecord; - - ExceptionRecord.ExceptionCode = Status; - ExceptionRecord.ExceptionRecord = NULL; - ExceptionRecord.NumberParameters = 0; - ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - RtlRaiseException (& ExceptionRecord); -} - - -VOID STDCALL -RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame, - PVOID ReturnAddress, - PEXCEPTION_RECORD ExceptionRecord, - DWORD EaxValue) -{ - + DbgPrint("RtlRaiseException()"); } /* EOF */ diff --git a/reactos/lib/ntdll/rtl/i386/except.s b/reactos/lib/ntdll/rtl/i386/except.s new file mode 100755 index 00000000000..78b66b73ce3 --- /dev/null +++ b/reactos/lib/ntdll/rtl/i386/except.s @@ -0,0 +1,290 @@ +/* $Id: except.s,v 1.1 2002/10/26 00:32:18 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode exception support for IA-32 + * FILE: lib/ntdll/rtl/i386/except.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with ntoskrnl/rtl/i386/except.s. + * Please keep them in sync. + */ + +#define EXCEPTION_UNWINDING 0x02 + +#define EREC_FLAGS 0x04 + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +.globl _RtlpExecuteHandlerForException +.globl _RtlpExecuteHandlerForUnwind + +#define CONTEXT_FLAGS 0x00 +#define CONTEXT_SEGGS 0x8C +#define CONTEXT_SEGFS 0x90 +#define CONTEXT_SEGES 0x94 +#define CONTEXT_SEGDS 0x98 +#define CONTEXT_EDI 0x9C +#define CONTEXT_ESI 0xA0 +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EDX 0xA8 +#define CONTEXT_ECX 0xAC +#define CONTEXT_EAX 0xB0 +#define CONTEXT_EBP 0xB4 +#define CONTEXT_EIP 0xB8 +#define CONTEXT_SEGCS 0xBC +#define CONTEXT_EFLAGS 0xC0 +#define CONTEXT_ESP 0xC4 +#define CONTEXT_SEGSS 0xC8 + + +#define RCC_CONTEXT 0x08 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _AsmDebug@4 + popal + ret + +#ifndef __NTOSKRNL__ + +// +// VOID +// RtlpCaptureContext(PCONTEXT pContext); +// +// Parameters: +// [ESP+08h] - PCONTEXT_X86 pContext +// Registers: +// None +// Returns: +// Nothing +// Notes: +// Grabs the current CPU context. +.globl _RtlpCaptureContext +_RtlpCaptureContext: + pushl %ebp + movl %esp, %ebp + movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure + + cld + pushf + pop %eax + movl %eax, CONTEXT_EFLAGS(%edx) + xorl %eax, %eax + movl %eax, CONTEXT_EAX(%edx) + movl %eax, CONTEXT_EBX(%edx) + movl %eax, CONTEXT_ECX(%edx) + movl %eax, CONTEXT_EDX(%edx) + movl %eax, CONTEXT_ESI(%edx) + movl %eax, CONTEXT_EDI(%edx) + movl %cs, %eax + movl %eax, CONTEXT_SEGCS(%edx) + movl %ds, %eax + movl %eax, CONTEXT_SEGDS(%edx) + movl %es, %eax + movl %eax, CONTEXT_SEGES(%edx) + movl %fs, %eax + movl %eax, CONTEXT_SEGFS(%edx) + movl %gs, %eax + movl %eax, CONTEXT_SEGGS(%edx) + movl %ss, %eax + movl %eax, CONTEXT_SEGSS(%edx) + + // + // STACK LAYOUT: - (ESP to put in context structure) + // - RETURN ADDRESS OF CALLER OF CALLER + // - EBP OF CALLER OF CALLER + // ... + // - RETURN ADDRESS OF CALLER + // - EBP OF CALLER + // ... + // + + // Get return address of the caller of the caller of this function + movl %ebp, %ebx + //movl 4(%ebx), %eax // EAX = return address of caller + movl (%ebx), %ebx // EBX = EBP of caller + + movl 4(%ebx), %eax // EAX = return address of caller of caller + movl (%ebx), %ebx // EBX = EBP of caller of caller + + movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller + movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller + addl $8, %ebx + movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 + + movl %ebp, %esp + popl %ebp + ret + +#endif /* !__NTOSKRNL__ */ + +#define REH_ERECORD 0x08 +#define REH_RFRAME 0x0C +#define REH_CONTEXT 0x10 +#define REH_DCONTEXT 0x14 +#define REH_EROUTINE 0x18 + +// Parameters: +// None +// Registers: +// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord +// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EBP+10h] - PVOID Context +// [EBP+14h] - PVOID DispatcherContext +// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine +// EDX - Address of protecting exception handler +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Setup the protecting exception handler and call the exception +// handler in the right context. +_RtlpExecuteHandler: + pushl %ebp + movl %esp, %ebp + pushl REH_RFRAME(%ebp) + + pushl %edx + pushl %fs:0x0 + movl %esp, %fs:0x0 + + // Prepare to call the exception handler + pushl REH_DCONTEXT(%ebp) + pushl REH_CONTEXT(%ebp) + pushl REH_RFRAME(%ebp) + pushl REH_ERECORD(%ebp) + + // Now call the exception handler + movl REH_EROUTINE(%ebp), %eax + call *%eax + + cmpl $-1, %fs:0x0 + jne .reh_stack_looks_ok + + // This should not happen + pushl 0 + pushl 0 + pushl 0 + pushl 0 + call _RtlAssert@16 + +.reh_loop: + jmp .reh_loop + +.reh_stack_looks_ok: + movl %fs:0x0, %esp + + // Return to the 'front-end' for this function + popl %fs:0x0 + movl %ebp, %esp + popl %ebp + ret + + +#define REP_ERECORD 0x04 +#define REP_RFRAME 0x08 +#define REP_CONTEXT 0x0C +#define REP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting nested exceptions. +_RtlpExceptionProtector: + movl $ExceptionContinueSearch, %eax + movl REP_ERECORD(%esp), %ecx + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jnz .rep_end + + // Unwinding is not taking place, so return ExceptionNestedException + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a nested exception occurred + movl REP_DCONTEXT(%esp), %ecx movl REP_RFRAME(%esp), %eax + movl %eax, (%ecx) + movl $ExceptionNestedException, %eax + +.rep_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Front-end +_RtlpExecuteHandlerForException: + movl $_RtlpExceptionProtector, %edx + jmp _RtlpExecuteHandler + + +#define RUP_ERECORD 0x04 +#define RUP_RFRAME 0x08 +#define RUP_CONTEXT 0x0C +#define RUP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting collided unwinds. +_RtlpUnwindProtector: + movl $ExceptionContinueSearch, %eax + movl %ecx, RUP_ERECORD(%esp) + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jz .rup_end + + // Unwinding is taking place, so return ExceptionCollidedUnwind + + movl RUP_RFRAME(%esp), %ecx + movl RUP_DCONTEXT(%esp), %edx + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a collision occurred + movl RUP_RFRAME(%ecx), %eax + movl %eax, (%edx) + movl $ExceptionCollidedUnwind, %eax + +.rup_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +_RtlpExecuteHandlerForUnwind: + movl $_RtlpUnwindProtector, %edx + jmp _RtlpExecuteHandler diff --git a/reactos/lib/ntdll/rtl/i386/exception.c b/reactos/lib/ntdll/rtl/i386/exception.c new file mode 100755 index 00000000000..8f6bba89f27 --- /dev/null +++ b/reactos/lib/ntdll/rtl/i386/exception.c @@ -0,0 +1,433 @@ +/* $Id: exception.c,v 1.1 2002/10/26 00:32:18 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode exception support for IA-32 + * FILE: lib/ntdll/rtl/i386/exception.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +/* Implemented in except.s */ + +VOID +RtlpCaptureContext(PCONTEXT pContext); + +/* Macros that will help streamline the SEH implementations for + kernel mode and user mode */ + +#define SehpGetStackLimits(StackBase, StackLimit) \ +{ \ + (*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \ + (*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \ +} + +#define SehpGetExceptionList() \ + (PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList) + +#define SehpSetExceptionList(NewExceptionList) \ + NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList) + +#define SehpCaptureContext(Context) \ +{ \ + RtlpCaptureContext(Context); \ +} + +/*** Code below this line is shared with ntoskrnl/rtl/i386/exception.c - please keep in sync ***/ + +VOID STDCALL +AsmDebug(ULONG Value) +{ + DbgPrint("Value 0x%.08x\n", Value); +} + + +/* Declare a few prototypes for the functions in except.s */ + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForException( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForUnwind( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + + +#ifndef NDEBUG + +VOID RtlpDumpExceptionRegistrations(VOID) +{ + PEXCEPTION_REGISTRATION Current; + + DbgPrint("Dumping exception registrations:\n"); + + Current = SehpGetExceptionList(); + + if ((ULONG_PTR)Current != -1) + { + while ((ULONG_PTR)Current != -1) + { + DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler); + Current = Current->prev; + } + DbgPrint(" End-Of-List\n"); + } else { + DbgPrint(" No exception registrations exists.\n"); + } +} + +#endif /* NDEBUG */ + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + PEXCEPTION_REGISTRATION RegistrationFrame; + DWORD DispatcherContext; + DWORD ReturnValue; + + DPRINT("RtlpDispatchException()\n"); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + RegistrationFrame = SehpGetExceptionList(); + + DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame); + + while ((ULONG_PTR)RegistrationFrame != -1) + { + EXCEPTION_RECORD ExceptionRecord2; + DWORD Temp = 0; + //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8; + + // Make sure the registration frame is located within the stack + + DPRINT("Error checking\n"); +#if 0 + if (Teb->Tib.StackBase > RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackBase, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + // FIXME: Stack top, correct? + if (Teb->Tib.StackLimit < RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackLimit, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + + // Make sure stack is DWORD aligned + if ((ULONG_PTR)RegistrationFrame & 3) + { + DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n", + RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } +#endif + +#if 0 + /* FIXME: */ + if (someFlag) + RtlpLogLastExceptionDisposition( hLog, retValue ); +#endif + + DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler); + DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord); + DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame); + DPRINT("Context 0x%X\n", Context); + DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext); + + ReturnValue = RtlpExecuteHandlerForException( + ExceptionRecord, + RegistrationFrame, + Context, + &DispatcherContext, + RegistrationFrame->handler); + + DPRINT("Exception handler said 0x%X\n", ReturnValue); + DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame); + { + PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08); + DPRINT("StandardESP == 0x%.08x\n", sp[0]); + DPRINT("Exception Pointers == 0x%.08x\n", sp[1]); + DPRINT("PrevFrame == 0x%.08x\n", sp[2]); + DPRINT("Handler == 0x%.08x\n", sp[3]); + DPRINT("ScopeTable == 0x%.08x\n", sp[4]); + DPRINT("TryLevel == 0x%.08x\n", sp[5]); + DPRINT("EBP == 0x%.08x\n", sp[6]); + } + + if (RegistrationFrame == NULL) + { + ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag + } + + if (ReturnValue == ExceptionContinueExecution) + { + DPRINT("ReturnValue == ExceptionContinueExecution\n"); + if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) + { + DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + else + { + /* Copy the (possibly changed) context back to the trap frame and return */ + NtContinue(Context, FALSE); + return ExceptionContinueExecution; + } + } + else if (ReturnValue == ExceptionContinueSearch) + { + DPRINT("ReturnValue == ExceptionContinueSearch\n"); + + /* Nothing to do here */ + } + else if (ReturnValue == ExceptionNestedException) + { + DPRINT("ReturnValue == ExceptionNestedException\n"); + + ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND; + if (DispatcherContext > Temp) + { + Temp = DispatcherContext; + } + } + else /* if (ReturnValue == ExceptionCollidedUnwind) */ + { + DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + + RegistrationFrame = RegistrationFrame->prev; // Go to previous frame + } + + /* No exception handler will handle this exception */ + + DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n"); + + return ExceptionContinueExecution; +} + +VOID STDCALL +RtlRaiseStatus(NTSTATUS Status) +{ + EXCEPTION_RECORD ExceptionRecord; + + DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status); + + ExceptionRecord.ExceptionCode = Status; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + RtlRaiseException (& ExceptionRecord); +} + +VOID STDCALL +RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame, + PVOID ReturnAddress, + PEXCEPTION_RECORD ExceptionRecord, + DWORD EaxValue) +{ + PEXCEPTION_REGISTRATION ERHead; + PEXCEPTION_RECORD pExceptRec; + EXCEPTION_RECORD TempER; + CONTEXT Context; + + DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + ERHead = SehpGetExceptionList(); + + DPRINT("ERHead is 0x%X\n", ERHead); + + if (ExceptionRecord == NULL) // The normal case + { + DPRINT("ExceptionRecord == NULL (normal)\n"); + + pExceptRec = &TempER; + pExceptRec->ExceptionFlags = 0; + pExceptRec->ExceptionCode = STATUS_UNWIND; + pExceptRec->ExceptionRecord = NULL; + pExceptRec->ExceptionAddress = ReturnAddress; + pExceptRec->ExceptionInformation[0] = 0; + } + + if (RegistrationFrame) + pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING; + else + pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND); + +#ifndef NDEBUG + DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags); + if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING) + { + DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING); + } + if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND) + { + DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND); + } +#endif /* NDEBUG */ + + Context.ContextFlags = + (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); + + SehpCaptureContext(&Context); + + DPRINT("Context.Eip = 0x%.08x\n", Context.Eip); + DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp); + DPRINT("Context.Esp = 0x%.08x\n", Context.Esp); + + Context.Esp += 0x10; + Context.Eax = EaxValue; + + // Begin traversing the list of EXCEPTION_REGISTRATION + while ((ULONG_PTR)ERHead != -1) + { + EXCEPTION_RECORD er2; + + DPRINT("ERHead 0x%X\n", ERHead); + + if (ERHead == RegistrationFrame) + { + DPRINT("Continueing execution\n"); + NtContinue(&Context, FALSE); + return; + } + else + { + // If there's an exception frame, but it's lower on the stack + // than the head of the exception list, something's wrong! + if (RegistrationFrame && (RegistrationFrame <= ERHead)) + { + DPRINT("The exception frame is bad\n"); + + // Generate an exception to bail out + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + +#if 0 + Stack = ERHead + sizeof(EXCEPTION_REGISTRATION); + if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead + && (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple + && (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane) + { +#else + if (1) { +#endif + PEXCEPTION_REGISTRATION NewERHead; + PEXCEPTION_REGISTRATION pCurrExceptReg; + EXCEPTION_DISPOSITION ReturnValue; + + DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler); + + ReturnValue = RtlpExecuteHandlerForUnwind( + pExceptRec, + ERHead, + &Context, + &NewERHead, + ERHead->handler); + + DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue); + + if (ReturnValue != ExceptionContinueSearch) + { + if (ReturnValue != ExceptionCollidedUnwind) + { + DPRINT("Bad return value\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_DISPOSITION; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + else + { + ERHead = NewERHead; + } + } + + pCurrExceptReg = ERHead; + ERHead = ERHead->prev; + + DPRINT("New ERHead is 0x%X\n", ERHead); + + DPRINT("Setting exception registration at 0x%X as current\n", + RegistrationFrame->prev); + + // Unlink the exception handler + SehpSetExceptionList(RegistrationFrame->prev); + } + else // The stack looks goofy! Raise an exception to bail out + { + DPRINT("Bad stack\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_BAD_STACK; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + + // If we get here, we reached the end of the EXCEPTION_REGISTRATION list. + // This shouldn't happen normally. + + DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n", + RegistrationFrame); + + if ((ULONG_PTR)RegistrationFrame == -1) + NtContinue(&Context, FALSE); + else + NtRaiseException(pExceptRec, &Context, 0); +} + +/* EOF */ diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index ccaa28ca408..be57d4b2075 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.85 2002/10/09 07:11:24 ei Exp $ +# $Id: Makefile,v 1.86 2002/10/26 00:32:18 chorns Exp $ # # ReactOS Operating System # @@ -99,7 +99,6 @@ OBJECTS_RTL = \ rtl/purecall.o \ rtl/qsort.o \ rtl/regio.o \ - rtl/seh.o \ rtl/sprintf.o \ rtl/stdlib.o \ rtl/string.o \ diff --git a/reactos/ntoskrnl/Makefile.i386 b/reactos/ntoskrnl/Makefile.i386 index 834f2934f32..9a12a5c4c8d 100644 --- a/reactos/ntoskrnl/Makefile.i386 +++ b/reactos/ntoskrnl/Makefile.i386 @@ -41,10 +41,14 @@ OBJECTS_MM_I386 := \ OBJECTS_RTL_I386 := \ rtl/i386/memset.o \ - rtl/i386/memcpy.o + rtl/i386/memcpy.o \ + rtl/i386/except.o \ + rtl/i386/exception.o \ + rtl/i386/seh.o RTL_EXCLUDE_FILTER := \ rtl/memset.o \ rtl/memcpy.o OBJECTS_ARCH = $(OBJECTS_BOOT) $(OBJECTS_EX_I386) $(OBJECTS_KE_I386) $(OBJECTS_MM_I386) $(OBJECTS_RTL_I386) + diff --git a/reactos/ntoskrnl/ke/catch.c b/reactos/ntoskrnl/ke/catch.c index 32933771017..805b2115925 100644 --- a/reactos/ntoskrnl/ke/catch.c +++ b/reactos/ntoskrnl/ke/catch.c @@ -16,12 +16,13 @@ * 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.25 2002/09/15 10:45:02 guido Exp $ +/* $Id: catch.c,v 1.26 2002/10/26 00:32:18 chorns Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/catch.c * PURPOSE: Exception handling * PROGRAMMER: David Welch (welch@mcmail.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ @@ -38,156 +39,9 @@ /* FUNCTIONS ****************************************************************/ -EXCEPTION_DISPOSITION -RtlpExecuteHandlerForException( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext, - PEXCEPTION_HANDLER Handler); - - -#ifndef NDEBUG - -VOID RtlpDumpExceptionRegistrations(VOID) -{ - PEXCEPTION_REGISTRATION Current; - PKTHREAD Thread; - - DbgPrint("Dumping exception registrations:\n"); - - Thread = KeGetCurrentThread(); - - assert(Thread); - assert(Thread->TrapFrame); - - Current = Thread->TrapFrame->ExceptionList; - - if ((ULONG_PTR)Current != -1) - { - while ((ULONG_PTR)Current != -1) - { - DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler); - Current = Current->prev; - } - DbgPrint(" End-Of-List\n"); - } else { - DbgPrint(" No exception registrations exists.\n"); - } -} - -#endif /* NDEBUG */ - -EXCEPTION_DISPOSITION -RtlpDispatchException( - PEXCEPTION_RECORD ExceptionRecord, - PCONTEXT Context) -{ - PEXCEPTION_REGISTRATION RegistrationFrame; - DWORD DispatcherContext; - DWORD ReturnValue; - PKPCR KPCR; - PKTHREAD Thread; - - DPRINT("RtlpDispatchException() called\n"); -#ifndef NDEBUG - RtlpDumpExceptionRegistrations(); -#endif /* NDEBUG */ - Thread = KeGetCurrentThread(); - - DPRINT("Thread is 0x%X\n", Thread); - - KPCR = KeGetCurrentKPCR(); - - RegistrationFrame = Thread->TrapFrame->ExceptionList; - - DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame); - - while ((ULONG_PTR)RegistrationFrame != -1) - { - EXCEPTION_RECORD ExceptionRecord2; - DWORD Temp = 0; - //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8; - - // Make sure the registration frame is located within the stack - - DPRINT("Error checking\n"); -#if 0 - if (Thread->KernelStack > RegistrationFrameEnd) - { - ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; - return ExceptionDismiss; - } - // FIXME: Correct? - if (Thread->StackLimit < RegistrationFrameEnd) - { - ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; - return ExceptionDismiss; - } - - // Make sure stack is DWORD aligned - if ((ULONG_PTR)RegistrationFrame & 3) - { - ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; - return ExceptionDismiss; - } -#endif - - DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler); - - ReturnValue = RtlpExecuteHandlerForException( - ExceptionRecord, - RegistrationFrame, - Context, - &DispatcherContext, - RegistrationFrame->handler); - - if (RegistrationFrame == NULL) - { - ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag - } - - if (ReturnValue == ExceptionContinueExecution) - { - /* Copy the changed context back to the trap frame and return */ - NtContinue(Context, FALSE); - return ExceptionContinueExecution; - } - else if (ReturnValue == ExceptionDismiss) - { - if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) - { - ExceptionRecord2.ExceptionRecord = ExceptionRecord; - ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; - ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - ExceptionRecord2.NumberParameters = 0; - RtlRaiseException(&ExceptionRecord2); - } - /* Else continue search */ - } - else if (ReturnValue == ExceptionNestedException) - { - ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND; - if (DispatcherContext > Temp) - Temp = DispatcherContext; - } - else if (ReturnValue == ExceptionCollidedUnwind) - { - ExceptionRecord2.ExceptionRecord = ExceptionRecord; - ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; - ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - ExceptionRecord2.NumberParameters = 0; - RtlRaiseException(&ExceptionRecord2); - } - - RegistrationFrame = RegistrationFrame->prev; // Go to previous frame - } - - /* No exception handler will handle this exception */ - - return ExceptionDismiss; -} - +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); VOID KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, @@ -215,6 +69,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, Context = &TContext; } + #if 0 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) { @@ -268,7 +123,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, } else { - KD_CONTINUE_TYPE Action = 0; + KD_CONTINUE_TYPE Action = kdContinue; /* PreviousMode == KernelMode */ @@ -282,10 +137,6 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf); } #endif /* KDBG */ - else - { - KeBugCheckWithTf (KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf); - } if (Action != kdHandleException) { Value = RtlpDispatchException (ExceptionRecord, Context); @@ -355,274 +206,4 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) ZwRaiseException(ExceptionRecord, NULL, TRUE); } - -inline -EXCEPTION_DISPOSITION -RtlpExecuteHandler( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext, - PEXCEPTION_HANDLER Handler, - PEXCEPTION_HANDLER RawHandler) -{ - EXCEPTION_DISPOSITION Value; - - // Set up an EXCEPTION_REGISTRATION - __asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (RawHandler)); - - // Invoke the exception callback function - Value = Handler( - ExceptionRecord, - ExceptionRegistration, - Context, - DispatcherContext); - - // Remove the minimal EXCEPTION_REGISTRATION frame - //__asm__ ("movl %fs:0,%esp; popl %fs:0"); - - __asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" : : : "%eax"); - - return Value; -} - - -EXCEPTION_DISPOSITION -RtlpExceptionHandler( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext) -{ - // If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else - // assign DispatcherContext context and return DISPOSITION_NESTED_EXCEPTION - - if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING) - { - DPRINT("RtlpExceptionHandler(). Returning ExceptionContinueSearch\n"); - return ExceptionContinueSearch; - } - else - { - DPRINT("RtlpExceptionHandler(). Returning ExceptionNestedException\n"); - *(PEXCEPTION_REGISTRATION*)DispatcherContext = ExceptionRegistration->prev; - return ExceptionNestedException; - } -} - - -EXCEPTION_DISPOSITION -RtlpUnwindHandler( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext) -{ - // If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else - // assign DispatcherContext and return DISPOSITION_COLLIDED_UNWIND - - if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING) - { - DPRINT("RtlpUnwindHandler(). Returning ExceptionContinueSearch\n"); - return ExceptionContinueSearch; - } - else - { - DPRINT("RtlpUnwindHandler(). Returning ExceptionCollidedUnwind\n"); - *(PEXCEPTION_REGISTRATION*)DispatcherContext = ExceptionRegistration->prev; - return ExceptionCollidedUnwind; - } -} - - -EXCEPTION_DISPOSITION -RtlpExecuteHandlerForException( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext, - PEXCEPTION_HANDLER Handler) -{ - return RtlpExecuteHandler( - ExceptionRecord, - ExceptionRegistration, - Context, - DispatcherContext, - Handler, - RtlpExceptionHandler); -} - - -EXCEPTION_DISPOSITION -RtlpExecuteHandlerForUnwind( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION ExceptionRegistration, - PCONTEXT Context, - PVOID DispatcherContext, - PEXCEPTION_HANDLER Handler) -{ - return RtlpExecuteHandler( - ExceptionRecord, - ExceptionRegistration, - Context, - DispatcherContext, - Handler, - RtlpUnwindHandler); -} - - -VOID STDCALL -RtlUnwind( - PEXCEPTION_REGISTRATION RegistrationFrame, - PVOID ReturnAddress, - PEXCEPTION_RECORD ExceptionRecord, - DWORD EaxValue) -{ - PEXCEPTION_REGISTRATION ERHead; - PEXCEPTION_RECORD pExceptRec = NULL; - EXCEPTION_RECORD TempER; - CONTEXT Context; - //PVOID Stack; - PKTHREAD Thread; - - DPRINT("RtlUnwind() called. RegistrationFrame 0x%X\n", RegistrationFrame); -#ifndef NDEBUG - RtlpDumpExceptionRegistrations(); -#endif /* NDEBUG */ - Thread = KeGetCurrentThread(); - - ERHead = Thread->TrapFrame->ExceptionList; - - if (ExceptionRecord == NULL) // The normal case - { - pExceptRec = &TempER; - - pExceptRec->ExceptionFlags = 0; - pExceptRec->ExceptionCode = STATUS_UNWIND; - pExceptRec->ExceptionRecord = NULL; - // FIXME: Find out if NT retrieves the return address from the stack instead - pExceptRec->ExceptionAddress = ReturnAddress; - //pExceptRec->ExceptionInformation[0] = 0; - } - - if (RegistrationFrame) - pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING; - else - pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND); - - Context.ContextFlags = - (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); - - KeTrapFrameToContext(Thread->TrapFrame, &Context); - - Context.Esp += 0x10; - Context.Eax = EaxValue; - - // Begin traversing the list of EXCEPTION_REGISTRATION - while ((ULONG_PTR)ERHead != -1) - { - EXCEPTION_RECORD er2; - - DPRINT("ERHead 0x%X\n", ERHead); - - if (ERHead == RegistrationFrame) - { - DPRINT("Continueing execution\n"); - NtContinue(&Context, FALSE); - return; - } - else - { - // If there's an exception frame, but it's lower on the stack - // then the head of the exception list, something's wrong! - if (RegistrationFrame && (RegistrationFrame <= ERHead)) - { - DPRINT("The exception frame is bad\n"); - - // Generate an exception to bail out - er2.ExceptionRecord = pExceptRec; - er2.NumberParameters = 0; - er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; - er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - - RtlRaiseException(&er2); - } - } - -#if 0 - Stack = ERHead + sizeof(EXCEPTION_REGISTRATION); - if ( (KPCR->StackBase <= (PVOID)ERHead ) // Make sure that ERHead - && (KPCR->StackLimit >= (PVOID)Stack ) // is in range, and a multiple - && (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane) - { -#else - if (1) { -#endif - PEXCEPTION_REGISTRATION NewERHead; - PEXCEPTION_REGISTRATION pCurrExceptReg; - EXCEPTION_DISPOSITION ReturnValue; - - DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler); - - ReturnValue = RtlpExecuteHandlerForUnwind( - pExceptRec, - ERHead, - &Context, - &NewERHead, - ERHead->handler); - - DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue); - - if (ReturnValue != ExceptionContinueSearch) - { - if (ReturnValue != ExceptionCollidedUnwind) - { - DPRINT("Bad return value\n"); - - er2.ExceptionRecord = pExceptRec; - er2.NumberParameters = 0; - er2.ExceptionCode = STATUS_INVALID_DISPOSITION; - er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - - RtlRaiseException(&er2); - } else - ERHead = NewERHead; - } - - pCurrExceptReg = ERHead; - ERHead = ERHead->prev; - - DPRINT("New ERHead is 0x%X\n", ERHead); - - DPRINT("Setting exception registration at 0x%X as current\n", - RegistrationFrame->prev); - - // Unlink the exception handler - KeGetCurrentKPCR()->ExceptionList = RegistrationFrame->prev; - } - else // The stack looks goofy! Raise an exception to bail out - { - DPRINT("Bad stack\n"); - - er2.ExceptionRecord = pExceptRec; - er2.NumberParameters = 0; - er2.ExceptionCode = STATUS_BAD_STACK; - er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - - RtlRaiseException(&er2); - } - } - - // If we get here, we reached the end of the EXCEPTION_REGISTRATION list. - // This shouldn't happen normally. - - DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n", - RegistrationFrame); - - if ((ULONG_PTR)RegistrationFrame == -1) - NtContinue(&Context, FALSE); - else - NtRaiseException(pExceptRec, &Context, 0); -} - /* EOF */ diff --git a/reactos/ntoskrnl/ke/i386/usertrap.c b/reactos/ntoskrnl/ke/i386/usertrap.c index 27e245f4cf6..19a300baeb5 100644 --- a/reactos/ntoskrnl/ke/i386/usertrap.c +++ b/reactos/ntoskrnl/ke/i386/usertrap.c @@ -43,33 +43,9 @@ #define NDEBUG #include -/* GLOBALS *****************************************************************/ - -static char *ExceptionTypeStrings[] = - { - "Divide Error", - "Debug Trap", - "NMI", - "Breakpoint", - "Overflow", - "BOUND range exceeded", - "Invalid Opcode", - "No Math Coprocessor", - "Double Fault", - "Unknown(9)", - "Invalid TSS", - "Segment Not Present", - "Stack Segment Fault", - "General Protection", - "Page Fault", - "Math Fault", - "Alignment Check", - "Machine Check" - }; - /* FUNCTIONS ****************************************************************/ -STATIC BOOLEAN +BOOLEAN print_user_address(PVOID address) { PLIST_ENTRY current_entry; @@ -120,10 +96,6 @@ print_user_address(PVOID address) return(FALSE); } -#if 0 -/* - * Disabled until SEH support is implemented. - */ ULONG KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) { @@ -175,104 +147,3 @@ KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) KiDispatchException(&Er, 0, Tf, UserMode, TRUE); return(0); } -#else -ULONG -KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) -{ - PULONG Frame; - ULONG cr3; - ULONG i; - ULONG ReturnAddress; - ULONG NextFrame; - NTSTATUS Status; - - /* - * Get the PDBR - */ - __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); - - /* - * Print out the CPU registers - */ - if (ExceptionNr < 19) - { - DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr], - ExceptionNr, Tf->ErrorCode&0xffff); - } - else - { - DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff); - } - DbgPrint("CS:EIP %x:%x ", Tf->Cs&0xffff, Tf->Eip); - print_user_address((PVOID)Tf->Eip); - DbgPrint("\n"); - __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); - DbgPrint("CR2 %x CR3 %x ", Cr2, cr3); - DbgPrint("Process: %x ",PsGetCurrentProcess()); - if (PsGetCurrentProcess() != NULL) - { - DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId); - DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName); - } - if (PsGetCurrentThread() != NULL) - { - DbgPrint("Thrd: %x Tid: %x", - PsGetCurrentThread(), - PsGetCurrentThread()->Cid.UniqueThread); - } - DbgPrint("\n"); - DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff, - Tf->Fs&0xffff, Tf->Gs&0xfff); - DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx); - DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi); - DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags); - DbgPrint("SS:ESP %x:%x\n", Tf->Ss, Tf->Esp); - - /* - * Dump the stack frames - */ - DbgPrint("Frames: "); - i = 1; - Frame = (PULONG)Tf->Ebp; - while (Frame != NULL && i < 50) - { - Status = MmSafeCopyFromUser(&ReturnAddress, &Frame[1], sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - DbgPrint("????????\n"); - break; - } - print_user_address((PVOID)ReturnAddress); - Status = MmSafeCopyFromUser(&NextFrame, &Frame[0], sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Frame is inaccessible.\n"); - break; - } - if ((NextFrame + sizeof(ULONG)) >= KERNEL_BASE) - { - DbgPrint("Next frame is in kernel space!\n"); - break; - } - if (NextFrame != 0 && NextFrame <= (ULONG)Frame) - { - DbgPrint("Next frame is not above current frame!\n"); - break; - } - Frame = (PULONG)NextFrame; - i++; - } - - /* - * Kill the faulting process - */ - __asm__("sti\n\t"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_NONCONTINUABLE_EXCEPTION); - - /* - * If terminating the process fails then bugcheck - */ - KeBugCheck(0); - return(0); -} -#endif diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 799ff551e90..03ef0693f6a 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.55 2002/10/01 19:27:25 chorns Exp $ +/* $Id: create.c,v 1.56 2002/10/26 00:32:19 chorns Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -468,6 +468,9 @@ PsCreateTeb(HANDLE ProcessHandle, Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; Teb.CurrentLocale = PsDefaultThreadLocaleId; + + /* Terminate the exception handler list */ + Teb.Tib.ExceptionList = (PVOID)-1; DPRINT("sizeof(TEB) %x\n", sizeof(TEB)); diff --git a/reactos/ntoskrnl/rtl/seh.c b/reactos/ntoskrnl/rtl/seh.c deleted file mode 100644 index 778119ed788..00000000000 --- a/reactos/ntoskrnl/rtl/seh.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/rtl/seh.c - * PURPOSE: Compiler level Structured Exception Handling - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 2001/10/10 CSH Created - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -int CDECL -_abnormal_termination(VOID) -{ - DPRINT("_abnormal_termination() called\n"); - return 0; -} - -VOID -CDECL -_local_unwind2( - PEXCEPTION_REGISTRATION RegistrationFrame, - DWORD TryLevel) -{ - PSCOPETABLE_ENTRY ScopeTableHead; - PRTL_EXCEPTION_REGISTRATION RtlRegistrationFrame = - (PRTL_EXCEPTION_REGISTRATION)RegistrationFrame; - - DbgPrint("RegistrationFrame (0x%X) - TryLevel (0x%X)\n", - RegistrationFrame, TryLevel); -return; - - ScopeTableHead = RtlRegistrationFrame->ScopeTable; - - /* Begin traversing the list of SCOPETABLE_ENTRY */ - while ((ULONG_PTR)ScopeTableHead != -1) - { - - } -} - - -VOID -CDECL -_global_unwind2( - PVOID RegistrationFrame) -{ - RtlUnwind(RegistrationFrame, &&__return_label, NULL, 0); - __return_label:; -} - -#if 1 -extern DWORD CDECL SEHFilterRoutine(VOID); -extern VOID CDECL SEHHandlerRoutine(VOID); -#endif - -DWORD CDECL SEHFilterRoutine(VOID) -{ - DbgPrint("Within filter routine.\n"); - return EXCEPTION_EXECUTE_HANDLER; - //return EXCEPTION_CONTINUE_EXECUTION; -} - -VOID CDECL SEHHandlerRoutine(VOID) -{ - DbgPrint("Within exception handler.\n"); - DbgPrint("System halted.\n"); - for (;;); -} - -EXCEPTION_DISPOSITION -CDECL -_except_handler2( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION RegistrationFrame, - PCONTEXT Context, - PVOID DispatcherContext) -{ - /* FIXME: */ - return ExceptionContinueSearch; -} - - -EXCEPTION_DISPOSITION -CDECL -_except_handler3( - PEXCEPTION_RECORD ExceptionRecord, - PEXCEPTION_REGISTRATION RegistrationFrame, - PCONTEXT Context, - PVOID DispatcherContext) -{ - DWORD FilterFuncRet; - DWORD TryLevel; - EXCEPTION_POINTERS ExceptionPointers; - //PSCOPETABLE_ENTRY pScopeTable; - PSCOPETABLE_ENTRY ScopeTable; - EXCEPTION_DISPOSITION ReturnValue; - PVOID Handler; - PVOID NewEBP; - PRTL_EXCEPTION_REGISTRATION RtlRegistrationFrame = - (PRTL_EXCEPTION_REGISTRATION)RegistrationFrame; - - DPRINT("__except_handler3() called\n"); - DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord); - DPRINT(" ExceptionCode 0x%X\n", ExceptionRecord->ExceptionCode); - DPRINT(" ExceptionFlags 0x%X\n", ExceptionRecord->ExceptionFlags); - DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame); - DPRINT("Context 0x%X\n", Context); - DPRINT("DispatcherContext 0x%X\n", DispatcherContext); - - // Clear the direction flag (make no assumptions!) - __asm__ ("cld"); - - // if neither the EXCEPTION_UNWINDING nor EXCEPTION_EXIT_UNWIND bit - // is set... This is true the first time through the handler (the - // non-unwinding case) - - if (!(ExceptionRecord->ExceptionFlags - & (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND))) - { - DPRINT("Exception caught\n"); - - // Build the EXCEPTION_POINTERS structure on the stack - ExceptionPointers.ExceptionRecord = ExceptionRecord; - ExceptionPointers.ContextRecord = Context; - - // Put the pointer to the EXCEPTION_POINTERS 4 bytes below the - // establisher frame - *(PDWORD)((ULONG_PTR)RtlRegistrationFrame - 4) = (ULONG_PTR)&ExceptionPointers; - - // Get a pointer to the scopetable array - ScopeTable = RtlRegistrationFrame->ScopeTable; - - DPRINT("ScopeTable is at 0x%X\n", ScopeTable); - - // Get initial "try-level" value - TryLevel = RtlRegistrationFrame->TryLevel; - - DPRINT("TryLevel is 0x%X\n", TryLevel); - -search_for_handler: - - DPRINT("RtlRegistrationFrame->TryLevel: 0x%X\n", - RtlRegistrationFrame->TryLevel); - - if (RtlRegistrationFrame->TryLevel != TRYLEVEL_NONE) - { - if (ScopeTable[TryLevel].FilterRoutine) - { - NewEBP = (PVOID)RtlRegistrationFrame->Ebp; - Handler = (PVOID)ScopeTable[TryLevel].FilterRoutine; - - DPRINT("Original EBP is: 0x%X\n", NewEBP); - - DPRINT("Calling filter routine at 0x%X\n", Handler); - - // Save this frame EBP - __asm__ ("pushl %ebp"); -DPRINT("\n"); - // Switch to original EBP. This is what allows all locals in the - // frame to have the same value as before the exception occurred. - __asm__ ("movl %0,%%eax; movl %0,%%ebp; call _SEHFilterRoutine;" : : \ - "g" (Handler), \ - "g" (NewEBP)); -DPRINT("\n"); - - // Call the filter function - //FilterFuncRet = ScopeTable[TryLevel].FilterRoutine(); - //FilterFuncRet = SEHFilterRoutine(); -DPRINT("\n"); - // Restore this frame EBP - __asm__ ("popl %%ebp" : "=a" (FilterFuncRet)); - - DPRINT("FilterRoutine returned: 0x%X\n", FilterFuncRet); - - if (FilterFuncRet != EXCEPTION_CONTINUE_SEARCH) - { - if (FilterFuncRet < 0) // EXCEPTION_CONTINUE_EXECUTION - return ExceptionContinueExecution; - - DPRINT("Filter routine said: execute handler\n"); - - // If we get here, EXCEPTION_EXECUTE_HANDLER was specified - - // Does the actual OS cleanup of registration frames - // Causes this function to recurse - _global_unwind2(RtlRegistrationFrame); - - _local_unwind2(RegistrationFrame, TryLevel); - - // NLG == "non-local-goto" (setjmp/longjmp stuff) - //__NLG_Notify( 1 ); // EAX == scopetable->lpfnHandler - - // Set the current trylevel to whatever SCOPETABLE entry - // was being used when a handler was found - RtlRegistrationFrame->TryLevel = ScopeTable->PreviousTryLevel; - - // Once we get here, everything is all cleaned up, except - // for the last frame, where we'll continue execution - - NewEBP = (PVOID)RtlRegistrationFrame->Ebp; - Handler = (PVOID)ScopeTable[TryLevel].HandlerRoutine; - - // Switch to original EBP and call the __except block. - // If the function returns bugcheck the system. - __asm__ ("movl %0,%%eax; movl %0,%%ebp; call _SEHHandlerRoutine;" : : \ - "g" (Handler), \ - "g" (NewEBP)); - - KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED); - } - } - - ScopeTable = RtlRegistrationFrame->ScopeTable; - - DPRINT("ScopeTable is at 0x%X\n", ScopeTable); - - TryLevel = ScopeTable->PreviousTryLevel; - - DPRINT("TryLevel is 0x%X\n", TryLevel); - - goto search_for_handler; - } - else // TryLevel == TRYLEVEL_NONE - { - ReturnValue = ExceptionContinueSearch; - } - } - else // Either EXCEPTION_UNWINDING or EXCEPTION_EXIT_UNWIND flags is set - { - DPRINT("Local unwind\n"); - - // Save EBP - __asm__ ("pushl %%ebp; movl %0,%%edx;" : : \ - "m" (RtlRegistrationFrame)); - - /* FIXME: Why is "addl $0x10,%%esp" needed? We only push 2*4 bytes, so why pop 16? */ - __asm__ ("pushl $-1; pushl %%edx; movl %0,%%ebp; call __local_unwind2; addl $0x10,%%esp;" : : \ - "m" (RtlRegistrationFrame->Ebp)); - - DPRINT("Local unwind3\n"); - - // Restore EBP for this frame - __asm__ ("popl %ebp"); - - ReturnValue = ExceptionContinueSearch; - } - - DPRINT("ReturnValue 0x%X\n", ReturnValue); - - return ReturnValue; -} - -/* EOF */ diff --git a/reactos/tools/helper.mk b/reactos/tools/helper.mk index 4d34e4b13c6..d00e5a40334 100644 --- a/reactos/tools/helper.mk +++ b/reactos/tools/helper.mk @@ -1,4 +1,4 @@ -# $Id: helper.mk,v 1.21 2002/09/08 10:23:53 chorns Exp $ +# $Id: helper.mk,v 1.22 2002/10/26 00:32:19 chorns Exp $ # # Helper makefile for ReactOS modules # Variables this makefile accepts: @@ -381,6 +381,7 @@ include $(PATH_TO_TOP)/config TARGET_CFLAGS += $(MK_CFLAGS) TARGET_CFLAGS += -pipe -march=$(ARCH) ifeq ($(DBG),1) +TARGET_ASFLAGS += -g TARGET_CFLAGS += -g TARGET_LFLAGS += -g endif