1 # Check prerequisites for compiling lib/c-stack.c.
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.
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_REQUIRE([AC_CANONICAL_HOST])
16 AC_CHECK_FUNCS_ONCE([setrlimit])
17 AC_CHECK_HEADERS_ONCE([ucontext.h])
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 }.
23 sunos4* | freebsd* | dragonfly* | openbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
24 FAULT_YIELDS_SIGBUS=1 ;;
26 FAULT_YIELDS_SIGBUS=1 ;;
27 macos* | darwin*) # MacOS X
28 FAULT_YIELDS_SIGBUS=1 ;;
30 FAULT_YIELDS_SIGBUS=1 ;;
32 FAULT_YIELDS_SIGBUS=0 ;;
34 AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
35 [Define to 1 if an invalid memory address access may yield a SIGBUS.])
37 AC_CACHE_CHECK([for working C stack overflow detection],
38 [ac_cv_sys_stack_overflow_works],
39 [AC_RUN_IFELSE([AC_LANG_SOURCE(
44 # include <sys/types.h>
45 # include <sys/time.h>
46 # include <sys/resource.h>
49 # define SIGSTKSZ 16384
54 char buffer[2 * SIGSTKSZ];
58 } alternate_signal_stack;
61 segv_handler (int signo)
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);
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)
88 return sigaction (SIGSEGV, &act, 0);
91 recurse_1 (volatile int n, volatile int *p)
94 *recurse_1 (n + 1, p) += n;
98 recurse (volatile int n)
101 return *recurse_1 (n, &sum);
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. */
112 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
113 setrlimit (RLIMIT_STACK, &rl);
116 return c_stack_action () || recurse (0);
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])])
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
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], [
138 #if HAVE_SYS_SIGNAL_H
139 # include <sys/signal.h>
142 # define SIGSTKSZ 16384
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)
153 static void stackoverflow_handler (int sig)
156 check_stack_location (&dummy);
160 char mystack[2 * SIGSTKSZ];
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)
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)
177 /* Provoke a SIGSEGV. */
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.])
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(
198 # include <ucontext.h>
201 # include <sys/types.h>
202 # include <sys/time.h>
203 # include <sys/resource.h>
206 # define SIGSTKSZ 16384
211 char buffer[2 * SIGSTKSZ];
215 } alternate_signal_stack;
218 # define find_stack_direction(ptr) STACK_DIRECTION
221 find_stack_direction (char const *addr)
224 return (! addr ? find_stack_direction (&dummy)
225 : addr < &dummy ? 1 : -1);
230 segv_handler (int signo, siginfo_t *info, void *context)
232 if (0 < info->si_code)
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)
245 if (s < stack_size + page_size)
256 struct sigaction act;
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);
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)
274 return sigaction (SIGSEGV, &act, 0);
276 static volatile int *
277 recurse_1 (volatile int n, volatile int *p)
280 *recurse_1 (n + 1, p) += n;
284 recurse (volatile int n)
287 return *recurse_1 (n, &sum);
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. */
298 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
299 setrlimit (RLIMIT_STACK, &rl);
302 return c_stack_action () || recurse (0);
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])])
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.])
322 AC_DEFUN([gl_PREREQ_C_STACK],
323 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
324 AC_REQUIRE([gl_LIBSIGSEGV])
326 # for STACK_DIRECTION
327 AC_REQUIRE([AC_FUNC_ALLOCA])
329 AC_CHECK_FUNCS_ONCE([sigaltstack])
330 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
332 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
334 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
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])
344 AC_DEFUN([gl_C_STACK],
346 dnl Prerequisites of lib/c-stack.c.