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,19 +1537,26 @@ _cygtls::call_signal_handler () | |||
| 	      RtlCaptureContext ((CONTEXT *) &context.uc_mcontext); | ||||
| 	    } | ||||
| 
 | ||||
| 	  /* FIXME: If/when sigaltstack is implemented, this will need to do
 | ||||
| 	     something more complicated */ | ||||
| 	  context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase; | ||||
| 	  context.uc_stack.ss_flags = 0; | ||||
| 	  if (!NtCurrentTeb ()->DeallocationStack) | ||||
| 	    context.uc_stack.ss_size | ||||
| 	      = (uintptr_t) NtCurrentTeb ()->Tib.StackLimit | ||||
| 		- (uintptr_t) NtCurrentTeb ()->Tib.StackBase; | ||||
| 	  if (this_sa_flags & SA_ONSTACK | ||||
| 	      && !_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_size | ||||
| 	      = (uintptr_t) NtCurrentTeb ()->DeallocationStack | ||||
| 		- (uintptr_t) NtCurrentTeb ()->Tib.StackBase; | ||||
| 
 | ||||
| 	    { | ||||
| 	      context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase; | ||||
| 	      context.uc_stack.ss_flags = 0; | ||||
| 	      if (!NtCurrentTeb ()->DeallocationStack) | ||||
| 		context.uc_stack.ss_size | ||||
| 		  = (uintptr_t) NtCurrentTeb ()->Tib.StackLimit | ||||
| 		    - (uintptr_t) NtCurrentTeb ()->Tib.StackBase; | ||||
| 	      else | ||||
| 		context.uc_stack.ss_size | ||||
| 		  = (uintptr_t) NtCurrentTeb ()->DeallocationStack | ||||
| 		    - (uintptr_t) NtCurrentTeb ()->Tib.StackBase; | ||||
| 	    } | ||||
| 	  context.uc_sigmask = context.uc_mcontext.oldmask = this_oldmask; | ||||
| 
 | ||||
| 	  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 */ | ||||
|       unlock ();	/* unlock signal stack */ | ||||
| 
 | ||||
|       thisfunc (thissig, &thissi, thiscontext); | ||||
|       /* 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); | ||||
| 
 | ||||
|       incyg = true; | ||||
| 
 | ||||
|       set_signal_mask (_my_tls.sigmask, this_oldmask); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue