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[SIGSTKSZ];
39 } alternate_signal_stack;
42 segv_handler (int signo)
55 st.ss_sp = alternate_signal_stack.buffer;
56 st.ss_size = sizeof alternate_signal_stack.buffer;
57 r = sigaltstack (&st, 0);
61 sigemptyset (&act.sa_mask);
62 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
63 act.sa_handler = segv_handler;
64 return sigaction (SIGSEGV, &act, 0);
72 return *p + recurse (array);
78 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
79 /* Before starting the endless recursion, try to be friendly
80 to the user's machine. On some Linux 2.2.x systems, there
81 is no stack limit for user processes at all. We don't want
82 to kill such systems. */
84 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
85 setrlimit (RLIMIT_STACK, &rl);
88 return c_stack_action () || recurse ("\1");
91 [ac_cv_sys_stack_overflow_works=yes],
92 [ac_cv_sys_stack_overflow_works=no],
93 [ac_cv_sys_stack_overflow_works=cross-compiling])])
95 if test $ac_cv_sys_stack_overflow_works = yes; then
96 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
97 [Define to 1 if extending the stack slightly past the limit causes
98 a SIGSEGV which can be handled on an alternate stack established
101 AC_CACHE_CHECK([for precise C stack overflow detection],
102 ac_cv_sys_xsi_stack_overflow_heuristic,
108 # include <ucontext.h>
111 # include <sys/types.h>
112 # include <sys/time.h>
113 # include <sys/resource.h>
116 # define SIGSTKSZ 16384
121 char buffer[SIGSTKSZ];
125 } alternate_signal_stack;
128 # define find_stack_direction(ptr) STACK_DIRECTION
131 find_stack_direction (char const *addr)
134 return (! addr ? find_stack_direction (&dummy)
135 : addr < &dummy ? 1 : -1);
140 segv_handler (int signo, siginfo_t *info, void *context)
142 if (0 < info->si_code)
144 /* For XSI heuristics to work, we need uc_stack to describe
145 the interrupted stack (as on Solaris), and not the
146 currently executing stack (as on Linux). */
147 ucontext_t const *user_context = context;
148 char const *stack_min = user_context->uc_stack.ss_sp;
149 size_t stack_size = user_context->uc_stack.ss_size;
150 char const *faulting_address = info->si_addr;
151 size_t s = faulting_address - stack_min;
152 size_t page_size = sysconf (_SC_PAGESIZE);
153 if (find_stack_direction (0) < 0)
155 if (s < stack_size + page_size)
166 struct sigaction act;
170 st.ss_sp = alternate_signal_stack.buffer;
171 st.ss_size = sizeof alternate_signal_stack.buffer;
172 r = sigaltstack (&st, 0);
176 sigemptyset (&act.sa_mask);
177 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
178 act.sa_sigaction = segv_handler;
179 return sigaction (SIGSEGV, &act, 0);
187 return *p + recurse (array);
193 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
194 /* Before starting the endless recursion, try to be friendly
195 to the user's machine. On some Linux 2.2.x systems, there
196 is no stack limit for user processes at all. We don't want
197 to kill such systems. */
199 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
200 setrlimit (RLIMIT_STACK, &rl);
203 return c_stack_action () || recurse ("\1");
206 [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
207 [ac_cv_sys_xsi_stack_overflow_heuristic=no],
208 [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
210 if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
211 AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1,
212 [Define to 1 if extending the stack slightly past the limit causes
213 a SIGSEGV, and an alternate stack can be established with sigaltstack,
214 and the signal handler is passed a context that specifies the
215 run time stack. This behavior is defined by POSIX 1003.1-2001
216 with the X/Open System Interface (XSI) option
217 and is a standardized way to implement a SEGV-based stack
218 overflow detection heuristic.])
223 AC_DEFUN([gl_PREREQ_C_STACK],
224 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
225 AC_REQUIRE([gl_LIBSIGSEGV])
227 # for STACK_DIRECTION
228 AC_REQUIRE([AC_FUNC_ALLOCA])
230 AC_CHECK_FUNCS_ONCE([sigaltstack])
231 AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
233 AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
235 AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
237 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
238 if test "$gl_cv_lib_sigsegv" = yes \
239 && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
240 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
241 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
245 AC_DEFUN([gl_C_STACK],
247 dnl Prerequisites of lib/c-stack.c.