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