]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/none/tests/faultstatus.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / none / tests / faultstatus.c
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 /* Division by zero triggers a SIGFPE on x86 and x86_64,
13    but not on the PowerPC architecture.
14
15    On ARM-Linux, we do get a SIGFPE, but not from the faulting of a
16    division instruction (there isn't any such thing) but rather
17    because the process exits via tgkill, sending itself a SIGFPE.
18    Hence we get a SIGFPE but the SI_CODE is different from that on
19    x86/amd64-linux.
20  */
21 #if defined(__powerpc__)
22 #  define DIVISION_BY_ZERO_TRIGGERS_FPE 0
23 #  define DIVISION_BY_ZERO_SI_CODE      SI_TKILL
24 #elif defined(__arm__)
25 #  define DIVISION_BY_ZERO_TRIGGERS_FPE 1
26 #  define DIVISION_BY_ZERO_SI_CODE      SI_TKILL
27 #else
28 #  define DIVISION_BY_ZERO_TRIGGERS_FPE 1
29 #  define DIVISION_BY_ZERO_SI_CODE      FPE_INTDIV
30 #endif
31
32
33 struct test {
34         void (*test)(void);
35         int sig;
36         int code;
37         volatile void *addr;
38 };
39
40 static const struct test *cur_test;
41
42 static int zero();
43
44 static jmp_buf escape;
45
46 #define BADADDR ((int *)0x1234)
47
48 #define FILESIZE        (16*1024)
49 #define MAPSIZE         (2*FILESIZE)
50
51 static char volatile *volatile mapping;
52
53 static int testsig(int sig, int want)
54 {
55         if (sig != want) {
56                 fprintf(stderr, "  FAIL: expected signal %d, not %d\n", want, sig);
57                 return 0;
58         } 
59         return 1;
60 }
61
62 static int testcode(int code, int want)
63 {
64         if (code != want) {
65                 fprintf(stderr, "  FAIL: expected si_code==%d, not %d\n", want, code);
66                 return 0;
67         }
68         return 1;
69 }
70
71 static int testaddr(void *addr, volatile void *want)
72 {
73         /* Some architectures (e.g. s390) just provide enough information to
74          resolve the page fault, but do not provide the offset within a page */
75 #if defined(__s390__)
76         if (addr != (void *) ((unsigned long) want & ~0xffful)) {
77 #else
78         if (addr != want) {
79 #endif
80                 fprintf(stderr, "  FAIL: expected si_addr==%p, not %p\n", want, addr);
81                 return 0;
82         }
83         return 1;
84
85 }
86
87 static void handler(int sig, siginfo_t *si, void *uc)
88 {
89         int ok = 1;
90
91         ok = ok && testsig(sig, cur_test->sig);
92         ok = ok && testcode(si->si_code, cur_test->code);
93         if (cur_test->addr)
94                 ok = ok && testaddr(si->si_addr, cur_test->addr);
95
96         if (ok)
97                 fprintf(stderr, "  PASS\n");
98
99         siglongjmp(escape, ok + 1);
100 }
101
102
103 static void test1(void)
104 {
105         *BADADDR = 'x';
106 }
107
108 static void test2()
109 {
110         mapping[0] = 'x';
111 }
112
113 static void test3()
114 {
115         mapping[FILESIZE+10];
116 }
117
118 static void test4()
119 {
120         volatile int v = 44/zero();
121
122         (void)v;
123 #if DIVISION_BY_ZERO_TRIGGERS_FPE == 0
124         raise(SIGFPE);
125 #endif
126 }
127
128 int main()
129 {
130         int fd, i;
131         static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP };
132         struct sigaction sa;
133
134         sa.sa_sigaction = handler;
135         sa.sa_flags = SA_SIGINFO;
136         sigfillset(&sa.sa_mask);
137         
138         for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
139                 sigaction(sigs[i], &sa, NULL);
140
141         /* we need O_RDWR for the truncate below */
142         fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600);
143         if (fd == -1) {
144                 perror("tmpfile");
145                 exit(1);
146         }
147         unlink("faultstatus.tmp");
148         ftruncate(fd, FILESIZE);
149
150         mapping = mmap(0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0);
151         close(fd);
152
153         {
154                 const struct test tests[] = {
155 #define T(n, sig, code, addr) { test##n, sig, code, addr }
156                         T(1, SIGSEGV,   SEGV_MAPERR,    BADADDR),
157                         T(2, SIGSEGV,   SEGV_ACCERR,    mapping),
158                         T(3, SIGBUS,    BUS_ADRERR,     &mapping[FILESIZE+10]),
159                         T(4, SIGFPE,    DIVISION_BY_ZERO_SI_CODE, 0),
160 #undef T
161                 };
162
163                 for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
164                         cur_test = &tests[i];
165                 
166                         if (sigsetjmp(escape, 1) == 0) {
167                                 fprintf(stderr, "Test %d: ", i+1);
168                                 tests[i].test();
169                                 fprintf(stderr, "  FAIL: no fault, or handler returned\n");
170                         }
171                 }
172         }
173
174         return 0;
175 }
176
177 static int zero()
178 {
179         return 0;
180 }