windows-nt/Source/XPSP1/NT/base/crts/crtw32/eh/i386/ehprolg2.c
2020-09-26 16:20:57 +08:00

126 lines
3.5 KiB
C

/***
*ehprolg2.c - Defines _EH_prolog2 compiler helper
*
* Copyright (c) 1999-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* EH prologue helper function for an aligned stack.
*
*Revision History:
* 11-14-99 JB Module created
*
****/
/***
*void _EH_prolog2(alignment) - set up aligned stack with EH frame
*
*Purpose:
* Sets up an aligned frame for a C++ EH function with unwinds, by
* creating a link in the __except_list, setting EBX as the frame
* parameter pointer, and EBP as the frame base pointer.
*
*Entry:
* EAX = address of EH handler thunk
* Incoming stack frame has:
* [ESP + 8] = callee's return address
* [ESP + 4] = stack alignment requirement
* [ESP + 0] = _EH_prolog2's return address
*
*Exit:
* EAX = destroyed
* EBX = pointer to callee's parameters
* EBP = aligned pointer to callee's locals
* ESP = EBP - 12
* FS:[0] = set to EBP-8 to create new link in EH chain
* Stack frame has been set up as follows:
* [EBX + 4] = (entry [ESP+8]) callee's return address
* [EBX + 0] = saved EBX
* padding to align stack (if needed)
* [EBP + 4] = callee's return address (from [EBX+4])
* [EBP + 0] = saved EBP
* [EBP - 4] = EH record state index, initialized to -1
* [EBP - 8] = address of EH handler thunk
* [EBP - 12] = saved FS:[0]
*
*Exceptions:
*
*******************************************************************************/
#ifdef __cplusplus
extern "C"
#endif
void __declspec(naked) _EH_prolog2(void)
{
/*
* We want to generate a frame that is equivalent to
* push ebx
* ebx = esp
* sub esp, 8
* and esp, ~alignment
* add esp, 4
* push ebp
* ebp = esp
* mov [ebp+4], [ebx+4]
* [EH record]
*/
__asm {
; stack has:
; alignment
; ret addr <== esp
push ecx ; save ecx
; with ret addr == sub esp, 8
; stack has:
; alignment
; ret addr
; saved ecx <== esp
mov ecx, [esp+8] ; get alignment
mov [esp+8], ebx ; save ebx over alignment
lea ebx, [esp+8] ; set param pointer
; stack has:
; saved ebx <== ebx
; ret addr
; saved ecx <== esp
neg ecx ; create alignment mask
and esp, ecx ; align stack
mov ecx, [ebx-8] ; restore ecx since it will be in the same
; location we want to store ebp if no
; padding is inserted (esp is aligned at and)
mov [esp], ebp ; save ebp
mov ebp, esp ; initialize ebp
; stack has
; saved ebx <== ebx
; ret addr
; [padding]
; saved ebp <== ebp, esp
push -1 ; create EH record
push eax
mov eax,fs:[00000000]
push eax
mov dword ptr fs:[0],esp
push ecx ; we need this again
mov eax, [ebx-4] ; get helper return address
mov ecx, [ebx+4] ; copy orig function caller return address
mov [ebp+4], ecx ; (for ebp-based stack walks)
pop ecx ; we are done
push eax ; eax has return address
ret
}
}