Remove obsolete macros from several modules.
[gnulib.git] / m4 / c-stack.m4
1 # Check prerequisites for compiling lib/c-stack.c.
2
3 # Copyright (C) 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
4 # This file is free software; the Free Software Foundation
5 # gives unlimited permission to copy and/or distribute it,
6 # with or without modifications, as long as this notice is preserved.
7
8 # Written by Paul Eggert.
9
10 # serial 10
11
12 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
13   [# for STACK_DIRECTION
14    AC_REQUIRE([AC_FUNC_ALLOCA])
15    AC_REQUIRE([AC_CANONICAL_HOST])
16    AC_CHECK_FUNCS_ONCE([setrlimit])
17    AC_CHECK_HEADERS_ONCE([ucontext.h])
18
19    dnl List of signals that are sent when an invalid virtual memory address
20    dnl is accessed, or when the stack overflows.
21    dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
22    case "$host_os" in
23      sunos4* | freebsd* | dragonfly* | openbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
24        FAULT_YIELDS_SIGBUS=1 ;;
25      hpux*) # HP-UX
26        FAULT_YIELDS_SIGBUS=1 ;;
27      macos* | darwin*) # MacOS X
28        FAULT_YIELDS_SIGBUS=1 ;;
29      gnu*) # Hurd
30        FAULT_YIELDS_SIGBUS=1 ;;
31      *)
32        FAULT_YIELDS_SIGBUS=0 ;;
33    esac
34    AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
35      [Define to 1 if an invalid memory address access may yield a SIGBUS.])
36
37    AC_CACHE_CHECK([for working C stack overflow detection],
38      [ac_cv_sys_stack_overflow_works],
39      [AC_RUN_IFELSE([AC_LANG_SOURCE(
40            [[
41             #include <unistd.h>
42             #include <signal.h>
43             #if HAVE_SETRLIMIT
44             # include <sys/types.h>
45             # include <sys/time.h>
46             # include <sys/resource.h>
47             #endif
48             #ifndef SIGSTKSZ
49             # define SIGSTKSZ 16384
50             #endif
51
52             static union
53             {
54               char buffer[2 * SIGSTKSZ];
55               long double ld;
56               long u;
57               void *p;
58             } alternate_signal_stack;
59
60             static void
61             segv_handler (int signo)
62             {
63               _exit (0);
64             }
65
66             static int
67             c_stack_action ()
68             {
69               stack_t st;
70               struct sigaction act;
71               int r;
72
73               st.ss_flags = 0;
74               /* Use the midpoint to avoid Irix sigaltstack bug.  */
75               st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
76               st.ss_size = SIGSTKSZ;
77               r = sigaltstack (&st, 0);
78               if (r != 0)
79                 return r;
80
81               sigemptyset (&act.sa_mask);
82               act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
83               act.sa_handler = segv_handler;
84               #if FAULT_YIELDS_SIGBUS
85               if (sigaction (SIGBUS, &act, 0) < 0)
86                 return -1;
87               #endif
88               return sigaction (SIGSEGV, &act, 0);
89             }
90             static volatile int *
91             recurse_1 (volatile int n, volatile int *p)
92             {
93               if (n >= 0)
94                 *recurse_1 (n + 1, p) += n;
95               return p;
96             }
97             static int
98             recurse (volatile int n)
99             {
100               int sum = 0;
101               return *recurse_1 (n, &sum);
102             }
103             int
104             main ()
105             {
106               #if HAVE_SETRLIMIT && defined RLIMIT_STACK
107               /* Before starting the endless recursion, try to be friendly
108                  to the user's machine.  On some Linux 2.2.x systems, there
109                  is no stack limit for user processes at all.  We don't want
110                  to kill such systems.  */
111               struct rlimit rl;
112               rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
113               setrlimit (RLIMIT_STACK, &rl);
114               #endif
115
116               return c_stack_action () || recurse (0);
117             }
118            ]])],
119         [ac_cv_sys_stack_overflow_works=yes],
120         [ac_cv_sys_stack_overflow_works=no],
121         [ac_cv_sys_stack_overflow_works=cross-compiling])])
122
123   if test $ac_cv_sys_stack_overflow_works = yes; then
124    AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
125      [Define to 1 if extending the stack slightly past the limit causes
126       a SIGSEGV which can be handled on an alternate stack established
127       with sigaltstack.])
128
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       [gl_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)
147 {
148   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
149     exit (0);
150   else
151     exit (1);
152 }
153 static void stackoverflow_handler (int sig)
154 {
155   char dummy;
156   check_stack_location (&dummy);
157 }
158 int main ()
159 {
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       [gl_cv_sigaltstack_low_base=yes],
182       [gl_cv_sigaltstack_low_base=no],
183       [gl_cv_sigaltstack_low_base=cross-compiling])])
184    if test "$gl_cv_sigaltstack_low_base" = no; then
185       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
186         [Define if sigaltstack() interprets the stack_t.ss_sp field
187          incorrectly, as the highest address of the alternate stack range
188          rather than as the lowest address.])
189     fi
190
191    AC_CACHE_CHECK([for precise C stack overflow detection],
192      ac_cv_sys_xsi_stack_overflow_heuristic,
193      [AC_RUN_IFELSE([AC_LANG_SOURCE(
194            [[
195             #include <unistd.h>
196             #include <signal.h>
197             #if HAVE_UCONTEXT_H
198             # include <ucontext.h>
199             #endif
200             #if HAVE_SETRLIMIT
201             # include <sys/types.h>
202             # include <sys/time.h>
203             # include <sys/resource.h>
204             #endif
205             #ifndef SIGSTKSZ
206             # define SIGSTKSZ 16384
207             #endif
208
209             static union
210             {
211               char buffer[2 * SIGSTKSZ];
212               long double ld;
213               long u;
214               void *p;
215             } alternate_signal_stack;
216
217             #if STACK_DIRECTION
218             # define find_stack_direction(ptr) STACK_DIRECTION
219             #else
220             static int
221             find_stack_direction (char const *addr)
222             {
223               char dummy;
224               return (! addr ? find_stack_direction (&dummy)
225                       : addr < &dummy ? 1 : -1);
226             }
227             #endif
228
229             static void
230             segv_handler (int signo, siginfo_t *info, void *context)
231             {
232               if (0 < info->si_code)
233                 {
234                   /* For XSI heuristics to work, we need uc_stack to describe
235                      the interrupted stack (as on Solaris), and not the
236                      currently executing stack (as on Linux).  */
237                   ucontext_t const *user_context = context;
238                   char const *stack_min = user_context->uc_stack.ss_sp;
239                   size_t stack_size = user_context->uc_stack.ss_size;
240                   char const *faulting_address = info->si_addr;
241                   size_t s = faulting_address - stack_min;
242                   size_t page_size = sysconf (_SC_PAGESIZE);
243                   if (find_stack_direction (0) < 0)
244                     s += page_size;
245                   if (s < stack_size + page_size)
246                     _exit (0);
247                 }
248
249               _exit (1);
250             }
251
252             static int
253             c_stack_action ()
254             {
255               stack_t st;
256               struct sigaction act;
257               int r;
258
259               st.ss_flags = 0;
260               /* Use the midpoint to avoid Irix sigaltstack bug.  */
261               st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
262               st.ss_size = SIGSTKSZ;
263               r = sigaltstack (&st, 0);
264               if (r != 0)
265                 return r;
266
267               sigemptyset (&act.sa_mask);
268               act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
269               act.sa_sigaction = segv_handler;
270               #if FAULT_YIELDS_SIGBUS
271               if (sigaction (SIGBUS, &act, 0) < 0)
272                 return -1;
273               #endif
274               return sigaction (SIGSEGV, &act, 0);
275             }
276             static volatile int *
277             recurse_1 (volatile int n, volatile int *p)
278             {
279               if (n >= 0)
280                 *recurse_1 (n + 1, p) += n;
281               return p;
282             }
283             static int
284             recurse (volatile int n)
285             {
286               int sum = 0;
287               return *recurse_1 (n, &sum);
288             }
289             int
290             main ()
291             {
292               #if HAVE_SETRLIMIT && defined RLIMIT_STACK
293               /* Before starting the endless recursion, try to be friendly
294                  to the user's machine.  On some Linux 2.2.x systems, there
295                  is no stack limit for user processes at all.  We don't want
296                  to kill such systems.  */
297               struct rlimit rl;
298               rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
299               setrlimit (RLIMIT_STACK, &rl);
300               #endif
301
302               return c_stack_action () || recurse (0);
303             }
304            ]])],
305         [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
306         [ac_cv_sys_xsi_stack_overflow_heuristic=no],
307         [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
308
309    if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
310      AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
311        [Define to 1 if extending the stack slightly past the limit causes
312         a SIGSEGV, and an alternate stack can be established with sigaltstack,
313         and the signal handler is passed a context that specifies the
314         run time stack.  This behavior is defined by POSIX 1003.1-2001
315         with the X/Open System Interface (XSI) option
316         and is a standardized way to implement a SEGV-based stack
317         overflow detection heuristic.])
318    fi
319   fi])
320
321
322 AC_DEFUN([gl_PREREQ_C_STACK],
323   [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
324    AC_REQUIRE([gl_LIBSIGSEGV])
325
326    # for STACK_DIRECTION
327    AC_REQUIRE([AC_FUNC_ALLOCA])
328
329    AC_CHECK_FUNCS_ONCE([sigaltstack])
330    AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
331
332    AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
333
334    AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
335
336    dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
337    if test "$gl_cv_lib_sigsegv" = yes \
338        && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
339      AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
340      AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
341    fi
342 ])
343
344 AC_DEFUN([gl_C_STACK],
345 [
346   dnl Prerequisites of lib/c-stack.c.
347   gl_PREREQ_C_STACK
348 ])