Implement using alternate signal stack in Cygwin
* exceptions.cc (_cygtls::call_signal_handler): Implement alternate signal stack handling. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
6442e914d9
commit
0cbf19283b
|
@ -1537,8 +1537,15 @@ _cygtls::call_signal_handler ()
|
||||||
RtlCaptureContext ((CONTEXT *) &context.uc_mcontext);
|
RtlCaptureContext ((CONTEXT *) &context.uc_mcontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: If/when sigaltstack is implemented, this will need to do
|
if (this_sa_flags & SA_ONSTACK
|
||||||
something more complicated */
|
&& !_my_tls.altstack.ss_flags
|
||||||
|
&& _my_tls.altstack.ss_sp)
|
||||||
|
{
|
||||||
|
context.uc_stack = _my_tls.altstack;
|
||||||
|
context.uc_stack.ss_flags = SS_ONSTACK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase;
|
context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase;
|
||||||
context.uc_stack.ss_flags = 0;
|
context.uc_stack.ss_flags = 0;
|
||||||
if (!NtCurrentTeb ()->DeallocationStack)
|
if (!NtCurrentTeb ()->DeallocationStack)
|
||||||
|
@ -1549,7 +1556,7 @@ _cygtls::call_signal_handler ()
|
||||||
context.uc_stack.ss_size
|
context.uc_stack.ss_size
|
||||||
= (uintptr_t) NtCurrentTeb ()->DeallocationStack
|
= (uintptr_t) NtCurrentTeb ()->DeallocationStack
|
||||||
- (uintptr_t) NtCurrentTeb ()->Tib.StackBase;
|
- (uintptr_t) NtCurrentTeb ()->Tib.StackBase;
|
||||||
|
}
|
||||||
context.uc_sigmask = context.uc_mcontext.oldmask = this_oldmask;
|
context.uc_sigmask = context.uc_mcontext.oldmask = this_oldmask;
|
||||||
|
|
||||||
context.uc_mcontext.cr2 = (thissi.si_signo == SIGSEGV
|
context.uc_mcontext.cr2 = (thissi.si_signo == SIGSEGV
|
||||||
|
@ -1565,7 +1572,95 @@ _cygtls::call_signal_handler ()
|
||||||
sig = 0; /* Flag that we can accept another signal */
|
sig = 0; /* Flag that we can accept another signal */
|
||||||
unlock (); /* unlock signal stack */
|
unlock (); /* unlock signal stack */
|
||||||
|
|
||||||
|
/* Alternate signal stack requested for this signal and alternate signal
|
||||||
|
stack set up for this thread? */
|
||||||
|
if (this_sa_flags & SA_ONSTACK
|
||||||
|
&& !_my_tls.altstack.ss_flags
|
||||||
|
&& _my_tls.altstack.ss_sp)
|
||||||
|
{
|
||||||
|
/* Yes, use alternate signal stack.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
We DO NOT change the TEB's stack addresses and we DO NOT move the
|
||||||
|
_cygtls area to the alternate stack. This seems to work fine on
|
||||||
|
32 and 64 bit, but there may be Windows functions not working
|
||||||
|
correctly under these circumstances. Especially 32 bit exception
|
||||||
|
handling may be broken.
|
||||||
|
|
||||||
|
On the other hand, if a Windows function crashed and we're handling
|
||||||
|
this here, moving the TEB stack addresses may be fatal.
|
||||||
|
|
||||||
|
If the current code does not work as expected in the "usual"
|
||||||
|
POSIX circumstances, this problem must be revisited. */
|
||||||
|
|
||||||
|
/* Compute new stackbase. We start from the high address, subtract
|
||||||
|
16 bytes (safe/sorry) and align to 16 byte. */
|
||||||
|
uintptr_t new_sp = (uintptr_t) _my_tls.altstack.ss_sp
|
||||||
|
+ _my_tls.altstack.ss_size - 0x10;
|
||||||
|
new_sp &= ~0xf;
|
||||||
|
/* Mark alternate stack as used. */
|
||||||
|
_my_tls.altstack.ss_flags = SS_ONSTACK;
|
||||||
|
/* Move to alternate stack, call thisfunc, revert stack regs. */
|
||||||
|
#ifdef __x86_64__
|
||||||
|
__asm__ ("\n\
|
||||||
|
movq %[NEW_SP], %%r10 # Load alt stack into r10 \n\
|
||||||
|
movl %[SIG], %%ecx # thissig to 1st arg reg \n\
|
||||||
|
movq %[SI], %%rdx # &thissi to 2nd arg reg \n\
|
||||||
|
movq %[CTX], %%r8 # thiscontext to 3rd arg reg \n\
|
||||||
|
movq %[FUNC], %%rax # thisfunc to rax \n\
|
||||||
|
movq %%rbp, %%r12 # Save rbp in r12 \n\
|
||||||
|
movq %%rsp, %%r13 # Store rsp in r13 \n\
|
||||||
|
movq %%r10, %%rsp # Move alt stack into rsp \n\
|
||||||
|
xorq %%rbp, %%rbp # Set rbp to 0 \n\
|
||||||
|
subq $32, %%rsp # Setup shadow space \n\
|
||||||
|
call *%%rax # Call thisfunc \n\
|
||||||
|
movq %%r12, %%rbp # Restore rbp \n\
|
||||||
|
movq %%r13, %%rsp # Restore rsp \n"
|
||||||
|
: : [NEW_SP] "o" (new_sp),
|
||||||
|
[SIG] "o" (thissig),
|
||||||
|
[SI] "p" (&thissi),
|
||||||
|
[CTX] "o" (thiscontext),
|
||||||
|
[FUNC] "o" (thisfunc)
|
||||||
|
: "memory");
|
||||||
|
#else
|
||||||
|
__asm__ ("\n\
|
||||||
|
push %%ecx # Save ecx on orig stack \n\
|
||||||
|
push %%edx # Save edx on orig stack \n\
|
||||||
|
movl %[NEW_SP], %%ecx # Load alt stack into ecx \n\
|
||||||
|
subl $20, %%ecx # Make room on new stack \n\
|
||||||
|
movl %[SIG], %%edx # thissig to 1st arg slot \n\
|
||||||
|
movl %%edx, (%%ecx) \n\
|
||||||
|
movl %[SI], %%edx # &thissi to 2nd arg slot \n\
|
||||||
|
movl %%edx, 4(%%ecx) \n\
|
||||||
|
movl %[CTX], %%edx # thiscontext to 3rd arg slot\n\
|
||||||
|
movl %%edx, 8(%%ecx) \n\
|
||||||
|
movl %[FUNC], %%eax # thisfunc to eax \n\
|
||||||
|
movl %%ebp, 12(%%ecx) # Save ebp on alt stack \n\
|
||||||
|
movl %%esp, 16(%%ecx) # Save esp on alt stack \n\
|
||||||
|
movl %%ecx, %%esp # Move stackbase into esp \n\
|
||||||
|
xorl %%ebp, %%ebp # Set ebp to 0 \n\
|
||||||
|
call *%%eax # Call thisfunc \n\
|
||||||
|
movl %%esp, %%ecx # Move alt stack to ecx \n\
|
||||||
|
movl 12(%%ecx), %%ebp # Restore ebp \n\
|
||||||
|
movl 16(%%ecx), %%esp # Restore esp \n\
|
||||||
|
popl %%edx # Restore edx from orig stack\n\
|
||||||
|
popl %%ecx # Restore ecx from orig stack\n"
|
||||||
|
: : [NEW_SP] "o" (new_sp),
|
||||||
|
[SIG] "o" (thissig),
|
||||||
|
[SI] "p" (&thissi),
|
||||||
|
[CTX] "o" (thiscontext),
|
||||||
|
[FUNC] "o" (thisfunc)
|
||||||
|
: "memory");
|
||||||
|
#endif
|
||||||
|
/* Revert altstack info to normal. */
|
||||||
|
_my_tls.altstack.ss_flags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* No alternate signal stack requested or available, just call
|
||||||
|
signal handler. */
|
||||||
thisfunc (thissig, &thissi, thiscontext);
|
thisfunc (thissig, &thissi, thiscontext);
|
||||||
|
|
||||||
incyg = true;
|
incyg = true;
|
||||||
|
|
||||||
set_signal_mask (_my_tls.sigmask, this_oldmask);
|
set_signal_mask (_my_tls.sigmask, this_oldmask);
|
||||||
|
|
Loading…
Reference in New Issue