Signed-off-by: Paul Gofman pgofman@codeweavers.com --- Mortal Kombat 11 manually switches stacks and that interferes badly with the TIB handlers workaround. The condition for calling TIB handler gets satisified when it should not. It is possible to workaround that particular place by checking that the frame pointer is inside the stack but things get more convoluted when we are to pop frames while the game may switch back to original stack. The RtlUserThreadStart() stack handler is the only one it hits.
While there are much more places which use __TRY / __CATCH blocks most of those don't call app functions and thus are much less likely to place a long living handler which will get invalid if the app switches the stack. RtlUserThreadStart()'s handler is always there for any thread so maybe avoiding the TIB handlers workaround for this function only will cover the majority of such cases.
dlls/ntdll/thread.c | 36 +++++++++++++++++++++++++++++++++++- include/wine/asm.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 37dc7c8ab37..c42221c1ae0 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -231,7 +231,41 @@ void DECLSPEC_HIDDEN call_thread_func( PRTL_THREAD_START_ROUTINE entry, void *ar __ENDTRY }
-#else /* __i386__ */ +#elif /* __i386__ */ defined(__x86_64__) && defined(__ASM_SEH_SUPPORTED) +EXCEPTION_DISPOSITION WINAPI call_thread_func_handler( EXCEPTION_RECORD *rec, ULONG64 frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch ) +{ + EXCEPTION_POINTERS ep = { rec, context }; + + WARN( "Unhandled exception, calling filter.\n" ); + + switch (call_unhandled_exception_filter( &ep )) + { + case EXCEPTION_CONTINUE_SEARCH: + return ExceptionContinueSearch; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + case EXCEPTION_EXECUTE_HANDLER: + break; + } + NtTerminateProcess( GetCurrentProcess(), rec->ExceptionCode ); + return ExceptionContinueExecution; +} + +extern void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ); +__ASM_GLOBAL_FUNC( RtlUserThreadStart, + "subq $0x28, %rsp\n\t" + __ASM_SEH(".seh_stackalloc 0x28\n\t") + __ASM_SEH(".seh_endprologue\n\t") + "movq %rdx,%r8\n\t" + "movq %rcx,%rdx\n\t" + "xorq %rcx,%rcx\n\t" + "movq pBaseThreadInitThunk(%rip),%r9\n\t" + "call *%r9\n\t" + "int3\n\t" + __ASM_SEH(".seh_handler call_thread_func_handler, @except\n\t") ) + +#else /* defined(__x86_64__) && defined(__ASM_SEH_SUPPORTED) */
void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ) { diff --git a/include/wine/asm.h b/include/wine/asm.h index 0547ee94b19..9200491afd0 100644 --- a/include/wine/asm.h +++ b/include/wine/asm.h @@ -50,6 +50,7 @@ # define __ASM_SEH(str) # else # define __ASM_SEH(str) str +# define __ASM_SEH_SUPPORTED # endif #else # define __ASM_SEH(str)