mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 17:14:41 +00:00
dos2unix'd some more files.
svn path=/trunk/; revision=3660
This commit is contained in:
parent
9bbe34eb81
commit
31c69eaf8a
5 changed files with 1172 additions and 1172 deletions
|
@ -1,366 +1,366 @@
|
||||||
/* $Id: seh.s,v 1.2 2002/10/26 07:32:08 chorns Exp $
|
/* $Id: seh.s,v 1.3 2002/10/26 09:53:15 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS MSVCRT Runtime Library
|
* PROJECT: ReactOS MSVCRT Runtime Library
|
||||||
* PURPOSE: Runtime library exception support for IA-32
|
* PURPOSE: Runtime library exception support for IA-32
|
||||||
* FILE: lib/msvcrt/except/seh.s
|
* FILE: lib/msvcrt/except/seh.s
|
||||||
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
* NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s.
|
* NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s.
|
||||||
* Please keep them in sync.
|
* Please keep them in sync.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ExceptionContinueExecution 0
|
#define ExceptionContinueExecution 0
|
||||||
#define ExceptionContinueSearch 1
|
#define ExceptionContinueSearch 1
|
||||||
#define ExceptionNestedException 2
|
#define ExceptionNestedException 2
|
||||||
#define ExceptionCollidedUnwind 3
|
#define ExceptionCollidedUnwind 3
|
||||||
|
|
||||||
#define EXCEPTION_NONCONTINUABLE 0x01
|
#define EXCEPTION_NONCONTINUABLE 0x01
|
||||||
#define EXCEPTION_UNWINDING 0x02
|
#define EXCEPTION_UNWINDING 0x02
|
||||||
#define EXCEPTION_EXIT_UNWIND 0x04
|
#define EXCEPTION_EXIT_UNWIND 0x04
|
||||||
#define EXCEPTION_STACK_INVALID 0x08
|
#define EXCEPTION_STACK_INVALID 0x08
|
||||||
#define EXCEPTION_NESTED_CALL 0x10
|
#define EXCEPTION_NESTED_CALL 0x10
|
||||||
#define EXCEPTION_TARGET_UNWIND 0x20
|
#define EXCEPTION_TARGET_UNWIND 0x20
|
||||||
#define EXCEPTION_COLLIDED_UNWIND 0x40
|
#define EXCEPTION_COLLIDED_UNWIND 0x40
|
||||||
|
|
||||||
#define EXCEPTION_UNWIND_MODE \
|
#define EXCEPTION_UNWIND_MODE \
|
||||||
( EXCEPTION_UNWINDING \
|
( EXCEPTION_UNWINDING \
|
||||||
| EXCEPTION_EXIT_UNWIND \
|
| EXCEPTION_EXIT_UNWIND \
|
||||||
| EXCEPTION_TARGET_UNWIND \
|
| EXCEPTION_TARGET_UNWIND \
|
||||||
| EXCEPTION_COLLIDED_UNWIND)
|
| EXCEPTION_COLLIDED_UNWIND)
|
||||||
|
|
||||||
#define EREC_CODE 0x00
|
#define EREC_CODE 0x00
|
||||||
#define EREC_FLAGS 0x04
|
#define EREC_FLAGS 0x04
|
||||||
#define EREC_RECORD 0x08
|
#define EREC_RECORD 0x08
|
||||||
#define EREC_ADDRESS 0x0C
|
#define EREC_ADDRESS 0x0C
|
||||||
#define EREC_NUMPARAMS 0x10
|
#define EREC_NUMPARAMS 0x10
|
||||||
#define EREC_INFO 0x14
|
#define EREC_INFO 0x14
|
||||||
|
|
||||||
#define TRYLEVEL_NONE -1
|
#define TRYLEVEL_NONE -1
|
||||||
#define TRYLEVEL_INVALID -2
|
#define TRYLEVEL_INVALID -2
|
||||||
|
|
||||||
#define ER_STANDARDESP -0x08
|
#define ER_STANDARDESP -0x08
|
||||||
#define ER_EPOINTERS -0x04
|
#define ER_EPOINTERS -0x04
|
||||||
#define ER_PREVFRAME 0x00
|
#define ER_PREVFRAME 0x00
|
||||||
#define ER_HANDLER 0x04
|
#define ER_HANDLER 0x04
|
||||||
#define ER_SCOPETABLE 0x08
|
#define ER_SCOPETABLE 0x08
|
||||||
#define ER_TRYLEVEL 0x0C
|
#define ER_TRYLEVEL 0x0C
|
||||||
#define ER_EBP 0x10
|
#define ER_EBP 0x10
|
||||||
|
|
||||||
#define ST_TRYLEVEL 0x00
|
#define ST_TRYLEVEL 0x00
|
||||||
#define ST_FILTER 0x04
|
#define ST_FILTER 0x04
|
||||||
#define ST_HANDLER 0x08
|
#define ST_HANDLER 0x08
|
||||||
|
|
||||||
#define CONTEXT_EDI 0x9C
|
#define CONTEXT_EDI 0x9C
|
||||||
#define CONTEXT_EBX 0xA4
|
#define CONTEXT_EBX 0xA4
|
||||||
#define CONTEXT_EIP 0xB8
|
#define CONTEXT_EIP 0xB8
|
||||||
|
|
||||||
.globl __local_unwind2
|
.globl __local_unwind2
|
||||||
.globl __except_handler3
|
.globl __except_handler3
|
||||||
|
|
||||||
// EAX = value to print
|
// EAX = value to print
|
||||||
_do_debug:
|
_do_debug:
|
||||||
pushal
|
pushal
|
||||||
pushl %eax
|
pushl %eax
|
||||||
call _MsvcrtDebug@4
|
call _MsvcrtDebug@4
|
||||||
popal
|
popal
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#define LU2_TRYLEVEL 0x08
|
#define LU2_TRYLEVEL 0x08
|
||||||
#define LU2_REGFRAME 0x04
|
#define LU2_REGFRAME 0x04
|
||||||
|
|
||||||
//
|
//
|
||||||
// void
|
// void
|
||||||
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
|
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
|
||||||
// LONG TryLevel)
|
// LONG TryLevel)
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
|
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
|
||||||
// [EDX+04h] - LONG TryLevel
|
// [EDX+04h] - LONG TryLevel
|
||||||
// Registers:
|
// Registers:
|
||||||
// EBP - EBP of call frame we are unwinding
|
// EBP - EBP of call frame we are unwinding
|
||||||
// Returns:
|
// Returns:
|
||||||
// Nothing
|
// Nothing
|
||||||
// Notes:
|
// Notes:
|
||||||
// Run all termination handlers for a call frame from the current
|
// Run all termination handlers for a call frame from the current
|
||||||
// try-level up to (but not including) the given stop try-level.
|
// try-level up to (but not including) the given stop try-level.
|
||||||
__local_unwind2:
|
__local_unwind2:
|
||||||
// Setup our call frame so we can access parameters using EDX
|
// Setup our call frame so we can access parameters using EDX
|
||||||
//pushl %ebp
|
//pushl %ebp
|
||||||
movl %esp, %edx
|
movl %esp, %edx
|
||||||
|
|
||||||
// FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the
|
// FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the
|
||||||
// unwinding in case something goes wrong
|
// unwinding in case something goes wrong
|
||||||
|
|
||||||
.lu2_next_scope:
|
.lu2_next_scope:
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
// Keep a pointer to the exception registration in EBX
|
||||||
movl LU2_REGFRAME(%edx), %ebx
|
movl LU2_REGFRAME(%edx), %ebx
|
||||||
|
|
||||||
// If we have reached the end of the chain or we're asked to stop here
|
// If we have reached the end of the chain or we're asked to stop here
|
||||||
// by the caller then exit
|
// by the caller then exit
|
||||||
movl ER_TRYLEVEL(%ebx), %eax
|
movl ER_TRYLEVEL(%ebx), %eax
|
||||||
|
|
||||||
cmpl $-1, %eax
|
cmpl $-1, %eax
|
||||||
je .lu2_done
|
je .lu2_done
|
||||||
|
|
||||||
cmpl LU2_TRYLEVEL(%edx), %eax
|
cmpl LU2_TRYLEVEL(%edx), %eax
|
||||||
je .lu2_done
|
je .lu2_done
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable that describes
|
// Compute the offset of the entry in the scopetable that describes
|
||||||
// the scope that is to be unwound. Put the offset in EDI.
|
// the scope that is to be unwound. Put the offset in EDI.
|
||||||
movl ST_TRYLEVEL(%esi), %edi
|
movl ST_TRYLEVEL(%esi), %edi
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
|
|
||||||
// If this is not a termination handler then skip it
|
// If this is not a termination handler then skip it
|
||||||
cmpl $0, ST_FILTER(%edi)
|
cmpl $0, ST_FILTER(%edi)
|
||||||
jne .lu2_next_scope
|
jne .lu2_next_scope
|
||||||
|
|
||||||
// Save the previous try-level in the exception registration structure
|
// Save the previous try-level in the exception registration structure
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
movl ST_TRYLEVEL(%edi), %eax
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
movl %eax, ER_TRYLEVEL(%ebx)
|
||||||
|
|
||||||
// Fetch the address of the termination handler
|
// Fetch the address of the termination handler
|
||||||
movl ST_HANDLER(%edi), %eax
|
movl ST_HANDLER(%edi), %eax
|
||||||
|
|
||||||
// Termination handlers may trash all registers so save the
|
// Termination handlers may trash all registers so save the
|
||||||
// important ones and then call the handler
|
// important ones and then call the handler
|
||||||
pushl %edx
|
pushl %edx
|
||||||
call *%eax
|
call *%eax
|
||||||
|
|
||||||
// Get our base pointer back
|
// Get our base pointer back
|
||||||
popl %edx
|
popl %edx
|
||||||
|
|
||||||
jmp .lu2_next_scope
|
jmp .lu2_next_scope
|
||||||
|
|
||||||
.lu2_done:
|
.lu2_done:
|
||||||
|
|
||||||
// FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect
|
// FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect
|
||||||
// the unwinding
|
// the unwinding
|
||||||
|
|
||||||
//movl %esi, %esp
|
//movl %esi, %esp
|
||||||
//popl %ebp
|
//popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#define EH3_DISPCONTEXT 0x14
|
#define EH3_DISPCONTEXT 0x14
|
||||||
#define EH3_CONTEXT 0x10
|
#define EH3_CONTEXT 0x10
|
||||||
#define EH3_REGFRAME 0x0C
|
#define EH3_REGFRAME 0x0C
|
||||||
#define EH3_ERECORD 0x08
|
#define EH3_ERECORD 0x08
|
||||||
|
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// [ESP+14h] - PVOID DispatcherContext
|
// [ESP+14h] - PVOID DispatcherContext
|
||||||
// [ESP+10h] - PCONTEXT Context
|
// [ESP+10h] - PCONTEXT Context
|
||||||
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
|
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
|
||||||
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord
|
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord
|
||||||
// Registers:
|
// Registers:
|
||||||
// Unknown
|
// Unknown
|
||||||
// Returns:
|
// Returns:
|
||||||
// EXCEPTION_DISPOSITION - How this handler handled the exception
|
// EXCEPTION_DISPOSITION - How this handler handled the exception
|
||||||
// Notes:
|
// Notes:
|
||||||
// Try to find an exception handler that will handle the exception.
|
// Try to find an exception handler that will handle the exception.
|
||||||
// Traverse the entries in the scopetable that is associated with the
|
// Traverse the entries in the scopetable that is associated with the
|
||||||
// exception registration passed as a parameter to this function.
|
// exception registration passed as a parameter to this function.
|
||||||
// If an exception handler that will handle the exception is found, it
|
// If an exception handler that will handle the exception is found, it
|
||||||
// is called and this function never returns
|
// is called and this function never returns
|
||||||
__except_handler3:
|
__except_handler3:
|
||||||
// Setup our call frame so we can access parameters using EBP
|
// Setup our call frame so we can access parameters using EBP
|
||||||
pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
|
pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
|
|
||||||
// Don't trust the direction flag to be cleared
|
// Don't trust the direction flag to be cleared
|
||||||
cld
|
cld
|
||||||
|
|
||||||
// Either we're called to handle an exception or we're called to unwind
|
// Either we're called to handle an exception or we're called to unwind
|
||||||
movl EH3_ERECORD(%ebp), %eax
|
movl EH3_ERECORD(%ebp), %eax
|
||||||
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
|
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
|
||||||
jnz .eh3_unwind
|
jnz .eh3_unwind
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
// Keep a pointer to the exception registration in EBX
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
movl EH3_REGFRAME(%ebp), %ebx
|
||||||
|
|
||||||
// Build an EXCEPTION_POINTERS structure on the stack and store it's
|
// Build an EXCEPTION_POINTERS structure on the stack and store it's
|
||||||
// address in the EXCEPTION_REGISTRATION structure
|
// address in the EXCEPTION_REGISTRATION structure
|
||||||
movl EH3_CONTEXT(%esp), %eax
|
movl EH3_CONTEXT(%esp), %eax
|
||||||
pushl %ebx // Registration frame
|
pushl %ebx // Registration frame
|
||||||
pushl %eax // Context
|
pushl %eax // Context
|
||||||
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack
|
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack
|
||||||
|
|
||||||
// Keep current try-level in EDI
|
// Keep current try-level in EDI
|
||||||
movl ER_TRYLEVEL(%ebx), %edi
|
movl ER_TRYLEVEL(%ebx), %edi
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
.eh3_next_scope:
|
.eh3_next_scope:
|
||||||
|
|
||||||
// If we have reached the end of the chain then exit
|
// If we have reached the end of the chain then exit
|
||||||
cmpl $-1, %edi
|
cmpl $-1, %edi
|
||||||
je .eh3_search
|
je .eh3_search
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable and store
|
// Compute the offset of the entry in the scopetable and store
|
||||||
// the absolute address in EAX
|
// the absolute address in EAX
|
||||||
lea (%edi, %edi, 2), %eax
|
lea (%edi, %edi, 2), %eax
|
||||||
shll $2, %eax
|
shll $2, %eax
|
||||||
addl %esi, %eax
|
addl %esi, %eax
|
||||||
|
|
||||||
// Fetch the address of the filter routine
|
// Fetch the address of the filter routine
|
||||||
movl ST_FILTER(%eax), %eax
|
movl ST_FILTER(%eax), %eax
|
||||||
|
|
||||||
// If this is a termination handler then skip it
|
// If this is a termination handler then skip it
|
||||||
cmpl $0, %eax
|
cmpl $0, %eax
|
||||||
je .eh3_continue
|
je .eh3_continue
|
||||||
|
|
||||||
// Filter routines may trash all registers so save the important
|
// Filter routines may trash all registers so save the important
|
||||||
// ones before restoring the call frame ebp and calling the handler
|
// ones before restoring the call frame ebp and calling the handler
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
pushl %edi // Stop try-level
|
pushl %edi // Stop try-level
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
call *%eax
|
call *%eax
|
||||||
popl %edi // Stop try-level
|
popl %edi // Stop try-level
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
// Reload EBX with registration frame address
|
// Reload EBX with registration frame address
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
movl EH3_REGFRAME(%ebp), %ebx
|
||||||
|
|
||||||
// Be more flexible here by checking if the return value is less than
|
// 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
|
// zero, equal to zero, or larger than zero instead of the defined
|
||||||
// values:
|
// values:
|
||||||
// -1 (EXCEPTION_CONTINUE_EXECUTION)
|
// -1 (EXCEPTION_CONTINUE_EXECUTION)
|
||||||
// 0 (EXCEPTION_CONTINUE_SEARCH)
|
// 0 (EXCEPTION_CONTINUE_SEARCH)
|
||||||
// +1 (EXCEPTION_EXECUTE_HANDLER)
|
// +1 (EXCEPTION_EXECUTE_HANDLER)
|
||||||
orl %eax, %eax
|
orl %eax, %eax
|
||||||
jz .eh3_continue
|
jz .eh3_continue
|
||||||
js .eh3_dismiss
|
js .eh3_dismiss
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_EXECUTE_HANDLER
|
// Filter returned: EXCEPTION_EXECUTE_HANDLER
|
||||||
|
|
||||||
// Ask the OS to perform global unwinding.
|
// Ask the OS to perform global unwinding.
|
||||||
pushl %edi // Save stop try-level
|
pushl %edi // Save stop try-level
|
||||||
pushl %ebx // Save registration frame address
|
pushl %ebx // Save registration frame address
|
||||||
pushl %ebx // Registration frame address
|
pushl %ebx // Registration frame address
|
||||||
call __global_unwind2
|
call __global_unwind2
|
||||||
popl %eax // Remove parameter to __global_unwind2
|
popl %eax // Remove parameter to __global_unwind2
|
||||||
popl %ebx // Restore registration frame address
|
popl %ebx // Restore registration frame address
|
||||||
popl %edi // Restore stop try-level
|
popl %edi // Restore stop try-level
|
||||||
|
|
||||||
// Change the context structure so _except_finish is called in the
|
// Change the context structure so _except_finish is called in the
|
||||||
// correct context since we return ExceptionContinueExecution.
|
// correct context since we return ExceptionContinueExecution.
|
||||||
movl EH3_CONTEXT(%ebp), %eax
|
movl EH3_CONTEXT(%ebp), %eax
|
||||||
|
|
||||||
movl %edi, CONTEXT_EDI(%eax) // Stop try-level
|
movl %edi, CONTEXT_EDI(%eax) // Stop try-level
|
||||||
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address
|
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address
|
||||||
movl $_except_finish, CONTEXT_EIP(%eax)
|
movl $_except_finish, CONTEXT_EIP(%eax)
|
||||||
|
|
||||||
movl $ExceptionContinueExecution, %eax
|
movl $ExceptionContinueExecution, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_SEARCH
|
// Filter returned: EXCEPTION_CONTINUE_SEARCH
|
||||||
.eh3_continue:
|
.eh3_continue:
|
||||||
|
|
||||||
// Reload ESI because the filter routine may have trashed it
|
// Reload ESI because the filter routine may have trashed it
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Go one try-level closer to the top
|
// Go one try-level closer to the top
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
movl ST_TRYLEVEL(%edi), %edi
|
movl ST_TRYLEVEL(%edi), %edi
|
||||||
|
|
||||||
jmp .eh3_next_scope
|
jmp .eh3_next_scope
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_EXECUTION
|
// Filter returned: EXCEPTION_CONTINUE_EXECUTION
|
||||||
// Continue execution like nothing happened
|
// Continue execution like nothing happened
|
||||||
.eh3_dismiss:
|
.eh3_dismiss:
|
||||||
movl $ExceptionContinueExecution, %eax
|
movl $ExceptionContinueExecution, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Tell the OS to search for another handler that will handle the exception
|
// Tell the OS to search for another handler that will handle the exception
|
||||||
.eh3_search:
|
.eh3_search:
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Perform local unwinding
|
// Perform local unwinding
|
||||||
.eh3_unwind:
|
.eh3_unwind:
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
|
testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
|
||||||
jnz .eh3_return
|
jnz .eh3_return
|
||||||
|
|
||||||
// Save some important registers
|
// Save some important registers
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
pushl $-1
|
pushl $-1
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
|
|
||||||
// Restore some important registers
|
// Restore some important registers
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
|
|
||||||
// Get me out of here
|
// Get me out of here
|
||||||
.eh3_return:
|
.eh3_return:
|
||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// None
|
// None
|
||||||
// Registers:
|
// Registers:
|
||||||
// EBX - Pointer to exception registration structure
|
// EBX - Pointer to exception registration structure
|
||||||
// EDI - Stop try-level
|
// EDI - Stop try-level
|
||||||
// Returns:
|
// Returns:
|
||||||
// -
|
// -
|
||||||
// Notes:
|
// Notes:
|
||||||
// -
|
// -
|
||||||
_except_finish:
|
_except_finish:
|
||||||
|
|
||||||
// Setup EBP for the exception handler. By doing this the exception
|
// Setup EBP for the exception handler. By doing this the exception
|
||||||
// handler can access local variables as normal
|
// handler can access local variables as normal
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
|
|
||||||
// Save some important registers
|
// Save some important registers
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
pushl %edi
|
pushl %edi
|
||||||
|
|
||||||
// Stop try-level
|
// Stop try-level
|
||||||
pushl %edi
|
pushl %edi
|
||||||
|
|
||||||
// Pointer to exception registration structure
|
// Pointer to exception registration structure
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
|
|
||||||
// Restore some important registers
|
// Restore some important registers
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %ebx
|
popl %ebx
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable and store
|
// Compute the offset of the entry in the scopetable and store
|
||||||
// the absolute address in EDI
|
// the absolute address in EDI
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
|
|
||||||
// Set the current try-level to the previous try-level and call
|
// Set the current try-level to the previous try-level and call
|
||||||
// the exception handler
|
// the exception handler
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
movl ST_TRYLEVEL(%edi), %eax
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
movl %eax, ER_TRYLEVEL(%ebx)
|
||||||
movl ST_HANDLER(%edi), %eax
|
movl ST_HANDLER(%edi), %eax
|
||||||
|
|
||||||
call *%eax
|
call *%eax
|
||||||
|
|
||||||
// We should never get here
|
// We should never get here
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -1,433 +1,433 @@
|
||||||
/* $Id: exception.c,v 1.2 2002/10/26 07:32:08 chorns Exp $
|
/* $Id: exception.c,v 1.3 2002/10/26 09:53:15 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* PURPOSE: User-mode exception support for IA-32
|
* PURPOSE: User-mode exception support for IA-32
|
||||||
* FILE: lib/ntdll/rtl/i386/exception.c
|
* FILE: lib/ntdll/rtl/i386/exception.c
|
||||||
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
/* Implemented in except.s */
|
/* Implemented in except.s */
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
RtlpCaptureContext(PCONTEXT pContext);
|
RtlpCaptureContext(PCONTEXT pContext);
|
||||||
|
|
||||||
/* Macros that will help streamline the SEH implementations for
|
/* Macros that will help streamline the SEH implementations for
|
||||||
kernel mode and user mode */
|
kernel mode and user mode */
|
||||||
|
|
||||||
#define SehpGetStackLimits(StackBase, StackLimit) \
|
#define SehpGetStackLimits(StackBase, StackLimit) \
|
||||||
{ \
|
{ \
|
||||||
(*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \
|
(*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \
|
||||||
(*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
|
(*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SehpGetExceptionList() \
|
#define SehpGetExceptionList() \
|
||||||
(PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList)
|
(PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList)
|
||||||
|
|
||||||
#define SehpSetExceptionList(NewExceptionList) \
|
#define SehpSetExceptionList(NewExceptionList) \
|
||||||
NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
|
NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
|
||||||
|
|
||||||
#define SehpCaptureContext(Context) \
|
#define SehpCaptureContext(Context) \
|
||||||
{ \
|
{ \
|
||||||
RtlpCaptureContext(Context); \
|
RtlpCaptureContext(Context); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** Code below this line is shared with ntoskrnl/rtl/i386/exception.c - please keep in sync ***/
|
/*** Code below this line is shared with ntoskrnl/rtl/i386/exception.c - please keep in sync ***/
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
AsmDebug(ULONG Value)
|
AsmDebug(ULONG Value)
|
||||||
{
|
{
|
||||||
DbgPrint("Value 0x%.08x\n", Value);
|
DbgPrint("Value 0x%.08x\n", Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Declare a few prototypes for the functions in except.s */
|
/* Declare a few prototypes for the functions in except.s */
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION
|
EXCEPTION_DISPOSITION
|
||||||
RtlpExecuteHandlerForException(
|
RtlpExecuteHandlerForException(
|
||||||
PEXCEPTION_RECORD ExceptionRecord,
|
PEXCEPTION_RECORD ExceptionRecord,
|
||||||
PEXCEPTION_REGISTRATION RegistrationFrame,
|
PEXCEPTION_REGISTRATION RegistrationFrame,
|
||||||
PCONTEXT Context,
|
PCONTEXT Context,
|
||||||
PVOID DispatcherContext,
|
PVOID DispatcherContext,
|
||||||
PEXCEPTION_HANDLER ExceptionHandler);
|
PEXCEPTION_HANDLER ExceptionHandler);
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION
|
EXCEPTION_DISPOSITION
|
||||||
RtlpExecuteHandlerForUnwind(
|
RtlpExecuteHandlerForUnwind(
|
||||||
PEXCEPTION_RECORD ExceptionRecord,
|
PEXCEPTION_RECORD ExceptionRecord,
|
||||||
PEXCEPTION_REGISTRATION RegistrationFrame,
|
PEXCEPTION_REGISTRATION RegistrationFrame,
|
||||||
PCONTEXT Context,
|
PCONTEXT Context,
|
||||||
PVOID DispatcherContext,
|
PVOID DispatcherContext,
|
||||||
PEXCEPTION_HANDLER ExceptionHandler);
|
PEXCEPTION_HANDLER ExceptionHandler);
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
VOID RtlpDumpExceptionRegistrations(VOID)
|
VOID RtlpDumpExceptionRegistrations(VOID)
|
||||||
{
|
{
|
||||||
PEXCEPTION_REGISTRATION Current;
|
PEXCEPTION_REGISTRATION Current;
|
||||||
|
|
||||||
DbgPrint("Dumping exception registrations:\n");
|
DbgPrint("Dumping exception registrations:\n");
|
||||||
|
|
||||||
Current = SehpGetExceptionList();
|
Current = SehpGetExceptionList();
|
||||||
|
|
||||||
if ((ULONG_PTR)Current != -1)
|
if ((ULONG_PTR)Current != -1)
|
||||||
{
|
{
|
||||||
while ((ULONG_PTR)Current != -1)
|
while ((ULONG_PTR)Current != -1)
|
||||||
{
|
{
|
||||||
DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler);
|
DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler);
|
||||||
Current = Current->prev;
|
Current = Current->prev;
|
||||||
}
|
}
|
||||||
DbgPrint(" End-Of-List\n");
|
DbgPrint(" End-Of-List\n");
|
||||||
} else {
|
} else {
|
||||||
DbgPrint(" No exception registrations exists.\n");
|
DbgPrint(" No exception registrations exists.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
IN PCONTEXT Context)
|
IN PCONTEXT Context)
|
||||||
{
|
{
|
||||||
PEXCEPTION_REGISTRATION RegistrationFrame;
|
PEXCEPTION_REGISTRATION RegistrationFrame;
|
||||||
DWORD DispatcherContext;
|
DWORD DispatcherContext;
|
||||||
DWORD ReturnValue;
|
DWORD ReturnValue;
|
||||||
|
|
||||||
DPRINT("RtlpDispatchException()\n");
|
DPRINT("RtlpDispatchException()\n");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
RtlpDumpExceptionRegistrations();
|
RtlpDumpExceptionRegistrations();
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
RegistrationFrame = SehpGetExceptionList();
|
RegistrationFrame = SehpGetExceptionList();
|
||||||
|
|
||||||
DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame);
|
DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame);
|
||||||
|
|
||||||
while ((ULONG_PTR)RegistrationFrame != -1)
|
while ((ULONG_PTR)RegistrationFrame != -1)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD ExceptionRecord2;
|
EXCEPTION_RECORD ExceptionRecord2;
|
||||||
DWORD Temp = 0;
|
DWORD Temp = 0;
|
||||||
//PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8;
|
//PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8;
|
||||||
|
|
||||||
// Make sure the registration frame is located within the stack
|
// Make sure the registration frame is located within the stack
|
||||||
|
|
||||||
DPRINT("Error checking\n");
|
DPRINT("Error checking\n");
|
||||||
#if 0
|
#if 0
|
||||||
if (Teb->Tib.StackBase > RegistrationFrameEnd)
|
if (Teb->Tib.StackBase > RegistrationFrameEnd)
|
||||||
{
|
{
|
||||||
DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
|
DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
|
||||||
Teb->Tib.StackBase, RegistrationFrameEnd);
|
Teb->Tib.StackBase, RegistrationFrameEnd);
|
||||||
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
}
|
}
|
||||||
// FIXME: Stack top, correct?
|
// FIXME: Stack top, correct?
|
||||||
if (Teb->Tib.StackLimit < RegistrationFrameEnd)
|
if (Teb->Tib.StackLimit < RegistrationFrameEnd)
|
||||||
{
|
{
|
||||||
DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
|
DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
|
||||||
Teb->Tib.StackLimit, RegistrationFrameEnd);
|
Teb->Tib.StackLimit, RegistrationFrameEnd);
|
||||||
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure stack is DWORD aligned
|
// Make sure stack is DWORD aligned
|
||||||
if ((ULONG_PTR)RegistrationFrame & 3)
|
if ((ULONG_PTR)RegistrationFrame & 3)
|
||||||
{
|
{
|
||||||
DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n",
|
DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n",
|
||||||
RegistrationFrameEnd);
|
RegistrationFrameEnd);
|
||||||
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* FIXME: */
|
/* FIXME: */
|
||||||
if (someFlag)
|
if (someFlag)
|
||||||
RtlpLogLastExceptionDisposition( hLog, retValue );
|
RtlpLogLastExceptionDisposition( hLog, retValue );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler);
|
DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler);
|
||||||
DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord);
|
DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord);
|
||||||
DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame);
|
DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame);
|
||||||
DPRINT("Context 0x%X\n", Context);
|
DPRINT("Context 0x%X\n", Context);
|
||||||
DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext);
|
DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext);
|
||||||
|
|
||||||
ReturnValue = RtlpExecuteHandlerForException(
|
ReturnValue = RtlpExecuteHandlerForException(
|
||||||
ExceptionRecord,
|
ExceptionRecord,
|
||||||
RegistrationFrame,
|
RegistrationFrame,
|
||||||
Context,
|
Context,
|
||||||
&DispatcherContext,
|
&DispatcherContext,
|
||||||
RegistrationFrame->handler);
|
RegistrationFrame->handler);
|
||||||
|
|
||||||
DPRINT("Exception handler said 0x%X\n", ReturnValue);
|
DPRINT("Exception handler said 0x%X\n", ReturnValue);
|
||||||
DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame);
|
DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame);
|
||||||
{
|
{
|
||||||
PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08);
|
PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08);
|
||||||
DPRINT("StandardESP == 0x%.08x\n", sp[0]);
|
DPRINT("StandardESP == 0x%.08x\n", sp[0]);
|
||||||
DPRINT("Exception Pointers == 0x%.08x\n", sp[1]);
|
DPRINT("Exception Pointers == 0x%.08x\n", sp[1]);
|
||||||
DPRINT("PrevFrame == 0x%.08x\n", sp[2]);
|
DPRINT("PrevFrame == 0x%.08x\n", sp[2]);
|
||||||
DPRINT("Handler == 0x%.08x\n", sp[3]);
|
DPRINT("Handler == 0x%.08x\n", sp[3]);
|
||||||
DPRINT("ScopeTable == 0x%.08x\n", sp[4]);
|
DPRINT("ScopeTable == 0x%.08x\n", sp[4]);
|
||||||
DPRINT("TryLevel == 0x%.08x\n", sp[5]);
|
DPRINT("TryLevel == 0x%.08x\n", sp[5]);
|
||||||
DPRINT("EBP == 0x%.08x\n", sp[6]);
|
DPRINT("EBP == 0x%.08x\n", sp[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RegistrationFrame == NULL)
|
if (RegistrationFrame == NULL)
|
||||||
{
|
{
|
||||||
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
|
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReturnValue == ExceptionContinueExecution)
|
if (ReturnValue == ExceptionContinueExecution)
|
||||||
{
|
{
|
||||||
DPRINT("ReturnValue == ExceptionContinueExecution\n");
|
DPRINT("ReturnValue == ExceptionContinueExecution\n");
|
||||||
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
|
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
|
||||||
{
|
{
|
||||||
DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n");
|
DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n");
|
||||||
|
|
||||||
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
|
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
|
||||||
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
|
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
|
||||||
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
ExceptionRecord2.NumberParameters = 0;
|
ExceptionRecord2.NumberParameters = 0;
|
||||||
RtlRaiseException(&ExceptionRecord2);
|
RtlRaiseException(&ExceptionRecord2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Copy the (possibly changed) context back to the trap frame and return */
|
/* Copy the (possibly changed) context back to the trap frame and return */
|
||||||
NtContinue(Context, FALSE);
|
NtContinue(Context, FALSE);
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ReturnValue == ExceptionContinueSearch)
|
else if (ReturnValue == ExceptionContinueSearch)
|
||||||
{
|
{
|
||||||
DPRINT("ReturnValue == ExceptionContinueSearch\n");
|
DPRINT("ReturnValue == ExceptionContinueSearch\n");
|
||||||
|
|
||||||
/* Nothing to do here */
|
/* Nothing to do here */
|
||||||
}
|
}
|
||||||
else if (ReturnValue == ExceptionNestedException)
|
else if (ReturnValue == ExceptionNestedException)
|
||||||
{
|
{
|
||||||
DPRINT("ReturnValue == ExceptionNestedException\n");
|
DPRINT("ReturnValue == ExceptionNestedException\n");
|
||||||
|
|
||||||
ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND;
|
ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND;
|
||||||
if (DispatcherContext > Temp)
|
if (DispatcherContext > Temp)
|
||||||
{
|
{
|
||||||
Temp = DispatcherContext;
|
Temp = DispatcherContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* if (ReturnValue == ExceptionCollidedUnwind) */
|
else /* if (ReturnValue == ExceptionCollidedUnwind) */
|
||||||
{
|
{
|
||||||
DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n");
|
DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n");
|
||||||
|
|
||||||
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
|
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
|
||||||
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
|
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
|
||||||
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
ExceptionRecord2.NumberParameters = 0;
|
ExceptionRecord2.NumberParameters = 0;
|
||||||
RtlRaiseException(&ExceptionRecord2);
|
RtlRaiseException(&ExceptionRecord2);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegistrationFrame = RegistrationFrame->prev; // Go to previous frame
|
RegistrationFrame = RegistrationFrame->prev; // Go to previous frame
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No exception handler will handle this exception */
|
/* No exception handler will handle this exception */
|
||||||
|
|
||||||
DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n");
|
DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n");
|
||||||
|
|
||||||
return ExceptionContinueExecution;
|
return ExceptionContinueExecution;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
RtlRaiseStatus(NTSTATUS Status)
|
RtlRaiseStatus(NTSTATUS Status)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD ExceptionRecord;
|
EXCEPTION_RECORD ExceptionRecord;
|
||||||
|
|
||||||
DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status);
|
DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status);
|
||||||
|
|
||||||
ExceptionRecord.ExceptionCode = Status;
|
ExceptionRecord.ExceptionCode = Status;
|
||||||
ExceptionRecord.ExceptionRecord = NULL;
|
ExceptionRecord.ExceptionRecord = NULL;
|
||||||
ExceptionRecord.NumberParameters = 0;
|
ExceptionRecord.NumberParameters = 0;
|
||||||
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
RtlRaiseException (& ExceptionRecord);
|
RtlRaiseException (& ExceptionRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
|
RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
|
||||||
PVOID ReturnAddress,
|
PVOID ReturnAddress,
|
||||||
PEXCEPTION_RECORD ExceptionRecord,
|
PEXCEPTION_RECORD ExceptionRecord,
|
||||||
DWORD EaxValue)
|
DWORD EaxValue)
|
||||||
{
|
{
|
||||||
PEXCEPTION_REGISTRATION ERHead;
|
PEXCEPTION_REGISTRATION ERHead;
|
||||||
PEXCEPTION_RECORD pExceptRec;
|
PEXCEPTION_RECORD pExceptRec;
|
||||||
EXCEPTION_RECORD TempER;
|
EXCEPTION_RECORD TempER;
|
||||||
CONTEXT Context;
|
CONTEXT Context;
|
||||||
|
|
||||||
DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
|
DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
RtlpDumpExceptionRegistrations();
|
RtlpDumpExceptionRegistrations();
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
ERHead = SehpGetExceptionList();
|
ERHead = SehpGetExceptionList();
|
||||||
|
|
||||||
DPRINT("ERHead is 0x%X\n", ERHead);
|
DPRINT("ERHead is 0x%X\n", ERHead);
|
||||||
|
|
||||||
if (ExceptionRecord == NULL) // The normal case
|
if (ExceptionRecord == NULL) // The normal case
|
||||||
{
|
{
|
||||||
DPRINT("ExceptionRecord == NULL (normal)\n");
|
DPRINT("ExceptionRecord == NULL (normal)\n");
|
||||||
|
|
||||||
pExceptRec = &TempER;
|
pExceptRec = &TempER;
|
||||||
pExceptRec->ExceptionFlags = 0;
|
pExceptRec->ExceptionFlags = 0;
|
||||||
pExceptRec->ExceptionCode = STATUS_UNWIND;
|
pExceptRec->ExceptionCode = STATUS_UNWIND;
|
||||||
pExceptRec->ExceptionRecord = NULL;
|
pExceptRec->ExceptionRecord = NULL;
|
||||||
pExceptRec->ExceptionAddress = ReturnAddress;
|
pExceptRec->ExceptionAddress = ReturnAddress;
|
||||||
pExceptRec->ExceptionInformation[0] = 0;
|
pExceptRec->ExceptionInformation[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RegistrationFrame)
|
if (RegistrationFrame)
|
||||||
pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
|
pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
|
||||||
else
|
else
|
||||||
pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
|
pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags);
|
DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags);
|
||||||
if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING)
|
if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING)
|
||||||
{
|
{
|
||||||
DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING);
|
DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING);
|
||||||
}
|
}
|
||||||
if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND)
|
if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND)
|
||||||
{
|
{
|
||||||
DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND);
|
DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND);
|
||||||
}
|
}
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
Context.ContextFlags =
|
Context.ContextFlags =
|
||||||
(CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
|
(CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
|
||||||
|
|
||||||
SehpCaptureContext(&Context);
|
SehpCaptureContext(&Context);
|
||||||
|
|
||||||
DPRINT("Context.Eip = 0x%.08x\n", Context.Eip);
|
DPRINT("Context.Eip = 0x%.08x\n", Context.Eip);
|
||||||
DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp);
|
DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp);
|
||||||
DPRINT("Context.Esp = 0x%.08x\n", Context.Esp);
|
DPRINT("Context.Esp = 0x%.08x\n", Context.Esp);
|
||||||
|
|
||||||
Context.Esp += 0x10;
|
Context.Esp += 0x10;
|
||||||
Context.Eax = EaxValue;
|
Context.Eax = EaxValue;
|
||||||
|
|
||||||
// Begin traversing the list of EXCEPTION_REGISTRATION
|
// Begin traversing the list of EXCEPTION_REGISTRATION
|
||||||
while ((ULONG_PTR)ERHead != -1)
|
while ((ULONG_PTR)ERHead != -1)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD er2;
|
EXCEPTION_RECORD er2;
|
||||||
|
|
||||||
DPRINT("ERHead 0x%X\n", ERHead);
|
DPRINT("ERHead 0x%X\n", ERHead);
|
||||||
|
|
||||||
if (ERHead == RegistrationFrame)
|
if (ERHead == RegistrationFrame)
|
||||||
{
|
{
|
||||||
DPRINT("Continueing execution\n");
|
DPRINT("Continueing execution\n");
|
||||||
NtContinue(&Context, FALSE);
|
NtContinue(&Context, FALSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If there's an exception frame, but it's lower on the stack
|
// If there's an exception frame, but it's lower on the stack
|
||||||
// than the head of the exception list, something's wrong!
|
// than the head of the exception list, something's wrong!
|
||||||
if (RegistrationFrame && (RegistrationFrame <= ERHead))
|
if (RegistrationFrame && (RegistrationFrame <= ERHead))
|
||||||
{
|
{
|
||||||
DPRINT("The exception frame is bad\n");
|
DPRINT("The exception frame is bad\n");
|
||||||
|
|
||||||
// Generate an exception to bail out
|
// Generate an exception to bail out
|
||||||
er2.ExceptionRecord = pExceptRec;
|
er2.ExceptionRecord = pExceptRec;
|
||||||
er2.NumberParameters = 0;
|
er2.NumberParameters = 0;
|
||||||
er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
|
er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
|
||||||
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
|
|
||||||
RtlRaiseException(&er2);
|
RtlRaiseException(&er2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Stack = ERHead + sizeof(EXCEPTION_REGISTRATION);
|
Stack = ERHead + sizeof(EXCEPTION_REGISTRATION);
|
||||||
if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead
|
if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead
|
||||||
&& (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple
|
&& (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple
|
||||||
&& (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane)
|
&& (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
if (1) {
|
if (1) {
|
||||||
#endif
|
#endif
|
||||||
PEXCEPTION_REGISTRATION NewERHead;
|
PEXCEPTION_REGISTRATION NewERHead;
|
||||||
PEXCEPTION_REGISTRATION pCurrExceptReg;
|
PEXCEPTION_REGISTRATION pCurrExceptReg;
|
||||||
EXCEPTION_DISPOSITION ReturnValue;
|
EXCEPTION_DISPOSITION ReturnValue;
|
||||||
|
|
||||||
DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler);
|
DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler);
|
||||||
|
|
||||||
ReturnValue = RtlpExecuteHandlerForUnwind(
|
ReturnValue = RtlpExecuteHandlerForUnwind(
|
||||||
pExceptRec,
|
pExceptRec,
|
||||||
ERHead,
|
ERHead,
|
||||||
&Context,
|
&Context,
|
||||||
&NewERHead,
|
&NewERHead,
|
||||||
ERHead->handler);
|
ERHead->handler);
|
||||||
|
|
||||||
DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
|
DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
|
||||||
|
|
||||||
if (ReturnValue != ExceptionContinueSearch)
|
if (ReturnValue != ExceptionContinueSearch)
|
||||||
{
|
{
|
||||||
if (ReturnValue != ExceptionCollidedUnwind)
|
if (ReturnValue != ExceptionCollidedUnwind)
|
||||||
{
|
{
|
||||||
DPRINT("Bad return value\n");
|
DPRINT("Bad return value\n");
|
||||||
|
|
||||||
er2.ExceptionRecord = pExceptRec;
|
er2.ExceptionRecord = pExceptRec;
|
||||||
er2.NumberParameters = 0;
|
er2.NumberParameters = 0;
|
||||||
er2.ExceptionCode = STATUS_INVALID_DISPOSITION;
|
er2.ExceptionCode = STATUS_INVALID_DISPOSITION;
|
||||||
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
|
|
||||||
RtlRaiseException(&er2);
|
RtlRaiseException(&er2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERHead = NewERHead;
|
ERHead = NewERHead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pCurrExceptReg = ERHead;
|
pCurrExceptReg = ERHead;
|
||||||
ERHead = ERHead->prev;
|
ERHead = ERHead->prev;
|
||||||
|
|
||||||
DPRINT("New ERHead is 0x%X\n", ERHead);
|
DPRINT("New ERHead is 0x%X\n", ERHead);
|
||||||
|
|
||||||
DPRINT("Setting exception registration at 0x%X as current\n",
|
DPRINT("Setting exception registration at 0x%X as current\n",
|
||||||
RegistrationFrame->prev);
|
RegistrationFrame->prev);
|
||||||
|
|
||||||
// Unlink the exception handler
|
// Unlink the exception handler
|
||||||
SehpSetExceptionList(RegistrationFrame->prev);
|
SehpSetExceptionList(RegistrationFrame->prev);
|
||||||
}
|
}
|
||||||
else // The stack looks goofy! Raise an exception to bail out
|
else // The stack looks goofy! Raise an exception to bail out
|
||||||
{
|
{
|
||||||
DPRINT("Bad stack\n");
|
DPRINT("Bad stack\n");
|
||||||
|
|
||||||
er2.ExceptionRecord = pExceptRec;
|
er2.ExceptionRecord = pExceptRec;
|
||||||
er2.NumberParameters = 0;
|
er2.NumberParameters = 0;
|
||||||
er2.ExceptionCode = STATUS_BAD_STACK;
|
er2.ExceptionCode = STATUS_BAD_STACK;
|
||||||
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||||
|
|
||||||
RtlRaiseException(&er2);
|
RtlRaiseException(&er2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, we reached the end of the EXCEPTION_REGISTRATION list.
|
// If we get here, we reached the end of the EXCEPTION_REGISTRATION list.
|
||||||
// This shouldn't happen normally.
|
// This shouldn't happen normally.
|
||||||
|
|
||||||
DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n",
|
DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n",
|
||||||
RegistrationFrame);
|
RegistrationFrame);
|
||||||
|
|
||||||
if ((ULONG_PTR)RegistrationFrame == -1)
|
if ((ULONG_PTR)RegistrationFrame == -1)
|
||||||
NtContinue(&Context, FALSE);
|
NtContinue(&Context, FALSE);
|
||||||
else
|
else
|
||||||
NtRaiseException(pExceptRec, &Context, 0);
|
NtRaiseException(pExceptRec, &Context, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: Makefile,v 1.7 2002/10/20 14:53:02 ekohl Exp $
|
# $Id: Makefile,v 1.8 2002/10/26 09:53:15 dwelch Exp $
|
||||||
|
|
||||||
PATH_TO_TOP = ../..
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ TARGET_BASE = 0x77e70000
|
||||||
|
|
||||||
TARGET_SDKLIBS = ntdll.a kernel32.a gdi32.a
|
TARGET_SDKLIBS = ntdll.a kernel32.a gdi32.a
|
||||||
|
|
||||||
TARGET_CFLAGS = -I./include -DUNICODE -DDBG -Wall -Werror
|
TARGET_CFLAGS = -I./include -DUNICODE -Wall -Werror
|
||||||
|
|
||||||
TARGET_OBJECTS = $(TARGET_NAME).o
|
TARGET_OBJECTS = $(TARGET_NAME).o
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: exception.c,v 1.1 2002/10/26 00:36:54 chorns Exp $
|
/* $Id: exception.c,v 1.2 2002/10/26 09:53:16 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -76,10 +76,10 @@ RtlpCaptureContext(PCONTEXT pContext);
|
||||||
#define SehpSetExceptionList(NewExceptionList) \
|
#define SehpSetExceptionList(NewExceptionList) \
|
||||||
KeGetCurrentThread()->TrapFrame->ExceptionList = (PVOID)(NewExceptionList)
|
KeGetCurrentThread()->TrapFrame->ExceptionList = (PVOID)(NewExceptionList)
|
||||||
|
|
||||||
#define SehpCaptureContext(Context) \
|
#define SehpCaptureContext(Context) \
|
||||||
{ \
|
{ \
|
||||||
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, (Context)); \
|
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, (Context)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** Code below this line is shared with lib/ntdll/arch/ia32/exception.c - please keep in sync ***/
|
/*** Code below this line is shared with lib/ntdll/arch/ia32/exception.c - please keep in sync ***/
|
||||||
|
|
||||||
|
|
|
@ -1,366 +1,366 @@
|
||||||
/* $Id: seh.s,v 1.2 2002/10/26 07:32:08 chorns Exp $
|
/* $Id: seh.s,v 1.3 2002/10/26 09:53:16 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* PURPOSE: Runtime library exception support for IA-32
|
* PURPOSE: Runtime library exception support for IA-32
|
||||||
* FILE: ntoskrnl/rtl/i386/seh.s
|
* FILE: ntoskrnl/rtl/i386/seh.s
|
||||||
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
* NOTES: This file is shared with lib/msvcrt/except/seh.s.
|
* NOTES: This file is shared with lib/msvcrt/except/seh.s.
|
||||||
* Please keep them in sync.
|
* Please keep them in sync.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ExceptionContinueExecution 0
|
#define ExceptionContinueExecution 0
|
||||||
#define ExceptionContinueSearch 1
|
#define ExceptionContinueSearch 1
|
||||||
#define ExceptionNestedException 2
|
#define ExceptionNestedException 2
|
||||||
#define ExceptionCollidedUnwind 3
|
#define ExceptionCollidedUnwind 3
|
||||||
|
|
||||||
#define EXCEPTION_NONCONTINUABLE 0x01
|
#define EXCEPTION_NONCONTINUABLE 0x01
|
||||||
#define EXCEPTION_UNWINDING 0x02
|
#define EXCEPTION_UNWINDING 0x02
|
||||||
#define EXCEPTION_EXIT_UNWIND 0x04
|
#define EXCEPTION_EXIT_UNWIND 0x04
|
||||||
#define EXCEPTION_STACK_INVALID 0x08
|
#define EXCEPTION_STACK_INVALID 0x08
|
||||||
#define EXCEPTION_NESTED_CALL 0x10
|
#define EXCEPTION_NESTED_CALL 0x10
|
||||||
#define EXCEPTION_TARGET_UNWIND 0x20
|
#define EXCEPTION_TARGET_UNWIND 0x20
|
||||||
#define EXCEPTION_COLLIDED_UNWIND 0x40
|
#define EXCEPTION_COLLIDED_UNWIND 0x40
|
||||||
|
|
||||||
#define EXCEPTION_UNWIND_MODE \
|
#define EXCEPTION_UNWIND_MODE \
|
||||||
( EXCEPTION_UNWINDING \
|
( EXCEPTION_UNWINDING \
|
||||||
| EXCEPTION_EXIT_UNWIND \
|
| EXCEPTION_EXIT_UNWIND \
|
||||||
| EXCEPTION_TARGET_UNWIND \
|
| EXCEPTION_TARGET_UNWIND \
|
||||||
| EXCEPTION_COLLIDED_UNWIND)
|
| EXCEPTION_COLLIDED_UNWIND)
|
||||||
|
|
||||||
#define EREC_CODE 0x00
|
#define EREC_CODE 0x00
|
||||||
#define EREC_FLAGS 0x04
|
#define EREC_FLAGS 0x04
|
||||||
#define EREC_RECORD 0x08
|
#define EREC_RECORD 0x08
|
||||||
#define EREC_ADDRESS 0x0C
|
#define EREC_ADDRESS 0x0C
|
||||||
#define EREC_NUMPARAMS 0x10
|
#define EREC_NUMPARAMS 0x10
|
||||||
#define EREC_INFO 0x14
|
#define EREC_INFO 0x14
|
||||||
|
|
||||||
#define TRYLEVEL_NONE -1
|
#define TRYLEVEL_NONE -1
|
||||||
#define TRYLEVEL_INVALID -2
|
#define TRYLEVEL_INVALID -2
|
||||||
|
|
||||||
#define ER_STANDARDESP -0x08
|
#define ER_STANDARDESP -0x08
|
||||||
#define ER_EPOINTERS -0x04
|
#define ER_EPOINTERS -0x04
|
||||||
#define ER_PREVFRAME 0x00
|
#define ER_PREVFRAME 0x00
|
||||||
#define ER_HANDLER 0x04
|
#define ER_HANDLER 0x04
|
||||||
#define ER_SCOPETABLE 0x08
|
#define ER_SCOPETABLE 0x08
|
||||||
#define ER_TRYLEVEL 0x0C
|
#define ER_TRYLEVEL 0x0C
|
||||||
#define ER_EBP 0x10
|
#define ER_EBP 0x10
|
||||||
|
|
||||||
#define ST_TRYLEVEL 0x00
|
#define ST_TRYLEVEL 0x00
|
||||||
#define ST_FILTER 0x04
|
#define ST_FILTER 0x04
|
||||||
#define ST_HANDLER 0x08
|
#define ST_HANDLER 0x08
|
||||||
|
|
||||||
#define CONTEXT_EDI 0x9C
|
#define CONTEXT_EDI 0x9C
|
||||||
#define CONTEXT_EBX 0xA4
|
#define CONTEXT_EBX 0xA4
|
||||||
#define CONTEXT_EIP 0xB8
|
#define CONTEXT_EIP 0xB8
|
||||||
|
|
||||||
.globl __local_unwind2
|
.globl __local_unwind2
|
||||||
.globl __except_handler3
|
.globl __except_handler3
|
||||||
|
|
||||||
// EAX = value to print
|
// EAX = value to print
|
||||||
_do_debug:
|
_do_debug:
|
||||||
pushal
|
pushal
|
||||||
pushl %eax
|
pushl %eax
|
||||||
call _MsvcrtDebug@4
|
call _MsvcrtDebug@4
|
||||||
popal
|
popal
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#define LU2_TRYLEVEL 0x08
|
#define LU2_TRYLEVEL 0x08
|
||||||
#define LU2_REGFRAME 0x04
|
#define LU2_REGFRAME 0x04
|
||||||
|
|
||||||
//
|
//
|
||||||
// void
|
// void
|
||||||
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
|
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
|
||||||
// LONG TryLevel)
|
// LONG TryLevel)
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
|
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
|
||||||
// [EDX+04h] - LONG TryLevel
|
// [EDX+04h] - LONG TryLevel
|
||||||
// Registers:
|
// Registers:
|
||||||
// EBP - EBP of call frame we are unwinding
|
// EBP - EBP of call frame we are unwinding
|
||||||
// Returns:
|
// Returns:
|
||||||
// Nothing
|
// Nothing
|
||||||
// Notes:
|
// Notes:
|
||||||
// Run all termination handlers for a call frame from the current
|
// Run all termination handlers for a call frame from the current
|
||||||
// try-level up to (but not including) the given stop try-level.
|
// try-level up to (but not including) the given stop try-level.
|
||||||
__local_unwind2:
|
__local_unwind2:
|
||||||
// Setup our call frame so we can access parameters using EDX
|
// Setup our call frame so we can access parameters using EDX
|
||||||
//pushl %ebp
|
//pushl %ebp
|
||||||
movl %esp, %edx
|
movl %esp, %edx
|
||||||
|
|
||||||
// FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the
|
// FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the
|
||||||
// unwinding in case something goes wrong
|
// unwinding in case something goes wrong
|
||||||
|
|
||||||
.lu2_next_scope:
|
.lu2_next_scope:
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
// Keep a pointer to the exception registration in EBX
|
||||||
movl LU2_REGFRAME(%edx), %ebx
|
movl LU2_REGFRAME(%edx), %ebx
|
||||||
|
|
||||||
// If we have reached the end of the chain or we're asked to stop here
|
// If we have reached the end of the chain or we're asked to stop here
|
||||||
// by the caller then exit
|
// by the caller then exit
|
||||||
movl ER_TRYLEVEL(%ebx), %eax
|
movl ER_TRYLEVEL(%ebx), %eax
|
||||||
|
|
||||||
cmpl $-1, %eax
|
cmpl $-1, %eax
|
||||||
je .lu2_done
|
je .lu2_done
|
||||||
|
|
||||||
cmpl LU2_TRYLEVEL(%edx), %eax
|
cmpl LU2_TRYLEVEL(%edx), %eax
|
||||||
je .lu2_done
|
je .lu2_done
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable that describes
|
// Compute the offset of the entry in the scopetable that describes
|
||||||
// the scope that is to be unwound. Put the offset in EDI.
|
// the scope that is to be unwound. Put the offset in EDI.
|
||||||
movl ST_TRYLEVEL(%esi), %edi
|
movl ST_TRYLEVEL(%esi), %edi
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
|
|
||||||
// If this is not a termination handler then skip it
|
// If this is not a termination handler then skip it
|
||||||
cmpl $0, ST_FILTER(%edi)
|
cmpl $0, ST_FILTER(%edi)
|
||||||
jne .lu2_next_scope
|
jne .lu2_next_scope
|
||||||
|
|
||||||
// Save the previous try-level in the exception registration structure
|
// Save the previous try-level in the exception registration structure
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
movl ST_TRYLEVEL(%edi), %eax
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
movl %eax, ER_TRYLEVEL(%ebx)
|
||||||
|
|
||||||
// Fetch the address of the termination handler
|
// Fetch the address of the termination handler
|
||||||
movl ST_HANDLER(%edi), %eax
|
movl ST_HANDLER(%edi), %eax
|
||||||
|
|
||||||
// Termination handlers may trash all registers so save the
|
// Termination handlers may trash all registers so save the
|
||||||
// important ones and then call the handler
|
// important ones and then call the handler
|
||||||
pushl %edx
|
pushl %edx
|
||||||
call *%eax
|
call *%eax
|
||||||
|
|
||||||
// Get our base pointer back
|
// Get our base pointer back
|
||||||
popl %edx
|
popl %edx
|
||||||
|
|
||||||
jmp .lu2_next_scope
|
jmp .lu2_next_scope
|
||||||
|
|
||||||
.lu2_done:
|
.lu2_done:
|
||||||
|
|
||||||
// FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect
|
// FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect
|
||||||
// the unwinding
|
// the unwinding
|
||||||
|
|
||||||
//movl %esi, %esp
|
//movl %esi, %esp
|
||||||
//popl %ebp
|
//popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#define EH3_DISPCONTEXT 0x14
|
#define EH3_DISPCONTEXT 0x14
|
||||||
#define EH3_CONTEXT 0x10
|
#define EH3_CONTEXT 0x10
|
||||||
#define EH3_REGFRAME 0x0C
|
#define EH3_REGFRAME 0x0C
|
||||||
#define EH3_ERECORD 0x08
|
#define EH3_ERECORD 0x08
|
||||||
|
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// [ESP+14h] - PVOID DispatcherContext
|
// [ESP+14h] - PVOID DispatcherContext
|
||||||
// [ESP+10h] - PCONTEXT Context
|
// [ESP+10h] - PCONTEXT Context
|
||||||
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
|
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
|
||||||
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord
|
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord
|
||||||
// Registers:
|
// Registers:
|
||||||
// Unknown
|
// Unknown
|
||||||
// Returns:
|
// Returns:
|
||||||
// EXCEPTION_DISPOSITION - How this handler handled the exception
|
// EXCEPTION_DISPOSITION - How this handler handled the exception
|
||||||
// Notes:
|
// Notes:
|
||||||
// Try to find an exception handler that will handle the exception.
|
// Try to find an exception handler that will handle the exception.
|
||||||
// Traverse the entries in the scopetable that is associated with the
|
// Traverse the entries in the scopetable that is associated with the
|
||||||
// exception registration passed as a parameter to this function.
|
// exception registration passed as a parameter to this function.
|
||||||
// If an exception handler that will handle the exception is found, it
|
// If an exception handler that will handle the exception is found, it
|
||||||
// is called and this function never returns
|
// is called and this function never returns
|
||||||
__except_handler3:
|
__except_handler3:
|
||||||
// Setup our call frame so we can access parameters using EBP
|
// Setup our call frame so we can access parameters using EBP
|
||||||
pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
|
pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
|
|
||||||
// Don't trust the direction flag to be cleared
|
// Don't trust the direction flag to be cleared
|
||||||
cld
|
cld
|
||||||
|
|
||||||
// Either we're called to handle an exception or we're called to unwind
|
// Either we're called to handle an exception or we're called to unwind
|
||||||
movl EH3_ERECORD(%ebp), %eax
|
movl EH3_ERECORD(%ebp), %eax
|
||||||
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
|
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
|
||||||
jnz .eh3_unwind
|
jnz .eh3_unwind
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
// Keep a pointer to the exception registration in EBX
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
movl EH3_REGFRAME(%ebp), %ebx
|
||||||
|
|
||||||
// Build an EXCEPTION_POINTERS structure on the stack and store it's
|
// Build an EXCEPTION_POINTERS structure on the stack and store it's
|
||||||
// address in the EXCEPTION_REGISTRATION structure
|
// address in the EXCEPTION_REGISTRATION structure
|
||||||
movl EH3_CONTEXT(%esp), %eax
|
movl EH3_CONTEXT(%esp), %eax
|
||||||
pushl %ebx // Registration frame
|
pushl %ebx // Registration frame
|
||||||
pushl %eax // Context
|
pushl %eax // Context
|
||||||
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack
|
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack
|
||||||
|
|
||||||
// Keep current try-level in EDI
|
// Keep current try-level in EDI
|
||||||
movl ER_TRYLEVEL(%ebx), %edi
|
movl ER_TRYLEVEL(%ebx), %edi
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
.eh3_next_scope:
|
.eh3_next_scope:
|
||||||
|
|
||||||
// If we have reached the end of the chain then exit
|
// If we have reached the end of the chain then exit
|
||||||
cmpl $-1, %edi
|
cmpl $-1, %edi
|
||||||
je .eh3_search
|
je .eh3_search
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable and store
|
// Compute the offset of the entry in the scopetable and store
|
||||||
// the absolute address in EAX
|
// the absolute address in EAX
|
||||||
lea (%edi, %edi, 2), %eax
|
lea (%edi, %edi, 2), %eax
|
||||||
shll $2, %eax
|
shll $2, %eax
|
||||||
addl %esi, %eax
|
addl %esi, %eax
|
||||||
|
|
||||||
// Fetch the address of the filter routine
|
// Fetch the address of the filter routine
|
||||||
movl ST_FILTER(%eax), %eax
|
movl ST_FILTER(%eax), %eax
|
||||||
|
|
||||||
// If this is a termination handler then skip it
|
// If this is a termination handler then skip it
|
||||||
cmpl $0, %eax
|
cmpl $0, %eax
|
||||||
je .eh3_continue
|
je .eh3_continue
|
||||||
|
|
||||||
// Filter routines may trash all registers so save the important
|
// Filter routines may trash all registers so save the important
|
||||||
// ones before restoring the call frame ebp and calling the handler
|
// ones before restoring the call frame ebp and calling the handler
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
pushl %edi // Stop try-level
|
pushl %edi // Stop try-level
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
call *%eax
|
call *%eax
|
||||||
popl %edi // Stop try-level
|
popl %edi // Stop try-level
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
// Reload EBX with registration frame address
|
// Reload EBX with registration frame address
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
movl EH3_REGFRAME(%ebp), %ebx
|
||||||
|
|
||||||
// Be more flexible here by checking if the return value is less than
|
// 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
|
// zero, equal to zero, or larger than zero instead of the defined
|
||||||
// values:
|
// values:
|
||||||
// -1 (EXCEPTION_CONTINUE_EXECUTION)
|
// -1 (EXCEPTION_CONTINUE_EXECUTION)
|
||||||
// 0 (EXCEPTION_CONTINUE_SEARCH)
|
// 0 (EXCEPTION_CONTINUE_SEARCH)
|
||||||
// +1 (EXCEPTION_EXECUTE_HANDLER)
|
// +1 (EXCEPTION_EXECUTE_HANDLER)
|
||||||
orl %eax, %eax
|
orl %eax, %eax
|
||||||
jz .eh3_continue
|
jz .eh3_continue
|
||||||
js .eh3_dismiss
|
js .eh3_dismiss
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_EXECUTE_HANDLER
|
// Filter returned: EXCEPTION_EXECUTE_HANDLER
|
||||||
|
|
||||||
// Ask the OS to perform global unwinding.
|
// Ask the OS to perform global unwinding.
|
||||||
pushl %edi // Save stop try-level
|
pushl %edi // Save stop try-level
|
||||||
pushl %ebx // Save registration frame address
|
pushl %ebx // Save registration frame address
|
||||||
pushl %ebx // Registration frame address
|
pushl %ebx // Registration frame address
|
||||||
call __global_unwind2
|
call __global_unwind2
|
||||||
popl %eax // Remove parameter to __global_unwind2
|
popl %eax // Remove parameter to __global_unwind2
|
||||||
popl %ebx // Restore registration frame address
|
popl %ebx // Restore registration frame address
|
||||||
popl %edi // Restore stop try-level
|
popl %edi // Restore stop try-level
|
||||||
|
|
||||||
// Change the context structure so _except_finish is called in the
|
// Change the context structure so _except_finish is called in the
|
||||||
// correct context since we return ExceptionContinueExecution.
|
// correct context since we return ExceptionContinueExecution.
|
||||||
movl EH3_CONTEXT(%ebp), %eax
|
movl EH3_CONTEXT(%ebp), %eax
|
||||||
|
|
||||||
movl %edi, CONTEXT_EDI(%eax) // Stop try-level
|
movl %edi, CONTEXT_EDI(%eax) // Stop try-level
|
||||||
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address
|
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address
|
||||||
movl $_except_finish, CONTEXT_EIP(%eax)
|
movl $_except_finish, CONTEXT_EIP(%eax)
|
||||||
|
|
||||||
movl $ExceptionContinueExecution, %eax
|
movl $ExceptionContinueExecution, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_SEARCH
|
// Filter returned: EXCEPTION_CONTINUE_SEARCH
|
||||||
.eh3_continue:
|
.eh3_continue:
|
||||||
|
|
||||||
// Reload ESI because the filter routine may have trashed it
|
// Reload ESI because the filter routine may have trashed it
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Go one try-level closer to the top
|
// Go one try-level closer to the top
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
movl ST_TRYLEVEL(%edi), %edi
|
movl ST_TRYLEVEL(%edi), %edi
|
||||||
|
|
||||||
jmp .eh3_next_scope
|
jmp .eh3_next_scope
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_EXECUTION
|
// Filter returned: EXCEPTION_CONTINUE_EXECUTION
|
||||||
// Continue execution like nothing happened
|
// Continue execution like nothing happened
|
||||||
.eh3_dismiss:
|
.eh3_dismiss:
|
||||||
movl $ExceptionContinueExecution, %eax
|
movl $ExceptionContinueExecution, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Tell the OS to search for another handler that will handle the exception
|
// Tell the OS to search for another handler that will handle the exception
|
||||||
.eh3_search:
|
.eh3_search:
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
jmp .eh3_return
|
jmp .eh3_return
|
||||||
|
|
||||||
// Perform local unwinding
|
// Perform local unwinding
|
||||||
.eh3_unwind:
|
.eh3_unwind:
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
|
testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
|
||||||
jnz .eh3_return
|
jnz .eh3_return
|
||||||
|
|
||||||
// Save some important registers
|
// Save some important registers
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
pushl $-1
|
pushl $-1
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
|
|
||||||
// Restore some important registers
|
// Restore some important registers
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
movl $ExceptionContinueSearch, %eax
|
||||||
|
|
||||||
// Get me out of here
|
// Get me out of here
|
||||||
.eh3_return:
|
.eh3_return:
|
||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// None
|
// None
|
||||||
// Registers:
|
// Registers:
|
||||||
// EBX - Pointer to exception registration structure
|
// EBX - Pointer to exception registration structure
|
||||||
// EDI - Stop try-level
|
// EDI - Stop try-level
|
||||||
// Returns:
|
// Returns:
|
||||||
// -
|
// -
|
||||||
// Notes:
|
// Notes:
|
||||||
// -
|
// -
|
||||||
_except_finish:
|
_except_finish:
|
||||||
|
|
||||||
// Setup EBP for the exception handler. By doing this the exception
|
// Setup EBP for the exception handler. By doing this the exception
|
||||||
// handler can access local variables as normal
|
// handler can access local variables as normal
|
||||||
lea ER_EBP(%ebx), %ebp
|
lea ER_EBP(%ebx), %ebp
|
||||||
|
|
||||||
// Save some important registers
|
// Save some important registers
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
pushl %edi
|
pushl %edi
|
||||||
|
|
||||||
// Stop try-level
|
// Stop try-level
|
||||||
pushl %edi
|
pushl %edi
|
||||||
|
|
||||||
// Pointer to exception registration structure
|
// Pointer to exception registration structure
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
|
|
||||||
// Restore some important registers
|
// Restore some important registers
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %ebx
|
popl %ebx
|
||||||
popl %ebp
|
popl %ebp
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
// Keep a pointer to the scopetable in ESI
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
movl ER_SCOPETABLE(%ebx), %esi
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable and store
|
// Compute the offset of the entry in the scopetable and store
|
||||||
// the absolute address in EDI
|
// the absolute address in EDI
|
||||||
lea (%edi, %edi, 2), %edi
|
lea (%edi, %edi, 2), %edi
|
||||||
shll $2, %edi
|
shll $2, %edi
|
||||||
addl %esi, %edi
|
addl %esi, %edi
|
||||||
|
|
||||||
// Set the current try-level to the previous try-level and call
|
// Set the current try-level to the previous try-level and call
|
||||||
// the exception handler
|
// the exception handler
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
movl ST_TRYLEVEL(%edi), %eax
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
movl %eax, ER_TRYLEVEL(%ebx)
|
||||||
movl ST_HANDLER(%edi), %eax
|
movl ST_HANDLER(%edi), %eax
|
||||||
|
|
||||||
call *%eax
|
call *%eax
|
||||||
|
|
||||||
// We should never get here
|
// We should never get here
|
||||||
ret
|
ret
|
||||||
|
|
Loading…
Reference in a new issue