diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | win/tclWin32Dll.c | 92 | ||||
-rw-r--r-- | win/tclWinChan.c | 94 | ||||
-rw-r--r-- | win/tclWinFCmd.c | 133 |
4 files changed, 209 insertions, 125 deletions
@@ -1,5 +1,20 @@ 2003-01-25 Mo DeJong <mdejong@users.sourceforge.net> + * win/tclWin32Dll.c (TclpCheckStackSpace, squelch_warnings): + * win/tclWinChan.c (Tcl_MakeFileChannel, squelch_warnings): + * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, squelch_warnings): + Re-implement inline ASM SEH handlers for gcc. + The esp and ebp registers are now saved on the + stack instead of in global variables so that + the code is thread safe. Add additional checks + when TCL_MEM_DEBUG is defined to be sure the + values were recovered from the stack properly. + Remove squelch_warnings functions and add + a dummy call in the handler methods to squelch + compiler warnings. + +2003-01-25 Mo DeJong <mdejong@users.sourceforge.net> + * win/configure: * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that no alloca function is found diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 13f2a4b..62d9e1c 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWin32Dll.c,v 1.22 2003/01/25 12:48:12 mdejong Exp $ + * RCS: @(#) $Id: tclWin32Dll.c,v 1.23 2003/01/25 14:11:32 mdejong Exp $ */ #include "tclWinInt.h" @@ -37,13 +37,14 @@ typedef VOID (WINAPI UTUNREGISTER)(HANDLE hModule); static HINSTANCE hInstance; /* HINSTANCE of this DLL. */ static int platformId; /* Running under NT, or 95/98? */ -#ifdef HAVE_NO_SEH -static void *ESP; -static void *EBP; -static void* HANDLER[2]; -static void* NEW_HANDLER = &(HANDLER[0]); -static void* OLD_HANDLER = &(HANDLER[1]); -#endif /* HAVE_NO_SEH */ +#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG) +static void *INITIAL_ESP, + *INITIAL_EBP, + *INITIAL_HANDLER, + *RESTORED_ESP, + *RESTORED_EBP, + *RESTORED_HANDLER; +#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */ /* * The following function tables are used to dispatch to either the @@ -376,17 +377,21 @@ TclpCheckStackSpace() */ #ifdef HAVE_NO_SEH +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "movl %esp, _ESP" "\n\t" - "movl %ebp, _EBP"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(INITIAL_ESP), + "=m"(INITIAL_EBP), + "=r"(INITIAL_HANDLER) ); +# endif /* TCL_MEM_DEBUG */ __asm__ __volatile__ ( - "movl %fs:0, %eax" "\n\t" - "movl %eax, _OLD_HANDLER" "\n\t" - "movl __except_checkstackspace_handler, %eax" "\n\t" - "movl %eax, _NEW_HANDLER" "\n\t" - "movl _HANDLER, %eax" "\n\t" - "movl %eax, %fs:0"); + "pushl %ebp" "\n\t" + "pushl $__except_checkstackspace_handler" "\n\t" + "pushl %fs:0" "\n\t" + "movl %esp, %fs:0"); #else __try { #endif /* HAVE_NO_SEH */ @@ -403,15 +408,36 @@ TclpCheckStackSpace() retval = 1; #ifdef HAVE_NO_SEH __asm__ __volatile__ ( - "jmp checkstackspace_pop" "\n" - "checkstackspace_reentry:" "\n\t" - "movl _ESP, %esp" "\n\t" - "movl _EBP, %ebp"); + "movl %%fs:0, %%esp" "\n\t" + "jmp checkstackspace_pop" "\n" + "checkstackspace_reentry:" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl 0x8(%%eax), %%esp" "\n\t" + "movl 0x8(%%esp), %%ebp" "\n" + "checkstackspace_pop:" "\n\t" + "movl (%%esp), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + "add $12, %%esp" "\n\t" + : + : + : "%eax"); +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "checkstackspace_pop:" "\n\t" - "mov _OLD_HANDLER, %eax" "\n\t" - "mov %eax, %fs:0"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(RESTORED_ESP), + "=m"(RESTORED_EBP), + "=r"(RESTORED_HANDLER) ); + + if (INITIAL_ESP != RESTORED_ESP) + panic("ESP restored incorrectly"); + if (INITIAL_EBP != RESTORED_EBP) + panic("EBP restored incorrectly"); + if (INITIAL_HANDLER != RESTORED_HANDLER) + panic("HANDLER restored incorrectly"); +# endif /* TCL_MEM_DEBUG */ #else } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif /* HAVE_NO_SEH */ @@ -433,6 +459,8 @@ _except_checkstackspace_handler( { __asm__ __volatile__ ( "jmp checkstackspace_reentry"); + /* Nuke compiler warning about unused static function */ + _except_checkstackspace_handler(NULL, NULL, NULL, NULL); return 0; /* Function does not return */ } #endif /* HAVE_NO_SEH */ @@ -627,21 +655,3 @@ Tcl_WinTCharToUtf(string, len, dsPtr) return Tcl_ExternalToUtfDString(tclWinTCharEncoding, (CONST char *) string, len, dsPtr); } - -#ifdef HAVE_NO_SEH -/* - * This method exists only to stop the compiler from emitting - * warnings about variables and methods accessed only from asm. - */ -static void squelch_warnings() -{ - void *ptr; - ptr = _except_checkstackspace_handler; - ESP = 0; - EBP = 0; - OLD_HANDLER = 0; - NEW_HANDLER = 0; - HANDLER[0] = 0; - squelch_warnings(); -} -#endif /* HAVE_NO_SEH */ diff --git a/win/tclWinChan.c b/win/tclWinChan.c index 9ba2f64..c377245 100644 --- a/win/tclWinChan.c +++ b/win/tclWinChan.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinChan.c,v 1.28 2003/01/16 19:01:59 mdejong Exp $ + * RCS: @(#) $Id: tclWinChan.c,v 1.29 2003/01/25 14:11:32 mdejong Exp $ */ #include "tclWinInt.h" @@ -121,10 +121,14 @@ static Tcl_ChannelType fileChannelType = { FileWideSeekProc, /* Wide seek proc. */ }; -#ifdef HAVE_NO_SEH -static void *ESP; -static void *EBP; -#endif /* HAVE_NO_SEH */ +#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG) +static void *INITIAL_ESP, + *INITIAL_EBP, + *INITIAL_HANDLER, + *RESTORED_ESP, + *RESTORED_EBP, + *RESTORED_HANDLER; +#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */ /* @@ -1049,34 +1053,59 @@ Tcl_MakeFileChannel(rawHandle, mode) */ #ifdef HAVE_NO_SEH +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "movl %esp, _ESP" "\n\t" - "movl %ebp, _EBP"); - - __asm__ __volatile__ ( - "pushl $__except_makefilechannel_handler" "\n\t" - "pushl %fs:0" "\n\t" - "mov %esp, %fs:0"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(INITIAL_ESP), + "=m"(INITIAL_EBP), + "=r"(INITIAL_HANDLER) ); +# endif /* TCL_MEM_DEBUG */ result = 0; + + __asm__ __volatile__ ( + "pushl %ebp" "\n\t" + "pushl $__except_makefilechannel_handler" "\n\t" + "pushl %fs:0" "\n\t" + "movl %esp, %fs:0"); #else __try { #endif /* HAVE_NO_SEH */ CloseHandle(dupedHandle); #ifdef HAVE_NO_SEH __asm__ __volatile__ ( - "jmp makefilechannel_pop" "\n" - "makefilechannel_reentry:" "\n\t" - "movl _ESP, %esp" "\n\t" - "movl _EBP, %ebp"); - - result = 1; /* True when exception was raised */ - - __asm__ __volatile__ ( - "makefilechannel_pop:" "\n\t" - "mov (%esp), %eax" "\n\t" - "mov %eax, %fs:0" "\n\t" - "add $8, %esp"); + "jmp makefilechannel_pop" "\n" + "makefilechannel_reentry:" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl 0x8(%%eax), %%esp" "\n\t" + "movl 0x8(%%esp), %%ebp" "\n" + "movl $1, %0" "\n" + "makefilechannel_pop:" "\n\t" + "movl (%%esp), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + "add $12, %%esp" "\n\t" + : "=m"(result) + : + : "%eax"); + +# ifdef TCL_MEM_DEBUG + __asm__ __volatile__ ( + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(RESTORED_ESP), + "=m"(RESTORED_EBP), + "=r"(RESTORED_HANDLER) ); + + if (INITIAL_ESP != RESTORED_ESP) + panic("ESP restored incorrectly"); + if (INITIAL_EBP != RESTORED_EBP) + panic("EBP restored incorrectly"); + if (INITIAL_HANDLER != RESTORED_HANDLER) + panic("HANDLER restored incorrectly"); +# endif /* TCL_MEM_DEBUG */ if (result) return NULL; @@ -1116,6 +1145,8 @@ _except_makefilechannel_handler( { __asm__ __volatile__ ( "jmp makefilechannel_reentry"); + /* Nuke compiler warning about unused static function */ + _except_makefilechannel_handler(NULL, NULL, NULL, NULL); return 0; /* Function does not return */ } #endif @@ -1314,18 +1345,3 @@ TclWinFlushDirtyChannels () } } } - -#ifdef HAVE_NO_SEH -/* - * This method exists only to stop the compiler from emitting - * warnings about variables and methods accessed only from asm. - */ -static void squelch_warnings() -{ - void *ptr; - ptr = _except_makefilechannel_handler; - ESP = 0; - EBP = 0; - squelch_warnings(); -} -#endif /* HAVE_NO_SEH */ diff --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index f1d5dfe..66d2931 100644 --- a/win/tclWinFCmd.c +++ b/win/tclWinFCmd.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinFCmd.c,v 1.32 2003/01/16 19:01:59 mdejong Exp $ + * RCS: @(#) $Id: tclWinFCmd.c,v 1.33 2003/01/25 14:11:33 mdejong Exp $ */ #include "tclWinInt.h" @@ -73,10 +73,14 @@ CONST TclFileAttrProcs tclpFileAttrProcs[] = { {GetWinFileShortName, CannotSetAttribute}, {GetWinFileAttributes, SetWinFileAttributes}}; -#ifdef HAVE_NO_SEH -static void *ESP; -static void *EBP; -#endif /* HAVE_NO_SEH */ +#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG) +static void *INITIAL_ESP, + *INITIAL_EBP, + *INITIAL_HANDLER, + *RESTORED_ESP, + *RESTORED_EBP, + *RESTORED_HANDLER; +#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */ /* * Prototype for the TraverseWinTree callback function. @@ -188,14 +192,21 @@ DoRenameFile( */ #ifdef HAVE_NO_SEH +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "movl %esp, _ESP" "\n\t" - "movl %ebp, _EBP"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(INITIAL_ESP), + "=m"(INITIAL_EBP), + "=r"(INITIAL_HANDLER) ); +# endif /* TCL_MEM_DEBUG */ __asm__ __volatile__ ( + "pushl %ebp" "\n\t" "pushl $__except_dorenamefile_handler" "\n\t" "pushl %fs:0" "\n\t" - "mov %esp, %fs:0"); + "movl %esp, %fs:0"); #else __try { #endif /* HAVE_NO_SEH */ @@ -204,16 +215,35 @@ DoRenameFile( } #ifdef HAVE_NO_SEH __asm__ __volatile__ ( - "jmp dorenamefile_pop" "\n" - "dorenamefile_reentry:" "\n\t" - "movl _ESP, %esp" "\n\t" - "movl _EBP, %ebp"); - + "jmp dorenamefile_pop" "\n" + "dorenamefile_reentry:" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl 0x8(%%eax), %%esp" "\n\t" + "movl 0x8(%%esp), %%ebp" "\n" + "dorenamefile_pop:" "\n\t" + "movl (%%esp), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + "add $12, %%esp" "\n\t" + : + : + : "%eax"); + +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "dorenamefile_pop:" "\n\t" - "mov (%esp), %eax" "\n\t" - "mov %eax, %fs:0" "\n\t" - "add $8, %esp"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(RESTORED_ESP), + "=m"(RESTORED_EBP), + "=r"(RESTORED_HANDLER) ); + + if (INITIAL_ESP != RESTORED_ESP) + panic("ESP restored incorrectly"); + if (INITIAL_EBP != RESTORED_EBP) + panic("EBP restored incorrectly"); + if (INITIAL_HANDLER != RESTORED_HANDLER) + panic("HANDLER restored incorrectly"); +# endif /* TCL_MEM_DEBUG */ #else } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif /* HAVE_NO_SEH */ @@ -450,6 +480,8 @@ _except_dorenamefile_handler( { __asm__ __volatile__ ( "jmp dorenamefile_reentry"); + /* Nuke compiler warning about unused static function */ + _except_dorenamefile_handler(NULL, NULL, NULL, NULL); return 0; /* Function does not return */ } #endif /* HAVE_NO_SEH */ @@ -514,14 +546,21 @@ DoCopyFile( */ #ifdef HAVE_NO_SEH +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "movl %esp, _ESP" "\n\t" - "movl %ebp, _EBP"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(INITIAL_ESP), + "=m"(INITIAL_EBP), + "=r"(INITIAL_HANDLER) ); +# endif /* TCL_MEM_DEBUG */ __asm__ __volatile__ ( + "pushl %ebp" "\n\t" "pushl $__except_docopyfile_handler" "\n\t" "pushl %fs:0" "\n\t" - "mov %esp, %fs:0"); + "movl %esp, %fs:0"); #else __try { #endif /* HAVE_NO_SEH */ @@ -530,16 +569,35 @@ DoCopyFile( } #ifdef HAVE_NO_SEH __asm__ __volatile__ ( - "jmp docopyfile_pop" "\n" - "docopyfile_reentry:" "\n\t" - "movl _ESP, %esp" "\n\t" - "movl _EBP, %ebp"); - + "jmp docopyfile_pop" "\n" + "docopyfile_reentry:" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl 0x8(%%eax), %%esp" "\n\t" + "movl 0x8(%%esp), %%ebp" "\n" + "docopyfile_pop:" "\n\t" + "movl (%%esp), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + "add $12, %%esp" "\n\t" + : + : + : "%eax"); + +# ifdef TCL_MEM_DEBUG __asm__ __volatile__ ( - "docopyfile_pop:" "\n\t" - "mov (%esp), %eax" "\n\t" - "mov %eax, %fs:0" "\n\t" - "add $8, %esp"); + "movl %%esp, %0" "\n\t" + "movl %%ebp, %1" "\n\t" + "movl %%fs:0, %2" "\n\t" + : "=m"(RESTORED_ESP), + "=m"(RESTORED_EBP), + "=r"(RESTORED_HANDLER) ); + + if (INITIAL_ESP != RESTORED_ESP) + panic("ESP restored incorrectly"); + if (INITIAL_EBP != RESTORED_EBP) + panic("EBP restored incorrectly"); + if (INITIAL_HANDLER != RESTORED_HANDLER) + panic("HANDLER restored incorrectly"); +# endif /* TCL_MEM_DEBUG */ #else } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif /* HAVE_NO_SEH */ @@ -604,6 +662,7 @@ _except_docopyfile_handler( { __asm__ __volatile__ ( "jmp docopyfile_reentry"); + _except_docopyfile_handler(NULL,NULL,NULL,NULL); return 0; /* Function does not return */ } #endif /* HAVE_NO_SEH */ @@ -1834,19 +1893,3 @@ TclpObjListVolumes(void) Tcl_IncrRefCount(resultPtr); return resultPtr; } - -#ifdef HAVE_NO_SEH -/* - * This method exists only to stop the compiler from emitting - * warnings about variables and methods accessed only from asm. - */ -static void squelch_warnings() -{ - void *ptr; - ptr = _except_dorenamefile_handler; - ptr = _except_docopyfile_handler; - ESP = 0; - EBP = 0; - squelch_warnings(); -} -#endif /* HAVE_NO_SEH */ |