This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

setjmp/longjmp patch


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@1c.ru         *         egorovv@1c.ru
*********************************************


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]