summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authornijtmans <nijtmans>2010-12-13 09:24:08 (GMT)
committernijtmans <nijtmans>2010-12-13 09:24:08 (GMT)
commitd2674e76cf933113aa9181c43646b4fcc0313f42 (patch)
tree3e8d34c422b7ac37e4a71626b3415fc3619fabb7 /win
parent4ead18d0faa72586dea4066ba3f34e1fd7c8e899 (diff)
downloadtk-d2674e76cf933113aa9181c43646b4fcc0313f42.zip
tk-d2674e76cf933113aa9181c43646b4fcc0313f42.tar.gz
tk-d2674e76cf933113aa9181c43646b4fcc0313f42.tar.bz2
See also: [Patch 1910041] and [Patch 3059922]. SEH emulation on Win64 was not correct here: it sometimes results in a crash. Contrary to the other places, the code here is not meant to protect from OS bugs, but to protect Finalizing Tk when the application went in an invalid state.
Diffstat (limited to 'win')
-rw-r--r--win/tkWin32Dll.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c
index 338aaaf..9b7ad6b 100644
--- a/win/tkWin32Dll.c
+++ b/win/tkWin32Dll.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWin32Dll.c,v 1.13 2010/11/29 11:01:53 nijtmans Exp $
+ * RCS: @(#) $Id: tkWin32Dll.c,v 1.14 2010/12/13 09:24:08 nijtmans Exp $
*/
#include "tkWinInt.h"
@@ -134,6 +134,77 @@ DllMain(
*/
#ifdef HAVE_NO_SEH
+# ifdef __WIN64
+ __asm__ __volatile__ (
+
+ /*
+ * Construct an EXCEPTION_REGISTRATION to protect the call to
+ * TkFinalize
+ */
+
+ "leaq %[registration], %%rdx" "\n\t"
+ "movq %%gs:0, %%rax" "\n\t"
+ "movq %%rax, 0x0(%%edx)" "\n\t" /* link */
+ "leaq 1f, %%rax" "\n\t"
+ "movq %%rax, 0x8(%%rdx)" "\n\t" /* handler */
+ "movq %%rbp, 0x10(%%rdx)" "\n\t" /* ebp */
+ "movq %%rsp, 0x18(%%rdx)" "\n\t" /* esp */
+ "movl %[error], 0x20(%%rdx)" "\n\t" /* status */
+
+ /*
+ * Link the EXCEPTION_REGISTRATION on the chain
+ */
+
+ "movq %%rdx, %%gs:0" "\n\t"
+
+ /*
+ * Call TkFinalize
+ */
+
+ "movq $0x0, 0x0(%%esp)" "\n\t"
+ "call _TkFinalize" "\n\t"
+
+ /*
+ * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION
+ * and store a TCL_OK status
+ */
+
+ "movq %%gs:0, %%rdx" "\n\t"
+ "movl %[ok], %%eax" "\n\t"
+ "movl %%eax, 0x20(%%rdx)" "\n\t"
+ "jmp 2f" "\n"
+
+ /*
+ * Come here on an exception. Get the EXCEPTION_REGISTRATION that
+ * we previously put on the chain.
+ */
+
+ "1:" "\t"
+ "movq %%gs:0, %%rdx" "\n\t"
+ "movq 0x10(%%rdx), %%rdx" "\n\t"
+
+ /*
+ * Come here however we exited. Restore context from the
+ * EXCEPTION_REGISTRATION in case the stack is unbalanced.
+ */
+
+ "2:" "\t"
+ "movq 0x18(%%rdx), %%rsp" "\n\t"
+ "movq 0x10(%%rdx), %%rbp" "\n\t"
+ "movq 0x0(%%rdx), %%rax" "\n\t"
+ "movq %%rax, %%gs:0" "\n\t"
+
+ :
+ /* No outputs */
+ :
+ [registration] "m" (registration),
+ [ok] "i" (TCL_OK),
+ [error] "i" (TCL_ERROR)
+ :
+ "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "memory"
+ );
+
+# else
__asm__ __volatile__ (
/*
@@ -202,8 +273,9 @@ DllMain(
[error] "i" (TCL_ERROR)
:
"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
- );
+ );
+# endif
#else /* HAVE_NO_SEH */
__try {
/*