- After bugfixing, more complete except_nt exception handling implementation could be used, so get rid of the old one and thus code duplication.

- Move cpp/cppexcept.c to /except directory, and add a specific note in README.WINE that those files are shared with Wine.
- I moved PowerPC stubs too, but it will most probably break anyway, due to more missing stubs, my apologize.
See issue #2371 for more details.

svn path=/trunk/; revision=30359
This commit is contained in:
Aleksey Bragin 2007-11-11 15:47:21 +00:00
parent f0c9da09e2
commit 2db7ea2321
13 changed files with 427 additions and 851 deletions

View file

@ -40,7 +40,8 @@
</directory> </directory>
<directory name="except"> <directory name="except">
<file>abnorter.c</file> <file>abnorter.c</file>
<file>exhand2.c</file> <file>cpp.c</file>
<file>cppexcept.c</file>
<file>matherr.c</file> <file>matherr.c</file>
<if property="ARCH" value="i386"> <if property="ARCH" value="i386">
<directory name="i386"> <directory name="i386">
@ -49,6 +50,12 @@
<file>unwind.c</file> <file>unwind.c</file>
</directory> </directory>
</if> </if>
<if property="ARCH" value="powerpc">
<directory name="powerpc">
<file>seh.s</file>
<file>chkstk_asm.s</file>
</directory>
</if>
<file>xcptfil.c</file> <file>xcptfil.c</file>
</directory> </directory>
<directory name="float"> <directory name="float">
@ -475,8 +482,6 @@
<file>wlasttok.c</file> <file>wlasttok.c</file>
</directory> </directory>
<directory name="wine"> <directory name="wine">
<file>cpp.c</file>
<file>cppexcept.c</file>
<file>heap.c</file> <file>heap.c</file>
<file>scanf.c</file> <file>scanf.c</file>
<file>thread.c</file> <file>thread.c</file>

View file

@ -1,16 +1 @@
#include <precomp.h> #include <precomp.h>
#ifdef __GNUC__
/*
* @unimplemented
*/
int _abnormal_termination(void)
{
printf("Abnormal Termination\n");
// return AbnormalTermination();
return 0;
}
#else
#endif

View file

@ -1,33 +0,0 @@
#include <precomp.h>
#include <excpt.h>
#ifdef __GNUC__
#else
ULONG DbgPrint(PCH Format,...)
{
return 0;
}
#endif
VOID STDCALL
MsvcrtDebug(ULONG Value)
{
//DbgPrint("MsvcrtDebug 0x%.08x\n", Value);
}
struct _EXCEPTION_RECORD;
struct _CONTEXT;
/*
* @implemented
*/
EXCEPTION_DISPOSITION
_except_handler2(
struct _EXCEPTION_RECORD *ExceptionRecord,
void *Frame,
struct _CONTEXT *ContextRecord,
void *DispatcherContext)
{
//printf("_except_handler2()\n");
return 0;
}

729
reactos/lib/sdk/crt/except/i386/seh.s Executable file → Normal file
View file

@ -1,367 +1,468 @@
/* $Id$ /*
*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS MSVCRT Runtime Library * PROJECT: ReactOS CRT
* PURPOSE: Runtime library exception support for IA-32 * FILE: lib/crt/misc/i386/seh.S
* FILE: lib/msvcrt/except/seh.s * PURPOSE: SEH Support for the CRT
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s.
* Please keep them in sync.
*/ */
#define ExceptionContinueExecution 0 /* INCLUDES ******************************************************************/
#define ExceptionContinueSearch 1
#define ExceptionNestedException 2
#define ExceptionCollidedUnwind 3
#define EXCEPTION_NONCONTINUABLE 0x01 #include <ndk/asm.h>
#define EXCEPTION_UNWINDING 0x02 .intel_syntax noprefix
#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 \ #define DISPOSITION_DISMISS 0
( EXCEPTION_UNWINDING \ #define DISPOSITION_CONTINUE_SEARCH 1
| EXCEPTION_EXIT_UNWIND \ #define DISPOSITION_COLLIDED_UNWIND 3
| EXCEPTION_TARGET_UNWIND \
| EXCEPTION_COLLIDED_UNWIND)
#define EREC_CODE 0x00 /* GLOBALS *******************************************************************/
#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 __global_unwind2
.globl __local_unwind2 .globl __local_unwind2
.globl __abnormal_termination
.globl __except_handler2
.globl __except_handler3 .globl __except_handler3
// EAX = value to print /* FUNCTIONS *****************************************************************/
_do_debug:
pushal .func unwind_handler
pushl %eax _unwind_handler:
call _MsvcrtDebug@4
popal /* Check if we were unwinding and continue search if not */
mov ecx, [esp+4]
test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
mov eax, DISPOSITION_CONTINUE_SEARCH
jz unwind_handler_return
/* We have a collision, do a local unwind */
mov eax, [esp+20]
push ebp
mov ebp, [eax+16]
mov edx, [eax+40]
push edx
mov edx, [eax+36]
push edx
call __local_unwind2
add esp, 8
pop ebp
/* Set new try level */
mov eax, [esp+8]
mov edx, [esp+16]
mov [edx], eax
/* Return collided unwind */
mov eax, DISPOSITION_COLLIDED_UNWIND
unwind_handler_return:
ret ret
.endfunc
#define LU2_TRYLEVEL 0x08 .func _global_unwind2
#define LU2_REGFRAME 0x04 __global_unwind2:
// /* Create stack and save all registers */
// void push ebp
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame, mov ebp, esp
// LONG TryLevel) push ebx
// push esi
// Parameters: push edi
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame push ebp
// [EDX+04h] - LONG TryLevel
// Registers: /* Call unwind */
// EBP - EBP of call frame we are unwinding push 0
// Returns: push 0
// Nothing push glu_return
// Notes: push [ebp+8]
// Run all termination handlers for a call frame from the current call _RtlUnwind@16
// try-level up to (but not including) the given stop try-level.
glu_return:
/* Restore registers and return */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
.endfunc
.func _abnormal_termination
__abnormal_termination:
/* Assume false */
xor eax, eax
/* Check if the handler is the unwind handler */
mov ecx, fs:0
cmp dword ptr [ecx+4], offset _unwind_handler
jne short ab_return
/* Get the try level */
mov edx, [ecx+12]
mov edx, [edx+12]
/* Compare it */
cmp [ecx+8], edx
jne ab_return
/* Return true */
mov eax, 1
/* Return */
ab_return:
ret
.endfunc
.func _local_unwind2
__local_unwind2: __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 /* Save volatiles */
// unwinding in case something goes wrong push ebx
push esi
push edi
.lu2_next_scope: /* Get the exception registration */
mov eax, [esp+16]
// Keep a pointer to the exception registration in EBX /* Setup SEH to protect the unwind */
movl LU2_REGFRAME(%edx), %ebx push ebp
push eax
push -2
push offset _unwind_handler
push fs:0
mov fs:0, esp
// If we have reached the end of the chain or we're asked to stop here unwind_loop:
// by the caller then exit /* Get the exception registration and try level */
test %ebx, %ebx mov eax, [esp+36]
je .lu2_done mov ebx, [eax+8]
mov esi, [eax+12]
movl ER_TRYLEVEL(%ebx), %eax /* Validate the unwind */
cmpl $-1, %eax cmp esi, -1
je .lu2_done je unwind_return
cmp dword ptr [esp+40], -1
je unwind_ok
cmp esi, [esp+40]
jbe unwind_return
cmpl LU2_TRYLEVEL(%edx), %eax unwind_ok:
je .lu2_done /* Get the new enclosing level and save it */
lea esi, [esi+esi*2]
mov ecx, [ebx+esi*4]
mov [esp+8], ecx
mov [eax+12], ecx
// Keep a pointer to the scopetable in ESI /* Check the filter type */
movl ER_SCOPETABLE(%ebx), %esi cmp dword ptr [ebx+esi*4+4], 0
jnz __NLG_Return2
// Compute the offset of the entry in the scopetable that describes /* FIXME: NLG Notification */
// 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 /* Call the handler */
cmpl $0, ST_FILTER(%edi) call dword ptr [ebx+esi*4+8]
jne .lu2_next_scope
// Save the previous try-level in the exception registration structure __NLG_Return2:
movl ST_TRYLEVEL(%edi), %eax /* Unwind again */
movl %eax, ER_TRYLEVEL(%ebx) jmp unwind_loop
// Fetch the address of the termination handler unwind_return:
movl ST_HANDLER(%edi), %eax /* Cleanup SEH */
pop fs:0
// Termination handlers may trash all registers so save the add esp, 16
// important ones and then call the handler pop edi
pushl %edx pop esi
call *%eax pop ebx
// 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 ret
.endfunc
#define EH3_DISPCONTEXT 0x14 .func _except_handler2
#define EH3_CONTEXT 0x10 __except_handler2:
#define EH3_REGFRAME 0x0C
#define EH3_ERECORD 0x08
// Parameters: /* Setup stack and save volatiles */
// [ESP+14h] - PVOID DispatcherContext push ebp
// [ESP+10h] - PCONTEXT Context mov ebp, esp
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame sub esp, 8
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord push ebx
// Registers: push esi
// Unknown push edi
// Returns: push ebp
// 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 /* Clear direction flag */
cld cld
// Either we're called to handle an exception or we're called to unwind /* Get exception registration and record */
movl EH3_ERECORD(%ebp), %eax mov ebx, [ebp+12]
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax) mov eax, [ebp+8]
jnz .eh3_unwind
// Keep a pointer to the exception registration in EBX /* Check if this is an unwind */
movl EH3_REGFRAME(%ebp), %ebx test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
jnz except_unwind2
// Build an EXCEPTION_POINTERS structure on the stack and store it's /* Save exception pointers structure */
// address in the EXCEPTION_REGISTRATION structure mov [ebp-8], eax
movl EH3_CONTEXT(%esp), %eax mov eax, [ebp+16]
pushl %ebx // Registration frame mov [ebp-4], eax
pushl %eax // Context lea eax, [ebp-8]
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack mov [ebx+20], eax
// Keep current try-level in EDI /* Get the try level and scope table */
movl ER_TRYLEVEL(%ebx), %edi mov esi, [ebx+12]
mov edi, [ebx+8]
// Keep a pointer to the scopetable in ESI except_loop2:
movl ER_SCOPETABLE(%ebx), %esi /* Validate try level */
cmp esi, -1
je except_search2
.eh3_next_scope: /* Check if this is the termination handler */
lea ecx, [esi+esi*2]
cmp dword ptr [edi+ecx*4+4], 0
jz except_continue2
// If we have reached the end of the chain then exit /* Save registers and call filter, then restore them */
cmpl $-1, %edi push esi
je .eh3_search push ebp
mov ebp, [ebx+16]
call dword ptr [edi+ecx*4+4]
pop ebp
pop esi
// Compute the offset of the entry in the scopetable and store /* Restore ebx and check the result */
// the absolute address in EAX mov ebx, [ebp+12]
lea (%edi, %edi, 2), %eax or eax, eax
shll $2, %eax jz except_continue2
addl %esi, %eax js except_dismiss2
// Fetch the address of the filter routine /* So this is an accept, call the termination handlers */
movl ST_FILTER(%eax), %eax mov edi, [ebx+8]
push ebx
// 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 call __global_unwind2
popl %eax // Remove parameter to __global_unwind2 add esp, 4
popl %ebx // Restore registration frame address
popl %edi // Restore stop try-level
// Change the context structure so _except_finish is called in the /* Restore ebp */
// correct context since we return ExceptionContinueExecution. mov ebp, [ebx+16]
movl EH3_CONTEXT(%ebp), %eax
movl %edi, CONTEXT_EDI(%eax) // Stop try-level /* Do local unwind */
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address push esi
movl $_except_finish, CONTEXT_EIP(%eax) push ebx
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:
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 call __local_unwind2
addl $8, %esp add esp, 8
// Restore some important registers /* Set new try level */
popl %ebp lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4]
mov [ebx+12], eax
movl $ExceptionContinueSearch, %eax /* Call except handler */
call [edi+ecx*4+8]
// Get me out of here except_continue2:
.eh3_return: /* Reload try level and except again */
mov edi, [ebx+8]
lea ecx, [esi+esi*2]
mov esi, [edi+ecx*4]
jmp except_loop2
movl %ebp, %esp except_dismiss2:
popl %ebp /* Dismiss it */
ret mov eax, DISPOSITION_DISMISS
jmp except_return2
// Parameters: except_search2:
// None /* Continue searching */
// Registers: mov eax, DISPOSITION_CONTINUE_SEARCH
// EBX - Pointer to exception registration structure jmp except_return2
// EDI - Stop try-level
// Returns:
// -
// Notes:
// -
_except_finish:
// Setup EBP for the exception handler. By doing this the exception /* Do local unwind */
// handler can access local variables as normal except_unwind2:
lea ER_EBP(%ebx), %ebp push ebp
mov ebp, [ebx+16]
// Save some important registers push -1
pushl %ebp push ebx
pushl %ebx
pushl %edi
// Stop try-level
pushl %edi
// Pointer to exception registration structure
pushl %ebx
call __local_unwind2 call __local_unwind2
addl $8, %esp add esp, 8
// Restore some important registers /* Retore EBP and set return disposition */
popl %edi pop ebp
popl %ebx mov eax, DISPOSITION_CONTINUE_SEARCH
popl %ebp
// Keep a pointer to the scopetable in ESI except_return2:
movl ER_SCOPETABLE(%ebx), %esi /* Restore registers and stack */
pop ebp
// Compute the offset of the entry in the scopetable and store pop edi
// the absolute address in EDI pop esi
lea (%edi, %edi, 2), %edi pop ebx
shll $2, %edi mov esp, ebp
addl %esi, %edi pop ebp
// 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 ret
.endfunc
.func _except_handler3
__except_handler3:
/* Setup stack and save volatiles */
push ebp
mov ebp, esp
sub esp, 8
push ebx
push esi
push edi
push ebp
/* Clear direction flag */
cld
/* Get exception registration and record */
mov ebx, [ebp+12]
mov eax, [ebp+8]
/* Check if this is an unwind */
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
jnz except_unwind3
/* Save exception pointers structure */
mov [ebp-8], eax
mov eax, [ebp+16]
mov [ebp-4], eax
lea eax, [ebp-8]
mov [ebx-4], eax
/* Get the try level and scope table */
mov esi, [ebx+12]
mov edi, [ebx+8]
/* FIXME: Validate the SEH exception */
except_loop3:
/* Validate try level */
cmp esi, -1
je except_search3
/* Check if this is the termination handler */
lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4+4]
or eax, eax
jz except_continue3
/* Save registers clear them all */
push esi
push ebp
lea ebp, [ebx+16]
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
/* Call the filter and restore our registers */
call eax
pop ebp
pop esi
/* Restore ebx and check the result */
mov ebx, [ebp+12]
or eax, eax
jz except_continue3
js except_dismiss3
/* So this is an accept, call the termination handlers */
mov edi, [ebx+8]
push ebx
call __global_unwind2
add esp, 4
/* Restore ebp */
lea ebp, [ebx+16]
/* Do local unwind */
push esi
push ebx
call __local_unwind2
add esp, 8
/* FIXME: Do NLG Notification */
/* Set new try level */
lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4]
mov [ebx+12], eax
/* Clear registers and call except handler */
mov eax, [edi+ecx*4+8]
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
call eax
except_continue3:
/* Reload try level and except again */
mov edi, [ebx+8]
lea ecx, [esi+esi*2]
mov esi, [edi+ecx*4]
jmp except_loop3
except_dismiss3:
/* Dismiss it */
mov eax, DISPOSITION_DISMISS
jmp except_return3
except_search3:
/* Continue searching */
mov eax, DISPOSITION_CONTINUE_SEARCH
jmp except_return3
/* Do local unwind */
except_unwind3:
push ebp
mov ebp, [ebx+16]
push -1
push ebx
call __local_unwind2
add esp, 8
/* Retore EBP and set return disposition */
pop ebp
mov eax, DISPOSITION_CONTINUE_SEARCH
except_return3:
/* Restore registers and stack */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
.endfunc
//
//
// REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME
//
//
.func RtlpGetStackLimits@8
.globl _RtlpGetStackLimits@8
_RtlpGetStackLimits@8:
/* Get the current thread */
mov eax, [fs:KPCR_CURRENT_THREAD]
/* Get the stack limits */
mov ecx, [eax+KTHREAD_STACK_LIMIT]
mov edx, [eax+KTHREAD_INITIAL_STACK]
sub edx, SIZEOF_FX_SAVE_AREA
/* Return them */
mov eax, [esp+4]
mov [eax], ecx
mov eax, [esp+8]
mov [eax], edx
/* return */
ret 8
.endfunc

View file

@ -6,22 +6,6 @@
#include <ndk/extypes.h> #include <ndk/extypes.h>
#include <ndk/rtlfuncs.h> #include <ndk/rtlfuncs.h>
/*
* @implemented
*/
void __cdecl
_global_unwind2(PEXCEPTION_REGISTRATION_RECORD RegistrationFrame)
{
#ifdef __GNUC__
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
__ret_label:
// return is important
return;
#else
#endif
}
/* VC++ extensions to Win32 SEH */ /* VC++ extensions to Win32 SEH */
typedef struct _SCOPETABLE typedef struct _SCOPETABLE
{ {

View file

@ -1,468 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CRT
* FILE: lib/crt/misc/i386/seh.S
* PURPOSE: SEH Support for the CRT
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ndk/asm.h>
.intel_syntax noprefix
#define DISPOSITION_DISMISS 0
#define DISPOSITION_CONTINUE_SEARCH 1
#define DISPOSITION_COLLIDED_UNWIND 3
/* GLOBALS *******************************************************************/
.globl __global_unwind2
.globl __local_unwind2
.globl __abnormal_termination
.globl __except_handler2
.globl __except_handler3
/* FUNCTIONS *****************************************************************/
.func unwind_handler
_unwind_handler:
/* Check if we were unwinding and continue search if not */
mov ecx, [esp+4]
test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
mov eax, DISPOSITION_CONTINUE_SEARCH
jz unwind_handler_return
/* We have a collision, do a local unwind */
mov eax, [esp+20]
push ebp
mov ebp, [eax+16]
mov edx, [eax+40]
push edx
mov edx, [eax+36]
push edx
call __local_unwind2
add esp, 8
pop ebp
/* Set new try level */
mov eax, [esp+8]
mov edx, [esp+16]
mov [edx], eax
/* Return collided unwind */
mov eax, DISPOSITION_COLLIDED_UNWIND
unwind_handler_return:
ret
.endfunc
.func _global_unwind2
__global_unwind2:
/* Create stack and save all registers */
push ebp
mov ebp, esp
push ebx
push esi
push edi
push ebp
/* Call unwind */
push 0
push 0
push glu_return
push [ebp+8]
call _RtlUnwind@16
glu_return:
/* Restore registers and return */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
.endfunc
.func _abnormal_termination
__abnormal_termination:
/* Assume false */
xor eax, eax
/* Check if the handler is the unwind handler */
mov ecx, fs:0
cmp dword ptr [ecx+4], offset _unwind_handler
jne short ab_return
/* Get the try level */
mov edx, [ecx+12]
mov edx, [edx+12]
/* Compare it */
cmp [ecx+8], edx
jne ab_return
/* Return true */
mov eax, 1
/* Return */
ab_return:
ret
.endfunc
.func _local_unwind2
__local_unwind2:
/* Save volatiles */
push ebx
push esi
push edi
/* Get the exception registration */
mov eax, [esp+16]
/* Setup SEH to protect the unwind */
push ebp
push eax
push -2
push offset _unwind_handler
push fs:0
mov fs:0, esp
unwind_loop:
/* Get the exception registration and try level */
mov eax, [esp+36]
mov ebx, [eax+8]
mov esi, [eax+12]
/* Validate the unwind */
cmp esi, -1
je unwind_return
cmp dword ptr [esp+40], -1
je unwind_ok
cmp esi, [esp+40]
jbe unwind_return
unwind_ok:
/* Get the new enclosing level and save it */
lea esi, [esi+esi*2]
mov ecx, [ebx+esi*4]
mov [esp+8], ecx
mov [eax+12], ecx
/* Check the filter type */
cmp dword ptr [ebx+esi*4+4], 0
jnz __NLG_Return2
/* FIXME: NLG Notification */
/* Call the handler */
call dword ptr [ebx+esi*4+8]
__NLG_Return2:
/* Unwind again */
jmp unwind_loop
unwind_return:
/* Cleanup SEH */
pop fs:0
add esp, 16
pop edi
pop esi
pop ebx
ret
.endfunc
.func _except_handler2
__except_handler2:
/* Setup stack and save volatiles */
push ebp
mov ebp, esp
sub esp, 8
push ebx
push esi
push edi
push ebp
/* Clear direction flag */
cld
/* Get exception registration and record */
mov ebx, [ebp+12]
mov eax, [ebp+8]
/* Check if this is an unwind */
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
jnz except_unwind2
/* Save exception pointers structure */
mov [ebp-8], eax
mov eax, [ebp+16]
mov [ebp-4], eax
lea eax, [ebp-8]
mov [ebx+20], eax
/* Get the try level and scope table */
mov esi, [ebx+12]
mov edi, [ebx+8]
except_loop2:
/* Validate try level */
cmp esi, -1
je except_search2
/* Check if this is the termination handler */
lea ecx, [esi+esi*2]
cmp dword ptr [edi+ecx*4+4], 0
jz except_continue2
/* Save registers and call filter, then restore them */
push esi
push ebp
mov ebp, [ebx+16]
call dword ptr [edi+ecx*4+4]
pop ebp
pop esi
/* Restore ebx and check the result */
mov ebx, [ebp+12]
or eax, eax
jz except_continue2
js except_dismiss2
/* So this is an accept, call the termination handlers */
mov edi, [ebx+8]
push ebx
call __global_unwind2
add esp, 4
/* Restore ebp */
mov ebp, [ebx+16]
/* Do local unwind */
push esi
push ebx
call __local_unwind2
add esp, 8
/* Set new try level */
lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4]
mov [ebx+12], eax
/* Call except handler */
call [edi+ecx*4+8]
except_continue2:
/* Reload try level and except again */
mov edi, [ebx+8]
lea ecx, [esi+esi*2]
mov esi, [edi+ecx*4]
jmp except_loop2
except_dismiss2:
/* Dismiss it */
mov eax, DISPOSITION_DISMISS
jmp except_return2
except_search2:
/* Continue searching */
mov eax, DISPOSITION_CONTINUE_SEARCH
jmp except_return2
/* Do local unwind */
except_unwind2:
push ebp
mov ebp, [ebx+16]
push -1
push ebx
call __local_unwind2
add esp, 8
/* Retore EBP and set return disposition */
pop ebp
mov eax, DISPOSITION_CONTINUE_SEARCH
except_return2:
/* Restore registers and stack */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
.endfunc
.func _except_handler3
__except_handler3:
/* Setup stack and save volatiles */
push ebp
mov ebp, esp
sub esp, 8
push ebx
push esi
push edi
push ebp
/* Clear direction flag */
cld
/* Get exception registration and record */
mov ebx, [ebp+12]
mov eax, [ebp+8]
/* Check if this is an unwind */
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
jnz except_unwind3
/* Save exception pointers structure */
mov [ebp-8], eax
mov eax, [ebp+16]
mov [ebp-4], eax
lea eax, [ebp-8]
mov [ebx-4], eax
/* Get the try level and scope table */
mov esi, [ebx+12]
mov edi, [ebx+8]
/* FIXME: Validate the SEH exception */
except_loop3:
/* Validate try level */
cmp esi, -1
je except_search3
/* Check if this is the termination handler */
lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4+4]
or eax, eax
jz except_continue3
/* Save registers clear them all */
push esi
push ebp
lea ebp, [ebx+16]
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
/* Call the filter and restore our registers */
call eax
pop ebp
pop esi
/* Restore ebx and check the result */
mov ebx, [ebp+12]
or eax, eax
jz except_continue3
js except_dismiss3
/* So this is an accept, call the termination handlers */
mov edi, [ebx+8]
push ebx
call __global_unwind2
add esp, 4
/* Restore ebp */
lea ebp, [ebx+16]
/* Do local unwind */
push esi
push ebx
call __local_unwind2
add esp, 8
/* FIXME: Do NLG Notification */
/* Set new try level */
lea ecx, [esi+esi*2]
mov eax, [edi+ecx*4]
mov [ebx+12], eax
/* Clear registers and call except handler */
mov eax, [edi+ecx*4+8]
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
call eax
except_continue3:
/* Reload try level and except again */
mov edi, [ebx+8]
lea ecx, [esi+esi*2]
mov esi, [edi+ecx*4]
jmp except_loop3
except_dismiss3:
/* Dismiss it */
mov eax, DISPOSITION_DISMISS
jmp except_return3
except_search3:
/* Continue searching */
mov eax, DISPOSITION_CONTINUE_SEARCH
jmp except_return3
/* Do local unwind */
except_unwind3:
push ebp
mov ebp, [ebx+16]
push -1
push ebx
call __local_unwind2
add esp, 8
/* Retore EBP and set return disposition */
pop ebp
mov eax, DISPOSITION_CONTINUE_SEARCH
except_return3:
/* Restore registers and stack */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
.endfunc
//
//
// REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME
//
//
.func RtlpGetStackLimits@8
.globl _RtlpGetStackLimits@8
_RtlpGetStackLimits@8:
/* Get the current thread */
mov eax, [fs:KPCR_CURRENT_THREAD]
/* Get the stack limits */
mov ecx, [eax+KTHREAD_STACK_LIMIT]
mov edx, [eax+KTHREAD_INITIAL_STACK]
sub edx, SIZEOF_FX_SAVE_AREA
/* Return them */
mov eax, [esp+4]
mov [eax], ecx
mov eax, [esp+8]
mov [eax], edx
/* return */
ret 8
.endfunc

View file

@ -13,7 +13,7 @@
<define name="__MINGW_IMPORT">"extern __attribute__ ((dllexport))"</define> <define name="__MINGW_IMPORT">"extern __attribute__ ((dllexport))"</define>
</if> </if>
<directory name="except_nt"> <directory name="except">
<if property="ARCH" value="i386"> <if property="ARCH" value="i386">
<directory name="i386"> <directory name="i386">
<file>chkstk_asm.s</file> <file>chkstk_asm.s</file>

View file

@ -119,6 +119,8 @@ kernel32 -
msvcrt - msvcrt -
reactos/dll/win32/msvcrt/wine/*.c # Out of sync reactos/dll/win32/msvcrt/wine/*.c # Out of sync
reactos/lib/sdk/crt/except # Synced at XXXXXXXX
reactos/lib/sdk/crt/wine # Synced at XXXXXXXX
User32 - User32 -
reactos/dll/win32/user32/controls/button.c # Synced at 20071022 reactos/dll/win32/user32/controls/button.c # Synced at 20071022