126 lines
3.5 KiB
C
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
|
||
|
}
|
||
|
}
|