Mail Archives: cygwin-developers/1999/09/03/03:42:05
Hello,
Here is a patch for setjmp/longjmp to behave correctly when called
during win32 exception handling.
seljmp uses four bites to store fs:0 at offset 44 of jmp_buffer.
longjmp compares it with current fs:0 value and if doesn't match
calls seh_unwind. It shouldn't do much harm for a normal case.
seh_unwind makes an attempt to notify seh handlers to be removed
about unwinding and restore original seh frame state.
Regards,
Vadim
--- config/i386/setjmp.c Fri Oct 23 11:23:57 1998
+++ config/i386/setjmp.c.1 Fri Sep 03 08:29:54 1999
@@ -40,4 +40,6 @@ asm(" .globl _setjmp \n"
" movw %ss, %ax \n"
" movw %ax, 42(%edi) \n"
+" movl %fs:0, %eax \n"
+" movl %eax, 44(%edi) \n"
" popl %edi \n"
" movl $0,%eax \n"
--- config/i386/longjmp.c Fri Oct 23 11:23:57 1998
+++ config/i386/longjmp.c.1 Fri Sep 03 08:48:20 1999
@@ -11,4 +11,5 @@ details. */
#ifdef __i386__
#if 1
+
asm (" .globl _longjmp \n"
"_longjmp: \n"
@@ -16,4 +17,12 @@ asm (" .globl _longjmp \n"
" movl %esp,%ebp \n"
" movl 8(%ebp),%edi \n"
+" movl 8(%ebp),%eax \n"
+" movl 44(%eax),%eax \n"
+" cmpl %fs:0,%eax \n"
+" je L1 \n"
+" pushl %eax \n"
+" call _seh_unwind \n"
+" add $4, %esp \n"
+"L1: \n"
" movl 12(%ebp),%eax \n"
" testl %eax,%eax \n"
--- exceptions.cc Fri Sep 03 10:55:46 1999
+++ exceptions.cc.1 Fri Sep 03 10:36:29 1999
@@ -821,2 +821,49 @@ _sigreturn:
");
}
+
+#ifdef __i386__
+
+/* Win32 SEH stack unwinding. It is called from longjmp when
+current SEH frame doesnt match stored in jmp_buf one
+seh_unwind from currently installed at fs:0 SEH frame down to
+given frame and and calls tham for unwinding. Does the nearly
+the same _RtlUnwind API function's work but without any sanity
+checking
+*/
+extern "C"
+void seh_unwind(exception_list * frame)
+{
+ EXCEPTION_RECORD ex_rec;
+ CONTEXT ctx;
+ exception_list* dispatched_frame;
+
+ exception_list* p = _except_list;
+ if (p != frame)
+ debug_printf ("unwinding SEH frames down to %p", frame);
+ else
+ return ;
+
+ ex_rec.ExceptionCode = 0;
+ ex_rec.ExceptionFlags = 2;
+ ex_rec.ExceptionRecord = 0;
+ ex_rec.ExceptionAddress = 0;
+
+ GetThreadContext(GetCurrentThread(), &ctx);
+ while (p != (exception_list*)(-1))
+ {
+ if (p == frame)
+ {
+ _except_list = p;
+ return;
+ }
+ else
+ {
+ p->handler(&ex_rec, p, &ctx, &dispatched_frame);
+ debug_printf ("calling SEH frame %p", p);
+ p = p->prev;
+ }
+ }
+ // if we get here something is wrong
+ debug_printf ("failed to find SEH frame %p", frame);
+}
+#endif /*__i386__*/
--
*********************************************
Vadim Egorov, 1C * ÷ÁÄÉÍ åÇÏÒÏ×,1C
egorovv AT 1c DOT ru * egorovv AT 1c DOT ru
*********************************************
- Raw text -