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>
This commit is contained in:
Corinna Vinschen 2015-07-04 22:49:30 +02:00
parent 757c0871f7
commit 2cd7eb7f60
8 changed files with 291 additions and 134 deletions

View File

@ -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

View File

@ -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")

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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
};