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