Implement ms compatible __SEH_prolog

svn path=/branches/cmake-bringup/; revision=50482
This commit is contained in:
Timo Kreuzer 2011-01-25 01:28:41 +00:00
parent d5fecffd28
commit 776c09f1fd
2 changed files with 133 additions and 12 deletions

View file

@ -279,15 +279,12 @@ list(APPEND CRT_SOURCE
wine/heap.c
wine/undname.c)
if(NOT ARCH MATCHES arm)
list(APPEND CRT_SOURCE
except/${ARCH}/seh.s)
endif()
if(ARCH MATCHES i386)
list(APPEND CRT_SOURCE
except/i386/chkstk_asm.s
except/i386/prolog.s
except/i386/seh.s
except/i386/seh_prolog.s
except/i386/unwind.c
float/i386/clearfp.c
float/i386/cntrlfp.c
@ -298,6 +295,7 @@ if(ARCH MATCHES i386)
elseif(ARCH MATCHES amd64)
list(APPEND CRT_SOURCE
except/amd64/chkstk_asm.s
except/amd64/seh.s
float/i386/clearfp.c
float/i386/cntrlfp.c
float/i386/fpreset.c
@ -470,15 +468,12 @@ list(APPEND LIBCNTPR_SOURCE
wstring/wcsspn.c
wstring/wcsstr.c)
if(NOT ARCH MATCHES arm)
list(APPEND LIBCNTPR_SOURCE
except/${ARCH}/chkstk_asm.s
except/${ARCH}/seh.s
setjmp/${ARCH}/setjmp.s)
endif()
if(ARCH MATCHES i386)
list(APPEND LIBCNTPR_SOURCE
except/i386/chkstk_asm.s
except/i386/seh.s
except/i386/seh_prolog.s
setjmp/i386/setjmp.s
math/i386/alldiv_asm.s
math/i386/alldvrm_asm.s
math/i386/allmul_asm.s
@ -505,6 +500,9 @@ if(ARCH MATCHES i386)
misc/i386/readcr4.S)
elseif(ARCH MATCHES amd64)
list(APPEND LIBCNTPR_SOURCE
except/amd64/chkstk_asm.s
except/amd64/seh.s
setjmp/amd64/setjmp.s
math/cos.c
math/sin.c
math/amd64/alldiv.S

View file

@ -0,0 +1,123 @@
/*
* COPYRIGHT: GNU GPL, see COPYING in the top level directory
* PROJECT: ReactOS CRT
* FILE: lib/crt/misc/i386/seh_prolog.S
* PURPOSE: SEH Support for MSVC
* PROGRAMMERS: Timo Kreuzer
*/
/* INCLUDES ******************************************************************/
#include <asm.inc>
EXTERN __except_handler3:PROC
/* The very first thing a function compiled with MSVC containing SEH
* will do is call __SEH_prolog like this:
*
* push <Number of stackbytes>
* push <Address of exception handler>
* call __SEH_prolog
*
* When entering the function the stack layout is like this:
*
* esp + 08: OLDFRAME.StackBytes
* esp + 04: OLDFRAME.SEHTable
* esp + 00: OLDFRAME.ReturnAddress
*
* __SEH_prolog will now setup the stack to the following layout:
*
* esp + N + 24: SEH_FRAME.OriginalEbp OLDFRAME.StackBytes
* esp + N + 20: SEH_FRAME.Disable OLDFRAME.SEHTable
* esp + N + 1C: SEH_FRAME.SEHTable OLDFRAME.ReturnAddress
* esp + N + 18: SEH_FRAME.Handler
* esp + N + 14: SEH_FRAME.PreviousRecord
* esp + N + 10: SEH_FRAME.unused
* esp + N + 0c: SEH_FRAME.NewEsp
*
* N bytes local variables
* ...
* esp + 08: SAFE_AREA.Ebx
* esp + 04: SAFE_AREA.Esi
* esp + 00: SAFE_AREA.Edi
*
* all this is documented here (with some minor errors):
* http://reactos-blog.blogspot.com/2009/08/inside-mind-of-reactos-developer.html
*/
OLDFRAME_ReturnAddress = 0 /* 0x00 */
OLDFRAME_SEHTable = 4 /* 0x04 */
OLDFRAME_StackBytes = 8 /* 0x08 */
OLDFRAME_Size = 12 /* 0x0c */
SEH_FRAME_NewEsp = 0 /* 0x00 */
SEH_FRAME_unused = 4 /* 0x04 */
SEH_FRAME_PreviousRecord = 8 /* 0x08 */
SEH_FRAME_Handler = 12 /* 0x0c */
SEH_FRAME_SEHTable = 16 /* 0x10 */
SEH_FRAME_Disable = 20 /* 0x14 */
SEH_FRAME_OriginalEbp = 24 /* 0x18 */
SEH_FRAME_Size = 28 /* 0x1c */
SAFE_AREA_Edi = 0 /* 0x00 */
SAFE_AREA_Esi = 4 /* 0x04 */
SAFE_AREA_Ebx = 8 /* 0x08 */
SAFE_AREA_Size = 12 /* 0x0c */
.code
PUBLIC __SEH_prolog
__SEH_prolog:
/* Get the number of stack bytes to reserve */
mov eax, [esp + OLDFRAME_StackBytes]
/* Push address of __except_handler3 on the stack */
push offset __except_handler3
/* Push the old exception record on the stack */
push dword ptr fs:0
/* Adjust stack allocation, add size of the stack frame minus 2 pushes */
add eax, SEH_FRAME_Size + SAFE_AREA_Size - OLDFRAME_Size - 8
/* Save old ebp, overwriting OLDFRAME.StackBytes */
mov [esp + 8 + OLDFRAME_StackBytes], ebp
/* Load new ebp, pointing to OLDFRAME.StackBytes */
lea ebp, [esp + 8 + OLDFRAME_StackBytes]
/* Allocate stack space */
sub esp, eax
/* Push the return address on the stack */
push dword ptr [ebp - OLDFRAME_StackBytes + OLDFRAME_ReturnAddress]
/* Get address of the SEH table */
mov eax, [ebp + OLDFRAME_SEHTable]
/* Save new esp */
mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_NewEsp], esp
/* Safe SEH table, overwriting OLDFRAME.ReturnAddress */
mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_SEHTable], eax
/* Save registers */
mov [esp + SAFE_AREA_Edi], edi
mov [esp + SAFE_AREA_Esi], esi
mov [esp + SAFE_AREA_Ebx], ebx
/* Load the address of the new registration record */
lea eax, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
/* Safe the disable value, overwriting OLDFRAME.SEHTable */
mov dword ptr [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_Disable], -1
/* Enqueue the new record */
mov fs:[0], eax
/* Return to the caller */
ret
END