/* 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
#define _(msgid) gettext (msgid)
#include <errno.h>
-#ifndef ENOTSUP
-# define ENOTSUP EINVAL
-#endif
#include <signal.h>
#if ! HAVE_STACK_T && ! defined stack_t
#endif
#include <unistd.h>
-#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
-#endif
#if HAVE_LIBSIGSEGV
# include <sigsegv.h>
# define SIGACTION_WORKS 1
#else
# define SIGACTION_WORKS 0
+# ifndef SA_ONSTACK
+# define SA_ONSTACK 0
+# endif
#endif
extern char *program_name;
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
die ((!emergency || segv_handler_missing) ? 0 : SIGSEGV);
}
-/* Set up ACTION so that it is invoked on C stack overflow. Return -1
- (setting errno) if this cannot be done.
-
- When ACTION is called, it is passed an argument equal to SIGSEGV
- for a segmentation violation that does not appear related to stack
- overflow, and is passed zero otherwise. On many platforms it is
- hard to tell; when in doubt, zero is passed.
-
- A null ACTION acts like an action that does nothing.
-
- ACTION must be async-signal-safe. ACTION together with its callees
- must not require more than SIGSTKSZ bytes of stack space. Also,
- ACTION should not call longjmp, because this implementation does
- not guarantee that it is safe to return to the original stack. */
-
int
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. */
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. */
write (STDERR_FILENO, buf, strlen (buf));
}
# endif
-# endif
}
+# endif
die (signo);
}
# endif
-/* Set up ACTION so that it is invoked on C stack overflow. Return -1
- (setting errno) if this cannot be done.
-
- When ACTION is called, it is passed an argument equal to SIGSEGV
- for a segmentation violation that does not appear related to stack
- overflow, and is passed zero otherwise. On many platforms it is
- hard to tell; when in doubt, zero is passed.
-
- A null ACTION acts like an action that does nothing.
-
- ACTION must be async-signal-safe. ACTION together with its callees
- must not require more than SIGSTKSZ bytes of stack space. Also,
- ACTION should not call longjmp, because this implementation does
- not guarantee that it is safe to return to the original stack. */
-
int
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;
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)))