Home | History | Annotate | Download | only in x86
      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