www.delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2009/07/23/12:35:49

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_102,J_CHICKENPOX_47,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS
X-Spam-Check-By: sourceware.org
To: cygwin AT cygwin DOT com
From: Eric Blake <ebb9 AT byu DOT net>
Subject: Re: [1.7] Updated: libsigsegv-2.6-1
Date: Thu, 23 Jul 2009 16:35:12 +0000 (UTC)
Lines: 99
Message-ID: <loom.20090723T145926-237@post.gmane.org>
References: <4A678AC7 DOT 7090303 AT x-ray DOT at> <4A6854F8 DOT 4060204 AT byu DOT net> <20090723144038 DOT GA11519 AT ednor DOT casa DOT cgf DOT cx>
Mime-Version: 1.0
User-Agent: Loom/3.14 (http://gmane.org/)
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

> I'm still mystified as to how a package which uses automatic variables
> to deal with a stack overflow situation could claim to be handling stack
> overflow.

It's all in how Windows generates the stack overflow SEH fault.  The comments 
in libsigsegv/src/handler-win32.c are pretty clear:

/* Stack overflow handling is tricky:
   First, we must catch a STATUS_STACK_OVERFLOW exception. This is signalled
   when the guard page at the end of the stack has been touched. The operating
   system remaps the page with protection PAGE_READWRITE and only then calls
   our exception handler. Actually, it's even more complicated: The stack has
   the following layout:

           |                             |guard|----------stack-----------|

   and when the guard page is touched, the system maps it PAGE_READWRITE and
   allocates a new guard page below it:

           |                       |guard|-------------stack--------------|

   Only when no new guard page can be allocated (because the maximum stack
   size has been reached), will we see an exception.

           |guard|-------------------------stack--------------------------|

   Second, we must reinstall the guard page. Otherwise, on the next stack
   overflow, the application will simply crash (on WinNT: silently, on Win95:
   with an error message box and freezing the system).
   But since we don't know where %esp points to during the exception handling,
   we must first leave the exception handler, before we can restore the guard
   page. And %esp must be made to point to a reasonable value before we do
   this.

   Note: On WinNT, the guard page has protection PAGE_READWRITE|PAGE_GUARD.
   On Win95, which doesn't know PAGE_GUARD, it has protection PAGE_NOACCESS.
 */

Basically, by the time SEH wakes you up to tell you about stack overflow, the 
guard page is now read-write, so you effectively have an entire page of memory 
(but no more) in which to do all your management of setting up an alternate 
stack.  The automatic variables within libsigsegv's SEH handler occupy only a 
bounded amount of stack depth within the guard page to restart execution, but 
using stk_extra_stack (which was either carved out of the original stack via 
alloca, or carved out of the heap or static storage) as the new stack when 
resuming execution.  Then all further processing (including resetting the guard 
page and calling the user's stack-overflow-handler) is no longer up against the 
stack overflow issue, and the user's handler can still call siglongjmp to 
unwind back to a place earlier in the original stack.

              char *address = (char *) ExceptionInfo->ExceptionRecord-
>ExceptionInformation[1];
              /* Restart the program, giving it a sane value for %esp.
                 At the same time, copy the contents of
                 ExceptionInfo->ContextRecord (which, on Windows XP, happens
                 to be allocated in the guard page, where it will be
                 inaccessible as soon as we restore the PAGE_GUARD bit!) to
                 this new stack.  */
              unsigned long faulting_page_address = (unsigned long)address & -
0x1000;
              unsigned long new_safe_esp = ((stk_extra_stack + 
stk_extra_stack_size) & -16);
              CONTEXT *orig_context = ExceptionInfo->ContextRecord;
              CONTEXT *safe_context = (CONTEXT *) (new_safe_esp -= sizeof 
(CONTEXT)); /* make room */
              memcpy (safe_context, orig_context, sizeof (CONTEXT));
              new_safe_esp -= 8; /* make room for arguments */
              new_safe_esp &= -16; /* align */
              new_safe_esp -= 4; /* make room for (unused) return address slot 
*/
              ExceptionInfo->ContextRecord->Esp = new_safe_esp;
              /* Call stack_overflow_handler
(faulting_page_address,safe_context).  */
              ExceptionInfo->ContextRecord->Eip = (unsigned long)
&stack_overflow_handler;
              *(unsigned long *)(new_safe_esp + 4) = faulting_page_address;
              *(unsigned long *)(new_safe_esp + 8) = (unsigned long) 
safe_context;
              return EXCEPTION_CONTINUE_EXECUTION;


Another way of looking at this is that libsigsegv implemented its own version 
of sigaltstack; the ideas used here in libsigsegv seem like they could be 
ported to cygwin's exceptions.cc without too much trouble.

> 
> I really don't like the games this package plays.  I'm halfway tempted
> to just make it nonfunctional in Cygwin.

It works just fine, especially now that it only uses SEH for stack overflow 
detection instead of assuming that all SEH faults imply SIGSEGV.  I've hammered 
it pretty hard as part of using it in m4.  And if cygwin ever implements 
sigaltstack, then just rerunning libsigsegv's configure script will pick that 
up, and use sigaltstack rather than SEH for stack overflow management.

-- 
Eric Blake




--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019