diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2015-06-19 15:58:23 +0200 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2015-06-19 16:12:45 +0200 |
commit | 22465796edbfd6f156ca2930f56b3345cc54b164 (patch) | |
tree | a463488dc43aa43c698bf806602ba54975890889 | |
parent | 715ac1e872e495496f9a540a75e8b1f4cbcdf321 (diff) | |
download | cygnal-22465796edbfd6f156ca2930f56b3345cc54b164.tar.gz cygnal-22465796edbfd6f156ca2930f56b3345cc54b164.tar.bz2 cygnal-22465796edbfd6f156ca2930f56b3345cc54b164.zip |
Preliminary infrastructure to implement alternate stack
* libc/include/sys/signal.h: Define SS_ONSTACK and SS_DISABLE
unconditionally.
(sigaltstack): Enable prototype on Cygwin.
* common.din (sigaltstack): Export.
* cygtls.cc (_cygtls::init_thread): Initialize altstack.
* cygtls.h (__tlsstack_t): Rename from __stack_t to distinguish
more clearly from stack_t. Accommodate throughout.
(_cygtls): Add altstack member.
* exceptions.cc (exception::handle): Set SIGSEGV handler to SIG_DFL
if we encounter a stack overflow, and no alternate stack has been
defined.
* include/cygwin/signal.h (MINSIGSTKSZ): Define
(SIGSTKSZ): Define.
(SA_ONSTACK): Define.
* signal.cc (sigaltstack): New function.
* tlsoffset.h: Regenerate.
* tlsoffset64.h: Ditto.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r-- | newlib/libc/include/sys/signal.h | 13 | ||||
-rw-r--r-- | winsup/cygwin/common.din | 1 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.h | 13 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 14 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/signal.h | 6 | ||||
-rw-r--r-- | winsup/cygwin/signal.cc | 40 | ||||
-rw-r--r-- | winsup/cygwin/tlsoffsets.h | 140 | ||||
-rw-r--r-- | winsup/cygwin/tlsoffsets64.h | 140 |
9 files changed, 215 insertions, 153 deletions
diff --git a/newlib/libc/include/sys/signal.h b/newlib/libc/include/sys/signal.h index 6ff758ce7..f2087fe62 100644 --- a/newlib/libc/include/sys/signal.h +++ b/newlib/libc/include/sys/signal.h @@ -120,11 +120,6 @@ struct sigaction { #define SIGSTKSZ 8192 #endif -/* - * Possible values for ss_flags in stack_t below. - */ -#define SS_ONSTACK 0x1 -#define SS_DISABLE 0x2 #endif #elif defined(__CYGWIN__) @@ -143,6 +138,12 @@ struct sigaction #endif /* defined(__rtems__) */ /* + * Possible values for ss_flags in stack_t below. + */ +#define SS_ONSTACK 0x1 +#define SS_DISABLE 0x2 + +/* * Structure used in sigaltstack call. */ typedef struct sigaltstack { @@ -196,7 +197,7 @@ int _EXFUN(sigpending, (sigset_t *)); int _EXFUN(sigsuspend, (const sigset_t *)); int _EXFUN(sigpause, (int)); -#ifdef __rtems__ +#if defined(__CYGWIN__) || defined(__rtems__) #if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 int _EXFUN(sigaltstack, (const stack_t *__restrict, stack_t *__restrict)); #endif diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index dd9bb2576..644eb2eae 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -1099,6 +1099,7 @@ shmget SIGFE shutdown = cygwin_shutdown SIGFE sigaction SIGFE sigaddset SIGFE +sigaltstack SIGFE sigdelset SIGFE sigemptyset NOSIGFE sigfillset NOSIGFE diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 84170ca01..dc9a698f7 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -125,6 +125,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *)) memset (this, 0, sizeof (*this)); _REENT_INIT_PTR (&local_clib); stackptr = stack; + altstack.ss_flags = SS_DISABLE; if (_GLOBAL_REENT) { local_clib._stdin = _GLOBAL_REENT->_stdin; diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 97e403dea..0944811b0 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -167,7 +167,7 @@ extern "C" int __ljfault (jmp_buf, int); /*gentls_offsets*/ -typedef uintptr_t __stack_t; +typedef uintptr_t __tlsstack_t; class _cygtls { @@ -188,6 +188,7 @@ public: int *errno_addr; sigset_t sigmask; sigset_t sigwait_mask; + stack_t altstack; siginfo_t *sigwait_info; HANDLE signal_arrived; bool will_wait_for_signal; @@ -202,17 +203,17 @@ public: unsigned incyg; unsigned spinning; unsigned stacklock; - __stack_t *stackptr; - __stack_t stack[TLS_STACK_SIZE]; + __tlsstack_t *stackptr; + __tlsstack_t stack[TLS_STACK_SIZE]; unsigned initialized; /*gentls_offsets*/ void init_thread (void *, DWORD (*) (void *, void *)); static void call (DWORD (*) (void *, void *), void *); void remove (DWORD); - void push (__stack_t addr) {*stackptr++ = (__stack_t) addr;} - __stack_t __reg1 pop (); - __stack_t retaddr () {return stackptr[-1];} + void push (__tlsstack_t addr) {*stackptr++ = (__tlsstack_t) addr;} + __tlsstack_t __reg1 pop (); + __tlsstack_t retaddr () {return stackptr[-1];} bool isinitialized () const { return initialized == CYGTLS_INITIALIZED; diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 27b571ee1..112d79206 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -232,7 +232,7 @@ class stack_info #ifdef __x86_64__ CONTEXT c; UNWIND_HISTORY_TABLE hist; - __stack_t *sigstackptr; + __tlsstack_t *sigstackptr; #endif public: STACKFRAME sf; /* For storing the stack information */ @@ -696,11 +696,17 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, } break; + case STATUS_STACK_OVERFLOW: + /* 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; + /*FALLTHRU*/ case STATUS_ARRAY_BOUNDS_EXCEEDED: case STATUS_IN_PAGE_ERROR: case STATUS_NO_MEMORY: case STATUS_INVALID_DISPOSITION: - case STATUS_STACK_OVERFLOW: si.si_signo = SIGSEGV; si.si_code = SEGV_MAPERR; break; @@ -894,7 +900,7 @@ _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler, void __reg3 _cygtls::interrupt_setup (siginfo_t& si, void *handler, struct sigaction& siga) { - push ((__stack_t) sigdelayed); + push ((__tlsstack_t) sigdelayed); deltamask = siga.sa_mask & ~SIG_NONMASKABLE; sa_flags = siga.sa_flags; func = (void (*) (int, siginfo_t *, void *)) handler; @@ -1497,7 +1503,7 @@ _cygtls::call_signal_handler () /* Pop the stack if the next "return address" is sigdelayed, since this function is doing what sigdelayed would have done anyway. */ - if (retaddr () == (__stack_t) sigdelayed) + if (retaddr () == (__tlsstack_t) sigdelayed) pop (); debug_only_printf ("dealing with signal %d", sig); diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h index ef29baf7b..2db0a8069 100644 --- a/winsup/cygwin/include/cygwin/signal.h +++ b/winsup/cygwin/include/cygwin/signal.h @@ -332,12 +332,18 @@ struct sigaction int sa_flags; }; +#define MINSIGSTKSZ 32768 +#define SIGSTKSZ 65536 + #define SA_NOCLDSTOP 1 /* Do not generate SIGCHLD when children stop */ #define SA_SIGINFO 2 /* Invoke the signal catching function with three arguments instead of one */ #define SA_RESTART 0x10000000 /* Restart syscall on signal return */ +#define SA_ONSTACK 0x20000000 /* Call signal handler on alternate + signal stack provided by + sigaltstack(2). */ #define SA_NODEFER 0x40000000 /* Don't automatically block the signal when its handler is being executed */ #define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler */ diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index d2ca81e00..7cb668cda 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -587,7 +587,7 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info) *info = _my_tls.infodata; res = _my_tls.infodata.si_signo; _my_tls.sig = 0; - if (_my_tls.retaddr () == (__stack_t) sigdelayed) + if (_my_tls.retaddr () == (__tlsstack_t) sigdelayed) _my_tls.pop (); _my_tls.unlock (); } @@ -624,3 +624,41 @@ sigqueue (pid_t pid, int sig, const union sigval value) si.si_value = value; return sig_send (dest, si); } + +extern "C" int +sigaltstack (const stack_t *ss, stack_t *oss) +{ + _cygtls& me = _my_tls; + + if (ss) + { + if (me.altstack.ss_flags == SS_ONSTACK) + { + set_errno (EPERM); + return -1; + } + if (ss->ss_flags == SS_DISABLE) + { + me.altstack.ss_sp = NULL; + me.altstack.ss_flags = 0; + me.altstack.ss_size = 0; + } + else + { + if (ss->ss_flags) + { + set_errno (EINVAL); + return -1; + } + if (ss->ss_size < MINSIGSTKSZ) + { + set_errno (ENOMEM); + return -1; + } + memcpy (&me.altstack, ss, sizeof *ss); + } + } + if (oss) + memcpy (oss, &me.altstack, sizeof *oss); + return 0; +} diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index a74e22f69..daf610f19 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -23,40 +23,42 @@ //; $tls::psigmask = 2832; //; $tls::sigwait_mask = -9864; //; $tls::psigwait_mask = 2836; -//; $tls::sigwait_info = -9860; -//; $tls::psigwait_info = 2840; -//; $tls::signal_arrived = -9856; -//; $tls::psignal_arrived = 2844; -//; $tls::will_wait_for_signal = -9852; -//; $tls::pwill_wait_for_signal = 2848; -//; $tls::thread_context = -9848; -//; $tls::pthread_context = 2852; -//; $tls::thread_id = -9132; -//; $tls::pthread_id = 3568; -//; $tls::infodata = -9128; -//; $tls::pinfodata = 3572; -//; $tls::tid = -8980; -//; $tls::ptid = 3720; -//; $tls::_ctinfo = -8976; -//; $tls::p_ctinfo = 3724; -//; $tls::andreas = -8972; -//; $tls::pandreas = 3728; -//; $tls::wq = -8968; -//; $tls::pwq = 3732; -//; $tls::sig = -8940; -//; $tls::psig = 3760; -//; $tls::incyg = -8936; -//; $tls::pincyg = 3764; -//; $tls::spinning = -8932; -//; $tls::pspinning = 3768; -//; $tls::stacklock = -8928; -//; $tls::pstacklock = 3772; -//; $tls::stackptr = -8924; -//; $tls::pstackptr = 3776; -//; $tls::stack = -8920; -//; $tls::pstack = 3780; -//; $tls::initialized = -7896; -//; $tls::pinitialized = 4804; +//; $tls::altstack = -9860; +//; $tls::paltstack = 2840; +//; $tls::sigwait_info = -9848; +//; $tls::psigwait_info = 2852; +//; $tls::signal_arrived = -9844; +//; $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; //; __DATA__ #define tls_locals (-12700) @@ -81,37 +83,39 @@ #define tls_psigmask (2832) #define tls_sigwait_mask (-9864) #define tls_psigwait_mask (2836) -#define tls_sigwait_info (-9860) -#define tls_psigwait_info (2840) -#define tls_signal_arrived (-9856) -#define tls_psignal_arrived (2844) -#define tls_will_wait_for_signal (-9852) -#define tls_pwill_wait_for_signal (2848) -#define tls_thread_context (-9848) -#define tls_pthread_context (2852) -#define tls_thread_id (-9132) -#define tls_pthread_id (3568) -#define tls_infodata (-9128) -#define tls_pinfodata (3572) -#define tls_tid (-8980) -#define tls_ptid (3720) -#define tls__ctinfo (-8976) -#define tls_p_ctinfo (3724) -#define tls_andreas (-8972) -#define tls_pandreas (3728) -#define tls_wq (-8968) -#define tls_pwq (3732) -#define tls_sig (-8940) -#define tls_psig (3760) -#define tls_incyg (-8936) -#define tls_pincyg (3764) -#define tls_spinning (-8932) -#define tls_pspinning (3768) -#define tls_stacklock (-8928) -#define tls_pstacklock (3772) -#define tls_stackptr (-8924) -#define tls_pstackptr (3776) -#define tls_stack (-8920) -#define tls_pstack (3780) -#define tls_initialized (-7896) -#define tls_pinitialized (4804) +#define tls_altstack (-9860) +#define tls_paltstack (2840) +#define tls_sigwait_info (-9848) +#define tls_psigwait_info (2852) +#define tls_signal_arrived (-9844) +#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) diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h index e43dea7e2..3f171b0ff 100644 --- a/winsup/cygwin/tlsoffsets64.h +++ b/winsup/cygwin/tlsoffsets64.h @@ -23,40 +23,42 @@ //; $tls::psigmask = 4104; //; $tls::sigwait_mask = -8688; //; $tls::psigwait_mask = 4112; -//; $tls::sigwait_info = -8680; -//; $tls::psigwait_info = 4120; -//; $tls::signal_arrived = -8672; -//; $tls::psignal_arrived = 4128; -//; $tls::will_wait_for_signal = -8664; -//; $tls::pwill_wait_for_signal = 4136; -//; $tls::thread_context = -8656; -//; $tls::pthread_context = 4144; -//; $tls::thread_id = -7424; -//; $tls::pthread_id = 5376; -//; $tls::infodata = -7420; -//; $tls::pinfodata = 5380; -//; $tls::tid = -7272; -//; $tls::ptid = 5528; -//; $tls::_ctinfo = -7264; -//; $tls::p_ctinfo = 5536; -//; $tls::andreas = -7256; -//; $tls::pandreas = 5544; -//; $tls::wq = -7248; -//; $tls::pwq = 5552; -//; $tls::sig = -7200; -//; $tls::psig = 5600; -//; $tls::incyg = -7196; -//; $tls::pincyg = 5604; -//; $tls::spinning = -7192; -//; $tls::pspinning = 5608; -//; $tls::stacklock = -7188; -//; $tls::pstacklock = 5612; -//; $tls::stackptr = -7184; -//; $tls::pstackptr = 5616; -//; $tls::stack = -7176; -//; $tls::pstack = 5624; -//; $tls::initialized = -5128; -//; $tls::pinitialized = 7672; +//; $tls::altstack = -8680; +//; $tls::paltstack = 4120; +//; $tls::sigwait_info = -8656; +//; $tls::psigwait_info = 4144; +//; $tls::signal_arrived = -8648; +//; $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; //; __DATA__ #define tls_locals (-12800) @@ -81,37 +83,39 @@ #define tls_psigmask (4104) #define tls_sigwait_mask (-8688) #define tls_psigwait_mask (4112) -#define tls_sigwait_info (-8680) -#define tls_psigwait_info (4120) -#define tls_signal_arrived (-8672) -#define tls_psignal_arrived (4128) -#define tls_will_wait_for_signal (-8664) -#define tls_pwill_wait_for_signal (4136) -#define tls_thread_context (-8656) -#define tls_pthread_context (4144) -#define tls_thread_id (-7424) -#define tls_pthread_id (5376) -#define tls_infodata (-7420) -#define tls_pinfodata (5380) -#define tls_tid (-7272) -#define tls_ptid (5528) -#define tls__ctinfo (-7264) -#define tls_p_ctinfo (5536) -#define tls_andreas (-7256) -#define tls_pandreas (5544) -#define tls_wq (-7248) -#define tls_pwq (5552) -#define tls_sig (-7200) -#define tls_psig (5600) -#define tls_incyg (-7196) -#define tls_pincyg (5604) -#define tls_spinning (-7192) -#define tls_pspinning (5608) -#define tls_stacklock (-7188) -#define tls_pstacklock (5612) -#define tls_stackptr (-7184) -#define tls_pstackptr (5616) -#define tls_stack (-7176) -#define tls_pstack (5624) -#define tls_initialized (-5128) -#define tls_pinitialized (7672) +#define tls_altstack (-8680) +#define tls_paltstack (4120) +#define tls_sigwait_info (-8656) +#define tls_psigwait_info (4144) +#define tls_signal_arrived (-8648) +#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) |