Improve NetBSD support: Allow VMA determination with fewer system calls.
[libsigsegv/ericb.git] / m4 / sigaltstack.m4
blob076d98a12b23d15908c0b507b232f26bcf185dbc
1 # sigaltstack.m4 serial 11 (libsigsegv-2.9)
2 dnl Copyright (C) 2002-2006, 2008-2010 Bruno Haible <bruno@clisp.org>
3 dnl Copyright (C) 2008 Eric Blake <ebb9@byu.net>
4 dnl This file is free software, distributed under the terms of the GNU
5 dnl General Public License.  As a special exception to the GNU General
6 dnl Public License, this file may be distributed as part of a program
7 dnl that contains a configuration script generated by Autoconf, under
8 dnl the same distribution terms as the rest of that program.
10 AC_DEFUN([SV_SIGALTSTACK],
12   AC_REQUIRE([AC_PROG_CC])
13   AC_REQUIRE([AC_CANONICAL_HOST])
15   AC_CHECK_FUNCS([sigaltstack])
17   if test "$ac_cv_func_sigaltstack" = yes; then
18     AC_CHECK_TYPE([stack_t], ,
19       [AC_DEFINE(stack_t, [struct sigaltstack],
20          [Define to 'struct sigaltstack' if that's the type of the argument to sigaltstack])
21       ],
22       [
23 #include <signal.h>
24 #if HAVE_SYS_SIGNAL_H
25 # include <sys/signal.h>
26 #endif
27       ])
28   fi
30   AC_CACHE_CHECK([for working sigaltstack], [sv_cv_sigaltstack], [
31     if test "$ac_cv_func_sigaltstack" = yes; then
32       case "$host_os" in
33         macos* | darwin[[6-9]]* | darwin[[1-9]][[0-9]]*)
34           # On MacOS X 10.2 or newer, just assume that if it compiles, it will
35           # work. If we were to perform the real test, 1 Crash Report dialog
36           # window would pop up.
37           AC_LINK_IFELSE([
38             AC_LANG_PROGRAM([[#include <signal.h>]],
39               [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
40             [sv_cv_sigaltstack="guessing yes"],
41             [sv_cv_sigaltstack=no])
42           ;;
43         *)
44           AC_RUN_IFELSE([
45             AC_LANG_SOURCE([[
46 #include <stdlib.h>
47 #include <signal.h>
48 #if HAVE_SYS_SIGNAL_H
49 # include <sys/signal.h>
50 #endif
51 #if HAVE_SETRLIMIT
52 # include <sys/types.h>
53 # include <sys/time.h>
54 # include <sys/resource.h>
55 #endif
56 #ifndef SIGSTKSZ
57 # define SIGSTKSZ 16384
58 #endif
59 void stackoverflow_handler (int sig)
61   /* If we get here, the stack overflow was caught.  */
62   exit (0);
64 volatile int * recurse_1 (volatile int n, volatile int *p)
66   if (n >= 0)
67     *recurse_1 (n + 1, p) += n;
68   return p;
70 int recurse (volatile int n)
72   int sum = 0;
73   return *recurse_1 (n, &sum);
75 char mystack[2 * SIGSTKSZ];
76 int main ()
78   stack_t altstack;
79   struct sigaction action;
80 #if defined HAVE_SETRLIMIT && defined RLIMIT_STACK
81   /* Before starting the endless recursion, try to be friendly to the user's
82      machine.  On some Linux 2.2.x systems, there is no stack limit for user
83      processes at all.  We don't want to kill such systems.  */
84   struct rlimit rl;
85   rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
86   setrlimit (RLIMIT_STACK, &rl);
87 #endif
88   /* Install the alternate stack.  Use the midpoint of mystack, to guard
89      against a buggy interpretation of ss_sp on IRIX.  */
90   altstack.ss_sp = mystack + SIGSTKSZ;
91   altstack.ss_size = SIGSTKSZ;
92   altstack.ss_flags = 0; /* no SS_DISABLE */
93   if (sigaltstack (&altstack, NULL) < 0)
94     exit (1);
95   /* Install the SIGSEGV handler.  */
96   sigemptyset (&action.sa_mask);
97   action.sa_handler = &stackoverflow_handler;
98   action.sa_flags = SA_ONSTACK;
99   sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
100   sigaction (SIGBUS, &action, (struct sigaction *) NULL);
101   /* Provoke a stack overflow.  */
102   recurse (0);
103   exit (2);
104 }]])],
105             [sv_cv_sigaltstack=yes],
106             [sv_cv_sigaltstack=no],
107             [
108               dnl FIXME: Put in some more known values here.
109               case "$host_os" in
110                 *)
111                   AC_LINK_IFELSE([
112                     AC_LANG_PROGRAM([[#include <signal.h>]],
113                       [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
114                     [sv_cv_sigaltstack="guessing yes"],
115                     [sv_cv_sigaltstack=no])
116                   ;;
117               esac
118             ])
119           ;;
120       esac
121     else
122       sv_cv_sigaltstack=no
123     fi
124   ])
125   if test "$sv_cv_sigaltstack" != no; then
126     AC_DEFINE([HAVE_WORKING_SIGALTSTACK], [1],
127       [Define if you have the sigaltstack() function and it works.])
129     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
130     dnl of the memory block designated as an alternate stack. But IRIX 5.3
131     dnl interprets it as the highest address!
132     AC_CACHE_CHECK([for correct stack_t interpretation],
133       [sv_cv_sigaltstack_low_base], [
134       AC_RUN_IFELSE([
135         AC_LANG_SOURCE([[
136 #include <stdlib.h>
137 #include <signal.h>
138 #if HAVE_SYS_SIGNAL_H
139 # include <sys/signal.h>
140 #endif
141 #ifndef SIGSTKSZ
142 # define SIGSTKSZ 16384
143 #endif
144 volatile char *stack_lower_bound;
145 volatile char *stack_upper_bound;
146 static void check_stack_location (volatile char *addr)
148   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
149     exit (0);
150   else
151     exit (1);
153 static void stackoverflow_handler (int sig)
155   char dummy;
156   check_stack_location (&dummy);
158 int main ()
160   char mystack[2 * SIGSTKSZ];
161   stack_t altstack;
162   struct sigaction action;
163   /* Install the alternate stack.  */
164   altstack.ss_sp = mystack + SIGSTKSZ;
165   altstack.ss_size = SIGSTKSZ;
166   stack_lower_bound = (char *) altstack.ss_sp;
167   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
168   altstack.ss_flags = 0; /* no SS_DISABLE */
169   if (sigaltstack (&altstack, NULL) < 0)
170     exit (2);
171   /* Install the SIGSEGV handler.  */
172   sigemptyset (&action.sa_mask);
173   action.sa_handler = &stackoverflow_handler;
174   action.sa_flags = SA_ONSTACK;
175   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
176     exit(3);
177   /* Provoke a SIGSEGV.  */
178   raise (SIGSEGV);
179   exit (3);
180 }]])],
181       [sv_cv_sigaltstack_low_base=yes],
182       [sv_cv_sigaltstack_low_base=no],
183       [
184         dnl FIXME: Put in some more known values here.
185         case "$host_os" in
186           irix5*) sv_cv_sigaltstack_low_base="no" ;;
187           *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
188         esac
189       ])
190     ])
191     if test "$sv_cv_sigaltstack_low_base" = no; then
192       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
193         [Define if sigaltstack() interprets the stack_t.ss_sp field incorrectly,
194          as the highest address of the alternate stack range rather than as the
195          lowest address.])
196     fi
197   fi