modified include/reactos/libs/pseh/pseh2.h

modified   lib/pseh/framebased-gcchack.c
modified   lib/pseh/i386/framebased-gcchack.S
   Don't save just ESP and EBP, save all volatile registers because we might catch an exception thrown by another frame and end up clobbering all volatile registers (thanks to Dmitry Gorbachev for bug report and test case)
   Conversely, save volatile registers for _SEH2_EXCEPT scopes only
   Specialized frame setup routines, to reduce the amount of inline code and only de-optimize when strictly necessary

svn path=/trunk/; revision=38668
This commit is contained in:
KJK::Hyperion 2009-01-09 16:36:21 +00:00
parent 92d6cc1154
commit d728ecb2ca
3 changed files with 124 additions and 61 deletions

View file

@ -56,17 +56,28 @@ typedef struct __SEH2TryLevel
volatile struct __SEH2TryLevel * ST_Next;
void * ST_Filter;
void * ST_Body;
void * volatile ST_Ebp;
void * volatile ST_Esp;
}
_SEH2TryLevel_t;
typedef struct __SEH2HandleTryLevel
{
_SEH2TryLevel_t SHT_Common;
void * volatile SHT_Esp;
void * volatile SHT_Ebp;
void * volatile SHT_Ebx;
void * volatile SHT_Esi;
void * volatile SHT_Edi;
}
_SEH2HandleTryLevel_t;
#ifdef __cplusplus
extern "C"
{
#endif
extern __attribute__((returns_twice)) void __cdecl _SEH2EnterFrame(_SEH2Frame_t *);
extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
extern void __cdecl _SEH2LeaveFrame(void);
extern void __cdecl _SEH2Return(void);
@ -174,8 +185,25 @@ void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
__SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
}
#define __SEH_ENTER_TRYLEVEL() __SEH_SET_TRYLEVEL(&_SEHTryLevel)
#define __SEH_LEAVE_TRYLEVEL() __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP)
#define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
#define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
#define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
#define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
#define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
#define __SEH_ENTER_HANDLE_SCOPE(TRYLEVEL_, HANDLE_) (({ __SEH_BARRIER; __asm__ __volatile__("mov %%esp, %0" : "=m" ((TRYLEVEL_)->SHT_Esp)); __SEH_BARRIER; }), (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_)) : __SEH_ENTER_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_))))
#define __SEH_LEAVE_SCOPE() \
if(_SEHTopTryLevel) \
{ \
_SEH2LeaveFrame(); \
__asm__ __volatile__("mov %0, %%esp" : : "g" (_SEHStackPointer)); \
} \
else \
{ \
__SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
} \
#define __SEH_END_SCOPE_CHAIN \
static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
@ -200,27 +228,23 @@ void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
__label__ _SEHAfterTry; \
static const int _SEH2ScopeKind = 0; \
volatile _SEH2TryLevel_t _SEHTryLevel; \
volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
void * _SEHStackPointer; \
volatile _SEH2TryLevel_t * const _SEH2TryLevelP = &_SEHTryLevel; \
volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
_SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
({ __asm__ __volatile__("mov %%esp, %0" : "=g" (_SEHStackPointer)); __builtin_alloca(sizeof(_SEH2Frame_t)); }) : \
_SEHCurFrameP; \
\
(void)_SEH2ScopeKind; \
(void)_SEHTryLevel; \
(void)_SEHHandleTryLevel; \
(void)_SEHStackPointer; \
(void)_SEH2FrameP; \
(void)_SEH2TryLevelP; \
\
if(_SEHTopTryLevel) \
_SEH2EnterFrame(_SEH2FrameP); \
\
_SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
goto _SEHBeforeTry; \
\
_SEHDoTry:; \
\
__SEH_ENTER_TRYLEVEL();
_SEHDoTry:;
#define __SEH_END_SCOPE \
} \
@ -254,6 +278,9 @@ void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
\
_SEHTryLevel.ST_Filter = 0; \
_SEHTryLevel.ST_Body = &_SEHFinally; \
_SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
__SEH_ENTER_SCOPE(&_SEHTryLevel); \
_SEH2TryLevelP = &_SEHTryLevel; \
\
_SEHAbnormalTermination = 1; \
\
@ -262,12 +289,7 @@ void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
\
_SEHAbnormalTermination = 0; \
\
if(_SEHTopTryLevel) \
_SEH2LeaveFrame(); \
else \
{ \
__SEH_LEAVE_TRYLEVEL(); \
} \
__SEH_LEAVE_SCOPE(); \
\
_SEHFinally(); \
goto _SEHEndExcept; \
@ -296,64 +318,51 @@ void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
{ \
__attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
\
if(__builtin_constant_p((__VA_ARGS__))) \
if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
{ \
if((__VA_ARGS__) > 0) \
{ \
_SEHTryLevel.ST_Filter = (void *)1; \
_SEHTryLevel.ST_Body = &&_SEHBeginExcept; \
__SEH_USE_LABEL(_SEHBeginExcept); \
} \
else if((__VA_ARGS__) < 0) \
if((__VA_ARGS__) < 0) \
{ \
_SEHTryLevel.ST_Filter = (void *)-1; \
_SEHTryLevel.ST_Body = NULL; \
_SEHTryLevel.ST_Body = 0; \
} \
else \
{ \
_SEHTryLevel.ST_Filter = (void *)0; \
_SEHTryLevel.ST_Body = NULL; \
_SEHTryLevel.ST_Body = 0; \
} \
\
_SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
__SEH_ENTER_SCOPE(&_SEHTryLevel); \
_SEH2TryLevelP = &_SEHTryLevel; \
} \
else \
{ \
__SEH_DEFINE_EXCEPT(_SEHExcept) \
if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
_SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
else \
{ \
__SEH_RETURN_EXCEPT((__VA_ARGS__)); \
__SEH_DEFINE_EXCEPT(_SEHExcept) \
{ \
__SEH_RETURN_EXCEPT((__VA_ARGS__)); \
} \
\
_SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
} \
\
_SEHTryLevel.ST_Filter = &_SEHExcept; \
_SEHTryLevel.ST_Body = &&_SEHBeginExcept; \
__SEH_USE_LABEL(_SEHBeginExcept); \
_SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
_SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
\
if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
goto _SEHBeginExcept; \
} \
} \
\
__SEH_BARRIER; \
\
__asm__ __volatile__ \
( \
"mov %%ebp, %0\n" \
"mov %%esp, %1" : \
"=m" (_SEHTryLevel.ST_Ebp), \
"=m" (_SEHTryLevel.ST_Esp) \
); \
\
__SEH_BARRIER; \
\
goto _SEHDoTry; \
\
__attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
\
_SEHAfterTry:; \
if(_SEHTopTryLevel) \
{ \
_SEH2LeaveFrame(); \
__asm__ __volatile__("mov %0, %%esp" : : "g" (_SEHStackPointer)); \
} \
else \
{ \
__SEH_LEAVE_TRYLEVEL(); \
} \
__SEH_LEAVE_SCOPE(); \
\
goto _SEHEndExcept; \
\

View file

@ -38,7 +38,7 @@
#define EXCEPTION_UNWINDING 2
#endif
extern DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *);
extern DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *, void *, void *, void *);
extern int __cdecl __SEH2FrameHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
extern int __cdecl __SEH2UnwindHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
@ -188,9 +188,20 @@ void _SEH2LocalUnwind(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * dsttrylev
static DECLSPEC_NORETURN
void _SEH2Handle(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
{
volatile _SEH2HandleTryLevel_t * fulltrylevel = CONTAINING_RECORD(trylevel, _SEH2HandleTryLevel_t, SHT_Common);
_SEH2GlobalUnwind(frame);
_SEH2LocalUnwind(frame, trylevel);
__SEH2Handle(trylevel->ST_Body, trylevel->ST_Ebp, trylevel->ST_Esp);
_SEH2LocalUnwind(frame, &fulltrylevel->SHT_Common);
__SEH2Handle
(
fulltrylevel->SHT_Common.ST_Body,
fulltrylevel->SHT_Esp,
fulltrylevel->SHT_Ebp,
fulltrylevel->SHT_Ebx,
fulltrylevel->SHT_Esi,
fulltrylevel->SHT_Edi
);
}
extern
@ -241,11 +252,18 @@ extern
void __cdecl _SEH2EnterFrame(_SEH2Frame_t * frame)
{
frame->SF_Registration.SER_Handler = __SEH2FrameHandler;
frame->SF_TopTryLevel = 0;
frame->SF_Code = 0;
__SEH2EnterFrame(&frame->SF_Registration);
}
extern
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
{
frame->SF_TopTryLevel = trylevel;
_SEH2EnterFrame(frame);
return 0;
}
extern
void __cdecl _SEH2LeaveFrame(void)
{

View file

@ -21,12 +21,48 @@
.text
.intel_syntax noprefix
.func _SEH2EnterHandleTrylevel
.globl __SEH2EnterHandleTrylevel
__SEH2EnterHandleTrylevel:
mov eax, [esp+8]
mov ecx, [esp+12]
mov [eax+8], ecx
mov [eax+16], ebp
mov [eax+20], ebx
mov [eax+24], esi
mov [eax+28], edi
mov edx, [esp+4]
mov [edx+8], eax
xor eax, eax
ret
.endfunc
.func _SEH2EnterFrameAndHandleTrylevel
.globl __SEH2EnterFrameAndHandleTrylevel
__SEH2EnterFrameAndHandleTrylevel:
mov eax, [esp+8]
mov ecx, [esp+12]
mov [eax+8], ecx
mov [eax+16], ebp
mov [eax+20], ebx
mov [eax+24], esi
mov [eax+28], edi
.extern __SEH2EnterFrameAndTrylevel
jmp __SEH2EnterFrameAndTrylevel
.endfunc
.func __SEH2Handle
.globl ___SEH2Handle
___SEH2Handle:
mov eax, [esp+4]
mov ebp, [esp+8]
mov esp, [esp+12]
mov ebp, [esp+12]
mov ebx, [esp+16]
mov esi, [esp+20]
mov edi, [esp+24]
mov esp, [esp+8]
jmp eax
.endfunc