Ticket UUID: | 525746 | |||
Title: | SEH support under mingw | |||
Type: | Patch | Version: | None | |
Submitter: | mdejong | Created on: | 2002-03-05 01:32:25 | |
Subsystem: | 53. Configure and Build Tools | Assigned To: | mdejong | |
Priority: | 5 Medium | Severity: | ||
Status: | Closed | Last Modified: | 2003-01-25 03:28:38 | |
Resolution: | Accepted | Closed By: | mdejong | |
Closed on: | 2003-01-24 20:28:38 | |||
Description: |
Existing releases of mingw either fail to support SEH or "fake it" so that things compile. This is going to be a problem for Tcl since code in win/tclWin32Dll.c, win/tclWinChan.c, and win/tclWinFCmd.c depends on SEH. This patch ident will be used to collect patches related to SEH support before merging. | |||
User Comments: |
mdejong added on 2003-01-25 03:28:38:
File Added - 40566: new_handler.c Logged In: YES user_id=90858 After some more thinking about SEH I found that the current approach is not thread safe and needs to be fixed so that it uses the stack instead of global vars. The tricky part is that what we need to do is use the thread local fs:0 register to lookup the original exception handler info when our exception handler gets called. The new_handler.c file I just added is a short example of this new approach in action. I will create a larger patch for Tcl and check it into the CVS. mdejong added on 2002-03-15 08:12:15: Logged In: YES user_id=90858 I tested out gcc_asm.patch3 and it seems to be working just fine. Checked in to CVS on 2002-03-14. mdejong added on 2002-03-15 08:03:30: File Deleted - 19369: File Added - 19384: gcc_seh_asm.patch3 mdejong added on 2002-03-15 05:24:14: File Deleted - 19051: File Added - 19369: gcc_seh_asm.patch2 Logged In: YES user_id=90858 Here is a new patch to implement SEH in gcc. It should be ready to go, just needs a little testing. mdejong added on 2002-03-15 03:43:16: Logged In: YES user_id=90858 I just got a report back from a kind soul named Stephen Trier. He tested the patch out on NT and it did not change any test results. I have to assume that use of a continue handler was simply a mistake. I am checking this no_continue patch in. mdejong added on 2002-03-14 07:00:43: File Deleted - 19124: File Added - 19305: no_continue_handler.patch Logged In: YES user_id=90858 I am leaving saturday and will be gone for a couple of weeks. It would be nice if we could get this and the mingw asm thing worked out before then. davygrvy added on 2002-03-13 05:41:07: Logged In: YES user_id=7549 I'm a bit busy this week. I'll give it a shot this weekend. mdejong added on 2002-03-11 04:10:45: File Added - 19124: no_continue_handler.patch mdejong added on 2002-03-11 04:09:34: Logged In: YES user_id=90858 I thought about it, and I just can't come up with any reason this exception handler should continue instead of handling the exception. Bug 466102 shows what would happen if something does go wrong in the MoveFile or CopyFile API, the whole process locks up because the fault and the handler run in an infinite loop. This code dates back to Tcl 8.0 so I can't find any record of why it was it was added or what it should do. Could you grab this no_continue_handler.patch, apply it, and rerun the test cases under NT to see if there are any differences? The tests don't work properly under Win98 right now, but that is going to have to be dealt with in another bug report. davygrvy added on 2002-03-10 10:53:01: Logged In: YES user_id=7549 Lucky you. You've got time to play around with this while I'm nose deep in the daily grind. If MoveFileA and EXCEPTION_CONTINUE_EXECUTION don't work together, then I think you've found a deep bug. No infinite loop found on NT with your example (it needed a missing '}' though). Note that Tcl might be changing its error mode with SetErrorMode(), and that causes exceptions to behave a bit different on some operations. I don't know the exact details though. Let me know if I can assist. You've got it all done, and now I'm just an observer :) BTW, _except_handler3 is found in msvcrt.dll. here's the proof: D:\>dumpbin /exports c:\winnt\system32\msvcrt.dll | find "_except_handler" 205 CC 0001F17E _except_handler2 206 CD 0000DB11 _except_handler3 I'm not saying we should use it, but if we do need to interface with it, it's there. mdejong added on 2002-03-10 10:14:03: Logged In: YES user_id=90858 I did some testing of the asm SEH impl and found that it was going into an infinate loop when running test winFCmd-1.7. At first, I thought I coded something up wrong, but then I found that the VC++ compiled executable is also going into an infinate loop in this same place. I am seeing these results on a Win98 box. Here is a small example: #define WIN32_LEAN_AND_MEAN #include <windows.h> int main() { __try { MoveFileA(NULL, "C:\\A.TXT"); __except (EXCEPTION_CONTINUE_EXECUTION) {} } This loops forever because MoveFileA is generating a SIGSEGV over and over again. I just don't understand why these two calls in tclWinFCmd.c are coded to restart the faulting instruction and why others don't seem to be running into this infinate loop problem in winFCmd.test. mdejong added on 2002-03-09 07:12:25: File Added - 19051: gcc_seh_asm.patch mdejong added on 2002-03-09 07:11:30: File Deleted - 19049: mdejong added on 2002-03-09 06:44:12: File Added - 19049: gcc_seh_asm.patch Logged In: YES user_id=90858 I just attached the patch gcc_seh_asm.patch which should get Tcl to compile with gcc. This patch is going to need testing, but I think it will work. As far as _except_handler3 goes, I was under the impression that it was not defined in msvcrt.dll. This nm output of msvcrt.lib seems to support that view. msvcrt.lib:build/intel/dll_obj/wcrtexew.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/wcrtexe.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/ehvecdtr.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/ehveccvb.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/ehvecctr.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/crtexew.obj: U __except_handler3 msvcrt.lib:build/intel/dll_obj/crtexe.obj: U __except_handler3 Instead VC++ includes this handler in the statically linked runtime library. The inline ASM handlers I wrote would not invoke cleanup handlers farther up on the stack, but I don't think this will be a problem in the guarded calls to alloca() or CloseHandle(). The other two handlers just restart the faulting instruction. To be honest, I am not sure why they do that, it seems unsafe because a NULL pointer deref could send the application into an infinate loop. davygrvy added on 2002-03-08 10:32:41: Logged In: YES user_id=7549 we might be able to use the builtin one from msvcrt.dll called _except_handler3. Or maybe use our own. The logic would be easier. I'll play some more with listing outputs from VC++, and get a better grip on how it's innards are working. As long as it works, and cleans up after itself, I don't think it would matter which method is used. BTW, I didn't know you could specify labels with inline asm with gcc :) inline asm in VC++, that isn't allowed. mdejong added on 2002-03-08 07:46:40: File Added - 19015: handler.c Logged In: YES user_id=90858 I did some more hacking and came up with handler.c. It will create a SEH handler that does a jmp back into the original function. The only way I could see to implement this was to save the ESP and EBP pointers before entering the guard block and then restoring them after returning from the handler. Does this seem like a reasonable thing to be doing? davygrvy added on 2002-03-07 14:18:05: Logged In: YES user_id=7549 none at all. I like it. moseh.c rocks, too. I was almost that far, but have to stay focused on the day gig :( mdejong added on 2002-03-07 12:58:55: File Added - 18948: seh_return.patch Logged In: YES user_id=90858 I did some reading up on control flow statements in try blocks here: http://www.gamedev.net/reference/programming/features/sehbasics/ Since return statements in try blocks are bad news, I whipped up a new patch to get rid of them and use symbolic names instead of hard coded values. Any objection to checking this patch in? mdejong added on 2002-03-07 12:23:22: Logged In: YES user_id=90858 "Small comment. returns from a __try block aren't good." Well, I was just poking around in tclWinFCmd.c when I noticed this: __try { if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) { return TCL_OK; } } Should we move that return statement out of the __try block? Something like the following perhaps? int retval = -1; __try { if (func()) retval = TCL_OK; } __except(...) {} if (retval != -1) return retval; This also shows up in tclWin32Dll.c: __try { alloca(TCL_WIN_STACK_THRESHOLD); return 1; } __except (...) {} Should both of these be changed? I think that adding the asm statements will be easier if we make this change. I also noticed that we should be using EXCEPTION_CONTINUE_EXECUTION instead of -1 in tclWinFCmd.c. mdejong added on 2002-03-06 15:25:23: Logged In: YES user_id=90858 Here is another cool link for general 32 bit x86 asm stuff. http://www.drpaulcarter.com/pcasm/pcasm-book.pdf mdejong added on 2002-03-06 15:14:04: File Added - 18863: moseh.c mdejong added on 2002-03-06 15:02:39: Logged In: YES user_id=90858 You are right, that last URL is a really great ref. I took some time today to convert one of the examples over to AT&T syntax and compiles with Mingw 1.1. I will attach it so you can have a look. davygrvy added on 2002-03-06 07:07:33: Logged In: YES user_id=7549 I'm just logging this great resource. http://www.microsoft.com/msj/defaultframe.asp? page=/msj/0197/exception/exception.htm&nav=/msj/0197/newnav. htm davygrvy added on 2002-03-05 15:20:45: Logged In: YES user_id=7549 I spoke too soon. The docs say it only works on the ARM or AVR ports. testSEH.c:21: warning: `naked' attribute directive ignored davygrvy added on 2002-03-05 15:18:43: Logged In: YES user_id=7549 nevermind. found it. __attribute__((naked)) davygrvy added on 2002-03-05 14:53:07: Logged In: YES user_id=7549 small Q. How can one add an attribute to a function so that the prologue and epilogue is stripped? I saw -mschedule-prologue and -mno-epilogue as switches, but I'd rather, if possible, do it like how __stdcall and __cdecl are used for attributes. Is there such a thing for stripping? mdejong added on 2002-03-05 14:16:05: File Deleted - 18807: File Added - 18817: seh.patch Logged In: YES user_id=90858 Ok, uploading a new patch to fix that. davygrvy added on 2002-03-05 12:52:34: Logged In: YES user_id=7549 Looks good. Small comment. returns from a __try block aren't good. This is more strict: int main(...) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } mdejong added on 2002-03-05 08:32:26: File Added - 18807: seh.patch |
Attachments:
- new_handler.c [download] added by mdejong on 2003-01-25 03:28:38. [details]
- gcc_seh_asm.patch3 [download] added by mdejong on 2002-03-15 08:03:30. [details]
- no_continue_handler.patch [download] added by mdejong on 2002-03-14 07:00:43. [details]
- handler.c [download] added by mdejong on 2002-03-08 07:46:40. [details]
- seh_return.patch [download] added by mdejong on 2002-03-07 12:58:55. [details]
- moseh.c [download] added by mdejong on 2002-03-06 15:14:03. [details]