blob: bc19e04b026ef87cfdd1611c82bb6346feab718b [file] [log] [blame]
/*
Check that a fault signal handler gets the expected info
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <setjmp.h>
#include <unistd.h>
struct test {
void (*test)(void);
int sig;
int code;
};
static const struct test *curr_test;
static jmp_buf escape;
static int testsig(int sig, int want)
{
if (sig != want) {
fprintf(stderr, " FAIL: expected signal %d, not %d\n", want, sig);
return 0;
}
return 1;
}
static int testcode(int code, int want)
{
if (code != want) {
fprintf(stderr, " FAIL: expected si_code==%d, not %d\n", want, code);
return 0;
}
return 1;
}
static void handler(int sig, siginfo_t *si, void *uc)
{
int ok = 1;
ok = ok && testsig(sig, curr_test->sig);
ok = ok && testcode(si->si_code, curr_test->code);
if (ok)
fprintf(stderr, " PASS\n");
siglongjmp(escape, ok + 1);
}
static void test1(void)
{
__asm__ volatile("li $t0, 0x80000000\n\t"
"move $t1, $t0\n\t"
"add $a0, $t0, $t1\n\t"
: : : "t0", "t1", "a0", "cc", "memory");
}
static void test2()
{
__asm__ volatile("li $t0, 0x7fffffff\n\t"
"addi $a0, $t0, 0x7fff\n\t"
: : : "t0", "a0", "cc", "memory");
}
static void test3(void)
{
__asm__ volatile("li $t0, 0xffff0000\n\t"
"li $t1, 0x7fffffff\n\t"
"sub $a0, $t0, $t1\n\t"
: : : "t0", "t1", "a0", "cc", "memory");
}
int main()
{
int i;
static const int sigs[] = { SIGFPE };
struct sigaction sa;
sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO;
sigfillset(&sa.sa_mask);
for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
sigaction(sigs[i], &sa, NULL);
const struct test tests[] = {
#define T(n, sig, code) { test##n, sig, code }
T(1, SIGFPE, FPE_INTOVF),
T(2, SIGFPE, FPE_INTOVF),
T(3, SIGFPE, FPE_INTOVF),
#undef T
};
for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
curr_test = &tests[i];
if (sigsetjmp(escape, 1) == 0) {
fprintf(stderr, "Test %d: ", i+1);
tests[i].test();
fprintf(stderr, " FAIL: no fault, or handler returned\n");
}
}
return 0;
}