分类: WINDOWS
2009-12-18 11:01:30
Igor Skochinsky (igorsk) |
Monday, March 6 2006 12:02.38 CST |
...
Local variables
Other saved registers
Saved ebp
Return address
Function arguments
...
struct _SCOPETABLE_ENTRY {
DWORD EnclosingLevel;
void* FilterFunc;
void* HandlerFunc;
}
struct _EH4_SCOPETABLE {
DWORD GSCookieOffset;
DWORD GSCookieXOROffset;
DWORD EHCookieOffset;
DWORD EHCookieXOROffset;
_EH4_SCOPETABLE_RECORD ScopeRecord[1];
};
struct _EH4_SCOPETABLE_RECORD {
DWORD EnclosingLevel;
long (*FilterFunc)();
union {
void (*HandlerAddress)();
void (*FinallyFunc)();
};
};
(VC7+)
mov eax, OFFSET __ehfuncinfo
jmp ___CxxFrameHandler
struct FuncInfo {
// compiler version.
// 0x19930520: up to VC6, 0x19930521: VC7.x(2002-2003), 0x19930522: VC8 (2005)
DWORD magicNumber;
// number of entries in unwind table
int maxState;
// table of unwind destructors
UnwindMapEntry* pUnwindMap;
// number of try blocks in the function
DWORD nTryBlocks;
// mapping of catch blocks to try blocks
TryBlockMapEntry* pTryBlockMap;
// not used on x86
DWORD nIPMapEntries;
// not used on x86
void* pIPtoStateMap;
// VC7+ only, expected exceptions list (function "throw" specifier)
ESTypeList* pESTypeList;
// VC8+ only, bit 0 set if function was compiled with /EHs
int EHFlags;
};
struct UnwindMapEntry {
int toState; // target state
void (*action)(); // action to perform (unwind funclet address)
};
struct TryBlockMapEntry {
int tryLow;
int tryHigh; // this try {} covers states ranging from tryLow to tryHigh
int catchHigh; // highest state inside catch handlers of this try
int nCatches; // number of catch handlers
HandlerType* pHandlerArray; //catch handlers table
};
struct HandlerType {
// 0x01: const, 0x02: volatile, 0x08: reference
DWORD adjectives;
// RTTI descriptor of the exception type. 0=any (ellipsis)
TypeDescriptor* pType;
// ebp-based offset of the exception object in the function stack.
// 0 = no object (catch by type)
int dispCatchObj;
// address of the catch handler code.
// returns address where to continues execution (i.e. code after the try block)
void* addressOfHandler;
};
struct ESTypeList {
// number of entries in the list
int nCount;
// list of exceptions; it seems only pType field in HandlerType is used
HandlerType* pTypeArray;
};
struct TypeDescriptor {
// vtable of type_info class
const void * pVFTable;
// used to keep the demangled name returned by type_info::name()
void* spare;
// mangled type name, e.g. ".H" = "int", ".?AUA@@" = "struct A", ".?AVA@@" = "class A"
char name[0];
};
struct ThrowInfo {
// 0x01: const, 0x02: volatile
DWORD attributes;
// exception destructor
void (*pmfnUnwind)();
// forward compatibility handler
int (*pForwardCompat)();
// list of types that can catch this exception.
// i.e. the actual type and all its ancestors.
CatchableTypeArray* pCatchableTypeArray;
};
struct CatchableTypeArray {
// number of entries in the following array
int nCatchableTypes;
CatchableType* arrayOfCatchableTypes[0];
};
struct CatchableType {
// 0x01: simple type (can be copied by memmove), 0x02: can be caught by reference only, 0x04: has virtual bases
DWORD properties;
// see above
TypeDescriptor* pType;
// how to cast the thrown object to this type
PMD thisDisplacement;
// object size
int sizeOrOffset;
// copy constructor address
void (*copyFunction)();
};
// Pointer-to-member descriptor.
struct PMD {
// member offset
int mdisp;
// offset of the vbtable (-1 if not a virtual base)
int pdisp;
// offset to the displacement value inside the vbtable
int vdisp;
};
Name | Type | EH Cookie | GS Cookie | Catch Handlers |
_SEH_prolog/_SEH_epilog | SEH3 | - | - | |
_SEH_prolog4/_SEH_epilog4 S | EH4 | + | - | |
_SEH_prolog4_GS/_SEH_epilog4_GS | SEH4 | + | + | |
_EH_prolog | C++ EH | - | - | +/- |
_EH_prolog3/_EH_epilog3 | C++ EH | + | - | - |
_EH_prolog3_catch/_EH_epilog3 | C++ EH | + | - | + |
_EH_prolog3_GS/_EH_epilog3_GS | C++ EH | + | + | - |
_EH_prolog3_catch_GS/_EH_epilog3_catch_GS | C++ EH | + | + | + |
...
Saved edi
Saved esi
Saved ebx
Next SEH frame
Current SEH handler (__except_handler2)
Pointer to the scopetable
Try level
Saved ebp (of this function)
Exception pointers
Local variables
Saved ESP
Local variables
Callee EBP
Return address
Function arguments
...
func1 proc near
_excCode = dword ptr -28h
buf = byte ptr -24h
_saved_esp = dword ptr -18h
_exception_info = dword ptr -14h
_next = dword ptr -10h
_handler = dword ptr -0Ch
_scopetable = dword ptr -8
_trylevel = dword ptr -4
str = dword ptr 8
push ebp
mov ebp, esp
push -1
push offset _func1_scopetable
push offset _except_handler3
mov eax, large fs:0
push eax
mov large fs:0, esp
add esp, -18h
push ebx
push esi
push edi
; --- end of prolog ---
mov [ebp+_trylevel], 0 ;trylevel -1 -> 0: beginning of try block 0
mov [ebp+_trylevel], 1 ;trylevel 0 -> 1: beginning of try block 1
mov large dword ptr ds:123, 456
mov [ebp+_trylevel], 0 ;trylevel 1 -> 0: end of try block 1
jmp short _endoftry1
_func1_filter1: ; __except() filter of try block 1
mov ecx, [ebp+_exception_info]
mov edx, [ecx+EXCEPTION_POINTERS.ExceptionRecord]
mov eax, [edx+EXCEPTION_RECORD.ExceptionCode]
mov [ebp+_excCode], eax
mov ecx, [ebp+_excCode]
xor eax, eax
cmp ecx, EXCEPTION_ACCESS_VIOLATION
setz al
retn
_func1_handler1: ; beginning of handler for try block 1
mov esp, [ebp+_saved_esp]
push offset aAccessViolatio ; "Access violation"
call _printf
add esp, 4
mov [ebp+_trylevel], 0 ;trylevel 1 -> 0: end of try block 1
_endoftry1:
mov edx, [ebp+str]
push edx
lea eax, [ebp+buf]
push eax
call _strcpy
add esp, 8
mov [ebp+_trylevel], -1 ; trylevel 0 -> -1: end of try block 0
call _func1_handler0 ; execute __finally of try block 0
jmp short _endoftry0
_func1_handler0: ; __finally handler of try block 0
push offset aInFinally ; "in finally"
call _puts
add esp, 4
retn
_endoftry0:
; --- epilog ---
mov ecx, [ebp+_next]
mov large fs:0, ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
retn
func1 endp
_func1_scopetable
;try block 0
dd -1 ;EnclosingLevel
dd 0 ;FilterFunc
dd offset _func1_handler0 ;HandlerFunc
;try block 1
dd 0 ;EnclosingLevel
dd offset _func1_filter1 ;FilterFunc
dd offset _func1_handler1 ;HandlerFunc
void func1 (char* str)
{
char buf[12];
__try // try block 0
{
__try // try block 1
{
*(int*)123=456;
}
__except(GetExceptCode() == EXCEPTION_ACCESS_VIOLATION)
{
printf("Access violation");
}
strcpy(buf,str);
}
__finally
{
puts("in finally");
}
}
func1 proc near
_a1 = dword ptr -24h
_exc = dword ptr -20h
e = dword ptr -1Ch
a2 = dword ptr -18h
a1 = dword ptr -14h
_saved_esp = dword ptr -10h
_next = dword ptr -0Ch
_handler = dword ptr -8
_state = dword ptr -4
push ebp
mov ebp, esp
push 0FFFFFFFFh
push offset func1_ehhandler
mov eax, large fs:0
push eax
mov large fs:0, esp
push ecx
sub esp, 14h
push ebx
push esi
push edi
mov [ebp+_saved_esp], esp
; --- end of prolog ---
lea ecx, [ebp+a1]
call A::A(void)
mov [ebp+_state], 0 ; state -1 -> 0: a1 constructed
mov [ebp+a1], 1 ; a1.m1 = 1
mov byte ptr [ebp+_state], 1 ; state 0 -> 1: try {
lea ecx, [ebp+a2]
call A::A(void)
mov [ebp+_a1], eax
mov byte ptr [ebp+_state], 2 ; state 2: a2 constructed
mov [ebp+a2], 2 ; a2.m1 = 2
mov eax, [ebp+a1]
cmp eax, [ebp+a2] ; a1.m1 == a2.m1?
jnz short loc_40109F
mov [ebp+_exc], offset aAbc ; _exc = "abc"
push offset __TI1?PAD ; char *
lea ecx, [ebp+_exc]
push ecx
call _CxxThrowException ; throw "abc";
loc_40109F:
mov byte ptr [ebp+_state], 1 ; state 2 -> 1: destruct a2
lea ecx, [ebp+a2]
call A::~A(void)
jmp short func1_try0end
; catch (char * e)
func1_try0handler_pchar:
mov edx, [ebp+e]
push edx
push offset aCaughtS ; "Caught %s\n"
call ds:printf ;
add esp, 8
mov eax, offset func1_try0end
retn
; catch (...)
func1_try0handler_ellipsis:
push offset aCaught___ ; "Caught ...\n"
call ds:printf
add esp, 4
mov eax, offset func1_try0end
retn
func1_try0end:
mov [ebp+_state], 0 ; state 1 -> 0: }//try
push offset aAfterTry ; "after try\n"
call ds:printf
add esp, 4
mov [ebp+_state], -1 ; state 0 -> -1: destruct a1
lea ecx, [ebp+a1]
call A::~A(void)
; --- epilog ---
mov ecx, [ebp+_next]
mov large fs:0, ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
retn
func1 endp
func1_ehhandler proc near
mov eax, offset func1_funcinfo
jmp __CxxFrameHandler
func1_ehhandler endp
func1_funcinfo
dd 19930520h ; magicNumber
dd 4 ; maxState
dd offset func1_unwindmap ; pUnwindMap
dd 1 ; nTryBlocks
dd offset func1_trymap ; pTryBlockMap
dd 0 ; nIPMapEntries
dd 0 ; pIPtoStateMap
dd 0 ; pESTypeList
func1_unwindmap
dd -1
dd offset func1_unwind_1tobase ; action
dd 0 ; toState
dd 0 ; action
dd 1 ; toState
dd offset func1_unwind_2to1 ; action
dd 0 ; toState
dd 0 ; action
func1_trymap
dd 1 ; tryLow
dd 2 ; tryHigh
dd 3 ; catchHigh
dd 2 ; nCatches
dd offset func1_tryhandlers_0 ; pHandlerArray
dd 0
func1_tryhandlers_0
dd 0 ; adjectives
dd offset char * `RTTI Type Descriptor' ; pType
dd -1Ch ; dispCatchObj
dd offset func1_try0handler_pchar ; addressOfHandler
dd 0 ; adjectives
dd 0 ; pType
dd 0 ; dispCatchObj
dd offset func1_try0handler_ellipsis ; addressOfHandler
func1_unwind_1tobase proc near
a1 = byte ptr -14h
lea ecx, [ebp+a1]
call A::~A(void)
retn
func1_unwind_1tobase endp
func1_unwind_2to1 proc near
a2 = byte ptr -18h
lea ecx, [ebp+a2]
call A::~A(void)
retn
func1_unwind_2to1 endp
void func1 ()
{
A a1;
a1.m1 = 1;
try {
A a2;
a2.m1 = 2;
if (a1.m1 == a1.m2) throw "abc";
}
catch(char* e)
{
printf("Caught %s\n",e);
}
catch(...)
{
printf("Caught ...\n");
}
printf("after try\n");
}