Support for Linux/S390.
[libsigsegv/ericb.git] / m4 / fault.m4
blob2a2d72b0b08014d8dd6bc45288961e8f847cc215
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], [
17     AC_RUN_IFELSE([
18       AC_LANG_SOURCE([[
19 #include <stdlib.h>
20 #include <signal.h>
21 #if HAVE_SYS_SIGNAL_H
22 # include <sys/signal.h>
23 #endif
25 #include <sys/types.h>
26 #include <sys/mman.h>
27 #if HAVE_MMAP_DEVZERO
28 # include <fcntl.h>
29 # ifndef MAP_FILE
30 #  define MAP_FILE 0
31 # endif
32 #endif
33 #ifndef PROT_NONE
34 # define PROT_NONE 0
35 #endif
36 #if HAVE_MMAP_ANON
37 # define zero_fd -1
38 # define map_flags MAP_ANON | MAP_PRIVATE
39 #elif HAVE_MMAP_ANONYMOUS
40 # define zero_fd -1
41 # define map_flags MAP_ANONYMOUS | MAP_PRIVATE
42 #elif HAVE_MMAP_DEVZERO
43 static int zero_fd;
44 # define map_flags MAP_FILE | MAP_PRIVATE
45 #endif
46 #if defined __linux__ && (defined __s390__ || defined __s390x__)
47 # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (0x1000UL - 1)
48 #else
49 # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0UL
50 #endif
51 unsigned long page;
52 int handler_called = 0;
53 void sigsegv_handler ($5)
55   void *fault_address = (void *) ($6);
56   handler_called++;
57   if (handler_called == 10)
58     exit (4);
59   if (fault_address
60       != (void*)((page + 0x678) & ~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
61     exit (3);
62   if (mprotect ((void *) page, 0x10000, PROT_READ | PROT_WRITE) < 0)
63     exit (2);
65 void crasher (unsigned long p)
67   *(int *) (p + 0x678) = 42;
69 int main ()
71   void *p;
72   struct sigaction action;
73   /* Preparations.  */
74 #if !HAVE_MMAP_ANON && !HAVE_MMAP_ANONYMOUS && HAVE_MMAP_DEVZERO
75   zero_fd = open ("/dev/zero", O_RDONLY, 0644);
76 #endif
77   /* Setup some mmaped memory.  */
78 #ifdef __hpux
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);
82 #else
83   p = mmap ((void *) 0x12340000, 0x10000, PROT_READ | PROT_WRITE, map_flags, zero_fd, 0);
84 #endif
85   if (p == (void *)(-1))
86     exit (2);
87   page = (unsigned long) p;
88   /* Make it read-only.  */
89   if (mprotect ((void *) page, 0x10000, PROT_READ) < 0)
90     exit (2);
91   /* Install the SIGSEGV handler.  */
92   sigemptyset(&action.sa_mask);
93 ]m4_if([$7], [], [
94   action.sa_handler = (void (*) (int)) &sigsegv_handler;
95   action.sa_flags = 0;
96 ], [$7])[
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.  */
100   crasher (page);
101   /* The second write access should not invoke the handler.  */
102   crasher (page);
103   /* Check that the handler was called only once.  */
104   if (handler_called != 1)
105     exit (1);
106   /* Test passed!  */
107   return 0;
108 }]])],
109       [$2=yes],
110       [$2=no],
111       [case "$host" in
112          m4_if([$3], [], [], [[$3]) $2=yes ;;])
113          *)
114            AC_LINK_IFELSE([
115              AC_LANG_PROGRAM([[
116 #include <signal.h>
118 void sigsegv_handler ($5)
120   void *fault_address = (void *) ($6);
123                [[struct sigaction action;
124 $7]])],
125              [$2="guessing no"],
126              [$2=no])
127            ;;
128        esac
129       ])
130   ])