mirror of
https://github.com/reactos/reactos.git
synced 2024-08-11 13:48:01 +00:00
[PSEH3]
- Add AllocaFrame field to the exception registration record. It is required for Clang and C++ handlers. - Fix the way how "nested functions" are emulated on Clang and C++, respecting the fact that the compiler can and will use a temporary esp-based stack frame below any alloca-allocations for function invocation. This uses the AllocaFrame field to calculate and setup a new temp stack frame for the "nested functions". - Make use of the HandlerType field in the exception registration record to use different methods for invoking filters / finally functions. - Write @_SEH3$_CallRtlUnwind@4 in raw asm instead of inline, because Clang cannot deal with stdcall decorations in inline asm (see http://llvm.org/bugs/show_bug.cgi?id=19027) - Make sure ExceptionPointers are properly initialized in _SEH3$_except_handler svn path=/trunk/; revision=62466
This commit is contained in:
parent
1ff93cb52e
commit
7165a7c35b
|
@ -67,6 +67,8 @@ typedef struct _SEH3$_REGISTRATION_FRAME
|
||||||
/* Registers that we need to save */
|
/* Registers that we need to save */
|
||||||
unsigned long Esp;
|
unsigned long Esp;
|
||||||
unsigned long Ebp;
|
unsigned long Ebp;
|
||||||
|
|
||||||
|
char* AllocaFrame;
|
||||||
#ifdef _SEH3$_FRAME_ALL_NONVOLATILES
|
#ifdef _SEH3$_FRAME_ALL_NONVOLATILES
|
||||||
unsigned long Ebx;
|
unsigned long Ebx;
|
||||||
unsigned long Esi;
|
unsigned long Esi;
|
||||||
|
@ -101,10 +103,12 @@ enum
|
||||||
_SEH3$_TryLevel = 0,
|
_SEH3$_TryLevel = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef __clang__
|
||||||
/* These are global dummy definitions, that get overwritten in the local context of __finally / __except blocks */
|
/* These are global dummy definitions, that get overwritten in the local context of __finally / __except blocks */
|
||||||
int __cdecl __attribute__((error ("Can only be used inside a __finally block."))) _abnormal_termination(void);
|
int __cdecl __attribute__((error ("Can only be used inside a __finally block."))) _abnormal_termination(void);
|
||||||
unsigned long __cdecl __attribute__((error("Can only be used inside an exception filter or __except block."))) _exception_code(void);
|
unsigned long __cdecl __attribute__((error("Can only be used inside an exception filter or __except block."))) _exception_code(void);
|
||||||
void * __cdecl __attribute__((error("Can only be used inside an exception filter."))) _exception_info(void);
|
void * __cdecl __attribute__((error("Can only be used inside an exception filter."))) _exception_info(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This attribute allows automatic cleanup of the registered frames */
|
/* This attribute allows automatic cleanup of the registered frames */
|
||||||
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_Unregister)))
|
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_Unregister)))
|
||||||
|
@ -119,15 +123,16 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
|
||||||
#define _SEH3$_ASM_GOTO(_Label, ...)
|
#define _SEH3$_ASM_GOTO(_Label, ...)
|
||||||
|
|
||||||
int
|
int
|
||||||
__attribute__((regparm(2)))
|
__attribute__((regparm(3)))
|
||||||
__attribute__((returns_twice))
|
__attribute__((returns_twice))
|
||||||
_SEH3$_RegisterFrameWithNonVolatiles(
|
_SEH3$_RegisterFrameWithNonVolatiles(
|
||||||
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
||||||
const SEH3$_SCOPE_TABLE* ScopeTable);
|
const SEH3$_SCOPE_TABLE* ScopeTable,
|
||||||
|
void* AllocaFrame);
|
||||||
|
|
||||||
#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
|
#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
|
||||||
do { \
|
do { \
|
||||||
int result = _SEH3$_RegisterFrameWithNonVolatiles(_TrylevelFrame, _DataTable); \
|
int result = _SEH3$_RegisterFrameWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
|
||||||
if (__builtin_expect(result != 0, 0)) \
|
if (__builtin_expect(result != 0, 0)) \
|
||||||
{ \
|
{ \
|
||||||
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
||||||
|
@ -137,15 +142,16 @@ _SEH3$_RegisterFrameWithNonVolatiles(
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
int
|
int
|
||||||
__attribute__((regparm(2)))
|
__attribute__((regparm(3)))
|
||||||
__attribute__((returns_twice))
|
__attribute__((returns_twice))
|
||||||
_SEH3$_RegisterTryLevelWithNonVolatiles(
|
_SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
||||||
const SEH3$_SCOPE_TABLE* ScopeTable);
|
const SEH3$_SCOPE_TABLE* ScopeTable,
|
||||||
|
void* AllocaFrame);
|
||||||
|
|
||||||
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
||||||
do { \
|
do { \
|
||||||
int result = _SEH3$_RegisterTryLevelWithNonVolatiles(_TrylevelFrame, _DataTable); \
|
int result = _SEH3$_RegisterTryLevelWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
|
||||||
if (__builtin_expect(result != 0, 0)) \
|
if (__builtin_expect(result != 0, 0)) \
|
||||||
{ \
|
{ \
|
||||||
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
||||||
|
@ -163,25 +169,34 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
|
|
||||||
#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
|
#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
|
||||||
|
|
||||||
/* This is an asm wrapper around _SEH3$_RegisterFrame */
|
#ifdef __cplusplus
|
||||||
#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
|
#define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
|
||||||
asm goto ("leal %0, %%eax\n" \
|
asm goto ("leal %0, %%eax\n" \
|
||||||
"leal %1, %%edx\n" \
|
"leal %1, %%edx\n" \
|
||||||
"call __SEH3$_RegisterFrame\n" \
|
"call " #_Function "WithStackLayout\n" \
|
||||||
|
: \
|
||||||
|
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c"(__builtin_alloca(0)) \
|
||||||
|
: "eax", "edx", "memory" \
|
||||||
|
: _SEH3$_l_HandlerTarget, _SEH3$_l_FilterOrFinally)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
|
||||||
|
asm goto ("leal %0, %%eax\n" \
|
||||||
|
"leal %1, %%edx\n" \
|
||||||
|
"call " #_Function "\n" \
|
||||||
: \
|
: \
|
||||||
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \
|
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \
|
||||||
: "ecx", "edx", "memory" \
|
: "eax", "edx", "ecx", "memory" \
|
||||||
: _SEH3$_l_HandlerTarget)
|
: _SEH3$_l_HandlerTarget)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This is an asm wrapper around _SEH3$_RegisterFrame */
|
||||||
|
#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
|
||||||
|
_SEH3$_CALL_WRAPPER(__SEH3$_RegisterFrame, _TrylevelFrame, _DataTable)
|
||||||
|
|
||||||
/* This is an asm wrapper around _SEH3$_RegisterTryLevel */
|
/* This is an asm wrapper around _SEH3$_RegisterTryLevel */
|
||||||
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
||||||
asm goto ("leal %0, %%eax\n" \
|
_SEH3$_CALL_WRAPPER(__SEH3$_RegisterTryLevel, _TrylevelFrame, _DataTable)
|
||||||
"leal %1, %%edx\n" \
|
|
||||||
"call __SEH3$_RegisterTryLevel\n" \
|
|
||||||
: \
|
|
||||||
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \
|
|
||||||
: "ecx", "edx", "memory" \
|
|
||||||
: _SEH3$_l_HandlerTarget)
|
|
||||||
|
|
||||||
/* This construct scares GCC so much, that it will stop moving code
|
/* This construct scares GCC so much, that it will stop moving code
|
||||||
around into places that are never executed. */
|
around into places that are never executed. */
|
||||||
|
@ -214,15 +229,17 @@ _SEH3$_Unregister(
|
||||||
/* The "nested" functions are a piece of code with a ret instruction at the end */
|
/* The "nested" functions are a piece of code with a ret instruction at the end */
|
||||||
#define _SEH3$_NESTED_FUNC_OPEN() \
|
#define _SEH3$_NESTED_FUNC_OPEN() \
|
||||||
{ \
|
{ \
|
||||||
int SavedEsp, result = 0; \
|
int _SEH3$_Result = 0; \
|
||||||
\
|
|
||||||
/* Save esp */ \
|
/* On invocation, the AllocaFrame field is loaded with the return esp value */
|
||||||
asm volatile ("movl %%esp, %[SavedEsp]\n" : : [SavedEsp]"m"(SavedEsp));
|
#define _SEH3$_NESTED_FUNC_RETURN() \
|
||||||
|
/* Restore esp and return to the caller */ \
|
||||||
|
asm volatile ("movl %[FixedEsp], %%esp\nret\n" \
|
||||||
|
: : "a"(_SEH3$_Result), [FixedEsp]"m"(_SEH3$_TrylevelFrame.AllocaFrame) : "memory")
|
||||||
|
|
||||||
#define _SEH3$_NESTED_FUNC_CLOSE() \
|
#define _SEH3$_NESTED_FUNC_CLOSE() \
|
||||||
/* Restore esp and return to the caller */ \
|
/* Return to the caller */ \
|
||||||
asm volatile ("movl %[SavedEsp], %%esp\nret\n" \
|
_SEH3$_NESTED_FUNC_RETURN(); \
|
||||||
: : "a"(result), [SavedEsp]"irm"(SavedEsp)); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The filter function */
|
/* The filter function */
|
||||||
|
@ -230,7 +247,7 @@ _SEH3$_Unregister(
|
||||||
_SEH3$_NESTED_FUNC_OPEN() \
|
_SEH3$_NESTED_FUNC_OPEN() \
|
||||||
{ \
|
{ \
|
||||||
/* Evaluate the filter expression */ \
|
/* Evaluate the filter expression */ \
|
||||||
result = (expression); \
|
_SEH3$_Result = (expression); \
|
||||||
} \
|
} \
|
||||||
_SEH3$_NESTED_FUNC_CLOSE()
|
_SEH3$_NESTED_FUNC_CLOSE()
|
||||||
|
|
||||||
|
@ -238,11 +255,10 @@ _SEH3$_Unregister(
|
||||||
_SEH3$_NESTED_FUNC_OPEN() \
|
_SEH3$_NESTED_FUNC_OPEN() \
|
||||||
/* This construct makes sure that the finally function returns */ \
|
/* This construct makes sure that the finally function returns */ \
|
||||||
/* a proper value at the end */ \
|
/* a proper value at the end */ \
|
||||||
for (; ; (void)({asm volatile ("movl %[SavedEsp], %%esp\nret\n" \
|
for (; ; (void)({_SEH3$_NESTED_FUNC_RETURN(); 0;}))
|
||||||
: : "a"(result), [SavedEsp]"irm"(SavedEsp)); 0;}))
|
|
||||||
|
|
||||||
#define _SEH3$_FILTER(_Filter, _FilterExpression) (&&_SEH3$_l_FilterOrFinally)
|
#define _SEH3$_FILTER(_Filter, _FilterExpression) (&&_SEH3$_l_FilterOrFinally)
|
||||||
#define _SEH3$_FINALLY(_Finally) 0
|
#define _SEH3$_FINALLY(_Finally) (&&_SEH3$_l_FilterOrFinally)
|
||||||
|
|
||||||
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS()
|
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS()
|
||||||
|
|
||||||
|
@ -336,6 +352,7 @@ _SEH3$_Unregister(
|
||||||
__label__ _SEH3$_l_OnException; \
|
__label__ _SEH3$_l_OnException; \
|
||||||
__label__ _SEH3$_l_BeforeFilterOrFinally; \
|
__label__ _SEH3$_l_BeforeFilterOrFinally; \
|
||||||
__label__ _SEH3$_l_FilterOrFinally; \
|
__label__ _SEH3$_l_FilterOrFinally; \
|
||||||
|
(void)&&_SEH3$_l_OnException; \
|
||||||
(void)&&_SEH3$_l_BeforeFilterOrFinally; \
|
(void)&&_SEH3$_l_BeforeFilterOrFinally; \
|
||||||
(void)&&_SEH3$_l_FilterOrFinally; \
|
(void)&&_SEH3$_l_FilterOrFinally; \
|
||||||
\
|
\
|
||||||
|
@ -419,7 +436,7 @@ _SEH3$_Unregister(
|
||||||
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \
|
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \
|
||||||
\
|
\
|
||||||
/* Create a static data table that contains the finally function */ \
|
/* Create a static data table that contains the finally function */ \
|
||||||
static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { 0, _SEH3$_FINALLY(&_SEH3$_FinallyFunction) }; \
|
static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { 0, _SEH3$_FINALLY(&_SEH3$_FinallyFunction), _SEH3$_TryLevel, _SEH3$_HANDLER_TYPE }; \
|
||||||
\
|
\
|
||||||
/* Register the registration record. */ \
|
/* Register the registration record. */ \
|
||||||
if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
||||||
|
@ -431,6 +448,7 @@ _SEH3$_Unregister(
|
||||||
_SEH3$_EnforceFramePointer(); \
|
_SEH3$_EnforceFramePointer(); \
|
||||||
\
|
\
|
||||||
_SEH3$_l_BeforeFilterOrFinally: (void)0; \
|
_SEH3$_l_BeforeFilterOrFinally: (void)0; \
|
||||||
|
_SEH3$_EnforceFramePointer(); \
|
||||||
_SEH3$_l_FilterOrFinally: (void)0; \
|
_SEH3$_l_FilterOrFinally: (void)0; \
|
||||||
_SEH3$_FINALLY_FUNC_OPEN(_SEH3$_FinallyFunction)
|
_SEH3$_FINALLY_FUNC_OPEN(_SEH3$_FinallyFunction)
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ _SEH3$_Unregister(
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
LONG
|
LONG
|
||||||
_SEH3$_InvokeFilter(
|
_SEH3$_InvokeNestedFunctionFilter(
|
||||||
PVOID Record,
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame,
|
||||||
PVOID Filter)
|
PVOID Filter)
|
||||||
{
|
{
|
||||||
LONG FilterResult;
|
LONG FilterResult;
|
||||||
|
@ -78,18 +78,58 @@ _SEH3$_InvokeFilter(
|
||||||
/* The result is the frame base address that we passed in (0) plus the
|
/* The result is the frame base address that we passed in (0) plus the
|
||||||
offset to the registration record. */
|
offset to the registration record. */
|
||||||
"negl %%eax\n\t"
|
"negl %%eax\n\t"
|
||||||
"addl %[Record], %%eax\n\t"
|
"addl %[RegistrationFrame], %%eax\n\t"
|
||||||
|
|
||||||
/* Second call to get the filter result */
|
/* Second call to get the filter result */
|
||||||
"mov $1, %%ecx\n\t"
|
"mov $1, %%ecx\n\t"
|
||||||
"call *%[Filter]\n\t"
|
"call *%[Filter]\n\t"
|
||||||
: "=a"(FilterResult)
|
: "=a"(FilterResult)
|
||||||
: [Record] "m" (Record), [Filter] "m" (Filter)
|
: [RegistrationFrame] "m" (RegistrationFrame), [Filter] "m" (Filter)
|
||||||
: "ecx", "edx");
|
: "ecx", "edx");
|
||||||
|
|
||||||
return FilterResult;
|
return FilterResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
__attribute__((regparm(1)))
|
||||||
|
_SEH3$_InvokeEmbeddedFilter(
|
||||||
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame);
|
||||||
|
|
||||||
|
long
|
||||||
|
__attribute__((regparm(1)))
|
||||||
|
_SEH3$_InvokeEmbeddedFilterFromRegistration(
|
||||||
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame);
|
||||||
|
|
||||||
|
static inline
|
||||||
|
LONG
|
||||||
|
_SEH3$_InvokeFilter(
|
||||||
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame,
|
||||||
|
PVOID Filter)
|
||||||
|
{
|
||||||
|
LONG FilterResult;
|
||||||
|
|
||||||
|
if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_NESTED_HANDLER)
|
||||||
|
{
|
||||||
|
return _SEH3$_InvokeNestedFunctionFilter(RegistrationFrame, Filter);
|
||||||
|
}
|
||||||
|
else if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CPP_HANDLER)
|
||||||
|
{
|
||||||
|
/* Call the embedded filter function */
|
||||||
|
return _SEH3$_InvokeEmbeddedFilter(RegistrationFrame);
|
||||||
|
}
|
||||||
|
else if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CLANG_HANDLER)
|
||||||
|
{
|
||||||
|
return _SEH3$_InvokeEmbeddedFilterFromRegistration(RegistrationFrame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Should not happen! Skip this handler */
|
||||||
|
FilterResult = EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FilterResult;
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
LONG
|
LONG
|
||||||
_SEH3$_GetFilterResult(
|
_SEH3$_GetFilterResult(
|
||||||
|
@ -136,45 +176,51 @@ void
|
||||||
_SEH3$_JumpToTarget(
|
_SEH3$_JumpToTarget(
|
||||||
PSEH3$_REGISTRATION_FRAME RegistrationFrame)
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame)
|
||||||
{
|
{
|
||||||
asm volatile (
|
if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CLANG_HANDLER)
|
||||||
/* Load the registers */
|
{
|
||||||
"movl 20(%%ecx), %%esp\n"
|
asm volatile (
|
||||||
"movl 24(%%ecx), %%ebp\n"
|
/* Load the registers */
|
||||||
|
"movl 20(%%ecx), %%esp\n"
|
||||||
|
"movl 24(%%ecx), %%ebp\n"
|
||||||
|
|
||||||
/* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
|
/* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
|
||||||
"addl $4, %%esp\n"
|
"addl $4, %%esp\n"
|
||||||
|
|
||||||
/* Jump into the exception handler */
|
/* Jump into the exception handler */
|
||||||
"jmp *%[Target]\n"
|
"jmp *%[Target]\n"
|
||||||
: :
|
: :
|
||||||
"c" (RegistrationFrame),
|
"c" (RegistrationFrame),
|
||||||
"a" (RegistrationFrame->ScopeTable),
|
"a" (RegistrationFrame->ScopeTable),
|
||||||
[Target] "m" (RegistrationFrame->ScopeTable->Target)
|
[Target] "m" (RegistrationFrame->ScopeTable->Target)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asm volatile (
|
||||||
|
/* Load the registers */
|
||||||
|
"movl 20(%%ecx), %%esp\n"
|
||||||
|
"movl 24(%%ecx), %%ebp\n"
|
||||||
|
|
||||||
|
/* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
|
||||||
|
"addl $4, %%esp\n"
|
||||||
|
|
||||||
|
/* Jump into the exception handler */
|
||||||
|
"jmp *%[Target]\n"
|
||||||
|
: :
|
||||||
|
"c" (RegistrationFrame),
|
||||||
|
"a" (RegistrationFrame->ScopeTable),
|
||||||
|
[Target] "m" (RegistrationFrame->ScopeTable->Target)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
|
||||||
void
|
void
|
||||||
|
__fastcall
|
||||||
_SEH3$_CallRtlUnwind(
|
_SEH3$_CallRtlUnwind(
|
||||||
PSEH3$_REGISTRATION_FRAME RegistrationFrame)
|
PSEH3$_REGISTRATION_FRAME RegistrationFrame);
|
||||||
{
|
|
||||||
LONG ClobberedEax;
|
|
||||||
|
|
||||||
asm volatile(
|
|
||||||
"push %%ebp\n"
|
|
||||||
"push $0\n"
|
|
||||||
"push $0\n"
|
|
||||||
"push $0\n"
|
|
||||||
"push %[TargetFrame]\n"
|
|
||||||
"call _RtlUnwind@16\n"
|
|
||||||
"pop %%ebp\n"
|
|
||||||
: "=a" (ClobberedEax)
|
|
||||||
: [TargetFrame] "a" (RegistrationFrame)
|
|
||||||
: "ebx", "ecx", "edx", "esi",
|
|
||||||
"edi", "flags", "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION
|
EXCEPTION_DISPOSITION
|
||||||
__cdecl
|
__cdecl
|
||||||
|
@ -192,6 +238,10 @@ _SEH3$_except_handler(
|
||||||
/* Clear the direction flag. */
|
/* Clear the direction flag. */
|
||||||
asm volatile ("cld\n" : : : "memory");
|
asm volatile ("cld\n" : : : "memory");
|
||||||
|
|
||||||
|
/* Save the exception pointers on the stack */
|
||||||
|
ExceptionPointers.ExceptionRecord = ExceptionRecord;
|
||||||
|
ExceptionPointers.ContextRecord = ContextRecord;
|
||||||
|
|
||||||
/* Check if this is an unwind */
|
/* Check if this is an unwind */
|
||||||
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
|
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
|
||||||
{
|
{
|
||||||
|
@ -200,10 +250,6 @@ _SEH3$_except_handler(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Save the exception pointers on the stack */
|
|
||||||
ExceptionPointers.ExceptionRecord = ExceptionRecord;
|
|
||||||
ExceptionPointers.ContextRecord = ContextRecord;
|
|
||||||
|
|
||||||
/* Loop all frames for this registration */
|
/* Loop all frames for this registration */
|
||||||
CurrentFrame = EstablisherFrame->EndOfChain;
|
CurrentFrame = EstablisherFrame->EndOfChain;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
#define SEH3_REGISTRATION_FRAME_ExceptionPointers 16
|
#define SEH3_REGISTRATION_FRAME_ExceptionPointers 16
|
||||||
#define SEH3_REGISTRATION_FRAME_Esp 20
|
#define SEH3_REGISTRATION_FRAME_Esp 20
|
||||||
#define SEH3_REGISTRATION_FRAME_Ebp 24
|
#define SEH3_REGISTRATION_FRAME_Ebp 24
|
||||||
#define SEH3_REGISTRATION_FRAME_Ebx 28
|
#define SEH3_REGISTRATION_FRAME_AllocaFrame 28
|
||||||
#define SEH3_REGISTRATION_FRAME_Esi 32
|
#define SEH3_REGISTRATION_FRAME_Ebx 32
|
||||||
#define SEH3_REGISTRATION_FRAME_Edi 36
|
#define SEH3_REGISTRATION_FRAME_Esi 36
|
||||||
|
#define SEH3_REGISTRATION_FRAME_Edi 40
|
||||||
|
|
||||||
#define SEH3_SCOPE_TABLE_Target 0
|
#define SEH3_SCOPE_TABLE_Target 0
|
||||||
#define SEH3_SCOPE_TABLE_Filter 4
|
#define SEH3_SCOPE_TABLE_Filter 4
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void
|
* void
|
||||||
* __attribute__((regparm(2)))
|
* __attribute__((regparm(3)))
|
||||||
* __attribute__((returns_twice))
|
* __attribute__((returns_twice))
|
||||||
* _SEH3$_RegisterFrame[WithNonVolatiles](
|
* _SEH3$_RegisterFrame[WithNonVolatiles](
|
||||||
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
|
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
|
||||||
* PSEH3$_SCOPE_TABLE ScopeTable<edx>);
|
* PSEH3$_SCOPE_TABLE ScopeTable<edx>,
|
||||||
|
* PVOID AllocaFrame);
|
||||||
*/
|
*/
|
||||||
.global __SEH3$_RegisterFrameWithNonVolatiles
|
.global __SEH3$_RegisterFrameWithNonVolatiles
|
||||||
__SEH3$_RegisterFrameWithNonVolatiles:
|
__SEH3$_RegisterFrameWithNonVolatiles:
|
||||||
|
@ -29,6 +30,12 @@ __SEH3$_RegisterFrameWithNonVolatiles:
|
||||||
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
||||||
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
||||||
|
|
||||||
|
.global __SEH3$_RegisterFrameWithStackLayout
|
||||||
|
__SEH3$_RegisterFrameWithStackLayout:
|
||||||
|
|
||||||
|
/* Save the pointer to the alloca frame */
|
||||||
|
mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
|
||||||
|
|
||||||
.global __SEH3$_RegisterFrame
|
.global __SEH3$_RegisterFrame
|
||||||
__SEH3$_RegisterFrame:
|
__SEH3$_RegisterFrame:
|
||||||
|
|
||||||
|
@ -57,11 +64,12 @@ __SEH3$_RegisterFrame:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void
|
* void
|
||||||
* __attribute__((regparm(2)))
|
* __attribute__((regparm(3)))
|
||||||
* __attribute__((returns_twice))
|
* __attribute__((returns_twice))
|
||||||
* _SEH3$_RegisterTryLevel[WithNonVolatiles](
|
* _SEH3$_RegisterTryLevel[WithNonVolatiles](
|
||||||
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<edx>,
|
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<edx>,
|
||||||
* PSEH3$_SCOPE_TABLE ScopeTable<eax>);
|
* PSEH3$_SCOPE_TABLE ScopeTable<eax>,
|
||||||
|
* PVOID AllocaFrame);
|
||||||
*/
|
*/
|
||||||
.global __SEH3$_RegisterTryLevelWithNonVolatiles
|
.global __SEH3$_RegisterTryLevelWithNonVolatiles
|
||||||
__SEH3$_RegisterTryLevelWithNonVolatiles:
|
__SEH3$_RegisterTryLevelWithNonVolatiles:
|
||||||
|
@ -71,6 +79,12 @@ __SEH3$_RegisterTryLevelWithNonVolatiles:
|
||||||
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
||||||
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
||||||
|
|
||||||
|
.global __SEH3$_RegisterTryLevelWithStackLayout
|
||||||
|
__SEH3$_RegisterTryLevelWithStackLayout:
|
||||||
|
|
||||||
|
/* Save the pointer to the alloca frame */
|
||||||
|
mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
|
||||||
|
|
||||||
.global __SEH3$_RegisterTryLevel
|
.global __SEH3$_RegisterTryLevel
|
||||||
__SEH3$_RegisterTryLevel:
|
__SEH3$_RegisterTryLevel:
|
||||||
|
|
||||||
|
@ -98,3 +112,105 @@ __SEH3$_RegisterTryLevel:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global __SEH3$_InvokeEmbeddedFilterFromRegistration
|
||||||
|
__SEH3$_InvokeEmbeddedFilterFromRegistration:
|
||||||
|
|
||||||
|
/* Safe the current non-volatiles */
|
||||||
|
push ebp
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
/* Load the non-volatiles from the registration invocation */
|
||||||
|
mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
|
||||||
|
mov esi, [eax + SEH3_REGISTRATION_FRAME_Esi]
|
||||||
|
mov edi, [eax + SEH3_REGISTRATION_FRAME_Edi]
|
||||||
|
mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
|
||||||
|
|
||||||
|
/* Get the saved stack pointer */
|
||||||
|
mov edx, [eax + SEH3_REGISTRATION_FRAME_Esp]
|
||||||
|
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
call [edx]
|
||||||
|
|
||||||
|
/* Restore the current non-volatiles */
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global __SEH3$_InvokeEmbeddedFilter
|
||||||
|
__SEH3$_InvokeEmbeddedFilter:
|
||||||
|
|
||||||
|
/* Safe the current non-volatiles */
|
||||||
|
push ebp
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
/* Load ebp from the registration invocation */
|
||||||
|
mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
|
||||||
|
|
||||||
|
/* Calculate the size of the temp stack frame region */
|
||||||
|
mov ecx, [eax + SEH3_REGISTRATION_FRAME_AllocaFrame]
|
||||||
|
sub ecx, [eax + SEH3_REGISTRATION_FRAME_Esp]
|
||||||
|
|
||||||
|
/* Put the return address on the stack */
|
||||||
|
push offset __SEH3$_InvokeEmbeddedFilterReturn
|
||||||
|
|
||||||
|
/* Save the current stack pointer in the AllocaFrame member */
|
||||||
|
mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], esp
|
||||||
|
|
||||||
|
/* Allocate enough temp stack space on the stack */
|
||||||
|
sub esp, ecx
|
||||||
|
|
||||||
|
/* Get the scope table */
|
||||||
|
mov edx, [eax + SEH3_REGISTRATION_FRAME_ScopeTable]
|
||||||
|
|
||||||
|
/* Jump into the filter or finally function */
|
||||||
|
jmp [edx + SEH3_SCOPE_TABLE_Filter]
|
||||||
|
|
||||||
|
/* We return to this label with a cleaned up stack */
|
||||||
|
__SEH3$_InvokeEmbeddedFilterReturn:
|
||||||
|
|
||||||
|
/* Restore the current non-volatiles */
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void
|
||||||
|
* __fastcall
|
||||||
|
* _SEH3$_CallRtlUnwind(
|
||||||
|
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<ecx>)
|
||||||
|
*/
|
||||||
|
.global @_SEH3$_CallRtlUnwind@4
|
||||||
|
@_SEH3$_CallRtlUnwind@4:
|
||||||
|
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
push 0 /* ReturnValue */
|
||||||
|
push 0 /* ExceptionRecord */
|
||||||
|
push 0 /* TargetIp */
|
||||||
|
push ecx /* TargetFrame */
|
||||||
|
call _RtlUnwind@16
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue