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* | 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 return sigaction (SIGSEGV, &act, 0);
92 recurse_1 (volatile int n, volatile int *p)
95 *recurse_1 (n + 1, p) += n;
99 recurse (volatile int n)
102 return *recurse_1 (n, &sum);
107 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
108 /* Before starting the endless recursion, try to be friendly
109 to the user's machine. On some Linux 2.2.x systems, there
110 is no stack limit for user processes at all. We don't want
111 to kill such systems. */
113 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
114 setrlimit (RLIMIT_STACK, &rl);
117 return c_stack_action () || recurse (0);
120 [ac_cv_sys_stack_overflow_works=yes],
121 [ac_cv_sys_stack_overflow_works=no],
122 [ac_cv_sys_stack_overflow_works=cross-compiling])])
124 if test $ac_cv_sys_stack_overflow_works = yes; then
125 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
126 [Define to 1 if extending the stack slightly past the limit causes
127 a SIGSEGV which can be handled on an alternate stack established
130 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
131 dnl of the memory block designated as an alternate stack. But IRIX 5.3
132 dnl interprets it as the highest address!
133 AC_CACHE_CHECK([for correct stack_t interpretation],
134 [gl_cv_sigaltstack_low_base], [
139 #if HAVE_SYS_SIGNAL_H
140 # include <sys/signal.h>
143 # define SIGSTKSZ 16384
145 volatile char *stack_lower_bound;
146 volatile char *stack_upper_bound;
147 static void check_stack_location (volatile char *addr)
149 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
154 static void stackoverflow_handler (int sig)
157 check_stack_location (&dummy);
161 char mystack[2 * SIGSTKSZ];
163 struct sigaction action;
164 /* Install the alternate stack. */
165 altstack.ss_sp = mystack + SIGSTKSZ;
166 altstack.ss_size = SIGSTKSZ;
167 stack_lower_bound = (char *) altstack.ss_sp;
168 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
169 altstack.ss_flags = 0; /* no SS_DISABLE */
170 if (sigaltstack (&altstack, NULL) < 0)
172 /* Install the SIGSEGV handler. */
173 sigemptyset (&action.sa_mask);
174 action.sa_handler = &stackoverflow_handler;
175 action.sa_flags = SA_ONSTACK;
176 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
178 /* Provoke a SIGSEGV. */
182 [gl_cv_sigaltstack_low_base=yes],
183 [gl_cv_sigaltstack_low_base=no],
184 [gl_cv_sigaltstack_low_base=cross-compiling])])
185 if test "$gl_cv_sigaltstack_low_base" = no; then
186 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
187 [Define if sigaltstack() interprets the stack_t.ss_sp field
188 incorrectly, as the highest address of the alternate stack range
189 rather than as the lowest address.])
192 AC_CACHE_CHECK([for precise C stack overflow detection],
193 ac_cv_sys_xsi_stack_overflow_heuristic,
194 [AC_RUN_IFELSE([AC_LANG_SOURCE(
199 # include <ucontext.h>
202 # include <sys/types.h>
203 # include <sys/time.h>
204 # include <sys/resource.h>
207 # define SIGSTKSZ 16384
212 char buffer[2 * SIGSTKSZ];
216 } alternate_signal_stack;
219 # define find_stack_direction(ptr) STACK_DIRECTION
222 find_stack_direction (char const *addr)
225 return (! addr ? find_stack_direction (&dummy)
226 : addr < &dummy ? 1 : -1);
231 segv_handler (int signo, siginfo_t *info, void *context)
233 if (0 < info->si_code)
235 /* For XSI heuristics to work, we need uc_stack to describe
236 the interrupted stack (as on Solaris), and not the
237 currently executing stack (as on Linux). */
238 ucontext_t const *user_context = context;
239 char const *stack_min = user_context->uc_stack.ss_sp;
240 size_t stack_size = user_context->uc_stack.ss_size;
241 char const *faulting_address = info->si_addr;
242 size_t s = faulting_address - stack_min;
243 size_t page_size = sysconf (_SC_PAGESIZE);
244 if (find_stack_direction (0) < 0)
246 if (s < stack_size + page_size)
257 struct sigaction act;
261 /* Use the midpoint to avoid Irix sigaltstack bug. */
262 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
263 st.ss_size = SIGSTKSZ;
264 r = sigaltstack (&st, 0);
268 sigemptyset (&act.sa_mask);
269 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
270 act.sa_sigaction = segv_handler;
271 #if FAULT_YIELDS_SIGBUS
272 if (sigaction (SIGBUS, &act, 0) < 0)
275 return sigaction (SIGSEGV, &act, 0);
277 static volatile int *
278 recurse_1 (volatile int n, volatile int *p)
281 *recurse_1 (n + 1, p) += n;
285 recurse (volatile int n)
288 return *recurse_1 (n, &sum);
293 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
294 /* Before starting the endless recursion, try to be friendly
295 to the user's machine. On some Linux 2.2.x systems, there
296 is no stack limit for user processes at all. We don't want
297 to kill such systems. */
299 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
300 setrlimit (RLIMIT_STACK, &rl);
303 return c_stack_action () || recurse (0);
306 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
307 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
308 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
310 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
311 AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
312 [Define to 1 if extending the stack slightly past the limit causes
313 a SIGSEGV, and an alternate stack can be established with sigaltstack,
314 and the signal handler is passed a context that specifies the
315 run time stack. This behavior is defined by POSIX 1003.1-2001
316 with the X/Open System Interface (XSI) option
317 and is a standardized way to implement a SEGV-based stack
318 overflow detection heuristic.])
323 AC_DEFUN([gl_PREREQ_C_STACK],
324 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
325 AC_REQUIRE([gl_LIBSIGSEGV])
327 # for STACK_DIRECTION
328 AC_REQUIRE([AC_FUNC_ALLOCA])
330 AC_CHECK_FUNCS_ONCE([sigaltstack])
331 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
333 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
335 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
337 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
338 if test "$gl_cv_lib_sigsegv" = yes \
339 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
340 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
341 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
345 AC_DEFUN([gl_C_STACK],
347 dnl Prerequisites of lib/c-stack.c.