diff options
Diffstat (limited to 'win')
-rw-r--r-- | win/tclWinChan.c | 202 | ||||
-rw-r--r-- | win/tclWinFCmd.c | 396 |
2 files changed, 286 insertions, 312 deletions
diff --git a/win/tclWinChan.c b/win/tclWinChan.c index c4ec930..db8b75b 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.42 2005/06/08 14:12:19 dkf Exp $ + * RCS: @(#) $Id: tclWinChan.c,v 1.43 2005/06/23 19:48:50 kennykb Exp $ */ #include "tclWinInt.h" @@ -127,16 +127,24 @@ static Tcl_ChannelType fileChannelType = { FileTruncateProc, /* Truncate proc. */ }; -#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG) -static void *INITIAL_ESP, *INITIAL_EBP, *INITIAL_HANDLER; -static void *RESTORED_ESP, *RESTORED_EBP, *RESTORED_HANDLER; -#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */ - #ifdef HAVE_NO_SEH -static __attribute__ ((cdecl)) EXCEPTION_DISPOSITION -_except_makefilechannel_handler(struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, struct _CONTEXT *ContextRecord, - void *DispatcherContext); + +/* + * Unlike Borland and Microsoft, we don't register exception handlers + * by pushing registration records onto the runtime stack. Instead, we + * register them by creating an EXCEPTION_REGISTRATION within the activation + * record. + */ + +typedef struct EXCEPTION_REGISTRATION { + struct EXCEPTION_REGISTRATION* link; + EXCEPTION_DISPOSITION (*handler)( struct _EXCEPTION_RECORD*, void*, + struct _CONTEXT*, void* ); + void* ebp; + void* esp; + int status; +} EXCEPTION_REGISTRATION; + #endif /* @@ -1049,6 +1057,9 @@ Tcl_MakeFileChannel(rawHandle, mode) * and TCL_WRITABLE to indicate file * mode. */ { +#ifdef HAVE_NO_SEH + EXCEPTION_REGISTRATION registration; +#endif char channelName[16 + TCL_INTEGER_SPACE]; Tcl_Channel channel = NULL; HANDLE handle = (HANDLE) rawHandle; @@ -1137,81 +1148,93 @@ Tcl_MakeFileChannel(rawHandle, mode) * of this duped handle which might throw EXCEPTION_INVALID_HANDLE. */ -#ifdef HAVE_NO_SEH -# ifdef TCL_MEM_DEBUG - __asm__ __volatile__ ( - "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 %0" "\n\t" - "pushl %%fs:0" "\n\t" - "movl %%esp, %%fs:0" - : - : "r" (_except_makefilechannel_handler) ); - result = CloseHandle(dupedHandle); - __asm__ __volatile__ ( - "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 $0, %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 + result = 0; +#ifndef HAVE_NO_SEH + __try { + CloseHandle(dupedHandle); + result = 1; + } __except (EXCEPTION_EXECUTE_HANDLER) {} +#else + /* + * Don't have SEH available, do things the hard way. + * Note that this needs to be one block of asm, to avoid stack + * imbalance; also, it is illegal for one asm block to contain + * a jump to another. + */ + __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) { - Tcl_Panic("ESP restored incorrectly"); - } - if (INITIAL_EBP != RESTORED_EBP) { - Tcl_Panic("EBP restored incorrectly"); - } - if (INITIAL_HANDLER != RESTORED_HANDLER) { - Tcl_Panic("HANDLER restored incorrectly"); - } -# endif /* TCL_MEM_DEBUG */ - if (result == 0) { /* - * The handle failed to close. The original is therefore - * invalid. + * Pick up parameters before messing with the stack */ - return NULL; - } + "movl %[dupedHandle], %%ebx" "\n\t" -#else - __try { - result = CloseHandle(dupedHandle); - } __except (EXCEPTION_EXECUTE_HANDLER) { /* - * Definately an invalid handle. So, therefore, the original - * is invalid also. + * Construct an EXCEPTION_REGISTRATION to protect the + * call to CloseHandle */ + "leal %[registration], %%edx" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ + "leal 1f, %%eax" "\n\t" + "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ + "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ + "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ + "movl $0, 0x10(%%edx)" "\n\t" /* status */ + + /* Link the EXCEPTION_REGISTRATION on the chain */ + + "movl %%edx, %%fs:0" "\n\t" + + /* Call CloseHandle( dupedHandle ) */ + + "pushl %%ebx" "\n\t" + "call _CloseHandle@4" "\n\t" + + /* + * Come here on normal exit. Recover the EXCEPTION_REGISTRATION + * and put a TRUE status return into it. + */ + + "movl %%fs:0, %%edx" "\n\t" + "movl $1, %%eax" "\n\t" + "movl %%eax, 0x10(%%edx)" "\n\t" + "jmp 2f" "\n" + + /* + * Come here on an exception. Recover the EXCEPTION_REGISTRATION + */ + + "1:" "\t" + "movl %%fs:0, %%edx" "\n\t" + "movl 0x8(%%edx), %%edx" "\n\t" + + /* + * Come here however we exited. Restore context from the + * EXCEPTION_REGISTRATION in case the stack is unbalanced. + */ + + "2:" "\t" + "movl 0xc(%%edx), %%esp" "\n\t" + "movl 0x8(%%edx), %%ebp" "\n\t" + "movl 0x0(%%edx), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + + : + /* No outputs */ + : + [registration] "m" (registration), + [dupedHandle] "m" (dupedHandle) + : + "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" + ); + result = registration.status; +#endif + if (result == FALSE) { return NULL; } -#endif /* HAVE_NO_SEH */ /* Fall through, the handle is valid. */ @@ -1229,37 +1252,6 @@ Tcl_MakeFileChannel(rawHandle, mode) /* *---------------------------------------------------------------------- * - * _except_makefilechannel_handler -- - * - * SEH exception handler for Tcl_MakeFileChannel. - * - * Results: - * See Tcl_MakeFileChannel. - * - * Side effects: - * See Tcl_MakeFileChannel. - * - *---------------------------------------------------------------------- - */ -#ifdef HAVE_NO_SEH -static -__attribute__ ((cdecl)) -EXCEPTION_DISPOSITION -_except_makefilechannel_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT *ContextRecord, - void *DispatcherContext) -{ - __asm__ __volatile__ ( - "jmp makefilechannel_reentry"); - return 0; /* Function does not return */ -} -#endif - -/* - *---------------------------------------------------------------------- - * * TclpGetDefaultStdChannel -- * * Constructs a channel for the specified standard OS handle. diff --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index a5df717..0534971 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.45 2005/05/10 18:35:37 kennykb Exp $ + * RCS: @(#) $Id: tclWinFCmd.c,v 1.46 2005/06/23 19:48:51 kennykb Exp $ */ #include "tclWinInt.h" @@ -74,35 +74,25 @@ CONST TclFileAttrProcs tclpFileAttrProcs[] = { {GetWinFileShortName, CannotSetAttribute}, {GetWinFileAttributes, SetWinFileAttributes}}; -#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 */ - #ifdef HAVE_NO_SEH -static -__attribute__ ((cdecl)) -EXCEPTION_DISPOSITION -_except_dorenamefile_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT *ContextRecord, - void *DispatcherContext); - -static -__attribute__ ((cdecl)) -EXCEPTION_DISPOSITION -_except_docopyfile_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT *ContextRecord, - void *DispatcherContext); - -#endif /* HAVE_NO_SEH */ + +/* + * Unlike Borland and Microsoft, we don't register exception handlers + * by pushing registration records onto the runtime stack. Instead, we + * register them by creating an EXCEPTION_REGISTRATION within the activation + * record. + */ + +typedef struct EXCEPTION_REGISTRATION { + struct EXCEPTION_REGISTRATION* link; + EXCEPTION_DISPOSITION (*handler)( struct _EXCEPTION_RECORD*, void*, + struct _CONTEXT*, void* ); + void* ebp; + void* esp; + int status; +} EXCEPTION_REGISTRATION; + +#endif /* * Prototype for the TraverseWinTree callback function. @@ -193,6 +183,9 @@ DoRenameFile( CONST TCHAR *nativeDst) /* New pathname for file or directory * (native). */ { +#ifdef HAVE_NO_SEH + EXCEPTION_REGISTRATION registration; +#endif DWORD srcAttr, dstAttr; int retval = -1; @@ -212,72 +205,95 @@ DoRenameFile( * if one of the arguments is a char block device. */ -#ifdef HAVE_NO_SEH -# ifdef TCL_MEM_DEBUG - __asm__ __volatile__ ( - "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 %0" "\n\t" - "pushl %%fs:0" "\n\t" - "movl %%esp, %%fs:0" - : - : "r" (_except_dorenamefile_handler) - ); -#else +#ifndef HAVE_NO_SEH __try { -#endif /* HAVE_NO_SEH */ if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) { retval = TCL_OK; } -#ifdef HAVE_NO_SEH - __asm__ __volatile__ ( - "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__ ( - "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) { - Tcl_Panic("ESP restored incorrectly"); - } - if (INITIAL_EBP != RESTORED_EBP) { - Tcl_Panic("EBP restored incorrectly"); - } - if (INITIAL_HANDLER != RESTORED_HANDLER) { - Tcl_Panic("HANDLER restored incorrectly"); - } -# endif /* TCL_MEM_DEBUG */ -#else } __except (EXCEPTION_EXECUTE_HANDLER) {} -#endif /* HAVE_NO_SEH */ +#else /* - * Avoid using control flow statements in the SEH guarded block! + * Don't have SEH available, do things the hard way. + * Note that this needs to be one block of asm, to avoid stack + * imbalance; also, it is illegal for one asm block to contain + * a jump to another. */ + + __asm__ __volatile__ ( + /* + * Pick up params before messing with the stack */ + + "movl %[nativeDst], %%ebx" "\n\t" + "movl %[nativeSrc], %%ecx" "\n\t" + + /* + * Construct an EXCEPTION_REGISTRATION to protect the + * call to MoveFile + */ + "leal %[registration], %%edx" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ + "leal 1f, %%eax" "\n\t" + "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ + "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ + "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ + "movl $0, 0x10(%%edx)" "\n\t" /* status */ + + /* Link the EXCEPTION_REGISTRATION on the chain */ + + "movl %%edx, %%fs:0" "\n\t" + + /* Call MoveFile( nativeSrc, nativeDst ) */ + + "pushl %%ebx" "\n\t" + "pushl %%ecx" "\n\t" + "movl %[moveFile], %%eax" "\n\t" + "call *%%eax" "\n\t" + + /* + * Come here on normal exit. Recover the EXCEPTION_REGISTRATION + * and put the status return from MoveFile into it. + */ + + "movl %%fs:0, %%edx" "\n\t" + "movl %%eax, 0x10(%%edx)" "\n\t" + "jmp 2f" "\n" + + /* + * Come here on an exception. Recover the EXCEPTION_REGISTRATION + */ + + "1:" "\t" + "movl %%fs:0, %%edx" "\n\t" + "movl 0x8(%%edx), %%edx" "\n\t" + + /* + * Come here however we exited. Restore context from the + * EXCEPTION_REGISTRATION in case the stack is unbalanced. + */ + + "2:" "\t" + "movl 0xc(%%edx), %%esp" "\n\t" + "movl 0x8(%%edx), %%ebp" "\n\t" + "movl 0x0(%%edx), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + + : + /* No outputs */ + : + [registration] "m" (registration), + [nativeDst] "m" (nativeDst), + [nativeSrc] "m" (nativeSrc), + [moveFile] "r" (tclWinProcs->moveFileProc) + : + "%eax", "%ebx", "%ecx", "%edx", "memory" + ); + if (registration.status != FALSE) { + retval = TCL_OK; + } +#endif + if (retval != -1) { return retval; } @@ -506,37 +522,6 @@ DoRenameFile( } /* - *---------------------------------------------------------------------- - * - * _except_dorenamefile_handler -- - * - * SEH exception handler for DoRenameFile. - * - * Results: - * See DoRenameFile. - * - * Side effects: - * See DoRenameFile. - * - *---------------------------------------------------------------------- - */ -#ifdef HAVE_NO_SEH -static -__attribute__ ((cdecl)) -EXCEPTION_DISPOSITION -_except_dorenamefile_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT *ContextRecord, - void *DispatcherContext) -{ - __asm__ __volatile__ ( - "jmp dorenamefile_reentry"); - return 0; /* Function does not return */ -} -#endif /* HAVE_NO_SEH */ - -/* *--------------------------------------------------------------------------- * * TclpObjCopyFile, DoCopyFile -- @@ -577,6 +562,9 @@ DoCopyFile( CONST TCHAR *nativeSrc, /* Pathname of file to be copied (native). */ CONST TCHAR *nativeDst) /* Pathname of file to copy to (native). */ { +#ifdef HAVE_NO_SEH + EXCEPTION_REGISTRATION registration; +#endif int retval = -1; /* @@ -595,72 +583,97 @@ DoCopyFile( * of the arguments is a char block device. */ -#ifdef HAVE_NO_SEH -# ifdef TCL_MEM_DEBUG - __asm__ __volatile__ ( - "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 %0" "\n\t" - "pushl %%fs:0" "\n\t" - "movl %%esp, %%fs:0" - : - : "r" (_except_docopyfile_handler) - ); -#else +#ifndef HAVE_NO_SEH __try { -#endif /* HAVE_NO_SEH */ if ((*tclWinProcs->copyFileProc)(nativeSrc, nativeDst, 0) != FALSE) { retval = TCL_OK; } -#ifdef HAVE_NO_SEH - __asm__ __volatile__ ( - "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__ ( - "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) { - Tcl_Panic("ESP restored incorrectly"); - } - if (INITIAL_EBP != RESTORED_EBP) { - Tcl_Panic("EBP restored incorrectly"); - } - if (INITIAL_HANDLER != RESTORED_HANDLER) { - Tcl_Panic("HANDLER restored incorrectly"); - } -# endif /* TCL_MEM_DEBUG */ -#else } __except (EXCEPTION_EXECUTE_HANDLER) {} -#endif /* HAVE_NO_SEH */ +#else /* - * Avoid using control flow statements in the SEH guarded block! + * Don't have SEH available, do things the hard way. + * Note that this needs to be one block of asm, to avoid stack + * imbalance; also, it is illegal for one asm block to contain + * a jump to another. */ + + __asm__ __volatile__ ( + + /* + * Pick up parameters before messing with the stack + */ + + "movl %[nativeDst], %%ebx" "\n\t" + "movl %[nativeSrc], %%ecx" "\n\t" + /* + * Construct an EXCEPTION_REGISTRATION to protect the + * call to CopyFile + */ + "leal %[registration], %%edx" "\n\t" + "movl %%fs:0, %%eax" "\n\t" + "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ + "leal 1f, %%eax" "\n\t" + "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ + "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ + "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ + "movl $0, 0x10(%%edx)" "\n\t" /* status */ + + /* Link the EXCEPTION_REGISTRATION on the chain */ + + "movl %%edx, %%fs:0" "\n\t" + + /* Call CopyFile( nativeSrc, nativeDst, 0 ) */ + + "movl %[copyFile], %%eax" "\n\t" + "pushl $0" "\n\t" + "pushl %%ebx" "\n\t" + "pushl %%ecx" "\n\t" + "call *%%eax" "\n\t" + + /* + * Come here on normal exit. Recover the EXCEPTION_REGISTRATION + * and put the status return from CopyFile into it. + */ + + "movl %%fs:0, %%edx" "\n\t" + "movl %%eax, 0x10(%%edx)" "\n\t" + "jmp 2f" "\n" + + /* + * Come here on an exception. Recover the EXCEPTION_REGISTRATION + */ + + "1:" "\t" + "movl %%fs:0, %%edx" "\n\t" + "movl 0x8(%%edx), %%edx" "\n\t" + + /* + * Come here however we exited. Restore context from the + * EXCEPTION_REGISTRATION in case the stack is unbalanced. + */ + + "2:" "\t" + "movl 0xc(%%edx), %%esp" "\n\t" + "movl 0x8(%%edx), %%ebp" "\n\t" + "movl 0x0(%%edx), %%eax" "\n\t" + "movl %%eax, %%fs:0" "\n\t" + + : + /* No outputs */ + : + [registration] "m" (registration), + [nativeDst] "m" (nativeDst), + [nativeSrc] "m" (nativeSrc), + [copyFile] "r" (tclWinProcs->copyFileProc) + : + "%eax", "%ebx", "%ecx", "%edx", "memory" + ); + if (registration.status != FALSE) { + retval = TCL_OK; + } +#endif + if (retval != -1) { return retval; } @@ -709,37 +722,6 @@ DoCopyFile( } /* - *---------------------------------------------------------------------- - * - * _except_docopyfile_handler -- - * - * SEH exception handler for DoCopyFile. - * - * Results: - * See DoCopyFile. - * - * Side effects: - * See DoCopyFile. - * - *---------------------------------------------------------------------- - */ -#ifdef HAVE_NO_SEH -static -__attribute__ ((cdecl)) -EXCEPTION_DISPOSITION -_except_docopyfile_handler( - struct _EXCEPTION_RECORD *ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT *ContextRecord, - void *DispatcherContext) -{ - __asm__ __volatile__ ( - "jmp docopyfile_reentry"); - return 0; /* Function does not return */ -} -#endif /* HAVE_NO_SEH */ - -/* *--------------------------------------------------------------------------- * * TclpObjDeleteFile, TclpDeleteFile -- |