diff options
Diffstat (limited to 'win/tkWin32Dll.c')
-rw-r--r-- | win/tkWin32Dll.c | 87 |
1 files changed, 84 insertions, 3 deletions
diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c index 3978f1c..733d2b1 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.12 2005/12/02 00:19:04 dkf Exp $ + * RCS: @(#) $Id: tkWin32Dll.c,v 1.12.4.1 2010/12/13 21:23:59 nijtmans Exp $ */ #include "tkWinInt.h" @@ -90,13 +90,22 @@ DllEntryPoint( * Always TRUE. * * Side effects: - * This might call some sycronization functions, but MSDN documentation + * This might call some synchronization functions, but MSDN documentation * states: "Waiting on synchronization objects in DllMain can cause a * deadlock." * *---------------------------------------------------------------------- */ +#if defined(HAVE_NO_SEH) && defined(_WIN64) +/* A little trick to make the assembler code below + * compile on Win64 with gcc: It appears that Win64 + * does not decorate compiled functions with "_" + */ +static void _TkFinalize(ClientData clientData) __attribute__((used)); +static void _TkFinalize(ClientData clientData) {TkFinalize(clientData);} +#endif + BOOL APIENTRY DllMain( HINSTANCE hInstance, @@ -125,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__ ( /* @@ -193,8 +273,9 @@ DllMain( [error] "i" (TCL_ERROR) : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" - ); + ); +# endif #else /* HAVE_NO_SEH */ __try { /* |