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 
11 struct test {
12    void (*test)(void);
13    int sig;
14    int code;
15 };
16 
17 static const struct test *curr_test;
18 
19 static jmp_buf escape;
20 
testsig(int sig,int want)21 static int testsig(int sig, int want)
22 {
23    if (sig != want) {
24       fprintf(stderr, "  FAIL: expected signal %d, not %d\n", want, sig);
25       return 0;
26    }
27    return 1;
28 }
29 
testcode(int code,int want)30 static int testcode(int code, int want)
31 {
32    if (code != want) {
33       fprintf(stderr, "  FAIL: expected si_code==%d, not %d\n", want, code);
34       return 0;
35    }
36    return 1;
37 }
38 
handler(int sig,siginfo_t * si,void * uc)39 static void handler(int sig, siginfo_t *si, void *uc)
40 {
41    int ok = 1;
42 
43    ok = ok && testsig(sig, curr_test->sig);
44    ok = ok && testcode(si->si_code, curr_test->code);
45 
46    if (ok)
47       fprintf(stderr, "  PASS\n");
48 
49    siglongjmp(escape, ok + 1);
50 }
51 
test1(void)52 static void test1(void)
53 {
54    __asm__ volatile("li $t0, 0x80000000\n\t"
55                     "move $t1, $t0\n\t"
56                     "add $a0, $t0, $t1\n\t"
57                      : : : "t0", "t1", "a0", "cc", "memory");
58 }
59 
test2()60 static void test2()
61 {
62    __asm__ volatile("li $t0, 0x7fffffff\n\t"
63                     "li $a0, 0x7fff\n\t"
64                     "add $a0, $t0, $a0\n\t"
65                      : : : "t0", "a0", "cc", "memory");
66 }
67 
test3(void)68 static void test3(void)
69 {
70    __asm__ volatile("li $t0, 0xffff0000\n\t"
71                     "li $t1, 0x7fffffff\n\t"
72                     "sub $a0, $t0, $t1\n\t"
73                      : : : "t0", "t1", "a0", "cc", "memory");
74 }
75 
main()76 int main()
77 {
78    int i;
79    static const int sigs[] = { SIGFPE };
80    struct sigaction sa;
81    sa.sa_sigaction = handler;
82    sa.sa_flags = SA_SIGINFO;
83    sigfillset(&sa.sa_mask);
84 
85    for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
86       sigaction(sigs[i], &sa, NULL);
87 
88    const struct test tests[] = {
89 #define T(n, sig, code) { test##n, sig, code }
90       T(1, SIGFPE, FPE_INTOVF),
91       T(2, SIGFPE, FPE_INTOVF),
92       T(3, SIGFPE, FPE_INTOVF),
93 #undef T
94    };
95 
96    for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
97       curr_test = &tests[i];
98       if (sigsetjmp(escape, 1) == 0) {
99          fprintf(stderr, "Test %d: ", i+1);
100          tests[i].test();
101          fprintf(stderr, "  FAIL: no fault, or handler returned\n");
102       }
103    }
104    return 0;
105 }
106