faultstatus.c revision e739ac0589b4fb43561f801c4faba8c1b89f8680
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
13struct test {
14	void (*test)(void);
15	int sig;
16	int code;
17	volatile void *addr;
18};
19
20static const struct test *cur_test;
21
22
23
24static jmp_buf escape;
25
26#define BADADDR	((int *)0x1234)
27
28#define FILESIZE	(16*1024)
29#define MAPSIZE		(2*FILESIZE)
30
31static char volatile *volatile mapping;
32
33static 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
42static 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
51static 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
61static 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
77extern char test1_ill;
78static void test1()
79{
80	asm volatile(VG_SYM(test1_ill) ": ud2");
81}
82
83static void test2()
84{
85	asm volatile ("int3");
86}
87
88static void test3()
89{
90	asm volatile ("int $0x10");
91}
92
93static 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
101static void test5()
102{
103	static int limit[2] = { 0, 10 };
104
105	asm volatile ("bound %0, %1" : : "r" (11), "m" (limit[0]));
106}
107
108int 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