2002-10-26 Casper S. Hornstrup <chorns@users.sourceforge.net>

* 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.

svn path=/trunk/; revision=3657
This commit is contained in:
Casper Hornstrup 2002-10-26 00:32:19 +00:00
parent 5437114eaa
commit a1e055e943
17 changed files with 1179 additions and 889 deletions

View file

@ -1,3 +1,37 @@
2002-10-26 Casper S. Hornstrup <chorns@users.sourceforge.net>
* 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 <chorns@users.sourceforge.net>
* lib/kernel32/process/create.c (_except_handler): New function.

View file

@ -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

View file

@ -1,5 +1,11 @@
#include <windows.h>
VOID STDCALL
MsvcrtDebug(ULONG Value)
{
DbgPrint("MsvcrtDebug 0x%.08x\n", Value);
}
EXCEPTION_DISPOSITION
_except_handler2(
struct _EXCEPTION_RECORD *ExceptionRecord,

View file

@ -1,11 +0,0 @@
#include <windows.h>
EXCEPTION_DISPOSITION
_except_handler3(
struct _EXCEPTION_RECORD *ExceptionRecord,
void *Frame,
struct _CONTEXT *ContextRecord,
void *DispatcherContext)
{
printf("_except_handler3()\n");
}

366
reactos/lib/msvcrt/except/seh.s Executable file
View file

@ -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

View file

@ -1,13 +1,10 @@
#include <windows.h>
#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;
}

View file

@ -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) \

View file

@ -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 <windows.h>
#include <string.h>
#define NDEBUG
#include <debug.h>
/* 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 */

View file

@ -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

View file

@ -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 <ddk/ntddk.h>
#include <windows.h>
#include <string.h>
#define NDEBUG
#include <debug.h>
/* 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 */

View file

@ -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 \

View file

@ -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)

View file

@ -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 */

View file

@ -43,33 +43,9 @@
#define NDEBUG
#include <internal/debug.h>
/* 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

View file

@ -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));

View file

@ -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 <ntddk.h>
#define NDEBUG
#include <debug.h>
/* 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 */

View file

@ -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