2 Check that a fault signal handler gets the expected info
9 #include "tests/sys_mman.h"
12 /* Division by zero triggers a SIGFPE on x86 and x86_64,
13 but not on the PowerPC architecture.
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
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
28 # define DIVISION_BY_ZERO_TRIGGERS_FPE 1
29 # define DIVISION_BY_ZERO_SI_CODE FPE_INTDIV
40 static const struct test *cur_test;
44 static jmp_buf escape;
46 #define BADADDR ((int *)0x1234)
48 #define FILESIZE (16*1024)
49 #define MAPSIZE (2*FILESIZE)
51 static char volatile *volatile mapping;
53 static int testsig(int sig, int want)
56 fprintf(stderr, " FAIL: expected signal %d, not %d\n", want, sig);
62 static int testcode(int code, int want)
65 fprintf(stderr, " FAIL: expected si_code==%d, not %d\n", want, code);
71 static int testaddr(void *addr, volatile void *want)
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 */
76 if (addr != (void *) ((unsigned long) want & ~0xffful)) {
80 fprintf(stderr, " FAIL: expected si_addr==%p, not %p\n", want, addr);
87 static void handler(int sig, siginfo_t *si, void *uc)
91 ok = ok && testsig(sig, cur_test->sig);
92 ok = ok && testcode(si->si_code, cur_test->code);
94 ok = ok && testaddr(si->si_addr, cur_test->addr);
97 fprintf(stderr, " PASS\n");
99 siglongjmp(escape, ok + 1);
103 static void test1(void)
115 mapping[FILESIZE+10];
120 volatile int v = 44/zero();
123 #if DIVISION_BY_ZERO_TRIGGERS_FPE == 0
131 static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP };
134 sa.sa_sigaction = handler;
135 sa.sa_flags = SA_SIGINFO;
136 sigfillset(&sa.sa_mask);
138 for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
139 sigaction(sigs[i], &sa, NULL);
141 /* we need O_RDWR for the truncate below */
142 fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600);
147 unlink("faultstatus.tmp");
148 ftruncate(fd, FILESIZE);
150 mapping = mmap(0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0);
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),
163 for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
164 cur_test = &tests[i];
166 if (sigsetjmp(escape, 1) == 0) {
167 fprintf(stderr, "Test %d: ", i+1);
169 fprintf(stderr, " FAIL: no fault, or handler returned\n");