1 # fault.m4 serial 6 (libsigsegv-2.10)
2 dnl Copyright (C) 2002-2003, 2011 Bruno Haible <bruno@clisp.org>
3 dnl This file is free software, distributed under the terms of the GNU
4 dnl General Public License. As a special exception to the GNU General
5 dnl Public License, this file may be distributed as part of a program
6 dnl that contains a configuration script generated by Autoconf, under
7 dnl the same distribution terms as the rest of that program.
9 dnl How to write a SIGSEGV handler with access to the fault address.
10 dnl SV_TRY_FAULT(KIND, CACHESYMBOL, KNOWN-SYSTEMS,
11 dnl INCLUDES, FAULT_HANDLER_ARGLIST, FAULT_ADDRESS, [INSTALLCODE])
12 AC_DEFUN([SV_TRY_FAULT], [
13 AC_REQUIRE([AC_PROG_CC])
14 AC_REQUIRE([AC_CANONICAL_HOST])
16 AC_CACHE_CHECK([whether a fault handler according to $1 works], [$2], [
22 # include <sys/signal.h>
25 #include <sys/types.h>
38 # define map_flags MAP_ANON | MAP_PRIVATE
39 #elif HAVE_MMAP_ANONYMOUS
41 # define map_flags MAP_ANONYMOUS | MAP_PRIVATE
42 #elif HAVE_MMAP_DEVZERO
44 # define map_flags MAP_FILE | MAP_PRIVATE
46 #if defined __linux__ && (defined __s390__ || defined __s390x__)
47 # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (0x1000UL - 1)
49 # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0UL
52 int handler_called = 0;
53 void sigsegv_handler ($5)
55 void *fault_address = (void *) ($6);
57 if (handler_called == 10)
60 != (void*)((page + 0x678) & ~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
62 if (mprotect ((void *) page, 0x10000, PROT_READ | PROT_WRITE) < 0)
65 void crasher (unsigned long p)
67 *(int *) (p + 0x678) = 42;
72 struct sigaction action;
74 #if !HAVE_MMAP_ANON && !HAVE_MMAP_ANONYMOUS && HAVE_MMAP_DEVZERO
75 zero_fd = open ("/dev/zero", O_RDONLY, 0644);
77 /* Setup some mmaped memory. */
79 /* HP-UX 10 mmap() often fails when given a hint. So give the OS complete
80 freedom about the address range. */
81 p = mmap ((void *) 0, 0x10000, PROT_READ | PROT_WRITE, map_flags, zero_fd, 0);
83 p = mmap ((void *) 0x12340000, 0x10000, PROT_READ | PROT_WRITE, map_flags, zero_fd, 0);
85 if (p == (void *)(-1))
87 page = (unsigned long) p;
88 /* Make it read-only. */
89 if (mprotect ((void *) page, 0x10000, PROT_READ) < 0)
91 /* Install the SIGSEGV handler. */
92 sigemptyset(&action.sa_mask);
94 action.sa_handler = (void (*) (int)) &sigsegv_handler;
97 sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
98 sigaction (SIGBUS, &action, (struct sigaction *) NULL);
99 /* The first write access should invoke the handler and then complete. */
101 /* The second write access should not invoke the handler. */
103 /* Check that the handler was called only once. */
104 if (handler_called != 1)
112 m4_if([$3], [], [], [[$3]) $2=yes ;;])
118 void sigsegv_handler ($5)
120 void *fault_address = (void *) ($6);
123 [[struct sigaction action;