1 # Check prerequisites for compiling lib/c-stack.c.
3 # Copyright (C) 2002, 2003, 2004, 2008 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.
8 # Written by Paul Eggert.
12 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
13 [# for STACK_DIRECTION
14 AC_REQUIRE([AC_FUNC_ALLOCA])
15 AC_CHECK_FUNCS_ONCE([setrlimit])
16 AC_CHECK_HEADERS_ONCE([ucontext.h])
18 AC_CACHE_CHECK([for working C stack overflow detection],
19 [ac_cv_sys_stack_overflow_works],
25 # include <sys/types.h>
26 # include <sys/time.h>
27 # include <sys/resource.h>
30 # define SIGSTKSZ 16384
35 char buffer[2 * SIGSTKSZ];
39 } alternate_signal_stack;
42 segv_handler (int signo)
55 /* Use the midpoint to avoid Irix sigaltstack bug. */
56 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
57 st.ss_size = SIGSTKSZ;
58 r = sigaltstack (&st, 0);
62 sigemptyset (&act.sa_mask);
63 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
64 act.sa_handler = segv_handler;
65 return sigaction (SIGSEGV, &act, 0);
68 recurse_1 (volatile int n, volatile int *p)
71 *recurse_1 (n + 1, p) += n;
75 recurse (volatile int n)
78 return *recurse_1 (n, &sum);
83 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
84 /* Before starting the endless recursion, try to be friendly
85 to the user's machine. On some Linux 2.2.x systems, there
86 is no stack limit for user processes at all. We don't want
87 to kill such systems. */
89 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
90 setrlimit (RLIMIT_STACK, &rl);
93 return c_stack_action () || recurse (0);
96 [ac_cv_sys_stack_overflow_works=yes],
97 [ac_cv_sys_stack_overflow_works=no],
98 [ac_cv_sys_stack_overflow_works=cross-compiling])])
100 if test $ac_cv_sys_stack_overflow_works = yes; then
101 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
102 [Define to 1 if extending the stack slightly past the limit causes
103 a SIGSEGV which can be handled on an alternate stack established
106 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
107 dnl of the memory block designated as an alternate stack. But IRIX 5.3
108 dnl interprets it as the highest address!
109 AC_CACHE_CHECK([for correct stack_t interpretation],
110 [gl_cv_sigaltstack_low_base], [
115 #if HAVE_SYS_SIGNAL_H
116 # include <sys/signal.h>
119 # define SIGSTKSZ 16384
121 volatile char *stack_lower_bound;
122 volatile char *stack_upper_bound;
123 static void check_stack_location (volatile char *addr)
125 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
130 static void stackoverflow_handler (int sig)
133 check_stack_location (&dummy);
137 char mystack[2 * SIGSTKSZ];
139 struct sigaction action;
140 /* Install the alternate stack. */
141 altstack.ss_sp = mystack + SIGSTKSZ;
142 altstack.ss_size = SIGSTKSZ;
143 stack_lower_bound = (char *) altstack.ss_sp;
144 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
145 altstack.ss_flags = 0; /* no SS_DISABLE */
146 if (sigaltstack (&altstack, NULL) < 0)
148 /* Install the SIGSEGV handler. */
149 sigemptyset (&action.sa_mask);
150 action.sa_handler = &stackoverflow_handler;
151 action.sa_flags = SA_ONSTACK;
152 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
154 /* Provoke a SIGSEGV. */
158 [gl_cv_sigaltstack_low_base=yes],
159 [gl_cv_sigaltstack_low_base=no],
160 [gl_cv_sigaltstack_low_base=cross-compiling])])
161 if test "$gl_cv_sigaltstack_low_base" = no; then
162 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
163 [Define if sigaltstack() interprets the stack_t.ss_sp field
164 incorrectly, as the highest address of the alternate stack range
165 rather than as the lowest address.])
168 AC_CACHE_CHECK([for precise C stack overflow detection],
169 ac_cv_sys_xsi_stack_overflow_heuristic,
175 # include <ucontext.h>
178 # include <sys/types.h>
179 # include <sys/time.h>
180 # include <sys/resource.h>
183 # define SIGSTKSZ 16384
188 char buffer[2 * SIGSTKSZ];
192 } alternate_signal_stack;
195 # define find_stack_direction(ptr) STACK_DIRECTION
198 find_stack_direction (char const *addr)
201 return (! addr ? find_stack_direction (&dummy)
202 : addr < &dummy ? 1 : -1);
207 segv_handler (int signo, siginfo_t *info, void *context)
209 if (0 < info->si_code)
211 /* For XSI heuristics to work, we need uc_stack to describe
212 the interrupted stack (as on Solaris), and not the
213 currently executing stack (as on Linux). */
214 ucontext_t const *user_context = context;
215 char const *stack_min = user_context->uc_stack.ss_sp;
216 size_t stack_size = user_context->uc_stack.ss_size;
217 char const *faulting_address = info->si_addr;
218 size_t s = faulting_address - stack_min;
219 size_t page_size = sysconf (_SC_PAGESIZE);
220 if (find_stack_direction (0) < 0)
222 if (s < stack_size + page_size)
233 struct sigaction act;
237 /* Use the midpoint to avoid Irix sigaltstack bug. */
238 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
239 st.ss_size = SIGSTKSZ;
240 r = sigaltstack (&st, 0);
244 sigemptyset (&act.sa_mask);
245 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
246 act.sa_sigaction = segv_handler;
247 return sigaction (SIGSEGV, &act, 0);
249 static volatile int *
250 recurse_1 (volatile int n, volatile int *p)
253 *recurse_1 (n + 1, p) += n;
257 recurse (volatile int n)
260 return *recurse_1 (n, &sum);
265 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
266 /* Before starting the endless recursion, try to be friendly
267 to the user's machine. On some Linux 2.2.x systems, there
268 is no stack limit for user processes at all. We don't want
269 to kill such systems. */
271 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
272 setrlimit (RLIMIT_STACK, &rl);
275 return c_stack_action () || recurse (0);
278 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
279 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
280 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
282 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
283 AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1,
284 [Define to 1 if extending the stack slightly past the limit causes
285 a SIGSEGV, and an alternate stack can be established with sigaltstack,
286 and the signal handler is passed a context that specifies the
287 run time stack. This behavior is defined by POSIX 1003.1-2001
288 with the X/Open System Interface (XSI) option
289 and is a standardized way to implement a SEGV-based stack
290 overflow detection heuristic.])
295 AC_DEFUN([gl_PREREQ_C_STACK],
296 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
297 AC_REQUIRE([gl_LIBSIGSEGV])
299 # for STACK_DIRECTION
300 AC_REQUIRE([AC_FUNC_ALLOCA])
302 AC_CHECK_FUNCS_ONCE([sigaltstack])
303 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
305 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
307 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
309 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
310 if test "$gl_cv_lib_sigsegv" = yes \
311 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
312 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
313 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
317 AC_DEFUN([gl_C_STACK],
319 dnl Prerequisites of lib/c-stack.c.