Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com Message-ID: <37CF7B31.7D712E@1c.ru> Date: Fri, 03 Sep 1999 11:39:29 +0400 From: Vadim Egorov X-Mailer: Mozilla 4.61 [en] (WinNT; I) X-Accept-Language: ru,en MIME-Version: 1.0 To: "cygwin-developers AT sourceware DOT cygnus DOT com" Subject: setjmp/longjmp patch Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 8bit X-MDaemon-Deliver-To: cygwin-developers AT sourceware DOT cygnus DOT com X-Return-Path: EgorovV AT 1c DOT ru 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 *********************************************