1/* 2 Check that a fault signal handler gets the expected info 3 */ 4#include <signal.h> 5#include <stdio.h> 6#include <stdlib.h> 7#include <fcntl.h> 8#include <setjmp.h> 9#include <unistd.h> 10#include "tests/asm.h" 11#include "tests/sys_mman.h" 12 13struct test { 14 void (*test)(void); 15 int sig; 16 int code; 17 volatile void *addr; 18}; 19 20static const struct test *cur_test; 21 22 23 24static jmp_buf escape; 25 26#define BADADDR ((int *)0x1234) 27 28#define FILESIZE (16*1024) 29#define MAPSIZE (2*FILESIZE) 30 31static char volatile *volatile mapping; 32 33static int testsig(int sig, int want) 34{ 35 if (sig != want) { 36 fprintf(stderr, " FAIL: expected signal %d, not %d\n", want, sig); 37 return 0; 38 } 39 return 1; 40} 41 42static int testcode(int code, int want) 43{ 44 if (code != want) { 45 fprintf(stderr, " FAIL: expected si_code==%d, not %d\n", want, code); 46 return 0; 47 } 48 return 1; 49} 50 51static int testaddr(void *addr, volatile void *want) 52{ 53 if (addr != want) { 54 fprintf(stderr, " FAIL: expected si_addr==%p, not %p\n", want, addr); 55 return 0; 56 } 57 return 1; 58 59} 60 61static void handler(int sig, siginfo_t *si, void *uc) 62{ 63 int ok = 1; 64 65 ok = ok && testsig(sig, cur_test->sig); 66 ok = ok && testcode(si->si_code, cur_test->code); 67 if (cur_test->addr) 68 ok = ok && testaddr(si->si_addr, cur_test->addr); 69 70 if (ok) 71 fprintf(stderr, " PASS\n"); 72 73 siglongjmp(escape, ok + 1); 74} 75 76 77extern char test1_ill; 78static void test1() 79{ 80 asm volatile(VG_SYM(test1_ill) ": ud2"); 81} 82 83static void test2() 84{ 85 asm volatile ("int3"); 86} 87 88static void test3() 89{ 90 asm volatile ("int $0x10"); 91} 92 93static void test4() 94{ 95 volatile int a; 96 asm volatile ("add $1, %0;"/* set OF */ 97 "into" 98 : "=a" (a) : "0" (0x7fffffff) : "cc"); 99} 100 101static void test5() 102{ 103 static int limit[2] = { 0, 10 }; 104 105 asm volatile ("bound %0, %1" : : "r" (11), "m" (limit[0])); 106} 107 108int main() 109{ 110 int fd, i; 111 static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP }; 112 struct sigaction sa; 113 114 sa.sa_sigaction = handler; 115 sa.sa_flags = SA_SIGINFO; 116 sigfillset(&sa.sa_mask); 117 118 for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++) 119 sigaction(sigs[i], &sa, NULL); 120 121 fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL, 0600); 122 if (fd == -1) { 123 perror("tmpfile"); 124 exit(1); 125 } 126 unlink("faultstatus.tmp"); 127 ftruncate(fd, FILESIZE); 128 129 mapping = mmap(0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0); 130 close(fd); 131 132 { 133 const struct test tests[] = { 134#define T(n, sig, code, addr) { test##n, sig, code, addr } 135 T(1, SIGILL, ILL_ILLOPN, &test1_ill), 136 137 T(2, SIGTRAP, 128, 0), /* TRAP_BRKPT? */ 138 T(3, SIGSEGV, 128, 0), 139 T(4, SIGSEGV, 128, 0), 140 141 /* This is an expected failure - Valgrind 142 doesn't implement the BOUND instruction, 143 and so issues a SIGILL instead. */ 144 T(5, SIGSEGV, 128, 0), 145#undef T 146 }; 147 148 for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) { 149 cur_test = &tests[i]; 150 151 if (sigsetjmp(escape, 1) == 0) { 152 fprintf(stderr, "Test %d: ", i+1); 153 tests[i].test(); 154 fprintf(stderr, " FAIL: no fault, or handler returned\n"); 155 } 156 } 157 } 158 159 return 0; 160} 161 162