1 # Check prerequisites for compiling lib/c-stack.c.
3 # Copyright (C) 2002-2004, 2008-2011 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* | mirbsd* | 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 if (sigaction (SIGSEGV, &act, 0) < 0)
93 recurse_1 (volatile int n, volatile int *p)
96 *recurse_1 (n + 1, p) += n;
100 recurse (volatile int n)
103 return *recurse_1 (n, &sum);
109 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
110 /* Before starting the endless recursion, try to be friendly
111 to the user's machine. On some Linux 2.2.x systems, there
112 is no stack limit for user processes at all. We don't want
113 to kill such systems. */
115 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
116 setrlimit (RLIMIT_STACK, &rl);
119 result = c_stack_action ();
125 [ac_cv_sys_stack_overflow_works=yes],
126 [ac_cv_sys_stack_overflow_works=no],
127 [ac_cv_sys_stack_overflow_works=cross-compiling])])
129 if test $ac_cv_sys_stack_overflow_works = yes; then
130 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
131 [Define to 1 if extending the stack slightly past the limit causes
132 a SIGSEGV which can be handled on an alternate stack established
135 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
136 dnl of the memory block designated as an alternate stack. But IRIX 5.3
137 dnl interprets it as the highest address!
138 AC_CACHE_CHECK([for correct stack_t interpretation],
139 [gl_cv_sigaltstack_low_base], [
144 #if HAVE_SYS_SIGNAL_H
145 # include <sys/signal.h>
148 # define SIGSTKSZ 16384
150 volatile char *stack_lower_bound;
151 volatile char *stack_upper_bound;
152 static void check_stack_location (volatile char *addr)
154 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
159 static void stackoverflow_handler (int sig)
162 check_stack_location (&dummy);
166 char mystack[2 * SIGSTKSZ];
168 struct sigaction action;
169 /* Install the alternate stack. */
170 altstack.ss_sp = mystack + SIGSTKSZ;
171 altstack.ss_size = SIGSTKSZ;
172 stack_lower_bound = (char *) altstack.ss_sp;
173 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
174 altstack.ss_flags = 0; /* no SS_DISABLE */
175 if (sigaltstack (&altstack, NULL) < 0)
177 /* Install the SIGSEGV handler. */
178 sigemptyset (&action.sa_mask);
179 action.sa_handler = &stackoverflow_handler;
180 action.sa_flags = SA_ONSTACK;
181 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
183 /* Provoke a SIGSEGV. */
187 [gl_cv_sigaltstack_low_base=yes],
188 [gl_cv_sigaltstack_low_base=no],
189 [gl_cv_sigaltstack_low_base=cross-compiling])])
190 if test "$gl_cv_sigaltstack_low_base" = no; then
191 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
192 [Define if sigaltstack() interprets the stack_t.ss_sp field
193 incorrectly, as the highest address of the alternate stack range
194 rather than as the lowest address.])
197 AC_CACHE_CHECK([for precise C stack overflow detection],
198 ac_cv_sys_xsi_stack_overflow_heuristic,
199 [AC_RUN_IFELSE([AC_LANG_SOURCE(
204 # include <ucontext.h>
207 # include <sys/types.h>
208 # include <sys/time.h>
209 # include <sys/resource.h>
212 # define SIGSTKSZ 16384
217 char buffer[2 * SIGSTKSZ];
221 } alternate_signal_stack;
224 # define find_stack_direction(ptr) STACK_DIRECTION
227 find_stack_direction (char const *addr)
230 return (! addr ? find_stack_direction (&dummy)
231 : addr < &dummy ? 1 : -1);
236 segv_handler (int signo, siginfo_t *info, void *context)
238 if (0 < info->si_code)
240 /* For XSI heuristics to work, we need uc_stack to describe
241 the interrupted stack (as on Solaris), and not the
242 currently executing stack (as on Linux). */
243 ucontext_t const *user_context = context;
244 char const *stack_min = user_context->uc_stack.ss_sp;
245 size_t stack_size = user_context->uc_stack.ss_size;
246 char const *faulting_address = info->si_addr;
247 size_t s = faulting_address - stack_min;
248 size_t page_size = sysconf (_SC_PAGESIZE);
249 if (find_stack_direction (0) < 0)
251 if (s < stack_size + page_size)
262 struct sigaction act;
266 /* Use the midpoint to avoid Irix sigaltstack bug. */
267 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
268 st.ss_size = SIGSTKSZ;
269 r = sigaltstack (&st, 0);
273 sigemptyset (&act.sa_mask);
274 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
275 act.sa_sigaction = segv_handler;
276 #if FAULT_YIELDS_SIGBUS
277 if (sigaction (SIGBUS, &act, 0) < 0)
280 if (sigaction (SIGSEGV, &act, 0) < 0)
284 static volatile int *
285 recurse_1 (volatile int n, volatile int *p)
288 *recurse_1 (n + 1, p) += n;
292 recurse (volatile int n)
295 return *recurse_1 (n, &sum);
301 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
302 /* Before starting the endless recursion, try to be friendly
303 to the user's machine. On some Linux 2.2.x systems, there
304 is no stack limit for user processes at all. We don't want
305 to kill such systems. */
307 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
308 setrlimit (RLIMIT_STACK, &rl);
311 result = c_stack_action ();
317 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
318 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
319 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
321 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
322 AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
323 [Define to 1 if extending the stack slightly past the limit causes
324 a SIGSEGV, and an alternate stack can be established with sigaltstack,
325 and the signal handler is passed a context that specifies the
326 run time stack. This behavior is defined by POSIX 1003.1-2001
327 with the X/Open System Interface (XSI) option
328 and is a standardized way to implement a SEGV-based stack
329 overflow detection heuristic.])
334 AC_DEFUN([gl_PREREQ_C_STACK],
335 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
336 AC_REQUIRE([gl_LIBSIGSEGV])
338 # for STACK_DIRECTION
339 AC_REQUIRE([AC_FUNC_ALLOCA])
341 AC_CHECK_FUNCS_ONCE([sigaltstack])
342 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
344 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
346 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
348 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
349 if test "$gl_cv_lib_sigsegv" = yes \
350 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
351 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
352 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
356 AC_DEFUN([gl_C_STACK],
358 dnl Prerequisites of lib/c-stack.c.