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                     "addi $a0, $t0, 0x7fff\n\t"
64                      : : : "t0", "a0", "cc", "memory");
65 }
66 
test3(void)67 static void test3(void)
68 {
69    __asm__ volatile("li $t0, 0xffff0000\n\t"
70                     "li $t1, 0x7fffffff\n\t"
71                     "sub $a0, $t0, $t1\n\t"
72                      : : : "t0", "t1", "a0", "cc", "memory");
73 }
74 
main()75 int main()
76 {
77    int i;
78    static const int sigs[] = { SIGFPE };
79    struct sigaction sa;
80    sa.sa_sigaction = handler;
81    sa.sa_flags = SA_SIGINFO;
82    sigfillset(&sa.sa_mask);
83 
84    for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
85       sigaction(sigs[i], &sa, NULL);
86 
87    const struct test tests[] = {
88 #define T(n, sig, code) { test##n, sig, code }
89       T(1, SIGFPE, FPE_INTOVF),
90       T(2, SIGFPE, FPE_INTOVF),
91       T(3, SIGFPE, FPE_INTOVF),
92 #undef T
93    };
94 
95    for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
96       curr_test = &tests[i];
97       if (sigsetjmp(escape, 1) == 0) {
98          fprintf(stderr, "Test %d: ", i+1);
99          tests[i].test();
100          fprintf(stderr, "  FAIL: no fault, or handler returned\n");
101       }
102    }
103    return 0;
104 }
105