diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2015-07-07 20:45:06 +0200 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2015-07-07 20:45:06 +0200 |
commit | 60f10c64aa57d613471446ea3ec1b3ce6d3b9500 (patch) | |
tree | 0d7e41c913bb1d547cf3512dd3314dc332ca0585 /winsup/cygwin/exceptions.cc | |
parent | 29a12632278368f197f3270532e2f6c19642512e (diff) | |
download | cygnal-60f10c64aa57d613471446ea3ec1b3ce6d3b9500.tar.gz cygnal-60f10c64aa57d613471446ea3ec1b3ce6d3b9500.tar.bz2 cygnal-60f10c64aa57d613471446ea3ec1b3ce6d3b9500.zip |
x86_64: Handle myfault exceptions when running on alternate signal stack
x86_64 only:
* cygtls.cc (san::leave): Restore _my_tls.andreas.
* cygtls.h (class san): Add _clemente as in 32 bit case. Add ret and
frame members.
(san::san): Handle _my_tls.andreas as on 32 bit. Take parameter and
write it to new member ret. Store current stack pointer in frame.
(san::~san): New destructor to restore _my_tls.andreas.
(__try): Use __l_except address as parameter to san::san.
* dcrt0.cc (dll_crt0_0): Add myfault_altstack_handler as vectored
continuation handler.
* exception.h (myfault_altstack_handler): Declare.
* exceptions.cc (myfault_altstack_handler): New function. Explain what
it's good for.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 0ce22d9b3..2ba2f4945 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -588,6 +588,50 @@ exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, /* NOTREACHED, make gcc happy. */ return ExceptionContinueSearch; } + +/* If another exception occurs while running a signal handler on an alternate + signal stack, the normal SEH handlers are skipped, because the OS exception + handling considers the current (alternate) stack "broken". However, it + still calls vectored exception handlers. + + TODO: What we do here is to handle only __try/__except blocks in Cygwin. + "Normal" exceptions will simply exit the process. Still, better + than nothing... */ +LONG WINAPI +myfault_altstack_handler (EXCEPTION_POINTERS *exc) +{ + _cygtls& me = _my_tls; + + if (me.andreas) + { + PRUNTIME_FUNCTION f; + ULONG64 imagebase; + UNWIND_HISTORY_TABLE hist; + DWORD64 establisher; + PVOID hdl; + CONTEXT *c = exc->ContextRecord; + + /* Unwind the stack manually and call RtlRestoreContext. This + is necessary because RtlUnwindEx checks the stack for validity, + which, as outlined above, fails for the alternate stack. */ + while (c->Rsp < me.andreas->frame) + { + f = RtlLookupFunctionEntry (c->Rip, &imagebase, &hist); + if (f) + RtlVirtualUnwind (0, imagebase, c->Rip, f, c, &hdl, &establisher, + NULL); + else + { + c->Rip = *(ULONG_PTR *) c->Rsp; + c->Rsp += 8; + } + } + c->Rip = me.andreas->ret; + RtlRestoreContext (c, NULL); + } + return EXCEPTION_CONTINUE_SEARCH; +} + #endif /* Main exception handler. */ @@ -697,11 +741,13 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, break; case STATUS_STACK_OVERFLOW: +#if 0 /* If we encounter a stack overflow, and if the thread has no alternate stack, don't even try to call a signal handler. This is in line with Linux behaviour and also makes a lot of sense on Windows. */ if (me.altstack.ss_flags) global_sigs[SIGSEGV].sa_handler = SIG_DFL; +#endif /*FALLTHRU*/ case STATUS_ARRAY_BOUNDS_EXCEEDED: case STATUS_IN_PAGE_ERROR: |