[PATCH] ntdll: Use .seh handler instead of __TRY in RtlUserThreadStart() on x64.

Paul Gofman pgofman at codeweavers.com
Tue Feb 1 13:51:59 CST 2022


Signed-off-by: Paul Gofman <pgofman at 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)
-- 
2.34.1




More information about the wine-devel mailing list