mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
5437114eaa
commit
a1e055e943
17 changed files with 1179 additions and 889 deletions
|
@ -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>
|
2002-10-26 Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||||
|
|
||||||
* lib/kernel32/process/create.c (_except_handler): New function.
|
* lib/kernel32/process/create.c (_except_handler): New function.
|
||||||
|
|
|
@ -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 = ../..
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
@ -73,9 +73,9 @@ OBJECTS_DIRECT = \
|
||||||
direct/rmdir.o
|
direct/rmdir.o
|
||||||
|
|
||||||
OBJECTS_EXCEPT = \
|
OBJECTS_EXCEPT = \
|
||||||
|
except/seh.o \
|
||||||
except/abnorter.o \
|
except/abnorter.o \
|
||||||
except/exhand2.o \
|
except/exhand2.o \
|
||||||
except/exhand3.o \
|
|
||||||
except/matherr.o \
|
except/matherr.o \
|
||||||
except/unwind.o \
|
except/unwind.o \
|
||||||
except/xcptfil.o
|
except/xcptfil.o
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
MsvcrtDebug(ULONG Value)
|
||||||
|
{
|
||||||
|
DbgPrint("MsvcrtDebug 0x%.08x\n", Value);
|
||||||
|
}
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION
|
EXCEPTION_DISPOSITION
|
||||||
_except_handler2(
|
_except_handler2(
|
||||||
struct _EXCEPTION_RECORD *ExceptionRecord,
|
struct _EXCEPTION_RECORD *ExceptionRecord,
|
||||||
|
|
|
@ -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
366
reactos/lib/msvcrt/except/seh.s
Executable 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
|
|
@ -1,13 +1,10 @@
|
||||||
#include <windows.h>
|
#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 );
|
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
|
||||||
}
|
__ret_label:
|
||||||
|
// return is important
|
||||||
void _local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
|
|
||||||
{
|
|
||||||
//TRACE(crtdll,"(%p,%ld)\n",endframe,nr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = ../..
|
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
|
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_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/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 \
|
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/strpbrk.o string/strrchr.o string/strspn.o \
|
||||||
string/strstr.o string/strupr.o string/wstring.o
|
string/strstr.o string/strupr.o string/wstring.o
|
||||||
|
|
||||||
|
ARCH_OBJECTS = \
|
||||||
|
$(RTL_I386_OBJECTS)
|
||||||
|
|
||||||
TARGET_OBJECTS = \
|
TARGET_OBJECTS = \
|
||||||
napi.o \
|
napi.o \
|
||||||
ldr/startup.o \
|
ldr/startup.o \
|
||||||
|
$(ARCH_OBJECTS) \
|
||||||
$(DBG_OBJECTS) \
|
$(DBG_OBJECTS) \
|
||||||
$(RTL_OBJECTS) \
|
$(RTL_OBJECTS) \
|
||||||
$(STDIO_OBJECTS) \
|
$(STDIO_OBJECTS) \
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -13,31 +13,14 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* 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
|
ULONG
|
||||||
RtlDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
PCONTEXT Context)
|
IN PCONTEXT Context);
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
@ -46,42 +29,29 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
EXCEPTION_RECORD NestedExceptionRecord;
|
EXCEPTION_RECORD NestedExceptionRecord;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (RtlDispatchException(ExceptionRecord, Context) == 1)
|
DPRINT("KiUserExceptionDispatcher()\n");
|
||||||
|
|
||||||
|
if (RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
|
||||||
{
|
{
|
||||||
Status = ZwContinue(Context, FALSE);
|
Status = NtContinue(Context, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = ZwRaiseException(ExceptionRecord, Context, FALSE);
|
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NestedExceptionRecord.ExceptionCode = Status;
|
NestedExceptionRecord.ExceptionCode = Status;
|
||||||
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
|
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
|
||||||
|
NestedExceptionRecord.NumberParameters = Status;
|
||||||
|
|
||||||
RtlRaiseException(&NestedExceptionRecord);
|
RtlRaiseException(&NestedExceptionRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
RtlRaiseStatus(NTSTATUS Status)
|
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD ExceptionRecord;
|
DbgPrint("RtlRaiseException()");
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
290
reactos/lib/ntdll/rtl/i386/except.s
Executable file
290
reactos/lib/ntdll/rtl/i386/except.s
Executable 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
|
433
reactos/lib/ntdll/rtl/i386/exception.c
Executable file
433
reactos/lib/ntdll/rtl/i386/exception.c
Executable 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 */
|
|
@ -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
|
# ReactOS Operating System
|
||||||
#
|
#
|
||||||
|
@ -99,7 +99,6 @@ OBJECTS_RTL = \
|
||||||
rtl/purecall.o \
|
rtl/purecall.o \
|
||||||
rtl/qsort.o \
|
rtl/qsort.o \
|
||||||
rtl/regio.o \
|
rtl/regio.o \
|
||||||
rtl/seh.o \
|
|
||||||
rtl/sprintf.o \
|
rtl/sprintf.o \
|
||||||
rtl/stdlib.o \
|
rtl/stdlib.o \
|
||||||
rtl/string.o \
|
rtl/string.o \
|
||||||
|
|
|
@ -41,10 +41,14 @@ OBJECTS_MM_I386 := \
|
||||||
|
|
||||||
OBJECTS_RTL_I386 := \
|
OBJECTS_RTL_I386 := \
|
||||||
rtl/i386/memset.o \
|
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_EXCLUDE_FILTER := \
|
||||||
rtl/memset.o \
|
rtl/memset.o \
|
||||||
rtl/memcpy.o
|
rtl/memcpy.o
|
||||||
|
|
||||||
OBJECTS_ARCH = $(OBJECTS_BOOT) $(OBJECTS_EX_I386) $(OBJECTS_KE_I386) $(OBJECTS_MM_I386) $(OBJECTS_RTL_I386)
|
OBJECTS_ARCH = $(OBJECTS_BOOT) $(OBJECTS_EX_I386) $(OBJECTS_KE_I386) $(OBJECTS_MM_I386) $(OBJECTS_RTL_I386)
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,13 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: catch.c,v 1.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
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/catch.c
|
* FILE: ntoskrnl/ke/catch.c
|
||||||
* PURPOSE: Exception handling
|
* PURPOSE: Exception handling
|
||||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||||
|
* Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -38,156 +39,9 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION
|
ULONG
|
||||||
RtlpExecuteHandlerForException(
|
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
PEXCEPTION_RECORD ExceptionRecord,
|
IN PCONTEXT Context);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
@ -215,6 +69,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
|
||||||
Context = &TContext;
|
Context = &TContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
|
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
|
||||||
{
|
{
|
||||||
|
@ -268,7 +123,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
KD_CONTINUE_TYPE Action = 0;
|
KD_CONTINUE_TYPE Action = kdContinue;
|
||||||
|
|
||||||
/* PreviousMode == KernelMode */
|
/* PreviousMode == KernelMode */
|
||||||
|
|
||||||
|
@ -282,10 +137,6 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
|
Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
|
||||||
}
|
}
|
||||||
#endif /* KDBG */
|
#endif /* KDBG */
|
||||||
else
|
|
||||||
{
|
|
||||||
KeBugCheckWithTf (KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
|
|
||||||
}
|
|
||||||
if (Action != kdHandleException)
|
if (Action != kdHandleException)
|
||||||
{
|
{
|
||||||
Value = RtlpDispatchException (ExceptionRecord, Context);
|
Value = RtlpDispatchException (ExceptionRecord, Context);
|
||||||
|
@ -355,274 +206,4 @@ RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
|
||||||
ZwRaiseException(ExceptionRecord, NULL, TRUE);
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -43,33 +43,9 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#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 ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
STATIC BOOLEAN
|
BOOLEAN
|
||||||
print_user_address(PVOID address)
|
print_user_address(PVOID address)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
|
@ -120,10 +96,6 @@ print_user_address(PVOID address)
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Disabled until SEH support is implemented.
|
|
||||||
*/
|
|
||||||
ULONG
|
ULONG
|
||||||
KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
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);
|
KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
|
||||||
return(0);
|
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
|
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -469,6 +469,9 @@ PsCreateTeb(HANDLE ProcessHandle,
|
||||||
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
|
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
|
||||||
Teb.CurrentLocale = PsDefaultThreadLocaleId;
|
Teb.CurrentLocale = PsDefaultThreadLocaleId;
|
||||||
|
|
||||||
|
/* Terminate the exception handler list */
|
||||||
|
Teb.Tib.ExceptionList = (PVOID)-1;
|
||||||
|
|
||||||
DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
|
DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
|
||||||
|
|
||||||
/* write TEB data into teb page */
|
/* write TEB data into teb page */
|
||||||
|
|
|
@ -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 */
|
|
|
@ -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
|
# Helper makefile for ReactOS modules
|
||||||
# Variables this makefile accepts:
|
# Variables this makefile accepts:
|
||||||
|
@ -381,6 +381,7 @@ include $(PATH_TO_TOP)/config
|
||||||
TARGET_CFLAGS += $(MK_CFLAGS)
|
TARGET_CFLAGS += $(MK_CFLAGS)
|
||||||
TARGET_CFLAGS += -pipe -march=$(ARCH)
|
TARGET_CFLAGS += -pipe -march=$(ARCH)
|
||||||
ifeq ($(DBG),1)
|
ifeq ($(DBG),1)
|
||||||
|
TARGET_ASFLAGS += -g
|
||||||
TARGET_CFLAGS += -g
|
TARGET_CFLAGS += -g
|
||||||
TARGET_LFLAGS += -g
|
TARGET_LFLAGS += -g
|
||||||
endif
|
endif
|
||||||
|
|
Loading…
Reference in a new issue