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