This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Fix original stack when running signal handler on alternate stack


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2cd7eb7f60208b0ffd51a9e117a8846c33b4ad41

commit 2cd7eb7f60208b0ffd51a9e117a8846c33b4ad41
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Sat Jul 4 22:49:30 2015 +0200

    Fix original stack when running signal handler on alternate stack
    
            * autoload.cc (SetThreadStackGuarantee): Import.
            * cygtls.h (struct _cygtls): Replace thread_context with a ucontext_t
            called context.
            * exceptions.cc (exception::handle): Exit from process via signal_exit
            in case sig_send returns from handling a stack overflow SIGSEGV.
            Explain why.
            (dumpstack_overflow_wrapper): Thread wrapper to create a stackdump
            from another thread.
            (signal_exit): Fix argument list to reflect three-arg signal handler.
            In case we have to create a stackdump for a stack overflow condition,
            do so from a separate thread.  Explain why.
            (sigpacket::process): Don't run signal_exit on alternate stack.
            (altstack_wrapper): Wrapper function to do stack correction when
            calling the signal handler on an alternate stack to handle a stack
            overflow.  Make sure to have lots of comments.
            (_cygtls::call_signal_handler): Drop local context variable to reduce
            stack pressure.  Use this->context instead.  Change inline assembler
            to call altstack_wrapper.
            (_cygtls::signal_debugger): Accommodate aforementioned change to
            struct _cygtls.
            * tlsoffset.h: Regenerate.
            * tlsoffset64.h: Regenerate.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/ChangeLog      |  25 ++++++++
 winsup/cygwin/autoload.cc    |   1 +
 winsup/cygwin/cygtls.h       |   4 +-
 winsup/cygwin/exceptions.cc  | 142 ++++++++++++++++++++++++++++++++++++-------
 winsup/cygwin/tlsoffsets.h   | 116 ++++++++++++++++++-----------------
 winsup/cygwin/tlsoffsets64.h | 116 ++++++++++++++++++-----------------
 winsup/cygwin/wincap.cc      |  14 +++++
 winsup/cygwin/wincap.h       |   7 +++
 8 files changed, 291 insertions(+), 134 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eaa62a0..909996c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,28 @@
+2015-07-04  Corinna Vinschen  <corinna@vinschen.de>
+
+	* autoload.cc (SetThreadStackGuarantee): Import.
+	* cygtls.h (struct _cygtls): Replace thread_context with a ucontext_t
+	called context.
+	* exceptions.cc (exception::handle): Exit from process via signal_exit
+	in case sig_send returns from handling a stack overflow SIGSEGV.
+	Explain why.
+	(dumpstack_overflow_wrapper): Thread wrapper to create a stackdump
+	from another thread.
+	(signal_exit): Fix argument list to reflect three-arg signal handler.
+	In case we have to create a stackdump for a stack overflow condition,
+	do so from a separate thread.  Explain why.
+	(sigpacket::process): Don't run signal_exit on alternate stack.
+	(altstack_wrapper): Wrapper function to do stack correction when
+	calling the signal handler on an alternate stack to handle a stack
+	overflow.  Make sure to have lots of comments.
+	(_cygtls::call_signal_handler): Drop local context variable to reduce
+	stack pressure.  Use this->context instead.  Change inline assembler
+	to call altstack_wrapper.
+	(_cygtls::signal_debugger): Accommodate aforementioned change to
+	struct _cygtls.
+	* tlsoffset.h: Regenerate.
+	* tlsoffset64.h: Regenerate.
+
 2015-07-01  Corinna Vinschen  <corinna@vinschen.de>
 
 	* fork.cc (frok::parent): Set stacktop value based on requested stack
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 5832e27..6423a67 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -581,6 +581,7 @@ LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32)
 LoadDLLfuncEx (IdnToAscii, 20, kernel32, 1)
 LoadDLLfuncEx (IdnToUnicode, 20, kernel32, 1)
 LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
+LoadDLLfunc (SetThreadStackGuarantee, 4, kernel32)
 
 /* ldap functions are cdecl! */
 #pragma push_macro ("mangle")
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 0944811..3dfffbb 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -17,6 +17,7 @@ details. */
 #include <mntent.h>
 #undef _NOMNTENT_FUNCS
 #include <setjmp.h>
+#include <ucontext.h>
 
 #define CYGTLS_INITIALIZED 0xc763173f
 
@@ -192,7 +193,8 @@ public:
   siginfo_t *sigwait_info;
   HANDLE signal_arrived;
   bool will_wait_for_signal;
-  CONTEXT thread_context;
+  long __align;			/* Needed to align context to 16 byte. */
+  ucontext_t context;
   DWORD thread_id;
   siginfo_t infodata;
   struct pthread *tid;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 90a8ff2..0ce22d9 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -800,6 +800,19 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
 	       ? (void *) e->ExceptionInformation[1] : (void *) in->_GR(ip);
   me.incyg++;
   sig_send (NULL, si, &me);	/* Signal myself */
+  if ((NTSTATUS) e->ExceptionCode == STATUS_STACK_OVERFLOW)
+    {
+      /* If we catched a stack overflow, and if the signal handler didn't exit
+	 or longjmp, we're back here and about to continue, supposed to run the
+	 offending instruction again.  That works on Linux, but not on Windows.
+	 In case of a stack overflow we're not immediately returning to the
+	 system exception handler, but to NTDLL::__stkchk.  __stkchk will then
+	 terminate the applicaton.  So what we do here is to signal our current
+	 process again, but this time with SIG_DFL action.  This creates a
+	 stackdump and then exits through our own means. */
+      global_sigs[SIGSEGV].sa_handler = SIG_DFL;
+      sig_send (NULL, si, &me);
+    }
   me.incyg--;
   e->ExceptionFlags = 0;
   return ExceptionContinueExecution;
@@ -1237,10 +1250,20 @@ set_signal_mask (sigset_t& setmask, sigset_t newmask)
     sig_dispatch_pending (true);
 }
 
+
+DWORD WINAPI
+dumpstack_overflow_wrapper (PVOID arg)
+{
+  cygwin_exception *exc = (cygwin_exception *) arg;
+
+  exc->dumpstack ();
+  return 0;
+}
+
 /* Exit due to a signal.  Should only be called from the signal thread.  */
 extern "C" {
 static void
-signal_exit (int sig, siginfo_t *si)
+signal_exit (int sig, siginfo_t *si, void *)
 {
   debug_printf ("exiting due to signal %d", sig);
   exit_state = ES_SIGNAL_EXIT;
@@ -1262,7 +1285,27 @@ signal_exit (int sig, siginfo_t *si)
 	if (try_to_debug ())
 	  break;
 	if (si->si_code != SI_USER && si->si_cyg)
-	  ((cygwin_exception *) si->si_cyg)->dumpstack ();
+	  {
+	    cygwin_exception *exc = (cygwin_exception *) si->si_cyg;
+	    if ((NTSTATUS) exc->exception_record ()->ExceptionCode
+		== STATUS_STACK_OVERFLOW)
+	      {
+		/* We're handling a stack overflow so we're running low
+		   on stack (surprise!)  The dumpstack method needs lots
+		   of stack for buffers.  So what we do here is to run
+		   dumpstack in another thread with its own stack. */
+		HANDLE thread = CreateThread (&sec_none_nih, 0,
+					      dumpstack_overflow_wrapper,
+					      exc, 0, NULL);
+		if (thread)
+		  {
+		    WaitForSingleObject (thread, INFINITE);
+		    CloseHandle (thread);
+		  }
+	      }
+	    else
+	      ((cygwin_exception *) si->si_cyg)->dumpstack ();
+	  }
 	else
 	  {
 	    CONTEXT c;
@@ -1470,6 +1513,8 @@ stop:
 exit_sig:
   handler = (void *) signal_exit;
   thissig.sa_flags |= SA_SIGINFO;
+  /* Don't run signal_exit on alternate stack. */
+  thissig.sa_flags &= ~SA_ONSTACK;
 
 dosig:
   if (have_execed)
@@ -1488,6 +1533,58 @@ done:
 
 }
 
+static void
+altstack_wrapper (int sig, siginfo_t *siginfo, ucontext_t *sigctx,
+		  void (*handler) (int, siginfo_t *, void *))
+{
+  siginfo_t si = *siginfo;
+  ULONG guard_size = 0;
+  DWORD old_prot = (DWORD) -1;
+  PTEB teb = NtCurrentTeb ();
+  PVOID old_limit = NULL;
+
+  /* Check if we're just handling a stack overflow.  If so... */
+  if (sig == SIGSEGV && si.si_cyg
+      && ((cygwin_exception *) si.si_cyg)->exception_record ()->ExceptionCode
+	  == (DWORD) STATUS_STACK_OVERFLOW)
+    {
+      /* ...restore guard pages in original stack as if MSVCRT::_resetstkovlw
+	 has been called.
+
+	 Compute size of guard pages.  If SetThreadStackGuarantee isn't
+	 supported, or if it returns 0, use the default guard page size. */
+      if (wincap.has_set_thread_stack_guarantee ())
+	SetThreadStackGuarantee (&guard_size);
+      if (!guard_size)
+	guard_size = wincap.def_guard_page_size ();
+      else
+	guard_size += wincap.page_size ();
+      old_limit = teb->Tib.StackLimit;
+      /* Amazing but true: This VirtualProtect call automatically fixes the
+	 value of teb->Tib.StackLimit on some systems.*/
+      if (VirtualProtect (teb->Tib.StackLimit, guard_size,
+			  PAGE_READWRITE | PAGE_GUARD, &old_prot)
+	  && old_limit == teb->Tib.StackLimit)
+	teb->Tib.StackLimit = (caddr_t) old_limit + guard_size;
+    }
+  handler (sig, &si, sigctx);
+  if (old_prot != (DWORD) -1)
+    {
+      /* Typically the handler would exit or at least perform a siglongjmp
+	 trying to overcome a SEGV condition.  However, if we return from a
+	 segv handler after a stack overflow, we're dead.  While on Linux the
+	 process returns to the offending code and thus the handler is called
+	 ad infinitum, on Windows the NTDLL::__stkchk function will simply kill
+	 the process.  So what we do here is to remove the guard pages again so
+	 we can return to exception::handle.  exception::handle will then call
+	 sig_send again, this time with SIG_DFL action, so at least we get a
+	 stackdump. */
+      if (VirtualProtect ((caddr_t) teb->Tib.StackLimit - guard_size,
+			  guard_size, old_prot, &old_prot))
+	teb->Tib.StackLimit = old_limit;
+    }
+}
+
 int
 _cygtls::call_signal_handler ()
 {
@@ -1516,7 +1613,6 @@ _cygtls::call_signal_handler ()
       siginfo_t thissi = infodata;
       void (*thisfunc) (int, siginfo_t *, void *) = func;
 
-      ucontext_t context;
       ucontext_t *thiscontext = NULL;
 
       /* Only make a context for SA_SIGINFO handlers */
@@ -1596,9 +1692,8 @@ _cygtls::call_signal_handler ()
 
 	  /* Compute new stackbase.  We start from the high address, aligned
 	     to 16 byte. */
-	  uintptr_t new_sp = (uintptr_t) _my_tls.altstack.ss_sp
-			     + _my_tls.altstack.ss_size;
-	  new_sp &= ~0xf;
+	  uintptr_t new_sp = ((uintptr_t) _my_tls.altstack.ss_sp
+			      + _my_tls.altstack.ss_size) & ~0xf;
 	  /* In assembler: Save regs on new stack, move to alternate stack,
 	     call thisfunc, revert stack regs. */
 #ifdef __x86_64__
@@ -1620,8 +1715,9 @@ _cygtls::call_signal_handler ()
 		   leaq  %[SI], %%rdx      # &thissi to 2nd arg reg	\n\
 		   movq  %[CTX], %%r8      # thiscontext to 3rd arg reg	\n\
 		   movq  %[FUNC], %%r9     # thisfunc to r9		\n\
+		   leaq  %[WRAPPER], %%r10 # wrapper address to r10	\n\
 		   movq  %%rax, %%rsp      # Move alt stack into rsp	\n\
-		   call  *%%r9             # Call thisfunc		\n\
+		   call  *%%r10            # Call wrapper		\n\
 		   movq  %%rsp, %%rax      # Restore clobbered regs	\n\
 		   movq  0x58(%%rax), %%rsp				\n\
 		   movq  0x50(%%rax), %%rbp				\n\
@@ -1635,38 +1731,42 @@ _cygtls::call_signal_handler ()
 		       [SIG]	"o" (thissig),
 		       [SI]	"o" (thissi),
 		       [CTX]	"o" (thiscontext),
-		       [FUNC]	"o" (thisfunc)
+		       [FUNC]	"o" (thisfunc),
+		       [WRAPPER] "o" (altstack_wrapper)
 		   : "memory");
 #else
 	  /* Clobbered regs: ecx, edx, ebp, esp */
 	  __asm__ ("\n\
 		   movl  %[NEW_SP], %%eax  # Load alt stack into eax	\n\
-		   subl  $28, %%eax        # Make room on alt stack for	\n\
+		   subl  $32, %%eax        # Make room on alt stack for	\n\
 					   # clobbered regs and args to \n\
 					   # signal handler             \n\
-		   movl  %%ecx, 12(%%eax)  # Save other clobbered regs	\n\
-		   movl  %%edx, 16(%%eax)				\n\
-		   movl  %%ebp, 20(%%eax)				\n\
-		   movl  %%esp, 24(%%eax)				\n\
+		   movl  %%ecx, 16(%%eax)  # Save clobbered regs	\n\
+		   movl  %%edx, 20(%%eax)				\n\
+		   movl  %%ebp, 24(%%eax)				\n\
+		   movl  %%esp, 28(%%eax)				\n\
 		   movl  %[SIG], %%ecx     # thissig to 1st arg slot	\n\
 		   movl  %%ecx, (%%eax)					\n\
 		   leal  %[SI], %%ecx      # &thissi to 2nd arg slot	\n\
 		   movl  %%ecx, 4(%%eax)				\n\
 		   movl  %[CTX], %%ecx     # thiscontext to 3rd arg slot\n\
 		   movl  %%ecx, 8(%%eax)				\n\
-		   movl  %[FUNC], %%ecx    # thisfunc to ecx		\n\
+		   movl  %[FUNC], %%ecx    # thisfunc to 4th arg slot	\n\
+		   movl  %%ecx, 12(%%eax)				\n\
+		   leal  %[WRAPPER], %%ecx # thisfunc to ecx		\n\
 		   movl  %%eax, %%esp      # Move alt stack into esp	\n\
 		   call  *%%ecx            # Call thisfunc		\n\
 		   movl	 %%esp, %%eax      # Restore clobbered regs	\n\
-		   movl  24(%%eax), %%esp				\n\
-		   movl	 20(%%eax), %%ebp				\n\
-		   movl	 16(%%eax), %%edx				\n\
-		   movl	 12(%%eax), %%eax				\n"
+		   movl  28(%%eax), %%esp				\n\
+		   movl	 24(%%eax), %%ebp				\n\
+		   movl	 20(%%eax), %%edx				\n\
+		   movl	 16(%%eax), %%eax				\n"
 		   : : [NEW_SP]	"o" (new_sp),
 		       [SIG]	"o" (thissig),
 		       [SI]	"o" (thissi),
 		       [CTX]	"o" (thiscontext),
-		       [FUNC]	"o" (thisfunc)
+		       [FUNC]	"o" (thisfunc),
+		       [WRAPPER] "o" (altstack_wrapper)
 		   : "memory");
 #endif
 	}
@@ -1708,12 +1808,12 @@ _cygtls::signal_debugger (siginfo_t& si)
 #else
 	    c.Eip = retaddr ();
 #endif
-	  memcpy (&thread_context, &c, sizeof (CONTEXT));
+	  memcpy (&context.uc_mcontext, &c, sizeof (CONTEXT));
 	  /* Enough space for 32/64 bit addresses */
 	  char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING
 				  " ffffffff ffffffffffffffff")];
 	  __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %y %p",
-			   si.si_signo, thread_id, &thread_context);
+			   si.si_signo, thread_id, &context.uc_mcontext);
 	  OutputDebugString (sigmsg);
 	}
       ResumeThread (th);
diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h
index daf610f..13d1003 100644
--- a/winsup/cygwin/tlsoffsets.h
+++ b/winsup/cygwin/tlsoffsets.h
@@ -31,34 +31,36 @@
 //; $tls::psignal_arrived = 2856;
 //; $tls::will_wait_for_signal = -9840;
 //; $tls::pwill_wait_for_signal = 2860;
-//; $tls::thread_context = -9836;
-//; $tls::pthread_context = 2864;
-//; $tls::thread_id = -9120;
-//; $tls::pthread_id = 3580;
-//; $tls::infodata = -9116;
-//; $tls::pinfodata = 3584;
-//; $tls::tid = -8968;
-//; $tls::ptid = 3732;
-//; $tls::_ctinfo = -8964;
-//; $tls::p_ctinfo = 3736;
-//; $tls::andreas = -8960;
-//; $tls::pandreas = 3740;
-//; $tls::wq = -8956;
-//; $tls::pwq = 3744;
-//; $tls::sig = -8928;
-//; $tls::psig = 3772;
-//; $tls::incyg = -8924;
-//; $tls::pincyg = 3776;
-//; $tls::spinning = -8920;
-//; $tls::pspinning = 3780;
-//; $tls::stacklock = -8916;
-//; $tls::pstacklock = 3784;
-//; $tls::stackptr = -8912;
-//; $tls::pstackptr = 3788;
-//; $tls::stack = -8908;
-//; $tls::pstack = 3792;
-//; $tls::initialized = -7884;
-//; $tls::pinitialized = 4816;
+//; $tls::__align = -9836;
+//; $tls::p__align = 2864;
+//; $tls::context = -9832;
+//; $tls::pcontext = 2868;
+//; $tls::thread_id = -9084;
+//; $tls::pthread_id = 3616;
+//; $tls::infodata = -9080;
+//; $tls::pinfodata = 3620;
+//; $tls::tid = -8932;
+//; $tls::ptid = 3768;
+//; $tls::_ctinfo = -8928;
+//; $tls::p_ctinfo = 3772;
+//; $tls::andreas = -8924;
+//; $tls::pandreas = 3776;
+//; $tls::wq = -8920;
+//; $tls::pwq = 3780;
+//; $tls::sig = -8892;
+//; $tls::psig = 3808;
+//; $tls::incyg = -8888;
+//; $tls::pincyg = 3812;
+//; $tls::spinning = -8884;
+//; $tls::pspinning = 3816;
+//; $tls::stacklock = -8880;
+//; $tls::pstacklock = 3820;
+//; $tls::stackptr = -8876;
+//; $tls::pstackptr = 3824;
+//; $tls::stack = -8872;
+//; $tls::pstack = 3828;
+//; $tls::initialized = -7848;
+//; $tls::pinitialized = 4852;
 //; __DATA__
 
 #define tls_locals (-12700)
@@ -91,31 +93,33 @@
 #define tls_psignal_arrived (2856)
 #define tls_will_wait_for_signal (-9840)
 #define tls_pwill_wait_for_signal (2860)
-#define tls_thread_context (-9836)
-#define tls_pthread_context (2864)
-#define tls_thread_id (-9120)
-#define tls_pthread_id (3580)
-#define tls_infodata (-9116)
-#define tls_pinfodata (3584)
-#define tls_tid (-8968)
-#define tls_ptid (3732)
-#define tls__ctinfo (-8964)
-#define tls_p_ctinfo (3736)
-#define tls_andreas (-8960)
-#define tls_pandreas (3740)
-#define tls_wq (-8956)
-#define tls_pwq (3744)
-#define tls_sig (-8928)
-#define tls_psig (3772)
-#define tls_incyg (-8924)
-#define tls_pincyg (3776)
-#define tls_spinning (-8920)
-#define tls_pspinning (3780)
-#define tls_stacklock (-8916)
-#define tls_pstacklock (3784)
-#define tls_stackptr (-8912)
-#define tls_pstackptr (3788)
-#define tls_stack (-8908)
-#define tls_pstack (3792)
-#define tls_initialized (-7884)
-#define tls_pinitialized (4816)
+#define tls___align (-9836)
+#define tls_p__align (2864)
+#define tls_context (-9832)
+#define tls_pcontext (2868)
+#define tls_thread_id (-9084)
+#define tls_pthread_id (3616)
+#define tls_infodata (-9080)
+#define tls_pinfodata (3620)
+#define tls_tid (-8932)
+#define tls_ptid (3768)
+#define tls__ctinfo (-8928)
+#define tls_p_ctinfo (3772)
+#define tls_andreas (-8924)
+#define tls_pandreas (3776)
+#define tls_wq (-8920)
+#define tls_pwq (3780)
+#define tls_sig (-8892)
+#define tls_psig (3808)
+#define tls_incyg (-8888)
+#define tls_pincyg (3812)
+#define tls_spinning (-8884)
+#define tls_pspinning (3816)
+#define tls_stacklock (-8880)
+#define tls_pstacklock (3820)
+#define tls_stackptr (-8876)
+#define tls_pstackptr (3824)
+#define tls_stack (-8872)
+#define tls_pstack (3828)
+#define tls_initialized (-7848)
+#define tls_pinitialized (4852)
diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h
index 3f171b0..d137408 100644
--- a/winsup/cygwin/tlsoffsets64.h
+++ b/winsup/cygwin/tlsoffsets64.h
@@ -31,34 +31,36 @@
 //; $tls::psignal_arrived = 4152;
 //; $tls::will_wait_for_signal = -8640;
 //; $tls::pwill_wait_for_signal = 4160;
-//; $tls::thread_context = -8632;
-//; $tls::pthread_context = 4168;
-//; $tls::thread_id = -7400;
-//; $tls::pthread_id = 5400;
-//; $tls::infodata = -7396;
-//; $tls::pinfodata = 5404;
-//; $tls::tid = -7248;
-//; $tls::ptid = 5552;
-//; $tls::_ctinfo = -7240;
-//; $tls::p_ctinfo = 5560;
-//; $tls::andreas = -7232;
-//; $tls::pandreas = 5568;
-//; $tls::wq = -7224;
-//; $tls::pwq = 5576;
-//; $tls::sig = -7176;
-//; $tls::psig = 5624;
-//; $tls::incyg = -7172;
-//; $tls::pincyg = 5628;
-//; $tls::spinning = -7168;
-//; $tls::pspinning = 5632;
-//; $tls::stacklock = -7164;
-//; $tls::pstacklock = 5636;
-//; $tls::stackptr = -7160;
-//; $tls::pstackptr = 5640;
-//; $tls::stack = -7152;
-//; $tls::pstack = 5648;
-//; $tls::initialized = -5104;
-//; $tls::pinitialized = 7696;
+//; $tls::__align = -8632;
+//; $tls::p__align = 4168;
+//; $tls::context = -8624;
+//; $tls::pcontext = 4176;
+//; $tls::thread_id = -7328;
+//; $tls::pthread_id = 5472;
+//; $tls::infodata = -7324;
+//; $tls::pinfodata = 5476;
+//; $tls::tid = -7176;
+//; $tls::ptid = 5624;
+//; $tls::_ctinfo = -7168;
+//; $tls::p_ctinfo = 5632;
+//; $tls::andreas = -7160;
+//; $tls::pandreas = 5640;
+//; $tls::wq = -7152;
+//; $tls::pwq = 5648;
+//; $tls::sig = -7104;
+//; $tls::psig = 5696;
+//; $tls::incyg = -7100;
+//; $tls::pincyg = 5700;
+//; $tls::spinning = -7096;
+//; $tls::pspinning = 5704;
+//; $tls::stacklock = -7092;
+//; $tls::pstacklock = 5708;
+//; $tls::stackptr = -7088;
+//; $tls::pstackptr = 5712;
+//; $tls::stack = -7080;
+//; $tls::pstack = 5720;
+//; $tls::initialized = -5032;
+//; $tls::pinitialized = 7768;
 //; __DATA__
 
 #define tls_locals (-12800)
@@ -91,31 +93,33 @@
 #define tls_psignal_arrived (4152)
 #define tls_will_wait_for_signal (-8640)
 #define tls_pwill_wait_for_signal (4160)
-#define tls_thread_context (-8632)
-#define tls_pthread_context (4168)
-#define tls_thread_id (-7400)
-#define tls_pthread_id (5400)
-#define tls_infodata (-7396)
-#define tls_pinfodata (5404)
-#define tls_tid (-7248)
-#define tls_ptid (5552)
-#define tls__ctinfo (-7240)
-#define tls_p_ctinfo (5560)
-#define tls_andreas (-7232)
-#define tls_pandreas (5568)
-#define tls_wq (-7224)
-#define tls_pwq (5576)
-#define tls_sig (-7176)
-#define tls_psig (5624)
-#define tls_incyg (-7172)
-#define tls_pincyg (5628)
-#define tls_spinning (-7168)
-#define tls_pspinning (5632)
-#define tls_stacklock (-7164)
-#define tls_pstacklock (5636)
-#define tls_stackptr (-7160)
-#define tls_pstackptr (5640)
-#define tls_stack (-7152)
-#define tls_pstack (5648)
-#define tls_initialized (-5104)
-#define tls_pinitialized (7696)
+#define tls___align (-8632)
+#define tls_p__align (4168)
+#define tls_context (-8624)
+#define tls_pcontext (4176)
+#define tls_thread_id (-7328)
+#define tls_pthread_id (5472)
+#define tls_infodata (-7324)
+#define tls_pinfodata (5476)
+#define tls_tid (-7176)
+#define tls_ptid (5624)
+#define tls__ctinfo (-7168)
+#define tls_p_ctinfo (5632)
+#define tls_andreas (-7160)
+#define tls_pandreas (5640)
+#define tls_wq (-7152)
+#define tls_pwq (5648)
+#define tls_sig (-7104)
+#define tls_psig (5696)
+#define tls_incyg (-7100)
+#define tls_pincyg (5700)
+#define tls_spinning (-7096)
+#define tls_pspinning (5704)
+#define tls_stacklock (-7092)
+#define tls_pstacklock (5708)
+#define tls_stackptr (-7088)
+#define tls_pstackptr (5712)
+#define tls_stack (-7080)
+#define tls_pstack (5720)
+#define tls_initialized (-5032)
+#define tls_pinitialized (7768)
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 279754a..2c5880e 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -21,6 +21,7 @@ details. */
    puzzled that this has never been noticed before... */
 
 wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:1,
   max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:false,
@@ -46,9 +47,11 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:false,
   has_precise_system_time:false,
   has_microsoft_accounts:false,
+  has_set_thread_stack_guarantee:false,
 };
 
 wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:1,
   max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:false,
@@ -74,9 +77,11 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:false,
   has_precise_system_time:false,
   has_microsoft_accounts:false,
+  has_set_thread_stack_guarantee:true,
 };
 
 wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:1,
   max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:true,
@@ -102,9 +107,11 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:true,
   has_precise_system_time:false,
   has_microsoft_accounts:false,
+  has_set_thread_stack_guarantee:true,
 };
 
 wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:1,
   max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:true,
@@ -130,9 +137,11 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:true,
   has_precise_system_time:false,
   has_microsoft_accounts:false,
+  has_set_thread_stack_guarantee:true,
 };
 
 wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:2,
   max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:true,
@@ -158,9 +167,11 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:true,
   has_precise_system_time:true,
   has_microsoft_accounts:true,
+  has_set_thread_stack_guarantee:true,
 };
 
 wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
+  def_guard_pages:2,
   max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE,
   is_server:false,
   has_mandatory_integrity_control:true,
@@ -186,6 +197,7 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
   terminate_thread_frees_stack:true,
   has_precise_system_time:true,
   has_microsoft_accounts:true,
+  has_set_thread_stack_guarantee:true,
 };
 
 wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
@@ -240,6 +252,8 @@ wincapc::init ()
   ((wincaps *)caps)->is_server = (version.wProductType != VER_NT_WORKSTATION);
 #ifdef __x86_64__
   wow64 = 0;
+  /* 64 bit systems have one more guard page than their 32 bit counterpart. */
+  ++((wincaps *)caps)->def_guard_pages;
 #else
   if (NT_SUCCESS (NtQueryInformationProcess (NtCurrentProcess (),
 					     ProcessWow64Information,
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index b41a2c6..160085d 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -14,6 +14,7 @@ details. */
 
 struct wincaps
 {
+  DWORD    def_guard_pages;
   DWORD    max_sys_priv;
   unsigned is_server                                    : 1;
   unsigned has_mandatory_integrity_control		: 1;
@@ -39,6 +40,7 @@ struct wincaps
   unsigned terminate_thread_frees_stack			: 1;
   unsigned has_precise_system_time			: 1;
   unsigned has_microsoft_accounts			: 1;
+  unsigned has_set_thread_stack_guarantee		: 1;
 };
 
 class wincapc
@@ -64,6 +66,10 @@ public:
 
 #define IMPLEMENT(cap) cap() const { return ((wincaps *) this->caps)->cap; }
 
+  DWORD def_guard_page_size () const
+  {
+    return ((wincaps *) this->caps)->def_guard_pages * page_size ();
+  }
   DWORD IMPLEMENT (max_sys_priv)
   bool  IMPLEMENT (is_server)
   bool	IMPLEMENT (has_mandatory_integrity_control)
@@ -89,6 +95,7 @@ public:
   bool	IMPLEMENT (terminate_thread_frees_stack)
   bool	IMPLEMENT (has_precise_system_time)
   bool	IMPLEMENT (has_microsoft_accounts)
+  bool	IMPLEMENT (has_set_thread_stack_guarantee)
 
 #undef IMPLEMENT
 };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]