root/maint/gnulib/tests/test-sigsegv-catch-segv1.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. handler
  2. crasher
  3. main
  4. main

   1 /* Test that the handler is called, with the right fault address.
   2    Copyright (C) 2002-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 2 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Bruno Haible.  */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include "sigsegv.h"
  23 
  24 #include <stdint.h>
  25 #include <stdio.h>
  26 
  27 #if HAVE_SIGSEGV_RECOVERY
  28 
  29 # include "mmap-anon-util.h"
  30 # include <stdlib.h>
  31 
  32 # if SIGSEGV_FAULT_ADDRESS_ALIGNMENT > 1UL
  33 #  include <unistd.h>
  34 #  define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (getpagesize () - 1)
  35 # else
  36 #  define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0
  37 # endif
  38 
  39 uintptr_t page;
  40 
  41 volatile int handler_called = 0;
  42 
  43 static int
  44 handler (void *fault_address, int serious)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46   handler_called++;
  47   if (handler_called > 10)
  48     abort ();
  49   if (fault_address
  50       != (void *)((page + 0x678) & ~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
  51     abort ();
  52   if (mprotect ((void *) page, 0x4000, PROT_READ_WRITE) == 0)
  53     return 1;
  54   return 0;
  55 }
  56 
  57 static void
  58 crasher (uintptr_t p)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60   *(volatile int *) (p + 0x678) = 42;
  61 }
  62 
  63 int
  64 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66   int prot_unwritable;
  67   void *p;
  68 
  69   /* Preparations.  */
  70 # if !HAVE_MAP_ANONYMOUS
  71   zero_fd = open ("/dev/zero", O_RDONLY, 0644);
  72 # endif
  73 
  74 # if defined __linux__ && defined __sparc__
  75   /* On Linux 2.6.26/SPARC64, PROT_READ has the same effect as
  76      PROT_READ | PROT_WRITE.  */
  77   prot_unwritable = PROT_NONE;
  78 # else
  79   prot_unwritable = PROT_READ;
  80 # endif
  81 
  82   /* Setup some mmaped memory.  */
  83   p = mmap_zeromap ((void *) 0x12340000, 0x4000);
  84   if (p == (void *)(-1))
  85     {
  86       fprintf (stderr, "mmap_zeromap failed.\n");
  87       exit (2);
  88     }
  89   page = (uintptr_t) p;
  90 
  91   /* Make it read-only.  */
  92   if (mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
  93     {
  94       fprintf (stderr, "mprotect failed.\n");
  95       exit (2);
  96     }
  97   /* Test whether it's possible to make it read-write after it was read-only.
  98      This is not possible on Cygwin.  */
  99   if (mprotect ((void *) page, 0x4000, PROT_READ_WRITE) < 0
 100       || mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
 101     {
 102       fprintf (stderr, "mprotect failed.\n");
 103       exit (2);
 104     }
 105 
 106   /* Install the SIGSEGV handler.  */
 107   sigsegv_install_handler (&handler);
 108 
 109   /* The first write access should invoke the handler and then complete.  */
 110   crasher (page);
 111   /* The second write access should not invoke the handler.  */
 112   crasher (page);
 113 
 114   /* Check that the handler was called only once.  */
 115   if (handler_called != 1)
 116     exit (1);
 117   /* Test passed!  */
 118   printf ("Test passed.\n");
 119   return 0;
 120 }
 121 
 122 #else
 123 
 124 int
 125 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127   return 77;
 128 }
 129 
 130 #endif

/* [previous][next][first][last][top][bottom][index][help] */