Tcl Source Code

View Ticket
Login
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: