1*640235e2SEnji Cooper /* $NetBSD: t_siginfo.c,v 1.30 2015/12/22 14:25:58 christos Exp $ */
257718be8SEnji Cooper
357718be8SEnji Cooper /*-
457718be8SEnji Cooper * Copyright (c) 2010 The NetBSD Foundation, Inc.
557718be8SEnji Cooper * All rights reserved.
657718be8SEnji Cooper *
757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper * modification, are permitted provided that the following conditions
957718be8SEnji Cooper * are met:
1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer.
1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution.
1557718be8SEnji Cooper *
1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1757718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1857718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1957718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2057718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2157718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2257718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2357718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2457718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2557718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2657718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
2757718be8SEnji Cooper */
2857718be8SEnji Cooper
2957718be8SEnji Cooper #include <atf-c.h>
3057718be8SEnji Cooper
31ff0ba872SEnji Cooper #ifdef __NetBSD__
3257718be8SEnji Cooper #include <sys/inttypes.h>
33192a7b5fSEnji Cooper #endif
3457718be8SEnji Cooper #include <sys/resource.h>
3557718be8SEnji Cooper #include <sys/sysctl.h>
3657718be8SEnji Cooper #include <sys/time.h>
3757718be8SEnji Cooper #include <sys/ucontext.h>
3857718be8SEnji Cooper #include <sys/wait.h>
3957718be8SEnji Cooper
4057718be8SEnji Cooper #include <assert.h>
4157718be8SEnji Cooper #include <signal.h>
4257718be8SEnji Cooper #include <stdio.h>
4357718be8SEnji Cooper #include <stdlib.h>
4457718be8SEnji Cooper #include <string.h>
4557718be8SEnji Cooper #include <unistd.h>
4657718be8SEnji Cooper #include <setjmp.h>
4757718be8SEnji Cooper #include <float.h>
4857718be8SEnji Cooper
4957718be8SEnji Cooper #include <fenv.h>
50*640235e2SEnji Cooper #ifdef __HAVE_FENV
51*640235e2SEnji Cooper #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
5257718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
5357718be8SEnji Cooper #include <ieeefp.h>
5457718be8SEnji Cooper #endif
5557718be8SEnji Cooper
5657718be8SEnji Cooper #include "isqemu.h"
5757718be8SEnji Cooper
5857718be8SEnji Cooper /* for sigbus */
5957718be8SEnji Cooper volatile char *addr;
6057718be8SEnji Cooper
6157718be8SEnji Cooper /* for sigchild */
6257718be8SEnji Cooper pid_t child;
6357718be8SEnji Cooper int code;
6457718be8SEnji Cooper int status;
6557718be8SEnji Cooper
6657718be8SEnji Cooper /* for sigfpe */
6757718be8SEnji Cooper sig_atomic_t fltdiv_signalled = 0;
6857718be8SEnji Cooper sig_atomic_t intdiv_signalled = 0;
6957718be8SEnji Cooper
7057718be8SEnji Cooper static void
sig_debug(int signo,siginfo_t * info,ucontext_t * ctx)7157718be8SEnji Cooper sig_debug(int signo, siginfo_t *info, ucontext_t *ctx)
7257718be8SEnji Cooper {
7357718be8SEnji Cooper unsigned int i;
7457718be8SEnji Cooper
7557718be8SEnji Cooper printf("%d %p %p\n", signo, info, ctx);
7657718be8SEnji Cooper if (info != NULL) {
7757718be8SEnji Cooper printf("si_signo=%d\n", info->si_signo);
7857718be8SEnji Cooper printf("si_errno=%d\n", info->si_errno);
7957718be8SEnji Cooper printf("si_code=%d\n", info->si_code);
8057718be8SEnji Cooper printf("si_value.sival_int=%d\n", info->si_value.sival_int);
8157718be8SEnji Cooper }
8257718be8SEnji Cooper if (ctx != NULL) {
8357718be8SEnji Cooper printf("uc_flags 0x%x\n", ctx->uc_flags);
8457718be8SEnji Cooper printf("uc_link %p\n", ctx->uc_link);
8557718be8SEnji Cooper for (i = 0; i < __arraycount(ctx->uc_sigmask.__bits); i++)
8657718be8SEnji Cooper printf("uc_sigmask[%d] 0x%x\n", i,
8757718be8SEnji Cooper ctx->uc_sigmask.__bits[i]);
8857718be8SEnji Cooper printf("uc_stack %p %lu 0x%x\n", ctx->uc_stack.ss_sp,
8957718be8SEnji Cooper (unsigned long)ctx->uc_stack.ss_size,
9057718be8SEnji Cooper ctx->uc_stack.ss_flags);
91ff0ba872SEnji Cooper #ifdef __NetBSD__
9257718be8SEnji Cooper for (i = 0; i < __arraycount(ctx->uc_mcontext.__gregs); i++)
9357718be8SEnji Cooper printf("uc_mcontext.greg[%d] 0x%lx\n", i,
9457718be8SEnji Cooper (long)ctx->uc_mcontext.__gregs[i]);
95192a7b5fSEnji Cooper #endif
9657718be8SEnji Cooper }
9757718be8SEnji Cooper }
9857718be8SEnji Cooper
9957718be8SEnji Cooper static void
sigalrm_action(int signo,siginfo_t * info,void * ptr)10057718be8SEnji Cooper sigalrm_action(int signo, siginfo_t *info, void *ptr)
10157718be8SEnji Cooper {
10257718be8SEnji Cooper
10357718be8SEnji Cooper sig_debug(signo, info, (ucontext_t *)ptr);
10457718be8SEnji Cooper
10557718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGALRM);
10657718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, SI_TIMER);
10757718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_value.sival_int, ITIMER_REAL);
10857718be8SEnji Cooper
10957718be8SEnji Cooper atf_tc_pass();
11057718be8SEnji Cooper /* NOTREACHED */
11157718be8SEnji Cooper }
11257718be8SEnji Cooper
11357718be8SEnji Cooper ATF_TC(sigalarm);
11457718be8SEnji Cooper
ATF_TC_HEAD(sigalarm,tc)11557718be8SEnji Cooper ATF_TC_HEAD(sigalarm, tc)
11657718be8SEnji Cooper {
11757718be8SEnji Cooper
11857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
11957718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGALRM handler");
12057718be8SEnji Cooper }
12157718be8SEnji Cooper
ATF_TC_BODY(sigalarm,tc)12257718be8SEnji Cooper ATF_TC_BODY(sigalarm, tc)
12357718be8SEnji Cooper {
12457718be8SEnji Cooper struct sigaction sa;
12557718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
12657718be8SEnji Cooper sa.sa_sigaction = sigalrm_action;
12757718be8SEnji Cooper sigemptyset(&sa.sa_mask);
12857718be8SEnji Cooper sigaction(SIGALRM, &sa, NULL);
12957718be8SEnji Cooper for (;;) {
13057718be8SEnji Cooper alarm(1);
13157718be8SEnji Cooper sleep(1);
13257718be8SEnji Cooper }
13357718be8SEnji Cooper atf_tc_fail("SIGALRM handler wasn't called");
13457718be8SEnji Cooper }
13557718be8SEnji Cooper
13657718be8SEnji Cooper static void
sigchild_action(int signo,siginfo_t * info,void * ptr)13757718be8SEnji Cooper sigchild_action(int signo, siginfo_t *info, void *ptr)
13857718be8SEnji Cooper {
13957718be8SEnji Cooper if (info != NULL) {
14057718be8SEnji Cooper printf("info=%p\n", info);
14157718be8SEnji Cooper printf("ptr=%p\n", ptr);
14257718be8SEnji Cooper printf("si_signo=%d\n", info->si_signo);
14357718be8SEnji Cooper printf("si_errno=%d\n", info->si_errno);
14457718be8SEnji Cooper printf("si_code=%d\n", info->si_code);
14557718be8SEnji Cooper printf("si_uid=%d\n", info->si_uid);
14657718be8SEnji Cooper printf("si_pid=%d\n", info->si_pid);
14757718be8SEnji Cooper printf("si_status=%d\n", info->si_status);
148ff0ba872SEnji Cooper #ifdef __NetBSD__
14957718be8SEnji Cooper printf("si_utime=%lu\n", (unsigned long int)info->si_utime);
15057718be8SEnji Cooper printf("si_stime=%lu\n", (unsigned long int)info->si_stime);
151192a7b5fSEnji Cooper #endif
15257718be8SEnji Cooper }
15357718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, code);
15457718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGCHLD);
15557718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_uid, getuid());
15657718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_pid, child);
15757718be8SEnji Cooper if (WIFEXITED(info->si_status))
15857718be8SEnji Cooper ATF_REQUIRE_EQ(WEXITSTATUS(info->si_status), status);
15957718be8SEnji Cooper else if (WIFSTOPPED(info->si_status))
16057718be8SEnji Cooper ATF_REQUIRE_EQ(WSTOPSIG(info->si_status), status);
16157718be8SEnji Cooper else if (WIFSIGNALED(info->si_status))
16257718be8SEnji Cooper ATF_REQUIRE_EQ(WTERMSIG(info->si_status), status);
16357718be8SEnji Cooper }
16457718be8SEnji Cooper
16557718be8SEnji Cooper static void
setchildhandler(void (* action)(int,siginfo_t *,void *))16657718be8SEnji Cooper setchildhandler(void (*action)(int, siginfo_t *, void *))
16757718be8SEnji Cooper {
16857718be8SEnji Cooper struct sigaction sa;
16957718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
17057718be8SEnji Cooper sa.sa_sigaction = action;
17157718be8SEnji Cooper sigemptyset(&sa.sa_mask);
17257718be8SEnji Cooper sigaction(SIGCHLD, &sa, NULL);
17357718be8SEnji Cooper }
17457718be8SEnji Cooper
17557718be8SEnji Cooper static void
sigchild_setup(void)17657718be8SEnji Cooper sigchild_setup(void)
17757718be8SEnji Cooper {
17857718be8SEnji Cooper sigset_t set;
17957718be8SEnji Cooper struct rlimit rlim;
18057718be8SEnji Cooper
18157718be8SEnji Cooper (void)getrlimit(RLIMIT_CORE, &rlim);
18257718be8SEnji Cooper rlim.rlim_cur = rlim.rlim_max;
18357718be8SEnji Cooper (void)setrlimit(RLIMIT_CORE, &rlim);
18457718be8SEnji Cooper
18557718be8SEnji Cooper setchildhandler(sigchild_action);
18657718be8SEnji Cooper sigemptyset(&set);
18757718be8SEnji Cooper sigaddset(&set, SIGCHLD);
18857718be8SEnji Cooper sigprocmask(SIG_BLOCK, &set, NULL);
18957718be8SEnji Cooper }
19057718be8SEnji Cooper
19157718be8SEnji Cooper ATF_TC(sigchild_normal);
ATF_TC_HEAD(sigchild_normal,tc)19257718be8SEnji Cooper ATF_TC_HEAD(sigchild_normal, tc)
19357718be8SEnji Cooper {
19457718be8SEnji Cooper
19557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
19657718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGCHLD handler "
19757718be8SEnji Cooper "when child exits normally");
19857718be8SEnji Cooper }
19957718be8SEnji Cooper
ATF_TC_BODY(sigchild_normal,tc)20057718be8SEnji Cooper ATF_TC_BODY(sigchild_normal, tc)
20157718be8SEnji Cooper {
20257718be8SEnji Cooper sigset_t set;
20357718be8SEnji Cooper
20457718be8SEnji Cooper sigchild_setup();
20557718be8SEnji Cooper
20657718be8SEnji Cooper status = 25;
20757718be8SEnji Cooper code = CLD_EXITED;
20857718be8SEnji Cooper
20957718be8SEnji Cooper switch ((child = fork())) {
21057718be8SEnji Cooper case 0:
21157718be8SEnji Cooper sleep(1);
21257718be8SEnji Cooper exit(status);
21357718be8SEnji Cooper case -1:
21457718be8SEnji Cooper atf_tc_fail("fork failed");
21557718be8SEnji Cooper default:
21657718be8SEnji Cooper sigemptyset(&set);
21757718be8SEnji Cooper sigsuspend(&set);
21857718be8SEnji Cooper }
21957718be8SEnji Cooper }
22057718be8SEnji Cooper
22157718be8SEnji Cooper ATF_TC(sigchild_dump);
ATF_TC_HEAD(sigchild_dump,tc)22257718be8SEnji Cooper ATF_TC_HEAD(sigchild_dump, tc)
22357718be8SEnji Cooper {
22457718be8SEnji Cooper
22557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
22657718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGCHLD handler "
22757718be8SEnji Cooper "when child segfaults");
22857718be8SEnji Cooper }
22957718be8SEnji Cooper
ATF_TC_BODY(sigchild_dump,tc)23057718be8SEnji Cooper ATF_TC_BODY(sigchild_dump, tc)
23157718be8SEnji Cooper {
23257718be8SEnji Cooper sigset_t set;
23357718be8SEnji Cooper
23457718be8SEnji Cooper sigchild_setup();
23557718be8SEnji Cooper
23657718be8SEnji Cooper status = SIGSEGV;
23757718be8SEnji Cooper code = CLD_DUMPED;
23857718be8SEnji Cooper
23957718be8SEnji Cooper switch ((child = fork())) {
24057718be8SEnji Cooper case 0:
24157718be8SEnji Cooper sleep(1);
24257718be8SEnji Cooper *(volatile long *)0 = 0;
24357718be8SEnji Cooper atf_tc_fail("Child did not segfault");
24457718be8SEnji Cooper /* NOTREACHED */
24557718be8SEnji Cooper case -1:
24657718be8SEnji Cooper atf_tc_fail("fork failed");
24757718be8SEnji Cooper default:
24857718be8SEnji Cooper sigemptyset(&set);
24957718be8SEnji Cooper sigsuspend(&set);
25057718be8SEnji Cooper }
25157718be8SEnji Cooper }
25257718be8SEnji Cooper
25357718be8SEnji Cooper ATF_TC(sigchild_kill);
ATF_TC_HEAD(sigchild_kill,tc)25457718be8SEnji Cooper ATF_TC_HEAD(sigchild_kill, tc)
25557718be8SEnji Cooper {
25657718be8SEnji Cooper
25757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
25857718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGCHLD handler "
25957718be8SEnji Cooper "when child is killed");
26057718be8SEnji Cooper }
26157718be8SEnji Cooper
ATF_TC_BODY(sigchild_kill,tc)26257718be8SEnji Cooper ATF_TC_BODY(sigchild_kill, tc)
26357718be8SEnji Cooper {
26457718be8SEnji Cooper sigset_t set;
26557718be8SEnji Cooper
26657718be8SEnji Cooper sigchild_setup();
26757718be8SEnji Cooper
26857718be8SEnji Cooper status = SIGPIPE;
26957718be8SEnji Cooper code = CLD_KILLED;
27057718be8SEnji Cooper
27157718be8SEnji Cooper switch ((child = fork())) {
27257718be8SEnji Cooper case 0:
27357718be8SEnji Cooper sigemptyset(&set);
27457718be8SEnji Cooper sigsuspend(&set);
27557718be8SEnji Cooper break;
27657718be8SEnji Cooper case -1:
27757718be8SEnji Cooper atf_tc_fail("fork failed");
27857718be8SEnji Cooper default:
27957718be8SEnji Cooper kill(child, SIGPIPE);
28057718be8SEnji Cooper sigemptyset(&set);
28157718be8SEnji Cooper sigsuspend(&set);
28257718be8SEnji Cooper }
28357718be8SEnji Cooper }
28457718be8SEnji Cooper
28557718be8SEnji Cooper static sigjmp_buf sigfpe_flt_env;
28657718be8SEnji Cooper static void
sigfpe_flt_action(int signo,siginfo_t * info,void * ptr)28757718be8SEnji Cooper sigfpe_flt_action(int signo, siginfo_t *info, void *ptr)
28857718be8SEnji Cooper {
28957718be8SEnji Cooper
29057718be8SEnji Cooper sig_debug(signo, info, (ucontext_t *)ptr);
29157718be8SEnji Cooper
29257718be8SEnji Cooper if (fltdiv_signalled++ != 0)
29357718be8SEnji Cooper atf_tc_fail("FPE handler called more than once");
29457718be8SEnji Cooper
29557718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
29657718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, FPE_FLTDIV);
29757718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_errno, 0);
29857718be8SEnji Cooper
29957718be8SEnji Cooper siglongjmp(sigfpe_flt_env, 1);
30057718be8SEnji Cooper }
30157718be8SEnji Cooper
30257718be8SEnji Cooper ATF_TC(sigfpe_flt);
ATF_TC_HEAD(sigfpe_flt,tc)30357718be8SEnji Cooper ATF_TC_HEAD(sigfpe_flt, tc)
30457718be8SEnji Cooper {
30557718be8SEnji Cooper
30657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
30757718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGFPE handler "
30857718be8SEnji Cooper "for floating div-by-zero");
30957718be8SEnji Cooper }
31057718be8SEnji Cooper
ATF_TC_BODY(sigfpe_flt,tc)31157718be8SEnji Cooper ATF_TC_BODY(sigfpe_flt, tc)
31257718be8SEnji Cooper {
31357718be8SEnji Cooper struct sigaction sa;
31457718be8SEnji Cooper double d = strtod("0", NULL);
31557718be8SEnji Cooper
31657718be8SEnji Cooper if (isQEMU())
31757718be8SEnji Cooper atf_tc_skip("Test does not run correctly under QEMU");
31857718be8SEnji Cooper #if defined(__powerpc__)
31957718be8SEnji Cooper atf_tc_skip("Test not valid on powerpc");
320*640235e2SEnji Cooper #elif defined(__arm__) && !__SOFTFP__
321*640235e2SEnji Cooper /*
322*640235e2SEnji Cooper * Some NEON fpus do not implement IEEE exception handling,
323*640235e2SEnji Cooper * skip these tests if running on them and compiled for
324*640235e2SEnji Cooper * hard float.
325*640235e2SEnji Cooper */
326*640235e2SEnji Cooper if (0 == fpsetmask(fpsetmask(FP_X_INV)))
327*640235e2SEnji Cooper atf_tc_skip("FPU does not implement exception handling");
32857718be8SEnji Cooper #endif
32957718be8SEnji Cooper if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
33057718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
33157718be8SEnji Cooper sa.sa_sigaction = sigfpe_flt_action;
33257718be8SEnji Cooper sigemptyset(&sa.sa_mask);
33357718be8SEnji Cooper sigaction(SIGFPE, &sa, NULL);
334*640235e2SEnji Cooper #ifdef __HAVE_FENV
33557718be8SEnji Cooper feenableexcept(FE_ALL_EXCEPT);
33657718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
33757718be8SEnji Cooper fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
33857718be8SEnji Cooper #endif
33957718be8SEnji Cooper printf("%g\n", 1 / d);
34057718be8SEnji Cooper }
34157718be8SEnji Cooper if (fltdiv_signalled == 0)
34257718be8SEnji Cooper atf_tc_fail("FPE signal handler was not invoked");
34357718be8SEnji Cooper }
34457718be8SEnji Cooper
34557718be8SEnji Cooper static sigjmp_buf sigfpe_int_env;
34657718be8SEnji Cooper static void
sigfpe_int_action(int signo,siginfo_t * info,void * ptr)34757718be8SEnji Cooper sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
34857718be8SEnji Cooper {
34957718be8SEnji Cooper
35057718be8SEnji Cooper sig_debug(signo, info, (ucontext_t *)ptr);
35157718be8SEnji Cooper
35257718be8SEnji Cooper if (intdiv_signalled++ != 0)
35357718be8SEnji Cooper atf_tc_fail("INTDIV handler called more than once");
35457718be8SEnji Cooper
35557718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
35657718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
35757718be8SEnji Cooper atf_tc_expect_pass();
35857718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_errno, 0);
35957718be8SEnji Cooper
36057718be8SEnji Cooper siglongjmp(sigfpe_int_env, 1);
36157718be8SEnji Cooper }
36257718be8SEnji Cooper
36357718be8SEnji Cooper ATF_TC(sigfpe_int);
ATF_TC_HEAD(sigfpe_int,tc)36457718be8SEnji Cooper ATF_TC_HEAD(sigfpe_int, tc)
36557718be8SEnji Cooper {
36657718be8SEnji Cooper
36757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
36857718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGFPE handler "
36957718be8SEnji Cooper "for integer div-by-zero (PR port-i386/43655)");
37057718be8SEnji Cooper }
37157718be8SEnji Cooper
ATF_TC_BODY(sigfpe_int,tc)37257718be8SEnji Cooper ATF_TC_BODY(sigfpe_int, tc)
37357718be8SEnji Cooper {
37457718be8SEnji Cooper struct sigaction sa;
37557718be8SEnji Cooper long l = strtol("0", NULL, 10);
37657718be8SEnji Cooper
37757718be8SEnji Cooper #if defined(__powerpc__)
37857718be8SEnji Cooper atf_tc_skip("Test not valid on powerpc");
37957718be8SEnji Cooper #endif
38057718be8SEnji Cooper if (sigsetjmp(sigfpe_int_env, 0) == 0) {
38157718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
38257718be8SEnji Cooper sa.sa_sigaction = sigfpe_int_action;
38357718be8SEnji Cooper sigemptyset(&sa.sa_mask);
38457718be8SEnji Cooper sigaction(SIGFPE, &sa, NULL);
385*640235e2SEnji Cooper #ifdef __HAVE_FENV
38657718be8SEnji Cooper feenableexcept(FE_ALL_EXCEPT);
38757718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
38857718be8SEnji Cooper fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
38957718be8SEnji Cooper #endif
39057718be8SEnji Cooper printf("%ld\n", 1 / l);
39157718be8SEnji Cooper }
39257718be8SEnji Cooper if (intdiv_signalled == 0)
39357718be8SEnji Cooper atf_tc_fail("FPE signal handler was not invoked");
39457718be8SEnji Cooper }
39557718be8SEnji Cooper
39657718be8SEnji Cooper static void
sigsegv_action(int signo,siginfo_t * info,void * ptr)39757718be8SEnji Cooper sigsegv_action(int signo, siginfo_t *info, void *ptr)
39857718be8SEnji Cooper {
39957718be8SEnji Cooper
40057718be8SEnji Cooper sig_debug(signo, info, (ucontext_t *)ptr);
40157718be8SEnji Cooper
40257718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
40357718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_errno, 0);
40457718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
40557718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_addr, (void *)0);
40657718be8SEnji Cooper
40757718be8SEnji Cooper atf_tc_pass();
40857718be8SEnji Cooper /* NOTREACHED */
40957718be8SEnji Cooper }
41057718be8SEnji Cooper
41157718be8SEnji Cooper ATF_TC(sigsegv);
ATF_TC_HEAD(sigsegv,tc)41257718be8SEnji Cooper ATF_TC_HEAD(sigsegv, tc)
41357718be8SEnji Cooper {
41457718be8SEnji Cooper
41557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
41657718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGSEGV handler");
41757718be8SEnji Cooper }
41857718be8SEnji Cooper
ATF_TC_BODY(sigsegv,tc)41957718be8SEnji Cooper ATF_TC_BODY(sigsegv, tc)
42057718be8SEnji Cooper {
42157718be8SEnji Cooper struct sigaction sa;
42257718be8SEnji Cooper
42357718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
42457718be8SEnji Cooper sa.sa_sigaction = sigsegv_action;
42557718be8SEnji Cooper sigemptyset(&sa.sa_mask);
42657718be8SEnji Cooper sigaction(SIGSEGV, &sa, NULL);
42757718be8SEnji Cooper
42857718be8SEnji Cooper *(volatile long *)0 = 0;
42957718be8SEnji Cooper atf_tc_fail("Test did not fault as expected");
43057718be8SEnji Cooper }
43157718be8SEnji Cooper
43257718be8SEnji Cooper static void
sigbus_action(int signo,siginfo_t * info,void * ptr)43357718be8SEnji Cooper sigbus_action(int signo, siginfo_t *info, void *ptr)
43457718be8SEnji Cooper {
43557718be8SEnji Cooper
43657718be8SEnji Cooper printf("si_addr = %p\n", info->si_addr);
43757718be8SEnji Cooper sig_debug(signo, info, (ucontext_t *)ptr);
43857718be8SEnji Cooper
43957718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
44057718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_errno, 0);
44157718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
44257718be8SEnji Cooper
44357718be8SEnji Cooper #if defined(__i386__) || defined(__x86_64__)
44457718be8SEnji Cooper atf_tc_expect_fail("x86 architecture does not correctly "
44557718be8SEnji Cooper "report the address where the unaligned access occured");
44657718be8SEnji Cooper #endif
44757718be8SEnji Cooper ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
44857718be8SEnji Cooper
44957718be8SEnji Cooper atf_tc_pass();
45057718be8SEnji Cooper /* NOTREACHED */
45157718be8SEnji Cooper }
45257718be8SEnji Cooper
45357718be8SEnji Cooper ATF_TC(sigbus_adraln);
ATF_TC_HEAD(sigbus_adraln,tc)45457718be8SEnji Cooper ATF_TC_HEAD(sigbus_adraln, tc)
45557718be8SEnji Cooper {
45657718be8SEnji Cooper
45757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
45857718be8SEnji Cooper "Checks that signal trampoline correctly calls SIGBUS handler "
45957718be8SEnji Cooper "for invalid address alignment");
46057718be8SEnji Cooper }
46157718be8SEnji Cooper
ATF_TC_BODY(sigbus_adraln,tc)46257718be8SEnji Cooper ATF_TC_BODY(sigbus_adraln, tc)
46357718be8SEnji Cooper {
46457718be8SEnji Cooper struct sigaction sa;
46557718be8SEnji Cooper
466*640235e2SEnji Cooper #if defined(__alpha__) || defined(__arm__)
46757718be8SEnji Cooper int rv, val;
46857718be8SEnji Cooper size_t len = sizeof(val);
46957718be8SEnji Cooper rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
47057718be8SEnji Cooper ATF_REQUIRE(rv == 0);
47157718be8SEnji Cooper if (val == 0)
472*640235e2SEnji Cooper atf_tc_skip("No SIGBUS signal for unaligned accesses");
47357718be8SEnji Cooper #endif
47457718be8SEnji Cooper
475*640235e2SEnji Cooper /* m68k (except sun2) never issue SIGBUS (PR lib/49653) */
476*640235e2SEnji Cooper if (strcmp(MACHINE_ARCH, "m68k") == 0)
477*640235e2SEnji Cooper atf_tc_skip("No SIGBUS signal for unaligned accesses");
478*640235e2SEnji Cooper
47957718be8SEnji Cooper sa.sa_flags = SA_SIGINFO;
48057718be8SEnji Cooper sa.sa_sigaction = sigbus_action;
48157718be8SEnji Cooper sigemptyset(&sa.sa_mask);
48257718be8SEnji Cooper sigaction(SIGBUS, &sa, NULL);
48357718be8SEnji Cooper
48457718be8SEnji Cooper /* Enable alignment checks for x86. 0x40000 is PSL_AC. */
48557718be8SEnji Cooper #if defined(__i386__)
48657718be8SEnji Cooper __asm__("pushf; orl $0x40000, (%esp); popf");
48757718be8SEnji Cooper #elif defined(__amd64__)
48857718be8SEnji Cooper __asm__("pushf; orl $0x40000, (%rsp); popf");
48957718be8SEnji Cooper #endif
49057718be8SEnji Cooper
49157718be8SEnji Cooper addr = calloc(2, sizeof(int));
49257718be8SEnji Cooper ATF_REQUIRE(addr != NULL);
49357718be8SEnji Cooper
49457718be8SEnji Cooper if (isQEMU())
49557718be8SEnji Cooper atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
49657718be8SEnji Cooper
49757718be8SEnji Cooper /* Force an unaligned access */
49857718be8SEnji Cooper addr++;
49957718be8SEnji Cooper printf("now trying to access unaligned address %p\n", addr);
50057718be8SEnji Cooper ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
50157718be8SEnji Cooper
50257718be8SEnji Cooper atf_tc_fail("Test did not fault as expected");
50357718be8SEnji Cooper }
50457718be8SEnji Cooper
ATF_TP_ADD_TCS(tp)50557718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
50657718be8SEnji Cooper {
50757718be8SEnji Cooper
50857718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigalarm);
50957718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigchild_normal);
51057718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigchild_dump);
51157718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigchild_kill);
51257718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigfpe_flt);
51357718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigfpe_int);
51457718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigsegv);
51557718be8SEnji Cooper ATF_TP_ADD_TC(tp, sigbus_adraln);
51657718be8SEnji Cooper
51757718be8SEnji Cooper return atf_no_error();
51857718be8SEnji Cooper }
519