/* Test the dispatcher. Copyright (C) 2002-2003 Bruno Haible 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. */ #include "sigsegv.h" #include #if HAVE_SIGSEGV_RECOVERY #include "mmaputil.h" #include static sigsegv_dispatcher dispatcher; static unsigned int logcount = 0; static unsigned long logdata[10]; static int area_handler (void *fault_address, void *user_arg) { unsigned long area = *(unsigned long *)user_arg; logdata[logcount++] = area; if (logcount >= sizeof (logdata) / sizeof (logdata[0])) abort (); if (!((unsigned long)fault_address >= area && (unsigned long)fault_address - area < 0x4000)) abort (); if (mprotect ((void *) area, 0x4000, PROT_READ_WRITE) == 0) return 1; return 0; } static int handler (void *fault_address, int serious) { return sigsegv_dispatch (&dispatcher, fault_address); } static void barrier () { } int main () { void *p; unsigned long area1; unsigned long area2; unsigned long area3; /* Preparations. */ #if !HAVE_MMAP_ANON && !HAVE_MMAP_ANONYMOUS && HAVE_MMAP_DEVZERO zero_fd = open ("/dev/zero", O_RDONLY, 0644); #endif sigsegv_init (&dispatcher); sigsegv_install_handler (&handler); /* Setup some mmaped memory. */ p = mmap_zeromap ((void *) 0x12340000, 0x4000); if (p == (void *)(-1)) { fprintf (stderr, "mmap_zeromap failed.\n"); exit (2); } area1 = (unsigned long) p; sigsegv_register (&dispatcher, (void *) area1, 0x4000, &area_handler, &area1); mprotect ((void *) area1, 0x4000, PROT_NONE); p = mmap_zeromap ((void *) 0x0BEE0000, 0x4000); if (p == (void *)(-1)) { fprintf (stderr, "mmap_zeromap failed.\n"); exit (2); } area2 = (unsigned long) p; sigsegv_register (&dispatcher, (void *) area2, 0x4000, &area_handler, &area2); mprotect ((void *) area2, 0x4000, PROT_READ); p = mmap_zeromap ((void *) 0x06990000, 0x4000); if (p == (void *)(-1)) { fprintf (stderr, "mmap_zeromap failed.\n"); exit (2); } area3 = (unsigned long) p; sigsegv_register (&dispatcher, (void *) area3, 0x4000, &area_handler, &area3); mprotect ((void *) area3, 0x4000, PROT_READ); /* This access should call the handler. */ ((int*)area2)[230] = 22; /* This access should call the handler. */ ((int*)area3)[412] = 33; /* This access should not give a signal. */ ((int*)area2)[135] = 22; /* This access should call the handler. */ ((int*)area1)[612] = 11; barrier(); /* Check that the handler was called three times. */ if (logcount != 3) exit (1); if (!(logdata[0] == area2 && logdata[1] == area3 && logdata[2] == area1)) exit (1); printf ("Test passed.\n"); return 0; } #else int main () { return 77; } #endif