X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fc-stack.c;h=1dddeefc412d1242c03839bebb583b1fbfc6dcf3;hb=26c5fd742f9136e2ddbd4695a9172c3fa30ea260;hp=c46c23136111701b7f77cb9609bfeded145475be;hpb=065a39d1ff7eb9dba34f3a4020be752a53546a43;p=gnulib.git diff --git a/lib/c-stack.c b/lib/c-stack.c index c46c23136..1dddeefc4 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -1,6 +1,7 @@ /* Stack overflow handling. - Copyright (C) 2002, 2004, 2006, 2008 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, 2008, 2009 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,9 +46,6 @@ #define _(msgid) gettext (msgid) #include -#ifndef ENOTSUP -# define ENOTSUP EINVAL -#endif #include #if ! HAVE_STACK_T && ! defined stack_t @@ -67,9 +65,6 @@ typedef struct sigaltstack stack_t; #endif #include -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif #if HAVE_LIBSIGSEGV # include @@ -82,6 +77,9 @@ typedef struct sigaltstack stack_t; # define SIGACTION_WORKS 1 #else # define SIGACTION_WORKS 0 +# ifndef SA_ONSTACK +# define SA_ONSTACK 0 +# endif #endif extern char *program_name; @@ -117,7 +115,8 @@ die (int signo) abort (); } -#if (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV +#if (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK \ + && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV /* Storage for the alternate signal stack. */ static union @@ -210,7 +209,7 @@ c_stack_action (void (*action) (int)) return 0; } -#elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK +#elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING /* Direction of the C runtime stack. This function is async-signal-safe. */ @@ -237,21 +236,21 @@ segv_handler (int signo, siginfo_t *info, void *context __attribute__ ((unused))) { /* Clear SIGNO if it seems to have been a stack overflow. */ - if (0 < info->si_code) - { # if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC - /* We can't easily determine whether it is a stack overflow; so - assume that the rest of our program is perfect (!) and that - this segmentation violation is a stack overflow. - - Note that although both Linux and Solaris provide - sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only - Solaris satisfies the XSI heueristic. This is because - Solaris populates uc_stack with the details of the - interrupted stack, while Linux populates it with the details - of the current stack. */ - signo = 0; + /* We can't easily determine whether it is a stack overflow; so + assume that the rest of our program is perfect (!) and that + this segmentation violation is a stack overflow. + + Note that although both Linux and Solaris provide + sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only + Solaris satisfies the XSI heueristic. This is because + Solaris populates uc_stack with the details of the + interrupted stack, while Linux populates it with the details + of the current stack. */ + signo = 0; # else + if (0 < info->si_code) + { /* If the faulting address is within the stack, or within one page of the stack end, assume that it is a stack overflow. */ @@ -276,8 +275,8 @@ segv_handler (int signo, siginfo_t *info, write (STDERR_FILENO, buf, strlen (buf)); } # endif -# endif } +# endif die (signo); } @@ -290,8 +289,15 @@ c_stack_action (void (*action) (int)) stack_t st; struct sigaction act; st.ss_flags = 0; +# if SIGALTSTACK_SS_REVERSED + /* Irix mistakenly treats ss_sp as the upper bound, rather than + lower bound, of the alternate stack. */ + st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ - sizeof (void *); + st.ss_size = sizeof alternate_signal_stack.buffer - sizeof (void *); +# else st.ss_sp = alternate_signal_stack.buffer; st.ss_size = sizeof alternate_signal_stack.buffer; +# endif r = sigaltstack (&st, NULL); if (r != 0) return r; @@ -309,14 +315,19 @@ c_stack_action (void (*action) (int)) act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; act.sa_sigaction = segv_handler; # else - act.sa_flags = SA_NODEFER | SA_RESETHAND; + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; act.sa_handler = die; # endif +# if FAULT_YIELDS_SIGBUS + if (sigaction (SIGBUS, &act, NULL) < 0) + return -1; +# endif return sigaction (SIGSEGV, &act, NULL); } -#else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV) */ +#else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK + && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV) */ int c_stack_action (void (*action) (int) __attribute__ ((unused)))