Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.

This commit is contained in:
Colin Finck 2017-10-03 07:45:34 +00:00
parent b94e2d8ca0
commit c2c66aff7d
24198 changed files with 0 additions and 37285 deletions

View 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()

View 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
View 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

View 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

View 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
View file

@ -0,0 +1,4 @@
/* intentionally empty file */
int _SEH2_Volatile0 = 0;
int _SEH2_VolatileExceptionCode = 0xC0000005;

503
sdk/lib/pseh/framebased.c Normal file
View 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 */

View 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

View 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 */

View 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
View 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);
}

View 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

View 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
View 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

View 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

View 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