1 # Check prerequisites for compiling lib/c-stack.c.
3 # Copyright (C) 2002, 2003, 2004, 2008, 2009, 2010 Free Software Foundation,
5 # This file is free software; the Free Software Foundation
6 # gives unlimited permission to copy and/or distribute it,
7 # with or without modifications, as long as this notice is preserved.
9 # Written by Paul Eggert.
13 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
14 [# for STACK_DIRECTION
15 AC_REQUIRE([AC_FUNC_ALLOCA])
16 AC_REQUIRE([AC_CANONICAL_HOST])
17 AC_CHECK_FUNCS_ONCE([setrlimit])
18 AC_CHECK_HEADERS_ONCE([ucontext.h])
20 dnl List of signals that are sent when an invalid virtual memory address
21 dnl is accessed, or when the stack overflows.
22 dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
24 sunos4* | freebsd* | dragonfly* | openbsd* | mirbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
25 FAULT_YIELDS_SIGBUS=1 ;;
27 FAULT_YIELDS_SIGBUS=1 ;;
28 macos* | darwin*) # MacOS X
29 FAULT_YIELDS_SIGBUS=1 ;;
31 FAULT_YIELDS_SIGBUS=1 ;;
33 FAULT_YIELDS_SIGBUS=0 ;;
35 AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
36 [Define to 1 if an invalid memory address access may yield a SIGBUS.])
38 AC_CACHE_CHECK([for working C stack overflow detection],
39 [ac_cv_sys_stack_overflow_works],
40 [AC_RUN_IFELSE([AC_LANG_SOURCE(
45 # include <sys/types.h>
46 # include <sys/time.h>
47 # include <sys/resource.h>
50 # define SIGSTKSZ 16384
55 char buffer[2 * SIGSTKSZ];
59 } alternate_signal_stack;
62 segv_handler (int signo)
75 /* Use the midpoint to avoid Irix sigaltstack bug. */
76 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
77 st.ss_size = SIGSTKSZ;
78 r = sigaltstack (&st, 0);
82 sigemptyset (&act.sa_mask);
83 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
84 act.sa_handler = segv_handler;
85 #if FAULT_YIELDS_SIGBUS
86 if (sigaction (SIGBUS, &act, 0) < 0)
89 if (sigaction (SIGSEGV, &act, 0) < 0)
94 recurse_1 (volatile int n, volatile int *p)
97 *recurse_1 (n + 1, p) += n;
101 recurse (volatile int n)
104 return *recurse_1 (n, &sum);
110 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
111 /* Before starting the endless recursion, try to be friendly
112 to the user's machine. On some Linux 2.2.x systems, there
113 is no stack limit for user processes at all. We don't want
114 to kill such systems. */
116 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
117 setrlimit (RLIMIT_STACK, &rl);
120 result = c_stack_action ();
126 [ac_cv_sys_stack_overflow_works=yes],
127 [ac_cv_sys_stack_overflow_works=no],
128 [ac_cv_sys_stack_overflow_works=cross-compiling])])
130 if test $ac_cv_sys_stack_overflow_works = yes; then
131 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
132 [Define to 1 if extending the stack slightly past the limit causes
133 a SIGSEGV which can be handled on an alternate stack established
136 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
137 dnl of the memory block designated as an alternate stack. But IRIX 5.3
138 dnl interprets it as the highest address!
139 AC_CACHE_CHECK([for correct stack_t interpretation],
140 [gl_cv_sigaltstack_low_base], [
145 #if HAVE_SYS_SIGNAL_H
146 # include <sys/signal.h>
149 # define SIGSTKSZ 16384
151 volatile char *stack_lower_bound;
152 volatile char *stack_upper_bound;
153 static void check_stack_location (volatile char *addr)
155 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
160 static void stackoverflow_handler (int sig)
163 check_stack_location (&dummy);
167 char mystack[2 * SIGSTKSZ];
169 struct sigaction action;
170 /* Install the alternate stack. */
171 altstack.ss_sp = mystack + SIGSTKSZ;
172 altstack.ss_size = SIGSTKSZ;
173 stack_lower_bound = (char *) altstack.ss_sp;
174 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
175 altstack.ss_flags = 0; /* no SS_DISABLE */
176 if (sigaltstack (&altstack, NULL) < 0)
178 /* Install the SIGSEGV handler. */
179 sigemptyset (&action.sa_mask);
180 action.sa_handler = &stackoverflow_handler;
181 action.sa_flags = SA_ONSTACK;
182 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
184 /* Provoke a SIGSEGV. */
188 [gl_cv_sigaltstack_low_base=yes],
189 [gl_cv_sigaltstack_low_base=no],
190 [gl_cv_sigaltstack_low_base=cross-compiling])])
191 if test "$gl_cv_sigaltstack_low_base" = no; then
192 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
193 [Define if sigaltstack() interprets the stack_t.ss_sp field
194 incorrectly, as the highest address of the alternate stack range
195 rather than as the lowest address.])
198 AC_CACHE_CHECK([for precise C stack overflow detection],
199 ac_cv_sys_xsi_stack_overflow_heuristic,
200 [AC_RUN_IFELSE([AC_LANG_SOURCE(
205 # include <ucontext.h>
208 # include <sys/types.h>
209 # include <sys/time.h>
210 # include <sys/resource.h>
213 # define SIGSTKSZ 16384
218 char buffer[2 * SIGSTKSZ];
222 } alternate_signal_stack;
225 # define find_stack_direction(ptr) STACK_DIRECTION
228 find_stack_direction (char const *addr)
231 return (! addr ? find_stack_direction (&dummy)
232 : addr < &dummy ? 1 : -1);
237 segv_handler (int signo, siginfo_t *info, void *context)
239 if (0 < info->si_code)
241 /* For XSI heuristics to work, we need uc_stack to describe
242 the interrupted stack (as on Solaris), and not the
243 currently executing stack (as on Linux). */
244 ucontext_t const *user_context = context;
245 char const *stack_min = user_context->uc_stack.ss_sp;
246 size_t stack_size = user_context->uc_stack.ss_size;
247 char const *faulting_address = info->si_addr;
248 size_t s = faulting_address - stack_min;
249 size_t page_size = sysconf (_SC_PAGESIZE);
250 if (find_stack_direction (0) < 0)
252 if (s < stack_size + page_size)
263 struct sigaction act;
267 /* Use the midpoint to avoid Irix sigaltstack bug. */
268 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
269 st.ss_size = SIGSTKSZ;
270 r = sigaltstack (&st, 0);
274 sigemptyset (&act.sa_mask);
275 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
276 act.sa_sigaction = segv_handler;
277 #if FAULT_YIELDS_SIGBUS
278 if (sigaction (SIGBUS, &act, 0) < 0)
281 if (sigaction (SIGSEGV, &act, 0) < 0)
285 static volatile int *
286 recurse_1 (volatile int n, volatile int *p)
289 *recurse_1 (n + 1, p) += n;
293 recurse (volatile int n)
296 return *recurse_1 (n, &sum);
302 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
303 /* Before starting the endless recursion, try to be friendly
304 to the user's machine. On some Linux 2.2.x systems, there
305 is no stack limit for user processes at all. We don't want
306 to kill such systems. */
308 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
309 setrlimit (RLIMIT_STACK, &rl);
312 result = c_stack_action ();
318 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
319 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
320 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
322 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
323 AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
324 [Define to 1 if extending the stack slightly past the limit causes
325 a SIGSEGV, and an alternate stack can be established with sigaltstack,
326 and the signal handler is passed a context that specifies the
327 run time stack. This behavior is defined by POSIX 1003.1-2001
328 with the X/Open System Interface (XSI) option
329 and is a standardized way to implement a SEGV-based stack
330 overflow detection heuristic.])
335 AC_DEFUN([gl_PREREQ_C_STACK],
336 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
337 AC_REQUIRE([gl_LIBSIGSEGV])
339 # for STACK_DIRECTION
340 AC_REQUIRE([AC_FUNC_ALLOCA])
342 AC_CHECK_FUNCS_ONCE([sigaltstack])
343 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
345 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
347 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
349 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
350 if test "$gl_cv_lib_sigsegv" = yes \
351 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
352 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
353 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
357 AC_DEFUN([gl_C_STACK],
359 dnl Prerequisites of lib/c-stack.c.