summaryrefslogtreecommitdiff
path: root/m4/c-stack.m4
diff options
context:
space:
mode:
Diffstat (limited to 'm4/c-stack.m4')
-rw-r--r--m4/c-stack.m4136
1 files changed, 136 insertions, 0 deletions
diff --git a/m4/c-stack.m4 b/m4/c-stack.m4
new file mode 100644
index 000000000..01c9a884c
--- /dev/null
+++ b/m4/c-stack.m4
@@ -0,0 +1,136 @@
+# Check prerequisites for compiling lib/c-stack.c.
+
+# Copyright (C) 2002 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# Written by Paul Eggert.
+
+AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
+ [# for STACK_DIRECTION
+ AC_REQUIRE([AC_FUNC_ALLOCA])
+
+ AC_CACHE_CHECK([for working C stack overflow detection],
+ ac_cv_sys_xsi_stack_overflow_heuristic,
+ [AC_TRY_RUN(
+ [
+ #include <signal.h>
+ #include <ucontext.h>
+
+ static union
+ {
+ char buffer[SIGSTKSZ];
+ long double ld;
+ long u;
+ void *p;
+ } alternate_signal_stack;
+
+ #if STACK_DIRECTION
+ # define find_stack_direction(ptr) STACK_DIRECTION
+ #else
+ static int
+ find_stack_direction (char const *addr)
+ {
+ char dummy;
+ return (! addr ? find_stack_direction (&dummy)
+ : addr < &dummy ? 1 : -1);
+ }
+ #endif
+
+ static void
+ segv_handler (int signo, siginfo_t *info, void *context)
+ {
+ if (0 < info->si_code)
+ {
+ ucontext_t const *user_context = context;
+ char const *stack_min = user_context->uc_stack.ss_sp;
+ size_t stack_size = user_context->uc_stack.ss_size;
+ char const *faulting_address = info->si_addr;
+ size_t s = faulting_address - stack_min;
+ size_t page_size = sysconf (_SC_PAGESIZE);
+ if (find_stack_direction (0) < 0)
+ s += page_size;
+ if (s < stack_size + page_size)
+ _exit (0);
+ }
+
+ _exit (1);
+ }
+
+ static int
+ c_stack_action (void)
+ {
+ stack_t st;
+ struct sigaction act;
+ int r;
+
+ st.ss_flags = 0;
+ st.ss_sp = alternate_signal_stack.buffer;
+ st.ss_size = sizeof alternate_signal_stack.buffer;
+ r = sigaltstack (&st, 0);
+ if (r != 0)
+ return r;
+
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
+ act.sa_sigaction = segv_handler;
+ return sigaction (SIGSEGV, &act, 0);
+ }
+
+ static int
+ recurse (char *p)
+ {
+ char array[500];
+ array[0] = 1;
+ return *p + recurse (array);
+ }
+
+ int
+ main (void)
+ {
+ c_stack_action ();
+ return recurse ("\1");
+ }
+ ],
+ [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
+ [ac_cv_sys_xsi_stack_overflow_heuristic=no],
+ [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
+
+ if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
+ AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1,
+ [Define to 1 if extending the stack slightly past the limit causes
+ a SIGSEGV, and an alternate stack can be established with sigaltstack,
+ and the signal handler is passed a context that specifies the
+ run time stack. This behavior is defined by POSIX 1003.1-2001
+ with the X/Open System Interface (XSI) option
+ and is a standardized way to implement a SEGV-based stack
+ overflow detection heuristic.])
+ fi])
+
+
+AC_DEFUN([jm_PREREQ_C_STACK],
+ [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
+
+ # for STACK_DIRECTION
+ AC_REQUIRE([AC_FUNC_ALLOCA])
+
+ AC_CHECK_FUNCS(getcontext sigaltstack)
+ AC_CHECK_DECLS([getcontext], , , [#include <ucontext.h>])
+ AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
+
+ AC_CHECK_HEADERS(sys/resource.h ucontext.h unistd.h)
+
+ AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])])