PATCH 1/7] msvcrt: Translate SEH exception on each call to __CxxFrameHandler.
Piotr Caban
piotr.caban at gmail.com
Wed May 31 05:47:21 CDT 2017
On 05/24/17 02:54, Daniel Lehman wrote:
> +extern void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record,
> + void (*target)(void) );
It's already defined in wine/exception.h.
> +extern void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec);
This is also already defined (in msvcrt.h)
> +
> +static void DECLSPEC_NORETURN seh_unwind_target(void)
> +{
> + seh_frame_info *seh_frame = (seh_frame_info *)__wine_get_frame();
> + __wine_pop_frame( &seh_frame->frame );
There's no need to call __wine_pop_frame here, it will be done after the
jump anyway.
I think that the whole series will be cleaner/easier to read if we add
the __EXCEPT_CTX/__FINALLY_CTX macros and use them here. I'm attaching a
patch with proposition of changes for this functions. With such changes
your patch will look like this (this is not tested):
typedef struct {
ULONG64 dest_frame;
ULONG64 orig_frame;
DISPATCHER_CONTEXT *dispatch;
const cxx_function_descr *descr;
} se_translator_ctx;
static DWORD se_translation_filter(EXCEPTION_POINTERS *ep, void *c)
{
se_translator_ctx *ctx = (se_translator_ctx*)c;
/* this is copied from original patch but I think that */
/* terminate should be called on non C++ exceptions here */
if (ep->rec->ExceptionCode != CXX_EXCEPTION)
return ExceptionContinueSearch;
find_catch_block(...);
__DestructExceptionObject(ep->rec);
return ExceptionExecuteHandler;
}
in cxx_frame_handler:
if (data->se_translator) {
se_translator_ctx ctx;
//initialize ctx
__TRY
{
except_ptrs.ExceptionRecord = rec;
except_ptrs.ContextRecord = context;
data->se_translator(rec->ExceptionCode, &except_ptrs);
}
__EXCEPT_CTX(se_translation_filter, &ctx)
{
}
__END_TRY
}
With such changes second patch can be also changed to use
__TRY/__FINALLY_CTX around "ret_addr = handler(0, frame);" file.
What do you think about it?
Thanks,
Piotr
-------------- next part --------------
>From 3cb2bb786b53fe226f1257dd8343b5b03d485203 Mon Sep 17 00:00:00 2001
From: Piotr Caban <piotr at codeweavers.com>
Date: Wed, 31 May 2017 12:39:29 +0200
Subject: [PATCH] __EXCEPT_CTX/__FINALLY_CTX draft
To: wine-patches <wine-patches at winehq.org>
---
dlls/winecrt0/exception.c | 38 ++++++++++++++++++++++++++++++++++++++
include/wine/exception.h | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/dlls/winecrt0/exception.c b/dlls/winecrt0/exception.c
index c81c8216a2..0e00f73a6f 100644
--- a/dlls/winecrt0/exception.c
+++ b/dlls/winecrt0/exception.c
@@ -99,6 +99,31 @@ DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
unwind_frame( record, frame );
}
+DWORD __wine_exception_ctx_handler( EXCEPTION_RECORD *record,
+ EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context,
+ EXCEPTION_REGISTRATION_RECORD **pdispatcher )
+{
+ __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
+ EXCEPTION_POINTERS ptrs;
+
+ if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))
+ return ExceptionContinueSearch;
+
+ ptrs.ExceptionRecord = record;
+ ptrs.ContextRecord = context;
+ switch(wine_frame->u.filter_ctx( &ptrs, wine_frame->ctx ))
+ {
+ case EXCEPTION_CONTINUE_SEARCH:
+ return ExceptionContinueSearch;
+ case EXCEPTION_CONTINUE_EXECUTION:
+ return ExceptionContinueExecution;
+ case EXCEPTION_EXECUTE_HANDLER:
+ break;
+ }
+ unwind_frame( record, frame );
+}
+
DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context,
@@ -133,3 +158,16 @@ DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
}
return ExceptionContinueSearch;
}
+
+DWORD __wine_finally_ctx_handler( EXCEPTION_RECORD *record,
+ EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context,
+ EXCEPTION_REGISTRATION_RECORD **pdispatcher )
+{
+ if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+ {
+ __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
+ wine_frame->u.finally_func_ctx( FALSE, wine_frame->ctx );
+ }
+ return ExceptionContinueSearch;
+}
diff --git a/include/wine/exception.h b/include/wine/exception.h
index f275568f4d..66cb55bbab 100644
--- a/include/wine/exception.h
+++ b/include/wine/exception.h
@@ -81,7 +81,9 @@ extern "C" {
#define __TRY __try
#define __EXCEPT(func) __except((func)(GetExceptionInformation()))
+#define __EXCEPT_CTX(func, ctx) __except((func)(GetExceptionInformation(), ctx))
#define __FINALLY(func) __finally { (func)(!AbnormalTermination()); }
+#define __FINALLY_CTX(func, ctx) __finally { (func)(!AbnormalTermination(), ctx); }
#define __ENDTRY /*nothing*/
#define __EXCEPT_PAGE_FAULT __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
#define __EXCEPT_ALL __except(EXCEPTION_EXECUTE_HANDLER)
@@ -100,6 +102,10 @@ extern DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context,
EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN;
+extern DWORD __wine_exception_ctx_handler( EXCEPTION_RECORD *record,
+ EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context,
+ EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN;
extern DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context,
@@ -112,6 +118,10 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context,
EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN;
+extern DWORD __wine_finally_ctx_handler( EXCEPTION_RECORD *record,
+ EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context,
+ EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN;
#define __TRY \
do { __WINE_FRAME __f; \
@@ -131,6 +141,18 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
do {
+#define __EXCEPT_CTX(func, context) \
+ } while(0); \
+ __wine_pop_frame( &__f.frame ); \
+ break; \
+ } else { \
+ __f.frame.Handler = __wine_exception_ctx_handler; \
+ __f.u.filter_ctx = (func); \
+ __f.ctx = context; \
+ if (sigsetjmp( __f.jmp, 0 )) { \
+ const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \
+ do {
+
/* convenience handler for page fault exceptions */
#define __EXCEPT_PAGE_FAULT \
} while(0); \
@@ -175,9 +197,25 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record,
} \
} while (0);
+#define __FINALLY_CTX(func, context) \
+ } while(0); \
+ __wine_pop_frame( &__f.frame ); \
+ (func)(1); \
+ break; \
+ } else { \
+ __f.frame.Handler = __wine_finally_ctx_handler; \
+ __f.u.finally_ctx_func = (func); \
+ __f.ctx = context; \
+ __wine_push_frame( &__f.frame ); \
+ __first = 0; \
+ } \
+ } while (0);
+
typedef LONG (CALLBACK *__WINE_FILTER)(PEXCEPTION_POINTERS);
+typedef LONG (CALLBACK *__WINE_FILTER_CTX)(PEXCEPTION_POINTERS, void*);
typedef void (CALLBACK *__WINE_FINALLY)(BOOL);
+typedef void (CALLBACK *__WINE_FINALLY_CTX)(BOOL, void*);
#define GetExceptionInformation() (__eptr)
#define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode)
@@ -190,9 +228,12 @@ typedef struct __tagWINE_FRAME
{
/* exception data */
__WINE_FILTER filter;
+ __WINE_FILTER_CTX filter_ctx;
/* finally data */
__WINE_FINALLY finally_func;
+ __WINE_FINALLY_CTX finally_func_ctx;
} u;
+ void *ctx;
sigjmp_buf jmp;
/* hack to make GetExceptionCode() work in handler */
DWORD ExceptionCode;
--
2.13.0
More information about the wine-devel
mailing list