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
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 jmp_buf escape;
22
23#define BADADDR	((int *)0x1234)
24
25#define FILESIZE	(16*1024)
26#define MAPSIZE		(2*FILESIZE)
27
28static char volatile *volatile mapping;
29
30static 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
39static 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
48static 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
58static 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
74extern char test1_ill;
75static void test1()
76{
77	asm volatile("test1_ill: ud2");
78}
79
80static void test2()
81{
82	asm volatile ("int3");
83}
84
85static void test3()
86{
87	asm volatile ("int $0x10");
88}
89
90int 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