# Check prerequisites for compiling lib/c-stack.c.
-# Copyright (C) 2002, 2003, 2004, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Written by Paul Eggert.
-# serial 5
+# serial 9
AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
[# for STACK_DIRECTION
AC_REQUIRE([AC_FUNC_ALLOCA])
+ AC_REQUIRE([AC_CANONICAL_HOST])
AC_CHECK_FUNCS_ONCE([setrlimit])
AC_CHECK_HEADERS_ONCE([ucontext.h])
+ dnl List of signals that are sent when an invalid virtual memory address
+ dnl is accessed, or when the stack overflows.
+ dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
+ case "$host_os" in
+ sunos4* | freebsd* | dragonfly* | openbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
+ FAULT_YIELDS_SIGBUS=1 ;;
+ hpux*) # HP-UX
+ FAULT_YIELDS_SIGBUS=1 ;;
+ macos* | darwin*) # MacOS X
+ FAULT_YIELDS_SIGBUS=1 ;;
+ gnu*) # Hurd
+ FAULT_YIELDS_SIGBUS=1 ;;
+ *)
+ FAULT_YIELDS_SIGBUS=0 ;;
+ esac
+ AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
+ [Define to 1 if an invalid memory address access may yield a SIGBUS.])
+
AC_CACHE_CHECK([for working C stack overflow detection],
[ac_cv_sys_stack_overflow_works],
[AC_TRY_RUN(
# include <sys/time.h>
# include <sys/resource.h>
#endif
- #ifndef SIGSTKSZ
- # define SIGSTKSZ 16384
- #endif
+ #ifndef SIGSTKSZ
+ # define SIGSTKSZ 16384
+ #endif
static union
{
- char buffer[SIGSTKSZ];
+ char buffer[2 * SIGSTKSZ];
long double ld;
long u;
void *p;
int r;
st.ss_flags = 0;
- st.ss_sp = alternate_signal_stack.buffer;
- st.ss_size = sizeof alternate_signal_stack.buffer;
+ /* Use the midpoint to avoid Irix sigaltstack bug. */
+ st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
+ st.ss_size = SIGSTKSZ;
r = sigaltstack (&st, 0);
if (r != 0)
return r;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
act.sa_handler = segv_handler;
+ #if FAULT_YIELDS_SIGBUS
+ if (sigaction (SIGBUS, &act, 0) < 0)
+ return -1;
+ #endif
return sigaction (SIGSEGV, &act, 0);
}
-
+ static volatile int *
+ recurse_1 (volatile int n, volatile int *p)
+ {
+ if (n >= 0)
+ *recurse_1 (n + 1, p) += n;
+ return p;
+ }
static int
- recurse (char *p)
+ recurse (volatile int n)
{
- char array[500];
- array[0] = 1;
- return *p + recurse (array);
+ int sum = 0;
+ return *recurse_1 (n, &sum);
}
-
int
main ()
{
setrlimit (RLIMIT_STACK, &rl);
#endif
- c_stack_action ();
- return recurse ("\1");
+ return c_stack_action () || recurse (0);
}
],
[ac_cv_sys_stack_overflow_works=yes],
a SIGSEGV which can be handled on an alternate stack established
with sigaltstack.])
+ dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
+ dnl of the memory block designated as an alternate stack. But IRIX 5.3
+ dnl interprets it as the highest address!
+ AC_CACHE_CHECK([for correct stack_t interpretation],
+ [gl_cv_sigaltstack_low_base], [
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <signal.h>
+#if HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif
+#ifndef SIGSTKSZ
+# define SIGSTKSZ 16384
+#endif
+volatile char *stack_lower_bound;
+volatile char *stack_upper_bound;
+static void check_stack_location (volatile char *addr)
+{
+ if (addr >= stack_lower_bound && addr <= stack_upper_bound)
+ exit (0);
+ else
+ exit (1);
+}
+static void stackoverflow_handler (int sig)
+{
+ char dummy;
+ check_stack_location (&dummy);
+}
+int main ()
+{
+ char mystack[2 * SIGSTKSZ];
+ stack_t altstack;
+ struct sigaction action;
+ /* Install the alternate stack. */
+ altstack.ss_sp = mystack + SIGSTKSZ;
+ altstack.ss_size = SIGSTKSZ;
+ stack_lower_bound = (char *) altstack.ss_sp;
+ stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
+ altstack.ss_flags = 0; /* no SS_DISABLE */
+ if (sigaltstack (&altstack, NULL) < 0)
+ exit (2);
+ /* Install the SIGSEGV handler. */
+ sigemptyset (&action.sa_mask);
+ action.sa_handler = &stackoverflow_handler;
+ action.sa_flags = SA_ONSTACK;
+ if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
+ exit(3);
+ /* Provoke a SIGSEGV. */
+ raise (SIGSEGV);
+ exit (3);
+}]])],
+ [gl_cv_sigaltstack_low_base=yes],
+ [gl_cv_sigaltstack_low_base=no],
+ [gl_cv_sigaltstack_low_base=cross-compiling])])
+ if test "$gl_cv_sigaltstack_low_base" = no; then
+ AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
+ [Define if sigaltstack() interprets the stack_t.ss_sp field
+ incorrectly, as the highest address of the alternate stack range
+ rather than as the lowest address.])
+ fi
+
AC_CACHE_CHECK([for precise C stack overflow detection],
ac_cv_sys_xsi_stack_overflow_heuristic,
[AC_TRY_RUN(
# include <sys/time.h>
# include <sys/resource.h>
#endif
- #ifndef SIGSTKSZ
- # define SIGSTKSZ 16384
- #endif
+ #ifndef SIGSTKSZ
+ # define SIGSTKSZ 16384
+ #endif
static union
{
- char buffer[SIGSTKSZ];
+ char buffer[2 * SIGSTKSZ];
long double ld;
long u;
void *p;
{
if (0 < info->si_code)
{
- /* For XSI heuristics to work, we need uc_stack to describe
- the interrupted stack (as on Solaris), and not the
+ /* For XSI heuristics to work, we need uc_stack to describe
+ the interrupted stack (as on Solaris), and not the
currently executing stack (as on Linux). */
ucontext_t const *user_context = context;
char const *stack_min = user_context->uc_stack.ss_sp;
int r;
st.ss_flags = 0;
- st.ss_sp = alternate_signal_stack.buffer;
- st.ss_size = sizeof alternate_signal_stack.buffer;
+ /* Use the midpoint to avoid Irix sigaltstack bug. */
+ st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
+ st.ss_size = SIGSTKSZ;
r = sigaltstack (&st, 0);
if (r != 0)
return r;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
act.sa_sigaction = segv_handler;
+ #if FAULT_YIELDS_SIGBUS
+ if (sigaction (SIGBUS, &act, 0) < 0)
+ return -1;
+ #endif
return sigaction (SIGSEGV, &act, 0);
}
-
+ static volatile int *
+ recurse_1 (volatile int n, volatile int *p)
+ {
+ if (n >= 0)
+ *recurse_1 (n + 1, p) += n;
+ return p;
+ }
static int
- recurse (char *p)
+ recurse (volatile int n)
{
- char array[500];
- array[0] = 1;
- return *p + recurse (array);
+ int sum = 0;
+ return *recurse_1 (n, &sum);
}
-
int
main ()
{
setrlimit (RLIMIT_STACK, &rl);
#endif
- c_stack_action ();
- return recurse ("\1");
+ return c_stack_action () || recurse (0);
}
],
[ac_cv_sys_xsi_stack_overflow_heuristic=yes],
[ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
- AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1,
+ AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
[Define to 1 if extending the stack slightly past the limit causes
a SIGSEGV, and an alternate stack can be established with sigaltstack,
and the signal handler is passed a context that specifies the