mirror of
https://github.com/reactos/reactos.git
synced 2025-06-10 20:34:59 +00:00
[PSEH] Add implementation for GCC amd64
Also, put include directory next to the library and use target_include_directories(.. INTERFACE ..) to get this right. This is because : - Having includes & implementation in two different places buggers me - This makes sure that there is no "if it compiles everything is fine" behaviour from anyone because now even static libraries need it for GCC amd64 build Also add __USE_PSEH2__ define for the non SEH-aware compilers out there and use it in a few headers where we define macros involving __try
This commit is contained in:
parent
d31856cda1
commit
ba74a05a17
14 changed files with 230 additions and 50 deletions
|
@ -12,13 +12,15 @@ elseif(ARCH STREQUAL "arm")
|
|||
arm/seh_prolog.s)
|
||||
endif()
|
||||
|
||||
if(MSVC OR ARCH STREQUAL "amd64")
|
||||
|
||||
if(MSVC OR ((CMAKE_C_COMPILER_ID STREQUAL "Clang") AND (ARCH STREQUAL "amd64")))
|
||||
list(APPEND SOURCE dummy.c)
|
||||
add_asm_files(pseh_asm ${ASM_SOURCE})
|
||||
add_library(pseh ${SOURCE} ${pseh_asm})
|
||||
add_dependencies(pseh asm)
|
||||
|
||||
elseif((CMAKE_C_COMPILER_ID STREQUAL "GNU") AND (ARCH STREQUAL "amd64"))
|
||||
# for GCC amd64 this is just an interface library, with our home-made plugin
|
||||
add_library(pseh INTERFACE)
|
||||
target_compile_options(pseh INTERFACE -fplugin=$<TARGET_FILE:native-gcc_plugin_seh>)
|
||||
else()
|
||||
|
||||
if(USE_PSEH3)
|
||||
|
@ -43,4 +45,13 @@ else()
|
|||
target_link_libraries(pseh chkstk)
|
||||
add_dependencies(pseh psdk)
|
||||
|
||||
target_include_directories(pseh PRIVATE include/pseh)
|
||||
endif()
|
||||
|
||||
target_include_directories(pseh INTERFACE include)
|
||||
|
||||
# Make it clear that we are using PSEH2
|
||||
if ((CMAKE_C_COMPILER_ID STREQUAL "GNU") OR
|
||||
((CMAKE_C_COMPILER_ID STREQUAL "Clang") AND (NOT (ARCH STREQUAL "amd64"))))
|
||||
target_compile_definitions(pseh INTERFACE __USE_PSEH2__)
|
||||
endif()
|
||||
|
|
32
sdk/lib/pseh/include/pseh/excpt.h
Normal file
32
sdk/lib/pseh/include/pseh/excpt.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (c) 2004/2005 KJK::Hyperion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KJK_PSEH_EXCPT_H_
|
||||
#define KJK_PSEH_EXCPT_H_
|
||||
|
||||
#define _SEH_CONTINUE_EXECUTION (-1)
|
||||
#define _SEH_CONTINUE_SEARCH (0)
|
||||
#define _SEH_EXECUTE_HANDLER (1)
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
377
sdk/lib/pseh/include/pseh/framebased.h
Normal file
377
sdk/lib/pseh/include/pseh/framebased.h
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
Copyright (c) 2004/2005 KJK::Hyperion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KJK_PSEH_FRAMEBASED_H_
|
||||
#define KJK_PSEH_FRAMEBASED_H_
|
||||
|
||||
#if ((__GNUC__ > 4) && (__GNUC_MINOR__ > 1))
|
||||
/* warning: this will hide uninitialized variable warnings in the following code */
|
||||
# pragma GCC diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
|
||||
#include <pseh/framebased/internal.h>
|
||||
#include <pseh/excpt.h>
|
||||
|
||||
#ifndef offsetof
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(_SEH_NO_NATIVE_NLG)
|
||||
# error PSEH setjmp/longjmp fallback is no longer supported
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define _SEHLongJmp __builtin_longjmp
|
||||
# define _SEHSetJmp __builtin_setjmp
|
||||
typedef void * _SEHJmpBuf_t[5];
|
||||
#else
|
||||
# include <setjmp.h>
|
||||
# define _SEHLongJmp longjmp
|
||||
# define _SEHSetJmp setjmp
|
||||
# define _SEHJmpBuf_t jmp_buf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define _SEH_INIT_CONST static const
|
||||
#else
|
||||
# define _SEH_INIT_CONST register const
|
||||
#endif
|
||||
|
||||
typedef struct __SEHFrame
|
||||
{
|
||||
_SEHPortableFrame_t SEH_Header;
|
||||
void * volatile SEH_Locals;
|
||||
}
|
||||
_SEHFrame_t;
|
||||
|
||||
typedef struct __SEHTryLevel
|
||||
{
|
||||
_SEHPortableTryLevel_t ST_Header;
|
||||
_SEHJmpBuf_t ST_JmpBuf;
|
||||
}
|
||||
_SEHTryLevel_t;
|
||||
|
||||
static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler
|
||||
(
|
||||
_SEHPortableTryLevel_t * trylevel
|
||||
)
|
||||
{
|
||||
_SEHTryLevel_t * mytrylevel;
|
||||
mytrylevel = _SEH_CONTAINING_RECORD(trylevel, _SEHTryLevel_t, ST_Header);
|
||||
_SEHLongJmp(mytrylevel->ST_JmpBuf, 1);
|
||||
}
|
||||
|
||||
static const int _SEHScopeKind = 1;
|
||||
static _SEHPortableFrame_t * const _SEHPortableFrame = 0;
|
||||
static _SEHPortableTryLevel_t * const _SEHPortableTryLevel = 0;
|
||||
|
||||
/* SHARED LOCALS */
|
||||
/* Access the locals for the current frame */
|
||||
#define _SEH_ACCESS_LOCALS(LOCALS_) \
|
||||
_SEH_LOCALS_TYPENAME(LOCALS_) * _SEHPLocals; \
|
||||
_SEHPLocals = \
|
||||
_SEH_PVOID_CAST \
|
||||
( \
|
||||
_SEH_LOCALS_TYPENAME(LOCALS_) *, \
|
||||
_SEH_CONTAINING_RECORD(_SEHPortableFrame, _SEHFrame_t, SEH_Header) \
|
||||
->SEH_Locals \
|
||||
);
|
||||
|
||||
/* Access local variable VAR_ */
|
||||
#define _SEH_VAR(VAR_) _SEHPLocals->VAR_
|
||||
|
||||
/* FILTER FUNCTIONS */
|
||||
/* Declares a filter function's prototype */
|
||||
#define _SEH_FILTER(NAME_) \
|
||||
long __stdcall NAME_ \
|
||||
( \
|
||||
struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \
|
||||
struct __SEHPortableFrame * _SEHPortableFrame \
|
||||
)
|
||||
|
||||
/* Declares a static filter */
|
||||
#define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2))
|
||||
|
||||
/* Declares a PSEH filter wrapping a regular filter function */
|
||||
#define _SEH_WRAP_FILTER(WRAPPER_, NAME_) \
|
||||
static __inline _SEH_FILTER(WRAPPER_) \
|
||||
{ \
|
||||
return (NAME_)(_SEHExceptionPointers); \
|
||||
}
|
||||
|
||||
/* FINALLY FUNCTIONS */
|
||||
/* Declares a finally function's prototype */
|
||||
#define _SEH_FINALLYFUNC(NAME_) \
|
||||
void __stdcall NAME_ \
|
||||
( \
|
||||
struct __SEHPortableFrame * _SEHPortableFrame \
|
||||
)
|
||||
|
||||
/* Declares a PSEH finally function wrapping a regular function */
|
||||
#define _SEH_WRAP_FINALLY(WRAPPER_, NAME_) \
|
||||
_SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ())
|
||||
|
||||
#define _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ARGS_) \
|
||||
static __inline _SEH_FINALLYFUNC(WRAPPER_) \
|
||||
{ \
|
||||
NAME_ ARGS_; \
|
||||
}
|
||||
|
||||
#define _SEH_WRAP_FINALLY_LOCALS_ARGS(WRAPPER_, LOCALS_, NAME_, ARGS_) \
|
||||
static __inline _SEH_FINALLYFUNC(WRAPPER_) \
|
||||
{ \
|
||||
_SEH_ACCESS_LOCALS(LOCALS_); \
|
||||
NAME_ ARGS_; \
|
||||
}
|
||||
|
||||
/* SAFE BLOCKS */
|
||||
#ifdef __cplusplus
|
||||
# define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
|
||||
static const _SEHHandlers_t _SEHHandlers = { (FILTER_), (FINALLY_) };
|
||||
#else
|
||||
# define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
|
||||
_SEHHandlers_t _SEHHandlers = { (0), (0) }; \
|
||||
_SEHHandlers.SH_Filter = (FILTER_); \
|
||||
_SEHHandlers.SH_Finally = (FINALLY_);
|
||||
#endif
|
||||
|
||||
#define _SEH_SetExceptionCode(CODE_) (_SEHPortableFrame->SPF_Code = (CODE_))
|
||||
#define _SEH_GetExceptionCode() (unsigned long)(_SEHPortableFrame->SPF_Code)
|
||||
|
||||
#define _SEH_GetExceptionPointers() \
|
||||
((struct _EXCEPTION_POINTERS *)_SEHExceptionPointers)
|
||||
|
||||
#define _SEH_AbnormalTermination() (_SEHPortableFrame->SPF_Code != 0)
|
||||
|
||||
#define _SEH_LEAVE break
|
||||
|
||||
#define _SEH_YIELD(STMT_) \
|
||||
for(;;) \
|
||||
{ \
|
||||
if(!_SEHScopeKind) \
|
||||
_SEHReturn(); \
|
||||
\
|
||||
STMT_; \
|
||||
}
|
||||
|
||||
#ifdef _ARM_
|
||||
|
||||
#define _SEH_TRY \
|
||||
for(;;) \
|
||||
{ \
|
||||
\
|
||||
{ \
|
||||
\
|
||||
for(;;) \
|
||||
{ \
|
||||
if(1) \
|
||||
{ \
|
||||
for(;;) \
|
||||
{ \
|
||||
{
|
||||
|
||||
#define _SEH_EXCEPT(FILTER_) \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
if(0) \
|
||||
{
|
||||
|
||||
#define _SEH_FINALLY(FINALLY_) \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
(FINALLY_)(&_SEHFrame.SEH_Header); \
|
||||
\
|
||||
if(0) \
|
||||
{
|
||||
|
||||
#define _SEH_END \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
\
|
||||
break; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define _SEH_TRY \
|
||||
for(;;) \
|
||||
{ \
|
||||
_SEH_INIT_CONST int _SEHTopTryLevel = (_SEHScopeKind != 0); \
|
||||
_SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
|
||||
_SEHPortableTryLevel_t * const _SEHPrevPortableTryLevel = _SEHPortableTryLevel; \
|
||||
\
|
||||
{ \
|
||||
_SEH_INIT_CONST int _SEHScopeKind = 0; \
|
||||
register int _SEHState = 0; \
|
||||
register int _SEHHandle = 0; \
|
||||
_SEHFrame_t _SEHFrame; \
|
||||
_SEHTryLevel_t _SEHTryLevel; \
|
||||
_SEHPortableFrame_t * const _SEHPortableFrame = \
|
||||
_SEHTopTryLevel ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
|
||||
_SEHPortableTryLevel_t * const _SEHPortableTryLevel = &_SEHTryLevel.ST_Header; \
|
||||
\
|
||||
(void)_SEHScopeKind; \
|
||||
(void)_SEHPortableFrame; \
|
||||
(void)_SEHPortableTryLevel; \
|
||||
(void)_SEHHandle; \
|
||||
\
|
||||
for(;;) \
|
||||
{ \
|
||||
if(_SEHState) \
|
||||
{ \
|
||||
for(;;) \
|
||||
{ \
|
||||
{
|
||||
|
||||
#define _SEH_EXCEPT(FILTER_) \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if((_SEHHandle = _SEHSetJmp(_SEHTryLevel.ST_JmpBuf)) == 0) \
|
||||
{ \
|
||||
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Filter = (FILTER_); \
|
||||
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally = 0; \
|
||||
\
|
||||
_SEHTryLevel.ST_Header.SPT_Next = _SEHPrevPortableTryLevel; \
|
||||
_SEHFrame.SEH_Header.SPF_TopTryLevel = &_SEHTryLevel.ST_Header; \
|
||||
\
|
||||
if(_SEHTopTryLevel) \
|
||||
{ \
|
||||
if(&_SEHLocals != _SEHDummyLocals) \
|
||||
_SEHFrame.SEH_Locals = &_SEHLocals; \
|
||||
\
|
||||
_SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
|
||||
_SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
|
||||
_SEHEnterFrame(&_SEHFrame.SEH_Header); \
|
||||
} \
|
||||
\
|
||||
++ _SEHState; \
|
||||
continue; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
_SEHPortableFrame->SPF_TopTryLevel = _SEHPrevPortableTryLevel; \
|
||||
\
|
||||
if(_SEHHandle) \
|
||||
{
|
||||
|
||||
#define _SEH_FINALLY(FINALLY_) \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
_SEHPortableFrame->SPF_TopTryLevel = _SEHPrevPortableTryLevel; \
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Filter = 0; \
|
||||
_SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally = (FINALLY_); \
|
||||
\
|
||||
_SEHTryLevel.ST_Header.SPT_Next = _SEHPrevPortableTryLevel; \
|
||||
_SEHFrame.SEH_Header.SPF_TopTryLevel = &_SEHTryLevel.ST_Header; \
|
||||
\
|
||||
if(_SEHTopTryLevel) \
|
||||
{ \
|
||||
if(&_SEHLocals != _SEHDummyLocals) \
|
||||
_SEHFrame.SEH_Locals = &_SEHLocals; \
|
||||
\
|
||||
_SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
|
||||
_SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
|
||||
_SEHEnterFrame(&_SEHFrame.SEH_Header); \
|
||||
} \
|
||||
\
|
||||
++ _SEHState; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
(FINALLY_)(&_SEHFrame.SEH_Header); \
|
||||
\
|
||||
if(0) \
|
||||
{
|
||||
|
||||
#define _SEH_END \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if(_SEHTopTryLevel) \
|
||||
_SEHLeaveFrame(); \
|
||||
\
|
||||
break; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define _SEH_HANDLE _SEH_EXCEPT(_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER))
|
||||
|
||||
#define _SEH_EnableTracing(LEVEL_) ((void)(_SEHPortableFrame->SPF_Tracing = (LEVEL_)))
|
||||
#define _SEH_DisableTracing() ((void)(_SEHPortableFrame->SPF_Tracing = _SEH_DO_TRACE_NONE))
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
140
sdk/lib/pseh/include/pseh/framebased/internal.h
Normal file
140
sdk/lib/pseh/include/pseh/framebased/internal.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
Copyright (c) 2004/2005 KJK::Hyperion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KJK_PSEH_FRAMEBASED_INTERNAL_H_
|
||||
#define KJK_PSEH_FRAMEBASED_INTERNAL_H_
|
||||
|
||||
#define _SEH_DO_TRACE_ENTER_LEAVE (1 << 0)
|
||||
#define _SEH_DO_TRACE_EXCEPTION_RECORD (1 << 1)
|
||||
#define _SEH_DO_TRACE_CONTEXT (1 << 2)
|
||||
#define _SEH_DO_TRACE_UNWIND (1 << 3)
|
||||
#define _SEH_DO_TRACE_TRYLEVEL (1 << 4)
|
||||
#define _SEH_DO_TRACE_CALL_FILTER (1 << 5)
|
||||
#define _SEH_DO_TRACE_FILTER (1 << 6)
|
||||
#define _SEH_DO_TRACE_CALL_HANDLER (1 << 7)
|
||||
#define _SEH_DO_TRACE_CALL_FINALLY (1 << 8)
|
||||
|
||||
#define _SEH_DO_TRACE_NONE (0)
|
||||
#define _SEH_DO_TRACE_ALL (-1)
|
||||
|
||||
#ifndef _SEH_DO_DEFAULT_TRACING
|
||||
#define _SEH_DO_DEFAULT_TRACING _SEH_DO_TRACE_NONE
|
||||
#endif
|
||||
|
||||
struct _EXCEPTION_RECORD;
|
||||
struct _EXCEPTION_POINTERS;
|
||||
struct _CONTEXT;
|
||||
|
||||
typedef int (__cdecl * _SEHFrameHandler_t)
|
||||
(
|
||||
struct _EXCEPTION_RECORD *,
|
||||
void *,
|
||||
struct _CONTEXT *,
|
||||
void *
|
||||
);
|
||||
|
||||
typedef struct __SEHRegistration
|
||||
{
|
||||
struct __SEHRegistration * SER_Prev;
|
||||
_SEHFrameHandler_t SER_Handler;
|
||||
}
|
||||
_SEHRegistration_t;
|
||||
|
||||
struct __SEHPortableFrame;
|
||||
struct __SEHPortableTryLevel;
|
||||
|
||||
typedef long (__stdcall * _SEHFilter_t)
|
||||
(
|
||||
struct _EXCEPTION_POINTERS *,
|
||||
struct __SEHPortableFrame *
|
||||
);
|
||||
|
||||
typedef void (__stdcall * _SEHHandler_t)
|
||||
(
|
||||
struct __SEHPortableTryLevel *
|
||||
);
|
||||
|
||||
typedef void (__stdcall * _SEHFinally_t)
|
||||
(
|
||||
struct __SEHPortableFrame *
|
||||
);
|
||||
|
||||
typedef struct __SEHHandlers
|
||||
{
|
||||
_SEHFilter_t SH_Filter;
|
||||
_SEHFinally_t SH_Finally;
|
||||
}
|
||||
_SEHHandlers_t;
|
||||
|
||||
typedef struct __SEHPortableTryLevel
|
||||
{
|
||||
struct __SEHPortableTryLevel * volatile SPT_Next;
|
||||
volatile _SEHHandlers_t SPT_Handlers;
|
||||
}
|
||||
_SEHPortableTryLevel_t;
|
||||
|
||||
typedef struct __SEHPortableFrame
|
||||
{
|
||||
_SEHRegistration_t SPF_Registration;
|
||||
unsigned long SPF_Code;
|
||||
volatile _SEHHandler_t SPF_Handler;
|
||||
_SEHPortableTryLevel_t * volatile SPF_TopTryLevel;
|
||||
volatile int SPF_Tracing;
|
||||
}
|
||||
_SEHPortableFrame_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern void __stdcall _SEHEnterFrame_s(_SEHPortableFrame_t *);
|
||||
extern void __stdcall _SEHLeaveFrame_s(void);
|
||||
extern void __stdcall _SEHReturn_s(void);
|
||||
|
||||
#if !defined(_SEH_NO_FASTCALL)
|
||||
# ifdef _M_IX86
|
||||
# define _SEH_FASTCALL __fastcall
|
||||
# else
|
||||
# define _SEH_FASTCALL __stdcall
|
||||
# endif
|
||||
|
||||
extern void _SEH_FASTCALL _SEHEnterFrame_f(_SEHPortableFrame_t *);
|
||||
extern void _SEH_FASTCALL _SEHLeaveFrame_f(void);
|
||||
extern void _SEH_FASTCALL _SEHReturn_f(void);
|
||||
|
||||
# define _SEHEnterFrame _SEHEnterFrame_f
|
||||
# define _SEHLeaveFrame _SEHLeaveFrame_f
|
||||
# define _SEHReturn _SEHReturn_f
|
||||
#else
|
||||
# define _SEHEnterFrame _SEHEnterFrame_s
|
||||
# define _SEHLeaveFrame _SEHLeaveFrame_s
|
||||
# define _SEHReturn _SEHReturn_s
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
84
sdk/lib/pseh/include/pseh/pseh.h
Normal file
84
sdk/lib/pseh/include/pseh/pseh.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Copyright (c) 2004/2005 KJK::Hyperion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KJK_PSEH_H_
|
||||
#define KJK_PSEH_H_
|
||||
|
||||
/* Some useful macros */
|
||||
#if defined(__cplusplus)
|
||||
# define _SEH_PVOID_CAST(TYPE_, P_) ((TYPE_)(P_))
|
||||
#else
|
||||
# define _SEH_PVOID_CAST(TYPE_, P_) (P_)
|
||||
#endif
|
||||
|
||||
#if defined(FIELD_OFFSET)
|
||||
# define _SEH_FIELD_OFFSET FIELD_OFFSET
|
||||
#else
|
||||
# include <stddef.h>
|
||||
# define _SEH_FIELD_OFFSET offsetof
|
||||
#endif
|
||||
|
||||
#if defined(CONTAINING_RECORD)
|
||||
# define _SEH_CONTAINING_RECORD CONTAINING_RECORD
|
||||
#else
|
||||
# define _SEH_CONTAINING_RECORD(ADDR_, TYPE_, FIELD_) \
|
||||
((TYPE_ *)(((char *)(ADDR_)) - _SEH_FIELD_OFFSET(TYPE_, FIELD_)))
|
||||
#endif
|
||||
|
||||
#if defined(__CONCAT)
|
||||
# define _SEH_CONCAT __CONCAT
|
||||
#else
|
||||
# define _SEH_CONCAT1(X_, Y_) X_ ## Y_
|
||||
# define _SEH_CONCAT(X_, Y_) _SEH_CONCAT1(X_, Y_)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Note: just define __inline to an empty symbol if your C compiler doesn't
|
||||
support it
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# ifndef __inline
|
||||
# define __inline inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Locals sharing support */
|
||||
#define _SEH_LOCALS_TYPENAME(BASENAME_) \
|
||||
struct _SEH_CONCAT(_SEHLocalsTag, BASENAME_)
|
||||
|
||||
#define _SEH_DEFINE_LOCALS(BASENAME_) \
|
||||
_SEH_LOCALS_TYPENAME(BASENAME_)
|
||||
|
||||
#define _SEH_DECLARE_LOCALS(BASENAME_) \
|
||||
_SEH_LOCALS_TYPENAME(BASENAME_) _SEHLocals; \
|
||||
_SEH_LOCALS_TYPENAME(BASENAME_) * _SEHPLocals; \
|
||||
_SEHPLocals = &_SEHLocals;
|
||||
|
||||
/* Dummy locals */
|
||||
static int _SEHLocals;
|
||||
static void * const _SEHDummyLocals = &_SEHLocals;
|
||||
|
||||
#include <pseh/framebased.h>
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
452
sdk/lib/pseh/include/pseh/pseh2.h
Normal file
452
sdk/lib/pseh/include/pseh/pseh2.h
Normal file
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
Copyright (c) 2008 KJK::Hyperion
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KJK_PSEH2_H_
|
||||
#define KJK_PSEH2_H_
|
||||
|
||||
#if defined(_USE_NATIVE_SEH) || defined(_MSC_VER)
|
||||
|
||||
#include <excpt.h>
|
||||
#define _SEH2_TRY __try
|
||||
#define _SEH2_FINALLY __finally
|
||||
#define _SEH2_EXCEPT(...) __except(__VA_ARGS__)
|
||||
#define _SEH2_END
|
||||
#define _SEH2_GetExceptionInformation() (GetExceptionInformation())
|
||||
#define _SEH2_GetExceptionCode() (GetExceptionCode())
|
||||
#define _SEH2_AbnormalTermination() (AbnormalTermination())
|
||||
#define _SEH2_YIELD(STMT_) STMT_
|
||||
#define _SEH2_LEAVE __leave
|
||||
#define _SEH2_VOLATILE
|
||||
|
||||
#elif defined(__GNUC__) && !defined(__clang__) && defined(_M_AMD64)
|
||||
|
||||
#include "pseh2_64.h"
|
||||
|
||||
#elif defined(_USE_DUMMY_PSEH) || defined (__arm__) || defined(_M_AMD64)
|
||||
|
||||
extern int _SEH2_Volatile0;
|
||||
extern int _SEH2_VolatileExceptionCode;
|
||||
|
||||
#define _SEH2_TRY \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wunused-label\"")\
|
||||
{ \
|
||||
__label__ __seh2_scope_end__;
|
||||
|
||||
#define _SEH2_FINALLY \
|
||||
__seh2_scope_end__:; \
|
||||
} \
|
||||
if (1) \
|
||||
{ \
|
||||
__label__ __seh2_scope_end__;
|
||||
|
||||
#define _SEH2_EXCEPT(...) \
|
||||
__seh2_scope_end__:; \
|
||||
} \
|
||||
if (_SEH2_Volatile0 || (0 && (__VA_ARGS__))) \
|
||||
{ \
|
||||
__label__ __seh2_scope_end__;
|
||||
|
||||
#define _SEH2_END \
|
||||
__seh2_scope_end__:; \
|
||||
} \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
|
||||
#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)0)
|
||||
#define _SEH2_GetExceptionCode() _SEH2_VolatileExceptionCode
|
||||
#define _SEH2_AbnormalTermination() (0)
|
||||
#define _SEH2_YIELD(STMT_) STMT_
|
||||
#define _SEH2_LEAVE goto __seh2_scope_end__;
|
||||
#define _SEH2_VOLATILE volatile
|
||||
|
||||
#elif defined(_USE_PSEH3)
|
||||
|
||||
#include "pseh3.h"
|
||||
|
||||
/* Compatibility macros */
|
||||
#define _SEH2_TRY _SEH3_TRY
|
||||
#define _SEH2_EXCEPT _SEH3_EXCEPT
|
||||
#define _SEH2_FINALLY _SEH3_FINALLY
|
||||
#define _SEH2_END _SEH3_END
|
||||
#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)_exception_info())
|
||||
#define _SEH2_GetExceptionCode _exception_code
|
||||
#define _SEH2_AbnormalTermination _abnormal_termination
|
||||
#define _SEH2_LEAVE _SEH3_LEAVE
|
||||
#define _SEH2_YIELD(x) x
|
||||
#define _SEH2_VOLATILE volatile
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
struct _EXCEPTION_RECORD;
|
||||
struct _EXCEPTION_POINTERS;
|
||||
struct _CONTEXT;
|
||||
|
||||
typedef int (__cdecl * _SEH2FrameHandler_t)
|
||||
(
|
||||
struct _EXCEPTION_RECORD *,
|
||||
void *,
|
||||
struct _CONTEXT *,
|
||||
void *
|
||||
);
|
||||
|
||||
typedef struct __SEH2Registration
|
||||
{
|
||||
struct __SEH2Registration * SER_Prev;
|
||||
_SEH2FrameHandler_t SER_Handler;
|
||||
}
|
||||
_SEH2Registration_t;
|
||||
|
||||
typedef struct __SEH2Frame
|
||||
{
|
||||
_SEH2Registration_t SF_Registration;
|
||||
volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
|
||||
volatile unsigned long SF_Code;
|
||||
}
|
||||
_SEH2Frame_t;
|
||||
|
||||
typedef struct __SEH2TryLevel
|
||||
{
|
||||
volatile struct __SEH2TryLevel * ST_Next;
|
||||
void * ST_Filter;
|
||||
void * ST_Body;
|
||||
}
|
||||
_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 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Prevent gcc from inlining functions that use SEH. */
|
||||
#if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7))
|
||||
static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH_DontInline() {}
|
||||
#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() _SEH_DontInline();
|
||||
#else
|
||||
#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
/* A no-op side effect that scares GCC */
|
||||
#define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
|
||||
|
||||
/* A no-op without any real side effects, but silences warnings */
|
||||
#define __SEH_PRETEND_SIDE_EFFECT (void)0
|
||||
|
||||
/* Forces GCC to consider the specified label reachable */
|
||||
#define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
|
||||
|
||||
/* Makes GCC pretend the specified label is reachable, to silence warnings */
|
||||
#define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
|
||||
|
||||
/* Soft memory barrier */
|
||||
#define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
|
||||
|
||||
/* GCC doesn't know that this equals zero */
|
||||
#define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
|
||||
|
||||
#define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
|
||||
#define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
|
||||
|
||||
#define ___SEH_STRINGIFY(X_) # X_
|
||||
#define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
|
||||
|
||||
#define __SEH_EXCEPT_RET long
|
||||
#define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
|
||||
#define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
|
||||
#define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
|
||||
#define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
|
||||
#define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
|
||||
#define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
|
||||
|
||||
#define __SEH_FINALLY_RET void
|
||||
#define __SEH_FINALLY_ARGS void
|
||||
#define __SEH_FINALLY_ARGS_
|
||||
#define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
|
||||
#define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
|
||||
#define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
|
||||
#define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
|
||||
|
||||
#define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
|
||||
#define __SEH_RETURN_FINALLY() return
|
||||
|
||||
#define __SEH_BEGIN_TRY \
|
||||
{ \
|
||||
__label__ _SEHEndTry; \
|
||||
\
|
||||
__SEH_PRETEND_USE_LABEL(_SEHEndTry); \
|
||||
\
|
||||
{ \
|
||||
__SEH_BARRIER;
|
||||
|
||||
#define __SEH_END_TRY \
|
||||
__SEH_BARRIER; \
|
||||
} \
|
||||
_SEHEndTry:; \
|
||||
}
|
||||
|
||||
#define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
|
||||
{ \
|
||||
__SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
|
||||
}
|
||||
|
||||
#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_TRYLEVEL() \
|
||||
if(!_SEHTopTryLevel) \
|
||||
{ \
|
||||
__SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
|
||||
} \
|
||||
|
||||
#define __SEH_LEAVE_FRAME() \
|
||||
if(_SEHTopTryLevel) \
|
||||
{ \
|
||||
_SEH2LeaveFrame(); \
|
||||
}
|
||||
|
||||
#define __SEH_END_SCOPE_CHAIN \
|
||||
static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
|
||||
static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
|
||||
static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
|
||||
|
||||
#define __SEH_BEGIN_SCOPE \
|
||||
for(;;) \
|
||||
{ \
|
||||
const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
|
||||
_SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
|
||||
volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
|
||||
__attribute__((unused)) int _SEHAbnormalTermination; \
|
||||
\
|
||||
(void)_SEHTopTryLevel; \
|
||||
(void)_SEHCurFrameP; \
|
||||
(void)_SEHPrevTryLevelP; \
|
||||
\
|
||||
{ \
|
||||
__label__ _SEHBeforeTry; \
|
||||
__label__ _SEHDoTry; \
|
||||
__label__ _SEHAfterTry; \
|
||||
static const int _SEH2ScopeKind = 0; \
|
||||
volatile _SEH2TryLevel_t _SEHTryLevel; \
|
||||
volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
|
||||
_SEH2Frame_t _SEH2Frame[_SEHTopTryLevel ? 1 : 0]; \
|
||||
volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
|
||||
_SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
|
||||
_SEH2Frame : _SEHCurFrameP; \
|
||||
\
|
||||
(void)_SEH2ScopeKind; \
|
||||
(void)_SEHTryLevel; \
|
||||
(void)_SEHHandleTryLevel; \
|
||||
(void)_SEH2FrameP; \
|
||||
(void)_SEH2TryLevelP; \
|
||||
\
|
||||
goto _SEHBeforeTry; \
|
||||
\
|
||||
_SEHDoTry:;
|
||||
|
||||
#define __SEH_END_SCOPE \
|
||||
} \
|
||||
\
|
||||
break; \
|
||||
}
|
||||
|
||||
#define __SEH_SCOPE_LOCALS \
|
||||
__label__ _SEHBeginExcept; \
|
||||
__label__ _SEHEndExcept; \
|
||||
\
|
||||
auto __SEH_DECLARE_FINALLY(_SEHFinally);
|
||||
|
||||
#define _SEH2_TRY \
|
||||
__PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() \
|
||||
__SEH_BEGIN_SCOPE \
|
||||
{ \
|
||||
__SEH_SCOPE_LOCALS; \
|
||||
\
|
||||
__SEH_BEGIN_TRY \
|
||||
{
|
||||
|
||||
#define _SEH2_FINALLY \
|
||||
} \
|
||||
__SEH_END_TRY; \
|
||||
\
|
||||
goto _SEHAfterTry; \
|
||||
_SEHBeforeTry:; \
|
||||
\
|
||||
__SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
|
||||
__SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
|
||||
\
|
||||
_SEHTryLevel.ST_Filter = 0; \
|
||||
_SEHTryLevel.ST_Body = &_SEHFinally; \
|
||||
_SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
|
||||
__SEH_ENTER_SCOPE(&_SEHTryLevel); \
|
||||
_SEH2TryLevelP = &_SEHTryLevel; \
|
||||
\
|
||||
_SEHAbnormalTermination = 1; \
|
||||
\
|
||||
goto _SEHDoTry; \
|
||||
_SEHAfterTry:; \
|
||||
\
|
||||
_SEHAbnormalTermination = 0; \
|
||||
\
|
||||
__SEH_LEAVE_TRYLEVEL(); \
|
||||
\
|
||||
_SEHFinally(); \
|
||||
goto _SEHEndExcept; \
|
||||
\
|
||||
_SEHBeginExcept:; \
|
||||
\
|
||||
__attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
|
||||
{ \
|
||||
__SEH_END_SCOPE_CHAIN; \
|
||||
\
|
||||
(void)_SEH2ScopeKind; \
|
||||
(void)_SEH2FrameP; \
|
||||
(void)_SEH2TryLevelP; \
|
||||
\
|
||||
for(;; ({ __SEH_RETURN_FINALLY(); })) \
|
||||
{
|
||||
|
||||
#define _SEH2_EXCEPT(...) \
|
||||
} \
|
||||
__SEH_END_TRY; \
|
||||
\
|
||||
goto _SEHAfterTry; \
|
||||
\
|
||||
_SEHBeforeTry:; \
|
||||
\
|
||||
{ \
|
||||
__attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
|
||||
\
|
||||
if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
|
||||
{ \
|
||||
if((__VA_ARGS__) < 0) \
|
||||
{ \
|
||||
_SEHTryLevel.ST_Filter = (void *)-1; \
|
||||
_SEHTryLevel.ST_Body = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_SEHTryLevel.ST_Filter = (void *)0; \
|
||||
_SEHTryLevel.ST_Body = 0; \
|
||||
} \
|
||||
\
|
||||
_SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
|
||||
__SEH_ENTER_SCOPE(&_SEHTryLevel); \
|
||||
_SEH2TryLevelP = &_SEHTryLevel; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
|
||||
_SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
|
||||
else \
|
||||
{ \
|
||||
__SEH_DEFINE_EXCEPT(_SEHExcept) \
|
||||
{ \
|
||||
__SEH_RETURN_EXCEPT((__VA_ARGS__)); \
|
||||
} \
|
||||
\
|
||||
_SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
|
||||
} \
|
||||
\
|
||||
_SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
|
||||
_SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
|
||||
\
|
||||
if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
|
||||
goto _SEHBeginExcept; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
goto _SEHDoTry; \
|
||||
\
|
||||
__attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
|
||||
\
|
||||
_SEHAfterTry:; \
|
||||
__SEH_LEAVE_TRYLEVEL(); \
|
||||
\
|
||||
goto _SEHEndExcept; \
|
||||
\
|
||||
_SEHBeginExcept:; \
|
||||
{ \
|
||||
{ \
|
||||
__SEH_BARRIER;
|
||||
|
||||
#define _SEH2_END \
|
||||
__SEH_BARRIER; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_SEHEndExcept:; \
|
||||
\
|
||||
__SEH_LEAVE_FRAME(); \
|
||||
} \
|
||||
__SEH_END_SCOPE;
|
||||
|
||||
#define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
|
||||
#define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
|
||||
#define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
|
||||
|
||||
#define _SEH2_YIELD(STMT_) \
|
||||
for(;;) \
|
||||
{ \
|
||||
if(!_SEH2ScopeKind) \
|
||||
_SEH2Return(); \
|
||||
\
|
||||
STMT_; \
|
||||
}
|
||||
|
||||
#define _SEH2_LEAVE goto _SEHEndTry
|
||||
|
||||
__SEH_END_SCOPE_CHAIN;
|
||||
|
||||
#define _SEH2_VOLATILE volatile
|
||||
|
||||
#else
|
||||
#error no PSEH support
|
||||
#endif
|
||||
|
||||
#endif /* !KJK_PSEH2_H_ */
|
||||
|
||||
/* EOF */
|
169
sdk/lib/pseh/include/pseh/pseh2_64.h
Normal file
169
sdk/lib/pseh/include/pseh/pseh2_64.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
/* Declare our global trampoline function for filter and unwinder */
|
||||
__asm__(
|
||||
".p2align 4, 0x90\n"
|
||||
".seh_proc __seh2_global_filter_func\n"
|
||||
"__seh2_global_filter_func:\n"
|
||||
"\tpush %rbp\n"
|
||||
"\t.seh_pushreg %rbp\n"
|
||||
"\tsub $32, %rsp\n"
|
||||
"\t.seh_stackalloc 32\n"
|
||||
"\t.seh_endprologue\n"
|
||||
/* Restore frame pointer. */
|
||||
"\tmov %rdx, %rbp\n"
|
||||
/* Actually execute the filter funclet */
|
||||
"\tjmp *%rax\n"
|
||||
"__seh2_global_filter_func_exit:\n"
|
||||
"\t.p2align 4\n"
|
||||
"\tadd $32, %rsp\n"
|
||||
"\tpop %rbp\n"
|
||||
"\tret\n"
|
||||
"\t.seh_endproc");
|
||||
|
||||
#define _SEH2_TRY \
|
||||
{ \
|
||||
__label__ __seh2$$begin_try__; \
|
||||
__label__ __seh2$$end_try__; \
|
||||
/* \
|
||||
* We close the current SEH block for this function and install our own. \
|
||||
* At this point GCC emitted its prologue, and if it saves more \
|
||||
* registers, the relevant instruction will be valid for our scope as well. \
|
||||
* We also count the number of try blocks at assembly level \
|
||||
* to properly set the handler data when we're done. \
|
||||
*/ \
|
||||
__seh2$$begin_try__: \
|
||||
{ \
|
||||
__label__ __seh2$$leave_scope__;
|
||||
|
||||
#define _SEH2_EXCEPT(...) \
|
||||
__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
|
||||
} \
|
||||
__seh2$$end_try__: \
|
||||
/* Call our home-made pragma */ \
|
||||
_Pragma("REACTOS seh(except)") \
|
||||
if (0) \
|
||||
{ \
|
||||
__label__ __seh2$$leave_scope__; \
|
||||
__label__ __seh2$$filter__; \
|
||||
__label__ __seh2$$begin_except__; \
|
||||
LONG __MINGW_ATTRIB_UNUSED __seh2$$exception_code__ = 0; \
|
||||
/* Add our handlers to the list */ \
|
||||
__asm__ __volatile__ goto ("\n" \
|
||||
"\t.seh_handlerdata\n" \
|
||||
"\t.rva %l0\n" /* Begin of tried code */ \
|
||||
"\t.rva %l1 + 1\n" /* End of tried code */ \
|
||||
"\t.rva %l2\n" /* Filter function */ \
|
||||
"\t.rva %l3\n" /* Called on except */ \
|
||||
"\t.seh_code\n" \
|
||||
: /* No output */ \
|
||||
: /* No input */ \
|
||||
: /* No clobber */ \
|
||||
: __seh2$$begin_try__, \
|
||||
__seh2$$end_try__, \
|
||||
__seh2$$filter__, \
|
||||
__seh2$$begin_except__); \
|
||||
if (0) \
|
||||
{ \
|
||||
/* Jump to the global filter. Tell it where the filter funclet lies */ \
|
||||
__label__ __seh2$$filter_funclet__; \
|
||||
__seh2$$filter__: \
|
||||
__asm__ __volatile__ goto( \
|
||||
"\tleaq %l0(%%rip), %%rax\n" \
|
||||
"\tjmp __seh2_global_filter_func\n" \
|
||||
: /* No output */ \
|
||||
: /* No input */ \
|
||||
: "%rax" \
|
||||
: __seh2$$filter_funclet__); \
|
||||
/* Actually declare our filter funclet */ \
|
||||
struct _EXCEPTION_POINTERS* __seh2$$exception_ptr__; \
|
||||
__seh2$$filter_funclet__: \
|
||||
/* At this point, the compiler can't count on any register being valid */ \
|
||||
__asm__ __volatile__("" \
|
||||
: "=c"(__seh2$$exception_ptr__) /* First argument of the filter function */ \
|
||||
: /* No input */ \
|
||||
: /* Everything */ \
|
||||
"%rax", "%rbx","%rdx", "%rdi", "%rsi", \
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \
|
||||
/* Save exception code */ \
|
||||
__seh2$$exception_code__ = __seh2$$exception_ptr__->ExceptionRecord->ExceptionCode; \
|
||||
/* Actually evaluate our filter */ \
|
||||
register long __MINGW_ATTRIB_UNUSED __seh2$$filter_funclet_ret __asm__("eax") = \
|
||||
((__VA_ARGS__)); \
|
||||
/* Go back to the global filter function */ \
|
||||
__asm__("jmp __seh2_global_filter_func_exit"); \
|
||||
} \
|
||||
/* Protect us from emitting instructions to jump back to the filter function */ \
|
||||
enum \
|
||||
{ \
|
||||
__seh2$$abnormal_termination__ = 0 \
|
||||
}; \
|
||||
__seh2$$begin_except__:
|
||||
|
||||
#define _SEH2_FINALLY \
|
||||
__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
|
||||
} \
|
||||
__seh2$$end_try__: \
|
||||
/* Call our home-made pragma */ \
|
||||
_Pragma("REACTOS seh(finally)") \
|
||||
if (1) \
|
||||
{ \
|
||||
__label__ __seh2$$finally__; \
|
||||
__label__ __seh2$$begin_finally__; \
|
||||
__label__ __seh2$$leave_scope__; \
|
||||
int __seh2$$abnormal_termination__; \
|
||||
/* Add our handlers to the list */ \
|
||||
__asm__ __volatile__ goto ("\n" \
|
||||
"\t.seh_handlerdata\n" \
|
||||
"\t.rva %l0\n" /* Begin of tried code */ \
|
||||
"\t.rva %l1 + 1\n" /* End of tried code */ \
|
||||
"\t.rva %l2\n" /* Filter function */ \
|
||||
"\t.long 0\n" /* Nothing for unwind code */ \
|
||||
"\t.seh_code\n" \
|
||||
: /* No output */ \
|
||||
: /* No input */ \
|
||||
: /* No clobber */ \
|
||||
: __seh2$$begin_try__, \
|
||||
__seh2$$end_try__, \
|
||||
__seh2$$finally__); \
|
||||
if (0) \
|
||||
{ \
|
||||
/* Jump to the global trampoline. Tell it where the unwind code really lies */ \
|
||||
__seh2$$finally__: \
|
||||
__asm__ __volatile__ goto( \
|
||||
"\tleaq %l0(%%rip), %%rax\n" \
|
||||
"\tjmp __seh2_global_filter_func\n" \
|
||||
: /* No output */ \
|
||||
: /* No input */ \
|
||||
: /* No clobber */ \
|
||||
: __seh2$$begin_finally__); \
|
||||
} \
|
||||
\
|
||||
/* Zero-out rcx to indicate normal termination */ \
|
||||
__asm__ __volatile__("xor %%rcx, %%rcx" \
|
||||
: /* No output */ \
|
||||
: /* No input */ \
|
||||
: /* Everything - We might come from __C_specific_handler here */ \
|
||||
"%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%rsi", \
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \
|
||||
/* Actually declare our finally funclet */ \
|
||||
__seh2$$begin_finally__: \
|
||||
__asm__ __volatile__("" \
|
||||
: "=c" (__seh2$$abnormal_termination__));
|
||||
|
||||
#define _SEH2_END \
|
||||
__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
|
||||
if (__seh2$$abnormal_termination__) \
|
||||
{ \
|
||||
__asm__("jmp __seh2_global_filter_func_exit"); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH2_GetExceptionInformation() __seh2$$exception_ptr__
|
||||
#define _SEH2_GetExceptionCode() __seh2$$exception_code__
|
||||
#define _SEH2_AbnormalTermination() __seh2$$abnormal_termination__
|
||||
#define _SEH2_LEAVE goto __seh2$$leave_scope__
|
||||
#define _SEH2_YIELD(__stmt) __stmt
|
||||
#define _SEH2_VOLATILE volatile
|
476
sdk/lib/pseh/include/pseh/pseh3.h
Normal file
476
sdk/lib/pseh/include/pseh/pseh3.h
Normal file
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* PROJECT: ReactOS system libraries
|
||||
* LICENSE: GNU GPL - See COPYING in the top level directory
|
||||
* PURPOSE: Header for PSEH3
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* For additional information see pseh3.c in the related library. */
|
||||
|
||||
#pragma once
|
||||
#define _PSEH3_H_
|
||||
|
||||
#include <excpt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CLANG must safe non-volatiles, because it uses a return-twice algorithm */
|
||||
#if defined(__clang__) && !defined(_SEH3$_FRAME_ALL_NONVOLATILES)
|
||||
#define _SEH3$_FRAME_ALL_NONVOLATILES 1
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
_SEH3$_NESTED_HANDLER = 0,
|
||||
_SEH3$_CPP_HANDLER = 1,
|
||||
_SEH3$_CLANG_HANDLER = 2,
|
||||
#ifdef __clang__
|
||||
_SEH3$_HANDLER_TYPE = _SEH3$_CLANG_HANDLER,
|
||||
#elif defined(__cplusplus)
|
||||
_SEH3$_HANDLER_TYPE = _SEH3$_CPP_HANDLER,
|
||||
#else
|
||||
_SEH3$_HANDLER_TYPE = _SEH3$_NESTED_HANDLER,
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _SEH3$_SCOPE_TABLE
|
||||
{
|
||||
void *Target;
|
||||
void *Filter;
|
||||
unsigned char TryLevel;
|
||||
unsigned char HandlerType;
|
||||
} SEH3$_SCOPE_TABLE, *PSEH3$_SCOPE_TABLE;
|
||||
|
||||
typedef struct _SEH3$_EXCEPTION_POINTERS
|
||||
{
|
||||
struct _EXCEPTION_RECORD *ExceptionRecord;
|
||||
struct _CONTEXT *ContextRecord;
|
||||
} SEH3$_EXCEPTION_POINTERS, *PSEH3$_EXCEPTION_POINTERS;
|
||||
|
||||
typedef struct _SEH3$_REGISTRATION_FRAME
|
||||
{
|
||||
/* First the Windows base record. Don't move this! */
|
||||
struct _SEH3$_REGISTRATION_FRAME *Next;
|
||||
void *Handler;
|
||||
|
||||
/* Points to the end of the internal registration chain */
|
||||
struct _SEH3$_REGISTRATION_FRAME *EndOfChain;
|
||||
|
||||
/* Pointer to the static scope table */
|
||||
PSEH3$_SCOPE_TABLE ScopeTable;
|
||||
|
||||
/* Except handler stores pointer to exception pointers here */
|
||||
PSEH3$_EXCEPTION_POINTERS volatile ExceptionPointers;
|
||||
|
||||
/* Except handler stores the exception code here */
|
||||
unsigned long ExceptionCode;
|
||||
|
||||
/* Registers that we need to save */
|
||||
unsigned long Esp;
|
||||
unsigned long Ebp;
|
||||
|
||||
char* AllocaFrame;
|
||||
#ifdef _SEH3$_FRAME_ALL_NONVOLATILES
|
||||
unsigned long Ebx;
|
||||
unsigned long Esi;
|
||||
unsigned long Edi;
|
||||
#endif
|
||||
#ifdef __clang__
|
||||
void *ReturnAddress;
|
||||
#endif
|
||||
} SEH3$_REGISTRATION_FRAME ,*PSEH3$_REGISTRATION_FRAME;
|
||||
|
||||
/* Prevent gcc from inlining functions that use SEH. */
|
||||
static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH3$_PreventInlining() {}
|
||||
|
||||
/* Unregister the root frame */
|
||||
extern inline __attribute__((always_inline,gnu_inline))
|
||||
void _SEH3$_UnregisterFrame(volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame)
|
||||
{
|
||||
asm volatile ("movl %k[NewHead], %%fs:0"
|
||||
: : [NewHead] "ir" (RegistrationFrame->Next) : "memory");
|
||||
}
|
||||
|
||||
/* Unregister a trylevel frame */
|
||||
extern inline __attribute__((always_inline,gnu_inline))
|
||||
void _SEH3$_UnregisterTryLevel(
|
||||
volatile SEH3$_REGISTRATION_FRAME *TrylevelFrame)
|
||||
{
|
||||
volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame;
|
||||
asm volatile ("movl %%fs:0, %k[RegistrationFrame]"
|
||||
: [RegistrationFrame] "=r" (RegistrationFrame) : );
|
||||
RegistrationFrame->EndOfChain = TrylevelFrame->Next;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
_SEH3$_TryLevel = 0,
|
||||
};
|
||||
|
||||
#ifndef __clang__
|
||||
/* 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);
|
||||
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);
|
||||
#endif
|
||||
|
||||
/* This attribute allows automatic cleanup of the registered frames */
|
||||
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_AutoCleanup)))
|
||||
|
||||
int
|
||||
__attribute__((regparm(3)))
|
||||
__attribute__((returns_twice))
|
||||
_SEH3$_RegisterFrameWithNonVolatiles(
|
||||
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
||||
const SEH3$_SCOPE_TABLE* ScopeTable,
|
||||
void* AllocaFrame);
|
||||
|
||||
int
|
||||
__attribute__((regparm(3)))
|
||||
__attribute__((returns_twice))
|
||||
_SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||
volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
|
||||
const SEH3$_SCOPE_TABLE* ScopeTable,
|
||||
void* AllocaFrame);
|
||||
|
||||
/* CLANG specific definitions! */
|
||||
#ifdef __clang__
|
||||
|
||||
/* CLANG thinks it is smart and optimizes the alloca away if it is 0 and with it the use of a frame register */
|
||||
#define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(4)) : "%esp", "memory")
|
||||
|
||||
/* CLANG doesn't have asm goto! */
|
||||
#define _SEH3$_ASM_GOTO(...)
|
||||
|
||||
#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
|
||||
do { \
|
||||
int result = _SEH3$_RegisterFrameWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
|
||||
if (__builtin_expect(result != 0, 0)) \
|
||||
{ \
|
||||
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
||||
if (result == 2) goto _SEH3$_l_HandlerTarget; \
|
||||
goto _SEH3$_l_BeforeFilterOrFinally; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
||||
do { \
|
||||
int result = _SEH3$_RegisterTryLevelWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
|
||||
if (__builtin_expect(result != 0, 0)) \
|
||||
{ \
|
||||
if (result == 1) goto _SEH3$_l_FilterOrFinally; \
|
||||
if (result == 2) goto _SEH3$_l_HandlerTarget; \
|
||||
goto _SEH3$_l_BeforeFilterOrFinally; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define _SEH3$_SCARE_GCC()
|
||||
|
||||
#else /* !__clang__ */
|
||||
|
||||
/* This will make GCC use ebp, even if it was disabled by -fomit-frame-pointer */
|
||||
#define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(0)) : "%esp", "memory")
|
||||
|
||||
#define _SEH3$_ASM_GOTO(...) asm goto ("#\n" : : : "memory" : __VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
|
||||
asm goto ("leal %0, %%eax\n\t" \
|
||||
"leal %1, %%edx\n\t" \
|
||||
"call " #_Function "WithStackLayout" \
|
||||
: \
|
||||
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c" (__builtin_alloca(0)), "p" (_SEH3$_RegisterFrameWithNonVolatiles) \
|
||||
: "eax", "edx", "memory" \
|
||||
: _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
|
||||
|
||||
#else
|
||||
#define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
|
||||
asm goto ("leal %0, %%eax\n\t" \
|
||||
"leal %1, %%edx\n\t" \
|
||||
"call " #_Function \
|
||||
: \
|
||||
: "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "p" (_SEH3$_RegisterFrameWithNonVolatiles) \
|
||||
: "eax", "edx", "ecx", "memory" \
|
||||
: _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
|
||||
#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 */
|
||||
#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
|
||||
_SEH3$_CALL_WRAPPER(__SEH3$_RegisterTryLevel, _TrylevelFrame, _DataTable)
|
||||
|
||||
/* This construct scares GCC so much, that it will stop moving code
|
||||
around into places that are never executed. */
|
||||
#define _SEH3$_SCARE_GCC() \
|
||||
void *plabel; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally); \
|
||||
asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException), "p"(&&_SEH3$_l_FilterOrFinally) \
|
||||
: "ebx", "ecx", "edx", "esi", "edi", "flags", "memory" ); \
|
||||
goto _SEH3$_l_OnException;
|
||||
|
||||
#endif /* __clang__ */
|
||||
|
||||
/* Neither CLANG nor C++ support nested functions */
|
||||
#if defined(__cplusplus) || defined(__clang__)
|
||||
|
||||
/* Use the global unregister function */
|
||||
void
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_AutoCleanup(
|
||||
volatile SEH3$_REGISTRATION_FRAME *Frame);
|
||||
|
||||
/* These are only dummies here */
|
||||
#define _SEH3$_DECLARE_CLEANUP_FUNC(_Name)
|
||||
#define _SEH3$_DEFINE_CLEANUP_FUNC(_Name)
|
||||
#define _SEH3$_DECLARE_FILTER_FUNC(_Name)
|
||||
#define _SEH3$_DEFINE_DUMMY_FINALLY(_Name)
|
||||
|
||||
/* On invocation, the AllocaFrame field is loaded with the return esp value */
|
||||
#define _SEH3$_NESTED_FUNC_RETURN(_Result) \
|
||||
/* Restore esp and return to the caller */ \
|
||||
asm volatile ("movl %[FixedEsp], %%esp\n\tret" \
|
||||
: : "a" (_Result), [FixedEsp] "m" (_SEH3$_TrylevelFrame.AllocaFrame) : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory")
|
||||
|
||||
/* The filter "function" */
|
||||
#define _SEH3$_DEFINE_FILTER_FUNC(_Name, expression) \
|
||||
{ \
|
||||
/* Evaluate and return the filter expression */ \
|
||||
asm volatile ("#\n" : : : "eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"); \
|
||||
_SEH3$_NESTED_FUNC_RETURN((expression)); \
|
||||
}
|
||||
|
||||
#define _SEH3$_FINALLY_FUNC_OPEN(_Name) \
|
||||
{ \
|
||||
asm volatile ("#\n" : : : "eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"); \
|
||||
/* This construct makes sure that the finally function returns */ \
|
||||
/* a proper value at the end */ \
|
||||
for (; ; (void)({_SEH3$_NESTED_FUNC_RETURN(0); 0;}))
|
||||
|
||||
#define _SEH3$_FILTER(_Filter, _FilterExpression) (&&_SEH3$_l_FilterOrFinally)
|
||||
#define _SEH3$_FINALLY(_Finally) (&&_SEH3$_l_FilterOrFinally)
|
||||
|
||||
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS()
|
||||
|
||||
/* Since we cannot use nested functions, we declare these globally as macros */
|
||||
#define _abnormal_termination() (_SEH3$_TrylevelFrame.ExceptionPointers != 0)
|
||||
#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionCode)
|
||||
#define _exception_info() (_SEH3$_TrylevelFrame.ExceptionPointers)
|
||||
|
||||
#else /* __cplusplus || __clang__ */
|
||||
|
||||
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \
|
||||
inline __attribute__((always_inline, gnu_inline)) \
|
||||
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; }
|
||||
|
||||
/* On GCC the filter function is a nested function with __fastcall calling
|
||||
convention. The eax register contains a base address the function uses
|
||||
to address the callers stack frame. __fastcall is chosen, because it gives
|
||||
us an effective was of passing one argument to the function, that we need
|
||||
to tell the function in a first pass to return informtion about the frame
|
||||
base address. Since this is something GCC chooses arbitrarily, we call
|
||||
the function with an arbitrary base address in eax first and then use the
|
||||
result to calculate the correct address for a second call to the function. */
|
||||
#define _SEH3$_DECLARE_FILTER_FUNC(_Name) \
|
||||
auto int __fastcall _Name(int Action)
|
||||
|
||||
#define _SEH3$_NESTED_FUNC_OPEN(_Name) \
|
||||
int __fastcall _Name(int Action) \
|
||||
{ \
|
||||
/* This is a fancy way to get information about the frame layout */ \
|
||||
if (Action == 0) return (int)&_SEH3$_TrylevelFrame;
|
||||
|
||||
#define _SEH3$_DEFINE_FILTER_FUNC(_Name, expression) \
|
||||
_SEH3$_NESTED_FUNC_OPEN(_Name) \
|
||||
/* Declare the intrinsics for exception filters */ \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wshadow\"") \
|
||||
inline __attribute__((always_inline, gnu_inline)) \
|
||||
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; } \
|
||||
inline __attribute__((always_inline, gnu_inline)) \
|
||||
void * _exception_info() { return _SEH3$_TrylevelFrame.ExceptionPointers; } \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
\
|
||||
/* Now handle the actual filter expression */ \
|
||||
return (expression); \
|
||||
}
|
||||
|
||||
#define _SEH3$_FINALLY_FUNC_OPEN(_Name) \
|
||||
_SEH3$_NESTED_FUNC_OPEN(_Name) \
|
||||
/* Declare the intrinsics for the finally function */ \
|
||||
inline __attribute__((always_inline, gnu_inline)) \
|
||||
int _abnormal_termination() { return (_SEH3$_TrylevelFrame.ExceptionPointers != 0); } \
|
||||
\
|
||||
/* This construct makes sure that the finally function returns */ \
|
||||
/* a proper value at the end */ \
|
||||
for (; ; (void)({return 0; 0;}))
|
||||
|
||||
#define _SEH3$_FILTER(_Filter, _FilterExpression) \
|
||||
(__builtin_constant_p(_FilterExpression) ? (void*)(unsigned long)(unsigned char)(unsigned long)(_FilterExpression) : _Filter)
|
||||
|
||||
#define _SEH3$_FINALLY(_Finally) (_Finally)
|
||||
|
||||
#define _SEH3$_DEFINE_DUMMY_FINALLY(_Name) \
|
||||
auto inline __attribute__((always_inline,gnu_inline)) int _Name(int Action) { (void)Action; return 0; }
|
||||
|
||||
#define _SEH3$_DECLARE_CLEANUP_FUNC(_Name) \
|
||||
auto inline __attribute__((always_inline,gnu_inline)) void _Name(volatile SEH3$_REGISTRATION_FRAME *p)
|
||||
|
||||
#define _SEH3$_DEFINE_CLEANUP_FUNC(_Name) \
|
||||
_SEH3$_DECLARE_CLEANUP_FUNC(_Name) \
|
||||
{ \
|
||||
(void)p; \
|
||||
/* Unregister the frame */ \
|
||||
if (_SEH3$_TryLevel == 1) _SEH3$_UnregisterFrame(&_SEH3$_TrylevelFrame); \
|
||||
else _SEH3$_UnregisterTryLevel(&_SEH3$_TrylevelFrame); \
|
||||
\
|
||||
/* Invoke the finally function (an inline dummy in the __except case) */ \
|
||||
_SEH3$_FinallyFunction(1); \
|
||||
}
|
||||
|
||||
#endif /* __cplusplus || __clang__ */
|
||||
|
||||
|
||||
|
||||
#define _SEH3_TRY \
|
||||
_SEH3$_PreventInlining(); \
|
||||
/* Enter the outer scope */ \
|
||||
if (1) { \
|
||||
/* Declare local labels */ \
|
||||
__label__ _SEH3$_l_BeforeTry; \
|
||||
__label__ _SEH3$_l_DoTry; \
|
||||
__label__ _SEH3$_l_AfterTry; \
|
||||
__label__ _SEH3$_l_EndTry; \
|
||||
__label__ _SEH3$_l_HandlerTarget; \
|
||||
__label__ _SEH3$_l_OnException; \
|
||||
__label__ _SEH3$_l_BeforeFilterOrFinally; \
|
||||
__label__ _SEH3$_l_FilterOrFinally; \
|
||||
(void)&&_SEH3$_l_OnException; \
|
||||
(void)&&_SEH3$_l_BeforeFilterOrFinally; \
|
||||
(void)&&_SEH3$_l_FilterOrFinally; \
|
||||
\
|
||||
/* Count the try level. Outside of any __try, _SEH3$_TryLevel is 0 */ \
|
||||
enum { \
|
||||
_SEH3$_PreviousTryLevel = _SEH3$_TryLevel, \
|
||||
_SEH3$_TryLevel = _SEH3$_PreviousTryLevel + 1, \
|
||||
}; \
|
||||
\
|
||||
/* Forward declaration of the auto cleanup function */ \
|
||||
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
||||
\
|
||||
/* Allocate a registration frame */ \
|
||||
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
|
||||
\
|
||||
goto _SEH3$_l_BeforeTry; \
|
||||
/* Silence warning */ goto _SEH3$_l_AfterTry; \
|
||||
\
|
||||
_SEH3$_l_DoTry: \
|
||||
if (1)
|
||||
|
||||
|
||||
#define _SEH3_EXCEPT(...) \
|
||||
/* End of the try block */ \
|
||||
_SEH3$_l_AfterTry: (void)0; \
|
||||
goto _SEH3$_l_EndTry; \
|
||||
\
|
||||
_SEH3$_l_BeforeTry: (void)0; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
\
|
||||
/* Forward declaration of the filter function */ \
|
||||
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FilterFunction); \
|
||||
\
|
||||
/* Create a static data table that contains the jump target and filter function */ \
|
||||
static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { &&_SEH3$_l_HandlerTarget, _SEH3$_FILTER(&_SEH3$_FilterFunction, (__VA_ARGS__)), _SEH3$_TryLevel, _SEH3$_HANDLER_TYPE }; \
|
||||
\
|
||||
/* Register the registration record. */ \
|
||||
if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
||||
else _SEH3$_RegisterTryLevel_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
||||
\
|
||||
/* Define an empty inline finally function */ \
|
||||
_SEH3$_DEFINE_DUMMY_FINALLY(_SEH3$_FinallyFunction) \
|
||||
\
|
||||
/* Allow intrinsics for __except to be used */ \
|
||||
_SEH3$_DECLARE_EXCEPT_INTRINSICS(); \
|
||||
\
|
||||
goto _SEH3$_l_DoTry; \
|
||||
\
|
||||
_SEH3$_l_BeforeFilterOrFinally: (void)0; \
|
||||
/* Make sure the filter function doesn't use esp */ \
|
||||
_SEH3$_EnforceFramePointer(); \
|
||||
\
|
||||
_SEH3$_l_FilterOrFinally: (void)0; \
|
||||
/* Emit the filter function */ \
|
||||
_SEH3$_DEFINE_FILTER_FUNC(_SEH3$_FilterFunction, (__VA_ARGS__)) \
|
||||
\
|
||||
_SEH3$_l_HandlerTarget: (void)0; \
|
||||
_SEH3$_EnforceFramePointer(); \
|
||||
\
|
||||
if (1) \
|
||||
{ \
|
||||
/* Prevent this block from being optimized away */ \
|
||||
asm volatile ("#\n"); \
|
||||
if (1)
|
||||
|
||||
|
||||
#define _SEH3_FINALLY \
|
||||
/* End of the try block */ \
|
||||
_SEH3$_l_AfterTry: (void)0; \
|
||||
/* Set ExceptionPointers to 0, this is used by _abnormal_termination() */ \
|
||||
_SEH3$_TrylevelFrame.ExceptionPointers = 0; \
|
||||
\
|
||||
goto _SEH3$_l_EndTry; \
|
||||
\
|
||||
_SEH3$_l_BeforeTry: (void)0; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
\
|
||||
/* Forward declaration of the finally function */ \
|
||||
_SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \
|
||||
\
|
||||
/* Create a static data table that contains the finally function */ \
|
||||
static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { 0, _SEH3$_FINALLY(&_SEH3$_FinallyFunction), _SEH3$_TryLevel, _SEH3$_HANDLER_TYPE }; \
|
||||
\
|
||||
/* Register the registration record. */ \
|
||||
if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
||||
else _SEH3$_RegisterTryLevel_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
|
||||
_SEH3$_TrylevelFrame.ExceptionPointers = (PSEH3$_EXCEPTION_POINTERS)1; \
|
||||
\
|
||||
goto _SEH3$_l_DoTry; \
|
||||
\
|
||||
_SEH3$_l_HandlerTarget: (void)0; \
|
||||
_SEH3$_EnforceFramePointer(); \
|
||||
\
|
||||
_SEH3$_l_BeforeFilterOrFinally: (void)0; \
|
||||
_SEH3$_EnforceFramePointer(); \
|
||||
_SEH3$_l_FilterOrFinally: (void)0; \
|
||||
_SEH3$_FINALLY_FUNC_OPEN(_SEH3$_FinallyFunction)
|
||||
|
||||
|
||||
#define _SEH3_END \
|
||||
}; \
|
||||
goto _SEH3$_l_EndTry; \
|
||||
\
|
||||
_SEH3$_l_OnException: (void)0; \
|
||||
/* Force GCC to create proper code pathes */ \
|
||||
_SEH3$_SCARE_GCC(); \
|
||||
\
|
||||
_SEH3$_l_EndTry:(void)0; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
\
|
||||
/* Implementation of the auto cleanup function */ \
|
||||
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
||||
\
|
||||
/* Close the outer scope */ \
|
||||
}
|
||||
|
||||
#define _SEH3_LEAVE goto _SEH3$_l_AfterTry
|
||||
|
||||
#define _SEH3_VOLATILE volatile
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; // extern "C"
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue