mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:25:41 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
48
sdk/lib/pseh/CMakeLists.txt
Normal file
48
sdk/lib/pseh/CMakeLists.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
|
||||
if(ARCH STREQUAL "i386")
|
||||
list(APPEND ASM_SOURCE
|
||||
i386/seh.s
|
||||
i386/seh_prolog.s)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
|
||||
if(USE_PSEH3)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/pseh)
|
||||
list(APPEND SOURCE
|
||||
i386/pseh3.c
|
||||
i386/pseh3_i386.S)
|
||||
elseif(USE_DUMMY_PSEH)
|
||||
list(APPEND SOURCE dummy.c)
|
||||
elseif(ARCH STREQUAL "i386")
|
||||
list(APPEND SOURCE
|
||||
i386/framebased.S
|
||||
i386/framebased-gcchack.c
|
||||
i386/framebased-gcchack-asm.S)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
list(APPEND SOURCE amd64/framebased.S)
|
||||
elseif(ARCH STREQUAL "powerpc")
|
||||
list(APPEND SOURCE powerpc/framebased.S)
|
||||
endif()
|
||||
|
||||
add_library(pseh ${SOURCE} ${ASM_SOURCE})
|
||||
target_link_libraries(pseh chkstk)
|
||||
add_dependencies(pseh psdk)
|
||||
|
||||
else()
|
||||
|
||||
if(ARCH STREQUAL "amd64")
|
||||
list(APPEND ASM_SOURCE
|
||||
amd64/seh.s
|
||||
amd64/seh_prolog.s)
|
||||
elseif(ARCH STREQUAL "arm")
|
||||
list(APPEND ASM_SOURCE
|
||||
arm/seh_prolog.s)
|
||||
endif()
|
||||
|
||||
list(APPEND SOURCE dummy.c)
|
||||
add_asm_files(pseh_asm ${ASM_SOURCE})
|
||||
add_library(pseh ${SOURCE} ${pseh_asm})
|
||||
add_dependencies(pseh asm)
|
||||
|
||||
endif()
|
25
sdk/lib/pseh/amd64/framebased.S
Normal file
25
sdk/lib/pseh/amd64/framebased.S
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
.text
|
||||
.intel_syntax noprefix
|
||||
|
||||
.globl _SEHCleanHandlerEnvironment
|
||||
_SEHCleanHandlerEnvironment:
|
||||
ret
|
||||
|
||||
.globl _SEHCurrentRegistration
|
||||
_SEHCurrentRegistration:
|
||||
ret
|
||||
|
||||
.globl _SEHRegisterFrame
|
||||
_SEHRegisterFrame:
|
||||
ret
|
||||
|
||||
.globl _SEHUnregisterFrame
|
||||
_SEHUnregisterFrame:
|
||||
ret
|
||||
|
||||
.globl _SEHGlobalUnwind
|
||||
_SEHGlobalUnwind:
|
||||
ret
|
||||
|
||||
// EOF
|
52
sdk/lib/pseh/amd64/seh.s
Normal file
52
sdk/lib/pseh/amd64/seh.s
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CRT
|
||||
* FILE: lib/pseh/amd64/seh.S
|
||||
* PURPOSE: SEH Support for the CRT
|
||||
* PROGRAMMERS:
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
#define DISPOSITION_DISMISS 0
|
||||
#define DISPOSITION_CONTINUE_SEARCH 1
|
||||
#define DISPOSITION_COLLIDED_UNWIND 3
|
||||
|
||||
#define EXCEPTION_EXIT_UNWIND 4
|
||||
#define EXCEPTION_UNWINDING 2
|
||||
|
||||
|
||||
EXTERN RtlUnwind:PROC
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PUBLIC _global_unwind2
|
||||
PUBLIC _local_unwind2
|
||||
PUBLIC _abnormal_termination
|
||||
PUBLIC _except_handler2
|
||||
PUBLIC _except_handler3
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
.code
|
||||
_unwind_handler:
|
||||
ret
|
||||
|
||||
_global_unwind2:
|
||||
ret
|
||||
|
||||
_abnormal_termination:
|
||||
ret
|
||||
|
||||
_local_unwind2:
|
||||
ret
|
||||
|
||||
_except_handler2:
|
||||
ret
|
||||
|
||||
_except_handler3:
|
||||
ret
|
||||
|
||||
END
|
25
sdk/lib/pseh/amd64/seh_prolog.s
Normal file
25
sdk/lib/pseh/amd64/seh_prolog.s
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* COPYRIGHT: GNU GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS CRT
|
||||
* FILE: lib/pseh/amd64/seh_prolog.S
|
||||
* PURPOSE: SEH Support for MSVC
|
||||
* PROGRAMMERS: Timo Kreuzer
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
EXTERN _except_handler3:PROC
|
||||
|
||||
.code
|
||||
|
||||
PUBLIC _SEH_prolog
|
||||
_SEH_prolog:
|
||||
|
||||
|
||||
PUBLIC _SEH_epilog
|
||||
_SEH_epilog:
|
||||
ret
|
||||
|
||||
END
|
31
sdk/lib/pseh/arm/seh_prolog.s
Normal file
31
sdk/lib/pseh/arm/seh_prolog.s
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* COPYRIGHT: GNU GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS CRT
|
||||
* FILE: lib/pseh/arm/seh_prolog.S
|
||||
* PURPOSE: SEH Support for MSVC / ARM
|
||||
* PROGRAMMERS: Timo Kreuzer
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "ksarm.h"
|
||||
|
||||
TEXTAREA
|
||||
|
||||
IMPORT __except_handler
|
||||
|
||||
LEAF_ENTRY _SEH_prolog
|
||||
|
||||
|
||||
LEAF_END _SEH_prolog
|
||||
|
||||
|
||||
|
||||
LEAF_ENTRY _SEH_epilog
|
||||
|
||||
|
||||
LEAF_END _SEH_epilog
|
||||
|
||||
|
||||
|
||||
END
|
4
sdk/lib/pseh/dummy.c
Normal file
4
sdk/lib/pseh/dummy.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* intentionally empty file */
|
||||
|
||||
int _SEH2_Volatile0 = 0;
|
||||
int _SEH2_VolatileExceptionCode = 0xC0000005;
|
503
sdk/lib/pseh/framebased.c
Normal file
503
sdk/lib/pseh/framebased.c
Normal file
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#define _NTSYSTEM_
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <pseh/pseh.h>
|
||||
#include <pseh/framebased/internal.h>
|
||||
#include <pseh/excpt.h>
|
||||
#include <pseh/framebased.h>
|
||||
|
||||
#include <excpt.h>
|
||||
|
||||
/* Tracing */
|
||||
#ifdef _SEH_ENABLE_TRACE
|
||||
extern unsigned long __cdecl DbgPrint(const char * format, ...);
|
||||
|
||||
#define _SEH_TRACE_HEADER_(FRAME_) \
|
||||
DbgPrint("[PSEH:%p]%s:%d:", FRAME_, __FILE__, __LINE__);
|
||||
|
||||
#define _SEH_TRACE_TRAILER_ \
|
||||
DbgPrint("\n");
|
||||
|
||||
#define _SEH_FILTER_RET_STRING_(RET_) \
|
||||
(((int)(RET_) < 0) ? "_SEH_CONTINUE_EXECUTION" : (((int)(RET_) > 0) ? "_SEH_EXECUTE_HANDLER" : "_SEH_CONTINUE_SEARCH"))
|
||||
|
||||
#define _SEH_TRACE_LINE_(FRAME_, ARGS_) \
|
||||
{ \
|
||||
_SEH_TRACE_HEADER_(FRAME_); \
|
||||
DbgPrint ARGS_; \
|
||||
_SEH_TRACE_TRAILER_; \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_ENTER_LEAVE) \
|
||||
{ \
|
||||
_SEH_TRACE_HEADER_(FRAME_); \
|
||||
DbgPrint(">>> %s(", (FUNCNAME_)); \
|
||||
DbgPrint ARGS_; \
|
||||
DbgPrint(")"); \
|
||||
_SEH_TRACE_TRAILER_; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_ENTER_LEAVE) \
|
||||
{ \
|
||||
_SEH_TRACE_HEADER_(FRAME_); \
|
||||
DbgPrint("<<< %s => ", (FUNCNAME_)); \
|
||||
DbgPrint ARGS_; \
|
||||
_SEH_TRACE_TRAILER_; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_EXCEPTION_RECORD) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"ExceptionRecord %p = { ExceptionCode : %08X, ExceptionFlags : %08X, ExceptionRecord : %p, ExceptionAddress : %p }", \
|
||||
(ER_), \
|
||||
(ER_)->ExceptionCode, \
|
||||
(ER_)->ExceptionFlags, \
|
||||
(ER_)->ExceptionRecord, \
|
||||
(ER_)->ExceptionAddress \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef _X86_
|
||||
#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CONTEXT) \
|
||||
{ \
|
||||
if(((CONTEXT_)->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"eax=%08X ebx=%08X ecx=%08X edx=%08X esi=%08X edi=%08X", \
|
||||
(CONTEXT_)->Eax, \
|
||||
(CONTEXT_)->Ebx, \
|
||||
(CONTEXT_)->Ecx, \
|
||||
(CONTEXT_)->Edx, \
|
||||
(CONTEXT_)->Esi, \
|
||||
(CONTEXT_)->Edi \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
if(((CONTEXT_)->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"eip=%08X esp=%08X ebp=%08X efl=%08X cs=%08X ss=%08X", \
|
||||
(CONTEXT_)->Eip, \
|
||||
(CONTEXT_)->Esp, \
|
||||
(CONTEXT_)->Ebp, \
|
||||
(CONTEXT_)->EFlags, \
|
||||
(CONTEXT_)->SegCs, \
|
||||
(CONTEXT_)->SegSs \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
if(((CONTEXT_)->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"ds=%08X es=%08X fs=%08X gs=%08X", \
|
||||
(CONTEXT_)->SegDs, \
|
||||
(CONTEXT_)->SegEs, \
|
||||
(CONTEXT_)->SegFs, \
|
||||
(CONTEXT_)->SegGs \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
|
||||
#endif
|
||||
|
||||
#define _SEH_TRACE_UNWIND(FRAME_, ARGS_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_UNWIND) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_((FRAME_), ARGS_); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_TRYLEVEL) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_((FRAME_), ("trylevel %p, filter %p", (TRYLEVEL_), (TRYLEVEL_)->SPT_Handlers.SH_Filter)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FILTER) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"trylevel %p, calling filter %p, ExceptionCode %08X", \
|
||||
(TRYLEVEL_), \
|
||||
(TRYLEVEL_)->SPT_Handlers.SH_Filter, \
|
||||
(ER_)->ExceptionCode \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FILTER) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"trylevel %p, filter %p => %s", \
|
||||
(TRYLEVEL_), \
|
||||
(TRYLEVEL_)->SPT_Handlers.SH_Filter, \
|
||||
_SEH_FILTER_RET_STRING_(RET_) \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_FILTER) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"trylevel %p => %s", \
|
||||
(TRYLEVEL_), \
|
||||
_SEH_FILTER_RET_STRING_(RET_) \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_HANDLER) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_((FRAME_), ("trylevel %p, handling", (TRYLEVEL_))); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FINALLY) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"trylevel %p, calling exit routine %p", \
|
||||
(TRYLEVEL_), \
|
||||
(TRYLEVEL_)->SPT_Handlers.SH_Finally \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_) \
|
||||
{ \
|
||||
if((FRAME_)->SPF_Tracing & _SEH_DO_TRACE_CALL_FINALLY) \
|
||||
{ \
|
||||
_SEH_TRACE_LINE_ \
|
||||
( \
|
||||
(FRAME_), \
|
||||
( \
|
||||
"trylevel %p, exit routine %p returned", \
|
||||
(TRYLEVEL_), \
|
||||
(TRYLEVEL_)->SPT_Handlers.SH_Finally \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
#define _SEH_TRACE_ENTER(FRAME_, FUNCNAME_, ARGS_)
|
||||
#define _SEH_TRACE_LEAVE(FRAME_, FUNCNAME_, ARGS_)
|
||||
#define _SEH_TRACE_EXCEPTION_RECORD(FRAME_, ER_)
|
||||
#define _SEH_TRACE_CONTEXT(FRAME_, CONTEXT_)
|
||||
#define _SEH_TRACE_UNWIND(FRAME_, ARGS_)
|
||||
#define _SEH_TRACE_TRYLEVEL(FRAME_, TRYLEVEL_)
|
||||
#define _SEH_TRACE_ENTER_CALL_FILTER(FRAME_, TRYLEVEL_, ER_)
|
||||
#define _SEH_TRACE_LEAVE_CALL_FILTER(FRAME_, TRYLEVEL_, RET_)
|
||||
#define _SEH_TRACE_FILTER(FRAME_, TRYLEVEL_, RET_)
|
||||
#define _SEH_TRACE_ENTER_CALL_HANDLER(FRAME_, TRYLEVEL_)
|
||||
#define _SEH_TRACE_ENTER_CALL_FINALLY(FRAME_, TRYLEVEL_)
|
||||
#define _SEH_TRACE_LEAVE_CALL_FINALLY(FRAME_, TRYLEVEL_)
|
||||
#endif
|
||||
|
||||
/* Assembly helpers, see i386/framebased.asm */
|
||||
extern void __cdecl _SEHCleanHandlerEnvironment(void);
|
||||
extern struct __SEHRegistration * __cdecl _SEHRegisterFrame(_SEHRegistration_t *);
|
||||
extern void __cdecl _SEHUnregisterFrame(void);
|
||||
extern void __cdecl _SEHGlobalUnwind(_SEHPortableFrame_t *);
|
||||
extern _SEHRegistration_t * __cdecl _SEHCurrentRegistration(void);
|
||||
|
||||
/* Borland C++ uses a different decoration (i.e. none) for stdcall functions */
|
||||
extern void __stdcall RtlUnwind(void *, void *, PEXCEPTION_RECORD, void *);
|
||||
void const * _SEHRtlUnwind = RtlUnwind;
|
||||
|
||||
static void __stdcall _SEHLocalUnwind
|
||||
(
|
||||
_SEHPortableFrame_t * frame,
|
||||
_SEHPortableTryLevel_t * dsttrylevel
|
||||
)
|
||||
{
|
||||
_SEHPortableTryLevel_t * trylevel;
|
||||
|
||||
_SEH_TRACE_UNWIND(frame, ("enter local unwind from %p to %p", frame->SPF_TopTryLevel, dsttrylevel));
|
||||
|
||||
for
|
||||
(
|
||||
trylevel = frame->SPF_TopTryLevel;
|
||||
trylevel != dsttrylevel;
|
||||
trylevel = trylevel->SPT_Next
|
||||
)
|
||||
{
|
||||
_SEHFinally_t pfnFinally;
|
||||
|
||||
/* ASSERT(trylevel); */
|
||||
|
||||
pfnFinally = trylevel->SPT_Handlers.SH_Finally;
|
||||
|
||||
if(pfnFinally)
|
||||
{
|
||||
_SEH_TRACE_ENTER_CALL_FINALLY(frame, trylevel);
|
||||
pfnFinally(frame);
|
||||
_SEH_TRACE_LEAVE_CALL_FINALLY(frame, trylevel);
|
||||
}
|
||||
}
|
||||
|
||||
_SEH_TRACE_UNWIND(frame, ("leave local unwind from %p to %p", frame->SPF_TopTryLevel, dsttrylevel));
|
||||
}
|
||||
|
||||
static void __cdecl _SEHCallHandler
|
||||
(
|
||||
_SEHPortableFrame_t * frame,
|
||||
_SEHPortableTryLevel_t * trylevel
|
||||
)
|
||||
{
|
||||
_SEHGlobalUnwind(frame);
|
||||
_SEHLocalUnwind(frame, trylevel);
|
||||
_SEH_TRACE_ENTER_CALL_HANDLER(frame, trylevel);
|
||||
frame->SPF_Handler(trylevel);
|
||||
/* ASSERT(0); */
|
||||
}
|
||||
|
||||
static int __cdecl _SEHFrameHandler
|
||||
(
|
||||
struct _EXCEPTION_RECORD * ExceptionRecord,
|
||||
void * EstablisherFrame,
|
||||
struct _CONTEXT * ContextRecord,
|
||||
void * DispatcherContext
|
||||
)
|
||||
{
|
||||
_SEHPortableFrame_t * frame;
|
||||
|
||||
_SEHCleanHandlerEnvironment();
|
||||
|
||||
frame = EstablisherFrame;
|
||||
|
||||
_SEH_TRACE_ENTER
|
||||
(
|
||||
frame,
|
||||
"_SEHFrameHandler",
|
||||
(
|
||||
"%p, %p, %p, %p",
|
||||
ExceptionRecord,
|
||||
EstablisherFrame,
|
||||
ContextRecord,
|
||||
DispatcherContext
|
||||
)
|
||||
);
|
||||
|
||||
_SEH_TRACE_EXCEPTION_RECORD(frame, ExceptionRecord);
|
||||
_SEH_TRACE_CONTEXT(frame, ContextRecord);
|
||||
|
||||
/* Unwinding */
|
||||
if(ExceptionRecord->ExceptionFlags & (4 | 2))
|
||||
{
|
||||
_SEH_TRACE_UNWIND(frame, ("enter forced unwind"));
|
||||
_SEHLocalUnwind(frame, NULL);
|
||||
_SEH_TRACE_UNWIND(frame, ("leave forced unwind"));
|
||||
}
|
||||
/* Handling */
|
||||
else
|
||||
{
|
||||
int ret;
|
||||
_SEHPortableTryLevel_t * trylevel;
|
||||
|
||||
if(ExceptionRecord->ExceptionCode)
|
||||
frame->SPF_Code = ExceptionRecord->ExceptionCode;
|
||||
else
|
||||
frame->SPF_Code = 0xC0000001;
|
||||
|
||||
for
|
||||
(
|
||||
trylevel = frame->SPF_TopTryLevel;
|
||||
trylevel != NULL;
|
||||
trylevel = trylevel->SPT_Next
|
||||
)
|
||||
{
|
||||
_SEHFilter_t pfnFilter = trylevel->SPT_Handlers.SH_Filter;
|
||||
|
||||
_SEH_TRACE_TRYLEVEL(frame, trylevel);
|
||||
|
||||
switch((UINT_PTR)pfnFilter)
|
||||
{
|
||||
case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER):
|
||||
case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH):
|
||||
case (UINT_PTR)_SEH_STATIC_FILTER(_SEH_CONTINUE_EXECUTION):
|
||||
{
|
||||
ret = (int)((UINT_PTR)pfnFilter) - 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if(trylevel->SPT_Handlers.SH_Filter)
|
||||
{
|
||||
EXCEPTION_POINTERS ep;
|
||||
|
||||
ep.ExceptionRecord = ExceptionRecord;
|
||||
ep.ContextRecord = ContextRecord;
|
||||
|
||||
_SEH_TRACE_ENTER_CALL_FILTER(frame, trylevel, ExceptionRecord);
|
||||
ret = pfnFilter(&ep, frame);
|
||||
_SEH_TRACE_LEAVE_CALL_FILTER(frame, trylevel, ret);
|
||||
}
|
||||
else
|
||||
ret = _SEH_CONTINUE_SEARCH;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_SEH_TRACE_FILTER(frame, trylevel, ret);
|
||||
|
||||
/* _SEH_CONTINUE_EXECUTION */
|
||||
if(ret < 0)
|
||||
{
|
||||
_SEH_TRACE_LEAVE(frame, "_SEHFrameHandler", ("ExceptionContinueExecution"));
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
/* _SEH_EXECUTE_HANDLER */
|
||||
else if(ret > 0)
|
||||
_SEHCallHandler(frame, trylevel);
|
||||
/* _SEH_CONTINUE_SEARCH */
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
|
||||
_SEH_TRACE_LEAVE(frame, "_SEHFrameHandler", ("ExceptionContinueSearch"));
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
void __stdcall _SEHEnterFrame_s(_SEHPortableFrame_t * frame)
|
||||
{
|
||||
_SEHEnterFrame_f(frame);
|
||||
}
|
||||
|
||||
void __stdcall _SEHLeaveFrame_s(void)
|
||||
{
|
||||
_SEHLeaveFrame_f();
|
||||
}
|
||||
|
||||
void __stdcall _SEHReturn_s(void)
|
||||
{
|
||||
_SEHReturn_f();
|
||||
}
|
||||
|
||||
void _SEH_FASTCALL _SEHEnterFrame_f(_SEHPortableFrame_t * frame)
|
||||
{
|
||||
/* ASSERT(frame); */
|
||||
/* ASSERT(trylevel); */
|
||||
frame->SPF_Registration.SER_Handler = _SEHFrameHandler;
|
||||
frame->SPF_Code = 0;
|
||||
_SEHRegisterFrame(&frame->SPF_Registration);
|
||||
}
|
||||
|
||||
void _SEH_FASTCALL _SEHLeaveFrame_f(void)
|
||||
{
|
||||
/* _SEHPortableFrame_t * frame;
|
||||
|
||||
frame = _SEH_CONTAINING_RECORD
|
||||
(
|
||||
_SEHCurrentRegistration(),
|
||||
_SEHPortableFrame_t,
|
||||
SPF_Registration
|
||||
); */
|
||||
|
||||
/* ASSERT(frame); */
|
||||
/* ASSERT(frame->SPF_TopTryLevel == NULL) */
|
||||
|
||||
_SEHUnregisterFrame();
|
||||
}
|
||||
|
||||
void _SEH_FASTCALL _SEHReturn_f(void)
|
||||
{
|
||||
_SEHPortableFrame_t * frame;
|
||||
|
||||
frame = _SEH_CONTAINING_RECORD
|
||||
(
|
||||
_SEHCurrentRegistration(),
|
||||
_SEHPortableFrame_t,
|
||||
SPF_Registration
|
||||
);
|
||||
|
||||
_SEHLocalUnwind(frame, NULL);
|
||||
_SEHUnregisterFrame();
|
||||
}
|
||||
|
||||
/* EOF */
|
89
sdk/lib/pseh/i386/framebased-gcchack-asm.S
Normal file
89
sdk/lib/pseh/i386/framebased-gcchack-asm.S
Normal file
|
@ -0,0 +1,89 @@
|
|||
// 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 dos 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.
|
||||
|
||||
.text
|
||||
.intel_syntax noprefix
|
||||
|
||||
.func _SEH2EnterHandleTrylevel
|
||||
.globl __SEH2EnterHandleTrylevel
|
||||
__SEH2EnterHandleTrylevel:
|
||||
mov eax, [esp+8]
|
||||
mov ecx, [esp]
|
||||
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]
|
||||
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+12]
|
||||
mov ebx, [esp+16]
|
||||
mov esi, [esp+20]
|
||||
mov edi, [esp+24]
|
||||
mov esp, [esp+8]
|
||||
jmp eax
|
||||
.endfunc
|
||||
|
||||
.func __SEH2FrameHandler
|
||||
.globl ___SEH2FrameHandler
|
||||
___SEH2FrameHandler:
|
||||
|
||||
.extern __SEH2FrameHandler
|
||||
|
||||
cld
|
||||
jmp __SEH2FrameHandler
|
||||
.endfunc
|
||||
|
||||
.func __SEH2UnwindHandler
|
||||
.globl ___SEH2UnwindHandler
|
||||
___SEH2UnwindHandler:
|
||||
|
||||
.extern __SEH2UnwindHandler
|
||||
|
||||
cld
|
||||
jmp __SEH2UnwindHandler
|
||||
.endfunc
|
||||
|
||||
// EOF
|
310
sdk/lib/pseh/i386/framebased-gcchack.c
Normal file
310
sdk/lib/pseh/i386/framebased-gcchack.c
Normal file
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#define _NTSYSTEM_ /* removes dllimport attribute from RtlUnwind */
|
||||
|
||||
#define STRICT
|
||||
#include <windef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <pseh/pseh2.h>
|
||||
#include <excpt.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#ifndef EXCEPTION_EXIT_UNWIND
|
||||
#define EXCEPTION_EXIT_UNWIND 4
|
||||
#endif
|
||||
|
||||
#ifndef EXCEPTION_UNWINDING
|
||||
#define EXCEPTION_UNWINDING 2
|
||||
#endif
|
||||
|
||||
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 *);
|
||||
|
||||
typedef struct __SEHTrampoline
|
||||
{
|
||||
unsigned char STR_MovEcx;
|
||||
unsigned char * STR_Closure;
|
||||
unsigned char STR_Jmp;
|
||||
unsigned char * STR_Function;
|
||||
}
|
||||
__attribute__((packed))
|
||||
_SEHTrampoline_t;
|
||||
|
||||
FORCEINLINE
|
||||
int _SEHIsTrampoline(_SEHTrampoline_t * trampoline_)
|
||||
{
|
||||
return trampoline_->STR_MovEcx == 0xb9 && trampoline_->STR_Jmp == 0xe9;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void * _SEHFunctionFromTrampoline(_SEHTrampoline_t * trampoline_)
|
||||
{
|
||||
return (int)(trampoline_ + 1) + trampoline_->STR_Function;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
|
||||
{
|
||||
return trampoline_->STR_Closure;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
_SEH2Registration_t * __cdecl _SEH2CurrentRegistration(void)
|
||||
{
|
||||
return (_SEH2Registration_t *)__readfsdword(0);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void __cdecl __SEH2EnterFrame(_SEH2Registration_t * frame)
|
||||
{
|
||||
frame->SER_Prev = _SEH2CurrentRegistration();
|
||||
__writefsdword(0, (unsigned long)frame);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void __cdecl __SEH2LeaveFrame(void)
|
||||
{
|
||||
__writefsdword(0, (unsigned long)_SEH2CurrentRegistration()->SER_Prev);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void _SEH2GlobalUnwind(void * target)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"push %%ebp\n\t"
|
||||
"push $0\n\t"
|
||||
"push $0\n\t"
|
||||
"push $Return%=\n\t"
|
||||
"push %[target]\n\t"
|
||||
"call %c[RtlUnwind]\n"
|
||||
"Return%=:\n\t"
|
||||
"pop %%ebp" :
|
||||
:
|
||||
[target] "g" (target), [RtlUnwind] "g" (&RtlUnwind) :
|
||||
"eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
__SEH_EXCEPT_RET _SEH2Except(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel, struct _EXCEPTION_POINTERS * ep)
|
||||
{
|
||||
void * filter = trylevel->ST_Filter;
|
||||
void * context = NULL;
|
||||
__SEH_EXCEPT_RET ret;
|
||||
|
||||
if(filter == (void *)0)
|
||||
return 0;
|
||||
|
||||
if(filter == (void *)1)
|
||||
return 1;
|
||||
|
||||
if(filter == (void *)-1)
|
||||
return -1;
|
||||
|
||||
if(_SEHIsTrampoline((_SEHTrampoline_t *)filter))
|
||||
{
|
||||
context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)filter);
|
||||
filter = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)filter);
|
||||
}
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"push %[ep]\n\t"
|
||||
"push %[frame]\n\t"
|
||||
"call *%[filter]\n\t"
|
||||
"pop %%edx\n\t"
|
||||
"pop %%edx" :
|
||||
[ret] "=a" (ret) :
|
||||
"c" (context), [filter] "r" (filter), [frame] "r" (frame), [ep] "r" (ep) :
|
||||
"edx", "flags", "memory"
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void _SEH2Finally(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
|
||||
{
|
||||
if(trylevel->ST_Filter == NULL && trylevel->ST_Body != NULL)
|
||||
{
|
||||
void * body = trylevel->ST_Body;
|
||||
void * context = NULL;
|
||||
|
||||
if(_SEHIsTrampoline((_SEHTrampoline_t *)body))
|
||||
{
|
||||
context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)body);
|
||||
body = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)body);
|
||||
}
|
||||
|
||||
__asm__ __volatile__("call *%1" : : "c" (context), "r" (body) : "eax", "edx", "flags", "memory");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct __SEH2UnwindFrame
|
||||
{
|
||||
_SEH2Registration_t SUF_Registration;
|
||||
_SEH2Frame_t * SUF_Frame;
|
||||
volatile _SEH2TryLevel_t * SUF_TargetTryLevel;
|
||||
}
|
||||
_SEH2UnwindFrame_t;
|
||||
|
||||
static void _SEH2LocalUnwind(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
|
||||
|
||||
extern
|
||||
int __cdecl _SEH2UnwindHandler
|
||||
(
|
||||
struct _EXCEPTION_RECORD * ExceptionRecord,
|
||||
void * EstablisherFrame,
|
||||
struct _CONTEXT * ContextRecord,
|
||||
void * DispatcherContext
|
||||
)
|
||||
{
|
||||
if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
|
||||
{
|
||||
_SEH2UnwindFrame_t * unwindframe = CONTAINING_RECORD(EstablisherFrame, _SEH2UnwindFrame_t, SUF_Registration);
|
||||
_SEH2LocalUnwind(unwindframe->SUF_Frame, unwindframe->SUF_TargetTryLevel);
|
||||
*((void **)DispatcherContext) = EstablisherFrame;
|
||||
return ExceptionCollidedUnwind;
|
||||
}
|
||||
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
static
|
||||
void _SEH2LocalUnwind(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * dsttrylevel)
|
||||
{
|
||||
volatile _SEH2TryLevel_t * trylevel;
|
||||
_SEH2UnwindFrame_t unwindframe;
|
||||
|
||||
unwindframe.SUF_Frame = frame;
|
||||
unwindframe.SUF_TargetTryLevel = dsttrylevel;
|
||||
|
||||
unwindframe.SUF_Registration.SER_Handler = &__SEH2UnwindHandler;
|
||||
__SEH2EnterFrame(&unwindframe.SUF_Registration);
|
||||
|
||||
for(trylevel = frame->SF_TopTryLevel; trylevel && trylevel != dsttrylevel; trylevel = trylevel->ST_Next)
|
||||
{
|
||||
frame->SF_TopTryLevel = trylevel->ST_Next;
|
||||
_SEH2Finally(frame, trylevel);
|
||||
}
|
||||
|
||||
__SEH2LeaveFrame();
|
||||
}
|
||||
|
||||
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, &fulltrylevel->SHT_Common);
|
||||
frame->SF_TopTryLevel = fulltrylevel->SHT_Common.ST_Next;
|
||||
|
||||
__SEH2Handle
|
||||
(
|
||||
fulltrylevel->SHT_Common.ST_Body,
|
||||
fulltrylevel->SHT_Esp,
|
||||
fulltrylevel->SHT_Ebp,
|
||||
fulltrylevel->SHT_Ebx,
|
||||
fulltrylevel->SHT_Esi,
|
||||
fulltrylevel->SHT_Edi
|
||||
);
|
||||
}
|
||||
|
||||
extern
|
||||
int __cdecl _SEH2FrameHandler
|
||||
(
|
||||
struct _EXCEPTION_RECORD * ExceptionRecord,
|
||||
void * EstablisherFrame,
|
||||
struct _CONTEXT * ContextRecord,
|
||||
void * DispatcherContext
|
||||
)
|
||||
{
|
||||
_SEH2Frame_t * frame;
|
||||
|
||||
frame = EstablisherFrame;
|
||||
|
||||
/* Unwinding */
|
||||
if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
|
||||
{
|
||||
_SEH2LocalUnwind(frame, NULL);
|
||||
}
|
||||
/* Handling */
|
||||
else
|
||||
{
|
||||
int ret = 0;
|
||||
volatile _SEH2TryLevel_t * trylevel;
|
||||
EXCEPTION_POINTERS ep;
|
||||
|
||||
ep.ExceptionRecord = ExceptionRecord;
|
||||
ep.ContextRecord = ContextRecord;
|
||||
|
||||
frame->SF_Code = ExceptionRecord->ExceptionCode;
|
||||
|
||||
for(trylevel = frame->SF_TopTryLevel; trylevel != NULL; trylevel = trylevel->ST_Next)
|
||||
{
|
||||
ret = _SEH2Except(frame, trylevel, &ep);
|
||||
|
||||
if(ret < 0)
|
||||
return ExceptionContinueExecution;
|
||||
else if(ret > 0)
|
||||
_SEH2Handle(frame, trylevel);
|
||||
}
|
||||
}
|
||||
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
extern
|
||||
void __cdecl _SEH2EnterFrame(_SEH2Frame_t * frame)
|
||||
{
|
||||
frame->SF_Registration.SER_Handler = __SEH2FrameHandler;
|
||||
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)
|
||||
{
|
||||
__SEH2LeaveFrame();
|
||||
}
|
||||
|
||||
extern
|
||||
void __cdecl _SEH2Return(void)
|
||||
{
|
||||
_SEH2LocalUnwind(CONTAINING_RECORD(_SEH2CurrentRegistration(), _SEH2Frame_t, SF_Registration), NULL);
|
||||
_SEH2LeaveFrame();
|
||||
}
|
||||
|
||||
/* EOF */
|
73
sdk/lib/pseh/i386/framebased.S
Normal file
73
sdk/lib/pseh/i386/framebased.S
Normal file
|
@ -0,0 +1,73 @@
|
|||
// 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 dos 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.
|
||||
|
||||
.text
|
||||
.intel_syntax noprefix
|
||||
|
||||
.globl __SEHCleanHandlerEnvironment
|
||||
__SEHCleanHandlerEnvironment:
|
||||
cld
|
||||
ret
|
||||
|
||||
.globl __SEHCurrentRegistration
|
||||
__SEHCurrentRegistration:
|
||||
mov eax, [fs:0]
|
||||
ret
|
||||
|
||||
.globl __SEHRegisterFrame
|
||||
__SEHRegisterFrame:
|
||||
mov ecx, [esp+4]
|
||||
mov eax, [fs:0]
|
||||
mov [ecx+0], eax
|
||||
mov [fs:0], ecx
|
||||
ret
|
||||
|
||||
.globl __SEHUnregisterFrame
|
||||
__SEHUnregisterFrame:
|
||||
mov ecx, [fs:0]
|
||||
mov ecx, [ecx+0]
|
||||
mov [fs:0], ecx
|
||||
ret
|
||||
|
||||
.globl __SEHGlobalUnwind
|
||||
__SEHGlobalUnwind:
|
||||
|
||||
.extern __SEHRtlUnwind
|
||||
|
||||
// RtlUnwind clobbers all the "don't clobber" registers, so we save them
|
||||
push ebx
|
||||
mov ebx, [esp+8]
|
||||
push esi
|
||||
push edi
|
||||
|
||||
push 0 // ReturnValue
|
||||
push 0 // ExceptionRecord
|
||||
push .RestoreRegisters // TargetIp
|
||||
push ebx // TargetFrame
|
||||
call [__SEHRtlUnwind]
|
||||
|
||||
.RestoreRegisters:
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
// EOF
|
361
sdk/lib/pseh/i386/pseh3.c
Normal file
361
sdk/lib/pseh/i386/pseh3.c
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* PROJECT: ReactOS system libraries
|
||||
* LICENSE: GNU GPL - See COPYING in the top level directory
|
||||
* PURPOSE: Support library for PSEH3
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* - Naming: To avoid naming conflicts, all internal identifiers are prefixed
|
||||
* with _SEH3$_.
|
||||
* - Frame graph: PSEH3 uses the same registration frame for every trylevel.
|
||||
* Only the top trylevel is registered in FS:0, the inner trylevels are linked
|
||||
* to the first trylevel frame. Only the first trylevel frame has the Handler
|
||||
* member set, it's 0 for all others as an identification. The EndOfChain
|
||||
* member of the FS:0 registered frame points to the last internal frame,
|
||||
* which is the frame itself, when only 1 trylevel is present.
|
||||
*
|
||||
* The registration graph looks like this:
|
||||
*
|
||||
* newer handlers
|
||||
* ---------------->
|
||||
*
|
||||
* fs:0 /----------------\
|
||||
* |-----------|<-\ |-----------|<-\ / |----------|<-\ \->|----------|
|
||||
* | <Next> | \-| <Next> | \--/--| <Next> | \---| <Next> |
|
||||
* | <Handler> | | <Handler> | / | <NULL> | | <NULL> |
|
||||
* |-----------| |-----------| / |----------| |----------|
|
||||
* |EndOfChain |---/
|
||||
* | ... |
|
||||
* |-----------|
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winnt.h>
|
||||
|
||||
/* We need the full structure with all non-volatile */
|
||||
#define _SEH3$_FRAME_ALL_NONVOLATILES 1
|
||||
#include "pseh3.h"
|
||||
#include "pseh3_asmdef.h"
|
||||
|
||||
/* Make sure the asm definitions match the structures */
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Next == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Next));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Handler == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Handler));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_EndOfChain == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, EndOfChain));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_ScopeTable == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ScopeTable));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_ExceptionPointers == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ExceptionPointers));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_ExceptionCode == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ExceptionCode));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Esp == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Esp));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Ebp == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Ebp));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_AllocaFrame == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, AllocaFrame));
|
||||
#ifdef _SEH3$_FRAME_ALL_NONVOLATILES
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Ebx == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Ebx));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Esi == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Esi));
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_Edi == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Edi));
|
||||
#endif
|
||||
#ifdef __clang__
|
||||
C_ASSERT(SEH3_REGISTRATION_FRAME_ReturnAddress == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ReturnAddress));
|
||||
#endif
|
||||
C_ASSERT(SEH3_SCOPE_TABLE_Filter == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Filter));
|
||||
C_ASSERT(SEH3_SCOPE_TABLE_Target == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target));
|
||||
|
||||
void
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_Unregister(
|
||||
volatile SEH3$_REGISTRATION_FRAME *Frame)
|
||||
{
|
||||
if (Frame->Handler)
|
||||
_SEH3$_UnregisterFrame(Frame);
|
||||
else
|
||||
_SEH3$_UnregisterTryLevel(Frame);
|
||||
}
|
||||
|
||||
static inline
|
||||
LONG
|
||||
_SEH3$_InvokeNestedFunctionFilter(
|
||||
volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame,
|
||||
PVOID Filter)
|
||||
{
|
||||
LONG FilterResult;
|
||||
|
||||
asm volatile (
|
||||
/* First call with param = 0 to get the frame layout */
|
||||
"xorl %%ecx, %%ecx\n\t"
|
||||
"xorl %%eax, %%eax\n\t"
|
||||
"call *%[Filter]\n\t"
|
||||
|
||||
/* The result is the frame base address that we passed in (0) plus the
|
||||
offset to the registration record. */
|
||||
"negl %%eax\n\t"
|
||||
"addl %[RegistrationFrame], %%eax\n\t"
|
||||
|
||||
/* Second call to get the filter result */
|
||||
"mov $1, %%ecx\n\t"
|
||||
"call *%[Filter]"
|
||||
: "=a" (FilterResult)
|
||||
: [RegistrationFrame] "m" (RegistrationFrame), [Filter] "m" (Filter)
|
||||
: "ecx", "edx");
|
||||
|
||||
return FilterResult;
|
||||
}
|
||||
|
||||
long
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_InvokeEmbeddedFilter(
|
||||
volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame);
|
||||
|
||||
long
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_InvokeEmbeddedFilterFromRegistration(
|
||||
volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame);
|
||||
|
||||
static inline
|
||||
LONG
|
||||
_SEH3$_InvokeFilter(
|
||||
volatile SEH3$_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;
|
||||
}
|
||||
|
||||
void
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_AutoCleanup(
|
||||
volatile SEH3$_REGISTRATION_FRAME *Frame)
|
||||
{
|
||||
if (Frame->Handler)
|
||||
_SEH3$_UnregisterFrame(Frame);
|
||||
else
|
||||
_SEH3$_UnregisterTryLevel(Frame);
|
||||
|
||||
/* Check for __finally frames */
|
||||
if (Frame->ScopeTable->Target == NULL)
|
||||
{
|
||||
_SEH3$_InvokeFilter(Frame, Frame->ScopeTable->Filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline
|
||||
LONG
|
||||
_SEH3$_GetFilterResult(
|
||||
PSEH3$_REGISTRATION_FRAME Record)
|
||||
{
|
||||
PVOID Filter = Record->ScopeTable->Filter;
|
||||
LONG Result;
|
||||
|
||||
/* Check for __finally frames */
|
||||
if (Record->ScopeTable->Target == NULL)
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
/* Check if we have a constant filter */
|
||||
if (((ULONG)Filter & 0xFFFFFF00) == 0)
|
||||
{
|
||||
/* Lowest 8 bit are sign extended to give the result */
|
||||
Result = (LONG)(CHAR)(ULONG)Filter;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the filter function */
|
||||
Result = _SEH3$_InvokeFilter(Record, Filter);
|
||||
}
|
||||
|
||||
/* Normalize the result */
|
||||
if (Result < 0) return EXCEPTION_CONTINUE_EXECUTION;
|
||||
else if (Result > 0) return EXCEPTION_EXECUTE_HANDLER;
|
||||
else return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
static inline
|
||||
VOID
|
||||
_SEH3$_CallFinally(
|
||||
PSEH3$_REGISTRATION_FRAME Record)
|
||||
{
|
||||
_SEH3$_InvokeFilter(Record, Record->ScopeTable->Filter);
|
||||
}
|
||||
|
||||
__attribute__((noreturn))
|
||||
static inline
|
||||
void
|
||||
_SEH3$_JumpToTarget(
|
||||
PSEH3$_REGISTRATION_FRAME RegistrationFrame)
|
||||
{
|
||||
if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CLANG_HANDLER)
|
||||
{
|
||||
asm volatile (
|
||||
/* Load the registers */
|
||||
"movl 24(%%ecx), %%esp\n\t"
|
||||
"movl 28(%%ecx), %%ebp\n\t"
|
||||
|
||||
"movl 36(%%ecx), %%ebx\n\t"
|
||||
"movl 40(%%ecx), %%esi\n\t"
|
||||
"movl 44(%%ecx), %%edi\n\t"
|
||||
|
||||
/* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
|
||||
"addl $4, %%esp\n\t"
|
||||
|
||||
/* Jump into the exception handler */
|
||||
"jmp *%[Target]"
|
||||
: :
|
||||
"c" (RegistrationFrame),
|
||||
"a" (RegistrationFrame->ScopeTable),
|
||||
[Target] "m" (RegistrationFrame->ScopeTable->Target)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile (
|
||||
/* Load the registers */
|
||||
"movl 24(%%ecx), %%esp\n\t"
|
||||
"movl 28(%%ecx), %%ebp\n\t"
|
||||
|
||||
/* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
|
||||
"addl $4, %%esp\n\t"
|
||||
|
||||
/* Jump into the exception handler */
|
||||
"jmp *%[Target]"
|
||||
: :
|
||||
"c" (RegistrationFrame),
|
||||
"a" (RegistrationFrame->ScopeTable),
|
||||
[Target] "m" (RegistrationFrame->ScopeTable->Target)
|
||||
);
|
||||
}
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void
|
||||
__fastcall
|
||||
_SEH3$_CallRtlUnwind(
|
||||
PSEH3$_REGISTRATION_FRAME RegistrationFrame);
|
||||
|
||||
|
||||
EXCEPTION_DISPOSITION
|
||||
__cdecl
|
||||
#ifndef __clang__
|
||||
__attribute__ ((__target__ ("cld")))
|
||||
#endif
|
||||
_SEH3$_except_handler(
|
||||
struct _EXCEPTION_RECORD * ExceptionRecord,
|
||||
PSEH3$_REGISTRATION_FRAME EstablisherFrame,
|
||||
struct _CONTEXT * ContextRecord,
|
||||
void * DispatcherContext)
|
||||
{
|
||||
PSEH3$_REGISTRATION_FRAME CurrentFrame, TargetFrame;
|
||||
SEH3$_EXCEPTION_POINTERS ExceptionPointers;
|
||||
LONG FilterResult;
|
||||
|
||||
/* Clear the direction flag. */
|
||||
asm volatile ("cld" : : : "memory");
|
||||
|
||||
/* Save the exception pointers on the stack */
|
||||
ExceptionPointers.ExceptionRecord = ExceptionRecord;
|
||||
ExceptionPointers.ContextRecord = ContextRecord;
|
||||
|
||||
/* Check if this is an unwind */
|
||||
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
|
||||
{
|
||||
/* Unwind all local frames */
|
||||
TargetFrame = EstablisherFrame->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Loop all frames for this registration */
|
||||
CurrentFrame = EstablisherFrame->EndOfChain;
|
||||
for (;;)
|
||||
{
|
||||
/* Check if we have an exception handler */
|
||||
if (CurrentFrame->ScopeTable->Target != NULL)
|
||||
{
|
||||
/* Set exception pointers and code for this frame */
|
||||
CurrentFrame->ExceptionPointers = &ExceptionPointers;
|
||||
CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
|
||||
|
||||
/* Get the filter result */
|
||||
FilterResult = _SEH3$_GetFilterResult(CurrentFrame);
|
||||
|
||||
/* Check, if continuuing is requested */
|
||||
if (FilterResult == EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
/* Check if the except handler shall be executed */
|
||||
if (FilterResult == EXCEPTION_EXECUTE_HANDLER) break;
|
||||
}
|
||||
|
||||
/* Bail out if this is the last handler */
|
||||
if (CurrentFrame == EstablisherFrame)
|
||||
return ExceptionContinueSearch;
|
||||
|
||||
/* Go to the next frame */
|
||||
CurrentFrame = CurrentFrame->Next;
|
||||
}
|
||||
|
||||
/* Call RtlUnwind to unwind the frames below this one */
|
||||
_SEH3$_CallRtlUnwind(EstablisherFrame);
|
||||
|
||||
/* Do a local unwind up to this frame */
|
||||
TargetFrame = CurrentFrame;
|
||||
}
|
||||
|
||||
/* Loop frames up to the target frame */
|
||||
for (CurrentFrame = EstablisherFrame->EndOfChain;
|
||||
CurrentFrame != TargetFrame;
|
||||
CurrentFrame = CurrentFrame->Next)
|
||||
{
|
||||
/* Manually unregister the frame */
|
||||
_SEH3$_Unregister(CurrentFrame);
|
||||
|
||||
/* Check if this is an unwind frame */
|
||||
if (CurrentFrame->ScopeTable->Target == NULL)
|
||||
{
|
||||
/* Set exception pointers and code for this frame */
|
||||
CurrentFrame->ExceptionPointers = &ExceptionPointers;
|
||||
CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
|
||||
|
||||
/* Call the finally function */
|
||||
_SEH3$_CallFinally(CurrentFrame);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if this was an unwind */
|
||||
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
|
||||
{
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/* Unregister the frame. It will be unregistered again at the end of the
|
||||
__except block, due to auto cleanup, but that doesn't hurt.
|
||||
All we do is set either fs:[0] or EstablisherFrame->EndOfChain to
|
||||
CurrentFrame->Next, which will not change it's value. */
|
||||
_SEH3$_Unregister(CurrentFrame);
|
||||
|
||||
/* Jump to the __except block (does not return) */
|
||||
_SEH3$_JumpToTarget(CurrentFrame);
|
||||
}
|
||||
|
18
sdk/lib/pseh/i386/pseh3_asmdef.h
Normal file
18
sdk/lib/pseh/i386/pseh3_asmdef.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
|
||||
#define SEH3_REGISTRATION_FRAME_Next 0
|
||||
#define SEH3_REGISTRATION_FRAME_Handler 4
|
||||
#define SEH3_REGISTRATION_FRAME_EndOfChain 8
|
||||
#define SEH3_REGISTRATION_FRAME_ScopeTable 12
|
||||
#define SEH3_REGISTRATION_FRAME_ExceptionPointers 16
|
||||
#define SEH3_REGISTRATION_FRAME_ExceptionCode 20
|
||||
#define SEH3_REGISTRATION_FRAME_Esp 24
|
||||
#define SEH3_REGISTRATION_FRAME_Ebp 28
|
||||
#define SEH3_REGISTRATION_FRAME_AllocaFrame 32
|
||||
#define SEH3_REGISTRATION_FRAME_Ebx 36
|
||||
#define SEH3_REGISTRATION_FRAME_Esi 40
|
||||
#define SEH3_REGISTRATION_FRAME_Edi 44
|
||||
#define SEH3_REGISTRATION_FRAME_ReturnAddress 48
|
||||
|
||||
#define SEH3_SCOPE_TABLE_Target 0
|
||||
#define SEH3_SCOPE_TABLE_Filter 4
|
255
sdk/lib/pseh/i386/pseh3_i386.S
Normal file
255
sdk/lib/pseh/i386/pseh3_i386.S
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* PROJECT: ReactOS system libraries
|
||||
* LICENSE: GNU GPL - See COPYING in the top level directory
|
||||
* PURPOSE: Support library for PSEH3
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "pseh3_asmdef.h"
|
||||
|
||||
.intel_syntax noprefix
|
||||
|
||||
.text
|
||||
|
||||
.extern __SEH3$_except_handler
|
||||
|
||||
/*
|
||||
* void
|
||||
* __attribute__((regparm(3)))
|
||||
* __attribute__((returns_twice))
|
||||
* _SEH3$_RegisterFrame[WithNonVolatiles](
|
||||
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
|
||||
* PSEH3$_SCOPE_TABLE ScopeTable<edx>,
|
||||
* PVOID AllocaFrame<ecx>);
|
||||
*/
|
||||
.global __SEH3$_RegisterFrameWithNonVolatiles
|
||||
__SEH3$_RegisterFrameWithNonVolatiles:
|
||||
|
||||
/* Save non-volatiles in the registration frame */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
||||
|
||||
/* Safe the return address */
|
||||
mov ebx, [esp]
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_ReturnAddress], ebx
|
||||
mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
|
||||
|
||||
.global __SEH3$_RegisterFrameWithStackLayout
|
||||
__SEH3$_RegisterFrameWithStackLayout:
|
||||
|
||||
/* Save the pointer to the alloca frame */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
|
||||
|
||||
.global __SEH3$_RegisterFrame
|
||||
__SEH3$_RegisterFrame:
|
||||
|
||||
/* Save the address of the static data table */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
|
||||
|
||||
/* Set the handler address */
|
||||
mov dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
|
||||
|
||||
/* Set this as the end of the internal chain */
|
||||
mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], eax
|
||||
|
||||
/* Register the frame in the TEB */
|
||||
mov edx, dword ptr fs:[0]
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Next], edx
|
||||
mov dword ptr fs:[0], eax
|
||||
|
||||
/* Save the stack registers */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
|
||||
|
||||
/* Set eax to 0 to indicate 1st return */
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void
|
||||
* __attribute__((regparm(3)))
|
||||
* __attribute__((returns_twice))
|
||||
* _SEH3$_RegisterTryLevel[WithNonVolatiles](
|
||||
* PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
|
||||
* PSEH3$_SCOPE_TABLE ScopeTable<edx>,
|
||||
* PVOID AllocaFrame<ecx>);
|
||||
*/
|
||||
.global __SEH3$_RegisterTryLevelWithNonVolatiles
|
||||
__SEH3$_RegisterTryLevelWithNonVolatiles:
|
||||
|
||||
/* Save non-volatiles in the registration frame */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
|
||||
|
||||
/* Safe the return address */
|
||||
mov ebx, [esp]
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_ReturnAddress], ebx
|
||||
mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
|
||||
|
||||
.global __SEH3$_RegisterTryLevelWithStackLayout
|
||||
__SEH3$_RegisterTryLevelWithStackLayout:
|
||||
|
||||
/* Save the pointer to the alloca frame */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
|
||||
|
||||
.global __SEH3$_RegisterTryLevel
|
||||
__SEH3$_RegisterTryLevel:
|
||||
|
||||
/* Save the address of the static data table */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
|
||||
|
||||
/* Set the handler address to NULL as identification */
|
||||
and dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], 0
|
||||
|
||||
/* Get the current registered frame */
|
||||
mov edx, dword ptr fs:[0]
|
||||
|
||||
/* Get the current end of the chain and set this as Next */
|
||||
mov ecx, [edx + SEH3_REGISTRATION_FRAME_EndOfChain]
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Next], ecx
|
||||
|
||||
/* Set this as the end of the internal chain */
|
||||
mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], eax
|
||||
|
||||
/* Save the stack registers */
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
|
||||
mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
|
||||
|
||||
/* Set eax to 0 to indicate 1st return */
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
.global __SEH3$_InvokeEmbeddedFilterFromRegistration
|
||||
__SEH3$_InvokeEmbeddedFilterFromRegistration:
|
||||
|
||||
/* Safe the current non-volatiles */
|
||||
push ebp
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
/* Save the registration frame pointer */
|
||||
push eax
|
||||
|
||||
/* 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]
|
||||
|
||||
/* 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$_InvokeEmbeddedFilterReturnClang
|
||||
|
||||
/* 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 return address that was saved when registering the frame */
|
||||
mov edx, [eax + SEH3_REGISTRATION_FRAME_ReturnAddress]
|
||||
|
||||
/* Jump into the filter or finally function */
|
||||
xor eax, eax
|
||||
inc eax
|
||||
jmp edx
|
||||
|
||||
/* We return to this label with a cleaned up stack */
|
||||
__SEH3$_InvokeEmbeddedFilterReturnClang:
|
||||
|
||||
/* Restore the registration frame pointer */
|
||||
pop ecx
|
||||
|
||||
/* Save the non-volatiles back in the registration frame */
|
||||
mov [ecx + SEH3_REGISTRATION_FRAME_Ebx], ebx
|
||||
mov [ecx + SEH3_REGISTRATION_FRAME_Esi], esi
|
||||
mov [ecx + SEH3_REGISTRATION_FRAME_Edi], edi
|
||||
mov [ecx + SEH3_REGISTRATION_FRAME_Ebp], ebp
|
||||
|
||||
/* 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
|
||||
|
452
sdk/lib/pseh/i386/seh.s
Normal file
452
sdk/lib/pseh/i386/seh.s
Normal file
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CRT
|
||||
* FILE: lib/crt/misc/i386/seh.S
|
||||
* PURPOSE: SEH Support for the CRT
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <ks386.inc>
|
||||
|
||||
#define DISPOSITION_DISMISS 0
|
||||
#define DISPOSITION_CONTINUE_SEARCH 1
|
||||
#define DISPOSITION_COLLIDED_UNWIND 3
|
||||
|
||||
#define EXCEPTION_EXIT_UNWIND 4
|
||||
#define EXCEPTION_UNWINDING 2
|
||||
|
||||
/* See seh_prolog.s */
|
||||
SEH_FRAME_NewEsp = 0 /* 0x00 */
|
||||
SEH_FRAME_unused = 4 /* 0x04 */
|
||||
SEH_FRAME_PreviousRecord = 8 /* 0x08 */
|
||||
SEH_FRAME_Handler = 12 /* 0x0c */
|
||||
SEH_FRAME_SEHTable = 16 /* 0x10 */
|
||||
SEH_FRAME_Disable = 20 /* 0x14 */
|
||||
SEH_FRAME_OriginalEbp = 24 /* 0x18 */
|
||||
SEH_FRAME_Size = 28 /* 0x1c */
|
||||
|
||||
|
||||
EXTERN _RtlUnwind@16:PROC
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PUBLIC __global_unwind2
|
||||
PUBLIC __local_unwind2
|
||||
PUBLIC __abnormal_termination
|
||||
PUBLIC __except_handler2
|
||||
PUBLIC __except_handler3
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
.code
|
||||
_unwind_handler:
|
||||
|
||||
/* Check if we were unwinding and continue search if not */
|
||||
mov ecx, [esp+4]
|
||||
test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||
jz unwind_handler_return
|
||||
|
||||
/* We have a collision, do a local unwind */
|
||||
mov eax, [esp+20]
|
||||
push ebp
|
||||
mov ebp, [eax+16]
|
||||
mov edx, [eax+40]
|
||||
push edx
|
||||
mov edx, [eax+36]
|
||||
push edx
|
||||
call __local_unwind2
|
||||
add esp, 8
|
||||
pop ebp
|
||||
|
||||
/* Set new try level */
|
||||
mov eax, [esp+8]
|
||||
mov edx, [esp+16]
|
||||
mov [edx], eax
|
||||
|
||||
/* Return collided unwind */
|
||||
mov eax, DISPOSITION_COLLIDED_UNWIND
|
||||
|
||||
unwind_handler_return:
|
||||
ret
|
||||
|
||||
|
||||
__global_unwind2:
|
||||
|
||||
/* Create stack and save all registers */
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
/* Call unwind */
|
||||
push 0
|
||||
push 0
|
||||
push glu_return
|
||||
push [ebp+8]
|
||||
call _RtlUnwind@16
|
||||
|
||||
glu_return:
|
||||
/* Restore registers and return */
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
__abnormal_termination:
|
||||
|
||||
/* Assume false */
|
||||
xor eax, eax
|
||||
|
||||
/* Check if the handler is the unwind handler */
|
||||
mov ecx, fs:0
|
||||
cmp dword ptr [ecx+4], offset _unwind_handler
|
||||
jne short ab_return
|
||||
|
||||
/* Get the try level */
|
||||
mov edx, [ecx+12]
|
||||
mov edx, [edx+12]
|
||||
|
||||
/* Compare it */
|
||||
cmp [ecx+8], edx
|
||||
jne ab_return
|
||||
|
||||
/* Return true */
|
||||
mov eax, 1
|
||||
|
||||
/* Return */
|
||||
ab_return:
|
||||
ret
|
||||
|
||||
|
||||
__local_unwind2:
|
||||
|
||||
/* Save volatiles */
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
/* Get the exception registration */
|
||||
mov eax, [esp+16]
|
||||
|
||||
/* Setup SEH to protect the unwind */
|
||||
push ebp
|
||||
push eax
|
||||
push -2
|
||||
push offset _unwind_handler
|
||||
push fs:0
|
||||
mov fs:0, esp
|
||||
|
||||
unwind_loop:
|
||||
/* Get the exception registration and try level */
|
||||
mov eax, [esp+36]
|
||||
mov ebx, [eax+8]
|
||||
mov esi, [eax+12]
|
||||
|
||||
/* Validate the unwind */
|
||||
cmp esi, -1
|
||||
je unwind_return
|
||||
cmp dword ptr [esp+40], -1
|
||||
je unwind_ok
|
||||
cmp esi, [esp+40]
|
||||
jbe unwind_return
|
||||
|
||||
unwind_ok:
|
||||
/* Get the new enclosing level and save it */
|
||||
lea esi, [esi+esi*2]
|
||||
mov ecx, [ebx+esi*4]
|
||||
mov [esp+8], ecx
|
||||
mov [eax+12], ecx
|
||||
|
||||
/* Check the filter type */
|
||||
cmp dword ptr [ebx+esi*4+4], 0
|
||||
jnz __NLG_Return2
|
||||
|
||||
/* FIXME: NLG Notification */
|
||||
|
||||
/* Call the handler */
|
||||
call dword ptr [ebx+esi*4+8]
|
||||
|
||||
__NLG_Return2:
|
||||
/* Unwind again */
|
||||
jmp unwind_loop
|
||||
|
||||
unwind_return:
|
||||
/* Cleanup SEH */
|
||||
pop fs:0
|
||||
add esp, 16
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
|
||||
__except_handler2:
|
||||
|
||||
/* Setup stack and save volatiles */
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 8
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
/* Clear direction flag */
|
||||
cld
|
||||
|
||||
/* Get exception registration and record */
|
||||
mov ebx, [ebp+12]
|
||||
mov eax, [ebp+8]
|
||||
|
||||
/* Check if this is an unwind */
|
||||
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||
jnz except_unwind2
|
||||
|
||||
/* Save exception pointers structure */
|
||||
mov [ebp-8], eax
|
||||
mov eax, [ebp+16]
|
||||
mov [ebp-4], eax
|
||||
lea eax, [ebp-8]
|
||||
mov [ebx+20], eax
|
||||
|
||||
/* Get the try level and scope table */
|
||||
mov esi, [ebx+12]
|
||||
mov edi, [ebx+8]
|
||||
|
||||
except_loop2:
|
||||
/* Validate try level */
|
||||
cmp esi, -1
|
||||
je except_search2
|
||||
|
||||
/* Check if this is the termination handler */
|
||||
lea ecx, [esi+esi*2]
|
||||
cmp dword ptr [edi+ecx*4+4], 0
|
||||
jz except_continue2
|
||||
|
||||
/* Save registers and call filter, then restore them */
|
||||
push esi
|
||||
push ebp
|
||||
mov ebp, [ebx+16]
|
||||
call dword ptr [edi+ecx*4+4]
|
||||
pop ebp
|
||||
pop esi
|
||||
|
||||
/* Restore ebx and check the result */
|
||||
mov ebx, [ebp+12]
|
||||
or eax, eax
|
||||
jz except_continue2
|
||||
js except_dismiss2
|
||||
|
||||
/* So this is an accept, call the termination handlers */
|
||||
mov edi, [ebx+8]
|
||||
push ebx
|
||||
call __global_unwind2
|
||||
add esp, 4
|
||||
|
||||
/* Restore ebp */
|
||||
mov ebp, [ebx+16]
|
||||
|
||||
/* Do local unwind */
|
||||
push esi
|
||||
push ebx
|
||||
call __local_unwind2
|
||||
add esp, 8
|
||||
|
||||
/* Set new try level */
|
||||
lea ecx, [esi+esi*2]
|
||||
mov eax, [edi+ecx*4]
|
||||
mov [ebx+12], eax
|
||||
|
||||
/* Call except handler */
|
||||
call dword ptr [edi+ecx*4+8]
|
||||
|
||||
except_continue2:
|
||||
/* Reload try level and except again */
|
||||
mov edi, [ebx+8]
|
||||
lea ecx, [esi+esi*2]
|
||||
mov esi, [edi+ecx*4]
|
||||
jmp except_loop2
|
||||
|
||||
except_dismiss2:
|
||||
/* Dismiss it */
|
||||
mov eax, DISPOSITION_DISMISS
|
||||
jmp except_return2
|
||||
|
||||
except_search2:
|
||||
/* Continue searching */
|
||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||
jmp except_return2
|
||||
|
||||
/* Do local unwind */
|
||||
except_unwind2:
|
||||
push ebp
|
||||
mov ebp, [ebx+16]
|
||||
push -1
|
||||
push ebx
|
||||
call __local_unwind2
|
||||
add esp, 8
|
||||
|
||||
/* Retore EBP and set return disposition */
|
||||
pop ebp
|
||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||
|
||||
except_return2:
|
||||
/* Restore registers and stack */
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
__except_handler3:
|
||||
PARAM_ExceptionRecord = 8
|
||||
PARAM_RegistrationFrame = 12
|
||||
PARAM_Context = 16
|
||||
/* Setup stack and save volatiles */
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 8
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
/* Clear direction flag */
|
||||
cld
|
||||
|
||||
/* Get exception registration and record */
|
||||
mov ebx, [ebp+PARAM_RegistrationFrame]
|
||||
mov eax, [ebp+PARAM_ExceptionRecord]
|
||||
|
||||
/* Check if this is an unwind */
|
||||
test dword ptr [eax+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||
jnz except_unwind3
|
||||
|
||||
/* Save exception pointers structure */
|
||||
mov [ebp-8+EXCEPTION_POINTERS_EXCEPTION_RECORD], eax
|
||||
mov eax, [ebp+PARAM_Context]
|
||||
mov [ebp-8+EXCEPTION_POINTERS_CONTEXT_RECORD], eax
|
||||
lea eax, [ebp-8]
|
||||
mov [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_unused], eax
|
||||
|
||||
/* Get the try level and scope table */
|
||||
mov esi, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_Disable]
|
||||
mov edi, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_SEHTable]
|
||||
|
||||
/* FIXME: Validate the SEH exception */
|
||||
|
||||
except_loop3:
|
||||
/* Validate try level */
|
||||
cmp esi, -1
|
||||
je except_search3
|
||||
|
||||
/* Check if this is the termination handler */
|
||||
lea ecx, [esi+esi*2]
|
||||
mov eax, [edi+ecx*4+4]
|
||||
test eax, eax
|
||||
jz except_continue3
|
||||
|
||||
/* Save registers clear them all */
|
||||
push esi
|
||||
push ebp
|
||||
lea ebp, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_OriginalEbp]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
xor edx, edx
|
||||
xor esi, esi
|
||||
xor edi, edi
|
||||
|
||||
/* Call the filter and restore our registers */
|
||||
call eax
|
||||
pop ebp
|
||||
pop esi
|
||||
|
||||
/* Restore ebx and check the result */
|
||||
mov ebx, [ebp+PARAM_RegistrationFrame]
|
||||
test eax, eax
|
||||
jz except_continue3
|
||||
js except_dismiss3
|
||||
|
||||
/* So this is an accept, call the termination handlers */
|
||||
mov edi, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_SEHTable]
|
||||
push ebx
|
||||
call __global_unwind2
|
||||
add esp, 4
|
||||
|
||||
/* Restore ebp */
|
||||
lea ebp, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_OriginalEbp]
|
||||
|
||||
/* Do local unwind */
|
||||
push esi
|
||||
push ebx
|
||||
call __local_unwind2
|
||||
add esp, 8
|
||||
|
||||
/* FIXME: Do NLG Notification */
|
||||
|
||||
/* Set new try level */
|
||||
lea ecx, [esi+esi*2]
|
||||
mov eax, [edi+ecx*4]
|
||||
mov [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_Disable], eax
|
||||
|
||||
/* Clear registers and call except handler */
|
||||
mov eax, [edi+ecx*4+8]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
xor edx, edx
|
||||
xor esi, esi
|
||||
xor edi, edi
|
||||
call eax
|
||||
|
||||
except_continue3:
|
||||
/* Reload try level and except again */
|
||||
mov edi, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_SEHTable]
|
||||
lea ecx, [esi+esi*2]
|
||||
mov esi, [edi+ecx*4]
|
||||
jmp except_loop3
|
||||
|
||||
except_dismiss3:
|
||||
/* Dismiss it */
|
||||
mov eax, DISPOSITION_DISMISS
|
||||
jmp except_return3
|
||||
|
||||
/* Do local unwind */
|
||||
except_unwind3:
|
||||
push ebp
|
||||
lea ebp, [ebx-SEH_FRAME_PreviousRecord+SEH_FRAME_OriginalEbp]
|
||||
push -1
|
||||
push ebx
|
||||
call __local_unwind2
|
||||
add esp, 8
|
||||
|
||||
/* Restore EBP */
|
||||
pop ebp
|
||||
|
||||
except_search3:
|
||||
/* Continue searching */
|
||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||
|
||||
except_return3:
|
||||
/* Restore registers and stack */
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
END
|
152
sdk/lib/pseh/i386/seh_prolog.s
Normal file
152
sdk/lib/pseh/i386/seh_prolog.s
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* COPYRIGHT: GNU GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS CRT
|
||||
* FILE: lib/crt/misc/i386/seh_prolog.S
|
||||
* PURPOSE: SEH Support for MSVC
|
||||
* PROGRAMMERS: Timo Kreuzer
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
EXTERN __except_handler3:PROC
|
||||
|
||||
/* The very first thing a function compiled with MSVC containing SEH
|
||||
* will do is call __SEH_prolog like this:
|
||||
*
|
||||
* push <Number of stackbytes>
|
||||
* push <Address of exception handler>
|
||||
* call __SEH_prolog
|
||||
*
|
||||
* When entering the function the stack layout is like this:
|
||||
*
|
||||
* esp + 08: OLDFRAME.StackBytes
|
||||
* esp + 04: OLDFRAME.SEHTable
|
||||
* esp + 00: OLDFRAME.ReturnAddress
|
||||
*
|
||||
* __SEH_prolog will now setup the stack to the following layout:
|
||||
*
|
||||
* esp + N + 24: SEH_FRAME.OriginalEbp OLDFRAME.StackBytes
|
||||
* esp + N + 20: SEH_FRAME.Disable OLDFRAME.SEHTable
|
||||
* esp + N + 1C: SEH_FRAME.SEHTable OLDFRAME.ReturnAddress
|
||||
* esp + N + 18: SEH_FRAME.Handler
|
||||
* esp + N + 14: SEH_FRAME.PreviousRecord
|
||||
* esp + N + 10: SEH_FRAME.unused
|
||||
* esp + N + 0c: SEH_FRAME.NewEsp
|
||||
*
|
||||
* N bytes local variables
|
||||
* ...
|
||||
* esp + 08: SAFE_AREA.Ebx
|
||||
* esp + 04: SAFE_AREA.Esi
|
||||
* esp + 00: SAFE_AREA.Edi
|
||||
*
|
||||
* all this is documented here (with some minor errors):
|
||||
* http://reactos-blog.blogspot.com/2009/08/inside-mind-of-reactos-developer.html
|
||||
*/
|
||||
|
||||
OLDFRAME_ReturnAddress = 0 /* 0x00 */
|
||||
OLDFRAME_SEHTable = 4 /* 0x04 */
|
||||
OLDFRAME_StackBytes = 8 /* 0x08 */
|
||||
OLDFRAME_Size = 12 /* 0x0c */
|
||||
|
||||
SEH_FRAME_NewEsp = 0 /* 0x00 */
|
||||
SEH_FRAME_unused = 4 /* 0x04 */
|
||||
SEH_FRAME_PreviousRecord = 8 /* 0x08 */
|
||||
SEH_FRAME_Handler = 12 /* 0x0c */
|
||||
SEH_FRAME_SEHTable = 16 /* 0x10 */
|
||||
SEH_FRAME_Disable = 20 /* 0x14 */
|
||||
SEH_FRAME_OriginalEbp = 24 /* 0x18 */
|
||||
SEH_FRAME_Size = 28 /* 0x1c */
|
||||
|
||||
SAFE_AREA_Edi = 0 /* 0x00 */
|
||||
SAFE_AREA_Esi = 4 /* 0x04 */
|
||||
SAFE_AREA_Ebx = 8 /* 0x08 */
|
||||
SAFE_AREA_Size = 12 /* 0x0c */
|
||||
|
||||
|
||||
.code
|
||||
|
||||
PUBLIC __SEH_prolog
|
||||
__SEH_prolog:
|
||||
|
||||
/* Get the number of stack bytes to reserve */
|
||||
mov eax, [esp + OLDFRAME_StackBytes]
|
||||
|
||||
/* Push address of __except_handler3 on the stack */
|
||||
push offset __except_handler3
|
||||
|
||||
/* Push the old exception record on the stack */
|
||||
push dword ptr fs:0
|
||||
|
||||
/* Adjust stack allocation, add size of the stack frame minus 2 pushes */
|
||||
add eax, SEH_FRAME_Size + SAFE_AREA_Size - OLDFRAME_Size - 8
|
||||
|
||||
/* Save old ebp, overwriting OLDFRAME.StackBytes */
|
||||
mov [esp + 8 + OLDFRAME_StackBytes], ebp
|
||||
|
||||
/* Load new ebp, pointing to OLDFRAME.StackBytes */
|
||||
lea ebp, [esp + 8 + OLDFRAME_StackBytes]
|
||||
|
||||
/* Allocate stack space */
|
||||
sub esp, eax
|
||||
|
||||
/* Push the return address on the stack */
|
||||
push dword ptr [ebp - OLDFRAME_StackBytes + OLDFRAME_ReturnAddress]
|
||||
|
||||
/* Get address of the SEH table */
|
||||
mov eax, [ebp + OLDFRAME_SEHTable]
|
||||
|
||||
/* Save new esp */
|
||||
mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_NewEsp], esp
|
||||
|
||||
/* Safe SEH table, overwriting OLDFRAME.ReturnAddress */
|
||||
mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_SEHTable], eax
|
||||
|
||||
/* Safe the disable value, overwriting OLDFRAME.SEHTable */
|
||||
mov dword ptr [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_Disable], -1
|
||||
|
||||
/* Load the address of the new registration record */
|
||||
lea eax, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
|
||||
|
||||
/* Save registers */
|
||||
mov [esp + SAFE_AREA_Edi], edi
|
||||
mov [esp + SAFE_AREA_Esi], esi
|
||||
mov [esp + SAFE_AREA_Ebx], ebx
|
||||
|
||||
/* Enqueue the new record */
|
||||
mov fs:[0], eax
|
||||
|
||||
/* Return to the caller */
|
||||
ret
|
||||
|
||||
|
||||
PUBLIC __SEH_epilog
|
||||
__SEH_epilog:
|
||||
|
||||
/* Restore the previous exception registration record */
|
||||
mov ecx, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
|
||||
mov fs:[0], ecx
|
||||
|
||||
/* Restore saved registers */
|
||||
mov edi, [esp + 4 + SAFE_AREA_Edi]
|
||||
mov esi, [esp + 4 + SAFE_AREA_Esi]
|
||||
mov ebx, [esp + 4 + SAFE_AREA_Ebx]
|
||||
|
||||
/* Get the return address */
|
||||
mov ecx, [esp]
|
||||
|
||||
/* Clean up stack */
|
||||
mov esp, ebp
|
||||
|
||||
/* Get previous ebp */
|
||||
mov ebp, [esp]
|
||||
|
||||
/* Save return address */
|
||||
mov [esp], ecx
|
||||
|
||||
/* Return to the caller */
|
||||
ret
|
||||
|
||||
|
||||
END
|
69
sdk/lib/pseh/powerpc/framebased.S
Normal file
69
sdk/lib/pseh/powerpc/framebased.S
Normal file
|
@ -0,0 +1,69 @@
|
|||
// 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 dos 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.
|
||||
|
||||
.text
|
||||
|
||||
.globl _SEHCleanHandlerEnvironment
|
||||
_SEHCleanHandlerEnvironment:
|
||||
blr
|
||||
|
||||
.globl _SEHCurrentRegistration
|
||||
_SEHCurrentRegistration:
|
||||
lwz 3,0(13)
|
||||
blr
|
||||
|
||||
// R3: Frame to store in
|
||||
.globl _SEHRegisterFrame
|
||||
_SEHRegisterFrame:
|
||||
lwz 4,0(13)
|
||||
stw 3,0(13)
|
||||
stw 4,0(3)
|
||||
blr
|
||||
|
||||
.globl _SEHUnregisterFrame
|
||||
_SEHUnregisterFrame:
|
||||
lwz 3,0(13)
|
||||
lwz 3,0(3)
|
||||
stw 3,0(13)
|
||||
blr
|
||||
|
||||
.globl _SEHGlobalUnwind
|
||||
_SEHGlobalUnwind:
|
||||
|
||||
.extern _SEHRtlUnwind
|
||||
|
||||
// RtlUnwind clobbers all the "don't clobber" registers, so we save them
|
||||
lwz 3,4(1)
|
||||
stwu 1,-132(1)
|
||||
stmw 2,-128(1)
|
||||
|
||||
xor 6,6,6
|
||||
xor 5,5,5
|
||||
lis 4,.RestoreRegisters@ha
|
||||
addi 4,4,.RestoreRegisters@l # Where to jump back to
|
||||
# We already have r3
|
||||
bl _SEHRtlUnwind
|
||||
|
||||
.RestoreRegisters:
|
||||
lmw 2,-128(1)
|
||||
addi 1,1,132
|
||||
blr
|
||||
|
||||
// EOF
|
Loading…
Add table
Add a link
Reference in a new issue