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 13 struct test { 14 void (*test)(void); 15 int sig; 16 int code; 17 volatile void *addr; 18 }; 19 20 static const struct test *cur_test; 21 22 23 24 static jmp_buf escape; 25 26 #define BADADDR ((int *)0x1234) 27 28 #define FILESIZE (16*1024) 29 #define MAPSIZE (2*FILESIZE) 30 31 static char volatile *volatile mapping; 32 33 static 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 42 static 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 51 static 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 61 static 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 77 extern char test1_ill; 78 static void test1() 79 { 80 asm volatile(VG_SYM(test1_ill) ": ud2"); 81 } 82 83 static void test2() 84 { 85 asm volatile ("int3"); 86 } 87 88 static void test3() 89 { 90 asm volatile ("int $0x10"); 91 } 92 93 static 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 101 static void test5() 102 { 103 static int limit[2] = { 0, 10 }; 104 105 asm volatile ("bound %0, %1" : : "r" (11), "m" (limit[0])); 106 } 107 108 int 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