[PATCH 2/2] winecrt0: Add .seh_proc, .seh_endproc and .seh_stackalloc to assembly

RĂ©mi Bernon rbernon at codeweavers.com
Tue Aug 20 10:46:57 CDT 2019


Without it, __wine_rtl_unwind confuses the unwinding code on x64 and it
then triggers an infinite exception loop.

This can be reproduced for example in msctf inputprocessor's test, with
the test_MultiThreadApartment test case that raises an E_NOINTERFACE
exception. It fails to unwind correctly on x64 with WINEDEBUG=-all,+seh.
---

I don't understand very well what is going on here, the issue looks to
be a misaligned stack somewhere that leads to invalid rsp/rbp when
unwinded. It happens when __widl_exception_handler calls
__wine_rtl_unwind to unwind the stack to the RpcFinally/RpcExcept
statements, for example when an RPC error is raised (in this case, when
E_NOINTERFACE is raised because of impossible marshalling).

These .seh_* statements are generated on cross-compiled C
functions, and adding them for assembly functions seems to solve the
issue.

 dlls/winecrt0/exception.c |  1 +
 include/wine/asm.h        | 14 ++++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/dlls/winecrt0/exception.c b/dlls/winecrt0/exception.c
index df7315e6d40..66c7efbb0e0 100644
--- a/dlls/winecrt0/exception.c
+++ b/dlls/winecrt0/exception.c
@@ -122,6 +122,7 @@ __ASM_GLOBAL_FUNC( __wine_rtl_unwind,
                    "movq %rsp,%rbp\n\t"
                    __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
                    "subq $0x20,%rsp\n\t"
+                   __ASM_SEH(".seh_stackalloc 0x20\n\t")
                    "movq %r8,%r9\n\t"  /* retval = final target */
                    "movq %rdx,%r8\n\t" /* record */
                    "leaq __wine_unwind_trampoline(%rip),%rdx\n\t"  /* target = trampoline */
diff --git a/include/wine/asm.h b/include/wine/asm.h
index c1a6819cd52..691a8aeb98b 100644
--- a/include/wine/asm.h
+++ b/include/wine/asm.h
@@ -49,14 +49,20 @@
 # define __ASM_FUNC_TYPE(name) ".type " name ", at function"
 #endif

+#if defined(_WIN64) && defined(__MINGW32__)
+#define __ASM_SEH(code) code
+#else
+#define __ASM_SEH(code) ""
+#endif
+
 #ifdef __GNUC__
 # define __ASM_DEFINE_FUNC(name,code) \
-    asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) "\n" name ":\n\t" \
-        __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") );
+    asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \
+        __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") );
 #else
 # define __ASM_DEFINE_FUNC(name,code) void __asm_dummy_##__LINE__(void) { \
-    asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) "\n" name ":\n\t" \
-        __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") ); }
+    asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \
+        __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") ); }
 #endif

 #define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(__ASM_NAME(#name),code)
--
2.23.0.rc1




More information about the wine-devel mailing list