This really needs to go in a branch. It needs heavy testing and can't coincide with the current shell32 due to PSDK interface changes

svn path=/branches/shell32_new-bringup/; revision=51893
This commit is contained in:
Ged Murphy 2011-05-24 18:40:34 +00:00
parent 4596e5e59b
commit 4019caae75
23116 changed files with 0 additions and 1109022 deletions

29
lib/pseh/CMakeLists.txt Normal file
View file

@ -0,0 +1,29 @@
if(NOT MSVC)
list(APPEND SOURCE framebased.c)
if(ARCH MATCHES i386)
list(APPEND SOURCE
i386/framebased.S
i386/framebased-gcchack.c
i386/framebased-gcchack-asm.S)
elseif(ARCH MATCHES amd64)
list(APPEND SOURCE amd64/framebased.S)
elseif(ARCH MATCHES powerpc)
list(APPEND SOURCE powerpc/framebased.S)
endif()
add_library(pseh ${SOURCE})
add_dependencies(pseh psdk)
else()
list(APPEND SOURCE
dummy.c
i386/seh.s
i386/seh_prolog.s)
add_library(pseh ${SOURCE})
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

2
lib/pseh/dummy.c Normal file
View file

@ -0,0 +1,2 @@
/* intentionally empty file */

503
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+12]
mov [eax+8], ecx
mov [eax+16], ebp
mov [eax+20], ebx
mov [eax+24], esi
mov [eax+28], edi
mov edx, [esp+4]
mov [edx+8], eax
xor eax, eax
ret
.endfunc
.func _SEH2EnterFrameAndHandleTrylevel
.globl __SEH2EnterFrameAndHandleTrylevel
__SEH2EnterFrameAndHandleTrylevel:
mov eax, [esp+8]
mov ecx, [esp+12]
mov [eax+8], ecx
mov [eax+16], ebp
mov [eax+20], ebx
mov [eax+24], esi
mov [eax+28], edi
.extern __SEH2EnterFrameAndTrylevel
jmp __SEH2EnterFrameAndTrylevel
.endfunc
.func __SEH2Handle
.globl ___SEH2Handle
___SEH2Handle:
mov eax, [esp+4]
mov ebp, [esp+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,309 @@
/*
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
#define WIN32_LEAN_AND_MEAN
#include <windows.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"
"push $0\n"
"push $0\n"
"push $Return%=\n"
"push %[target]\n"
"call %c[RtlUnwind]\n"
"Return%=: pop %%ebp\n" :
:
[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"
"push %[frame]\n"
"call *%[filter]\n"
"pop %%edx\n"
"pop %%edx\n" :
[ret] "=a" (ret) :
"c" (context), [filter] "r" (filter), [frame] "g" (frame), [ep] "g" (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\n" : : "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

441
lib/pseh/i386/seh.s Normal file
View file

@ -0,0 +1,441 @@
/*
* 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>
#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@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:
/* 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_unwind3
/* Save exception pointers structure */
mov [ebp-8], eax
mov eax, [ebp+16]
mov [ebp-4], eax
lea eax, [ebp-8]
mov [ebx-4], eax
/* Get the try level and scope table */
mov esi, [ebx+12]
mov edi, [ebx+8]
/* 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]
or eax, eax
jz except_continue3
/* Save registers clear them all */
push esi
push ebp
lea ebp, [ebx+16]
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+12]
or eax, eax
jz except_continue3
js except_dismiss3
/* So this is an accept, call the termination handlers */
mov edi, [ebx+8]
push ebx
call __global_unwind2
add esp, 4
/* Restore ebp */
lea ebp, [ebx+16]
/* 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+12], 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+8]
lea ecx, [esi+esi*2]
mov esi, [edi+ecx*4]
jmp except_loop3
except_dismiss3:
/* Dismiss it */
mov eax, DISPOSITION_DISMISS
jmp except_return3
except_search3:
/* Continue searching */
mov eax, DISPOSITION_CONTINUE_SEARCH
jmp except_return3
/* Do local unwind */
except_unwind3:
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_return3:
/* Restore registers and stack */
pop ebp
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
END

152
lib/pseh/i386/seh_prolog.s Normal file
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

25
lib/pseh/pseh.rbuild Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
<module name="pseh" type="staticlibrary">
<if property="ARCH" value="i386">
<directory name="i386">
<file>framebased.S</file>
<group compilerset="gcc">
<file>framebased-gcchack.c</file>
<file>framebased-gcchack-asm.S</file>
</group>
</directory>
</if>
<if property="ARCH" value="powerpc">
<directory name="powerpc">
<file>framebased.S</file>
</directory>
</if>
<if property="ARCH" value="amd64">
<directory name="amd64">
<file>framebased.S</file>
</directory>
</if>
<file>framebased.c</file>
</module>