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