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);
73 return *p + recurse (array);
79 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
80 /* Before starting the endless recursion, try to be friendly
81 to the user's machine. On some Linux 2.2.x systems, there
82 is no stack limit for user processes at all. We don't want
83 to kill such systems. */
85 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
86 setrlimit (RLIMIT_STACK, &rl);
89 return c_stack_action () || recurse ("\1");
92 [ac_cv_sys_stack_overflow_works=yes],
93 [ac_cv_sys_stack_overflow_works=no],
94 [ac_cv_sys_stack_overflow_works=cross-compiling])])
96 if test $ac_cv_sys_stack_overflow_works = yes; then
97 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
98 [Define to 1 if extending the stack slightly past the limit causes
99 a SIGSEGV which can be handled on an alternate stack established
102 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
103 dnl of the memory block designated as an alternate stack. But IRIX 5.3
104 dnl interprets it as the highest address!
105 AC_CACHE_CHECK([for correct stack_t interpretation],
106 [gl_cv_sigaltstack_low_base], [
111 #if HAVE_SYS_SIGNAL_H
112 # include <sys/signal.h>
115 # define SIGSTKSZ 16384
117 volatile char *stack_lower_bound;
118 volatile char *stack_upper_bound;
119 static void check_stack_location (volatile char *addr)
121 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
126 static void stackoverflow_handler (int sig)
129 check_stack_location (&dummy);
133 char mystack[2 * SIGSTKSZ];
135 struct sigaction action;
136 /* Install the alternate stack. */
137 altstack.ss_sp = mystack + SIGSTKSZ;
138 altstack.ss_size = SIGSTKSZ;
139 stack_lower_bound = (char *) altstack.ss_sp;
140 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
141 altstack.ss_flags = 0; /* no SS_DISABLE */
142 if (sigaltstack (&altstack, NULL) < 0)
144 /* Install the SIGSEGV handler. */
145 sigemptyset (&action.sa_mask);
146 action.sa_handler = &stackoverflow_handler;
147 action.sa_flags = SA_ONSTACK;
148 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
150 /* Provoke a SIGSEGV. */
154 [gl_cv_sigaltstack_low_base=yes],
155 [gl_cv_sigaltstack_low_base=no],
156 [gl_cv_sigaltstack_low_base=cross-compiling])])
157 if test "$gl_cv_sigaltstack_low_base" = no; then
158 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
159 [Define if sigaltstack() interprets the stack_t.ss_sp field
160 incorrectly, as the highest address of the alternate stack range
161 rather than as the lowest address.])
164 AC_CACHE_CHECK([for precise C stack overflow detection],
165 ac_cv_sys_xsi_stack_overflow_heuristic,
171 # include <ucontext.h>
174 # include <sys/types.h>
175 # include <sys/time.h>
176 # include <sys/resource.h>
179 # define SIGSTKSZ 16384
184 char buffer[2 * SIGSTKSZ];
188 } alternate_signal_stack;
191 # define find_stack_direction(ptr) STACK_DIRECTION
194 find_stack_direction (char const *addr)
197 return (! addr ? find_stack_direction (&dummy)
198 : addr < &dummy ? 1 : -1);
203 segv_handler (int signo, siginfo_t *info, void *context)
205 if (0 < info->si_code)
207 /* For XSI heuristics to work, we need uc_stack to describe
208 the interrupted stack (as on Solaris), and not the
209 currently executing stack (as on Linux). */
210 ucontext_t const *user_context = context;
211 char const *stack_min = user_context->uc_stack.ss_sp;
212 size_t stack_size = user_context->uc_stack.ss_size;
213 char const *faulting_address = info->si_addr;
214 size_t s = faulting_address - stack_min;
215 size_t page_size = sysconf (_SC_PAGESIZE);
216 if (find_stack_direction (0) < 0)
218 if (s < stack_size + page_size)
229 struct sigaction act;
233 /* Use the midpoint to avoid Irix sigaltstack bug. */
234 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
235 st.ss_size = SIGSTKSZ;
236 r = sigaltstack (&st, 0);
240 sigemptyset (&act.sa_mask);
241 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
242 act.sa_sigaction = segv_handler;
243 return sigaction (SIGSEGV, &act, 0);
251 return *p + recurse (array);
257 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
258 /* Before starting the endless recursion, try to be friendly
259 to the user's machine. On some Linux 2.2.x systems, there
260 is no stack limit for user processes at all. We don't want
261 to kill such systems. */
263 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
264 setrlimit (RLIMIT_STACK, &rl);
267 return c_stack_action () || recurse ("\1");
270 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
271 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
272 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
274 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
275 AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1,
276 [Define to 1 if extending the stack slightly past the limit causes
277 a SIGSEGV, and an alternate stack can be established with sigaltstack,
278 and the signal handler is passed a context that specifies the
279 run time stack. This behavior is defined by POSIX 1003.1-2001
280 with the X/Open System Interface (XSI) option
281 and is a standardized way to implement a SEGV-based stack
282 overflow detection heuristic.])
287 AC_DEFUN([gl_PREREQ_C_STACK],
288 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
289 AC_REQUIRE([gl_LIBSIGSEGV])
291 # for STACK_DIRECTION
292 AC_REQUIRE([AC_FUNC_ALLOCA])
294 AC_CHECK_FUNCS_ONCE([sigaltstack])
295 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
297 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
299 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
301 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
302 if test "$gl_cv_lib_sigsegv" = yes \
303 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
304 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
305 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
309 AC_DEFUN([gl_C_STACK],
311 dnl Prerequisites of lib/c-stack.c.