xref: /freebsd-src/contrib/netbsd-tests/lib/libc/gen/t_siginfo.c (revision 192a7b5f9ef64815200a192c5d8da321e8b1dac1)
157718be8SEnji Cooper /* $NetBSD: t_siginfo.c,v 1.23 2014/02/09 21:26:07 jmmv 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 #include <atf-c/config.h>
3157718be8SEnji Cooper 
32*192a7b5fSEnji Cooper #if defined(__NetBSD__)
3357718be8SEnji Cooper #include <sys/inttypes.h>
34*192a7b5fSEnji Cooper #endif
3557718be8SEnji Cooper #include <sys/resource.h>
3657718be8SEnji Cooper #include <sys/sysctl.h>
3757718be8SEnji Cooper #include <sys/time.h>
3857718be8SEnji Cooper #include <sys/ucontext.h>
3957718be8SEnji Cooper #include <sys/wait.h>
4057718be8SEnji Cooper 
4157718be8SEnji Cooper #include <assert.h>
4257718be8SEnji Cooper #include <signal.h>
4357718be8SEnji Cooper #include <stdio.h>
4457718be8SEnji Cooper #include <stdlib.h>
4557718be8SEnji Cooper #include <string.h>
4657718be8SEnji Cooper #include <unistd.h>
4757718be8SEnji Cooper #include <setjmp.h>
4857718be8SEnji Cooper #include <float.h>
4957718be8SEnji Cooper 
5057718be8SEnji Cooper #ifdef HAVE_FENV
5157718be8SEnji Cooper #include <fenv.h>
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
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);
91*192a7b5fSEnji Cooper #if defined(__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]);
95*192a7b5fSEnji Cooper #endif
9657718be8SEnji Cooper 	}
9757718be8SEnji Cooper }
9857718be8SEnji Cooper 
9957718be8SEnji Cooper static void
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 
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 
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
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);
148*192a7b5fSEnji Cooper #if defined(__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);
151*192a7b5fSEnji 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
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
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);
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 
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);
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 
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);
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 
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
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);
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 
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");
32057718be8SEnji Cooper #endif
32157718be8SEnji Cooper 	if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
32257718be8SEnji Cooper 		sa.sa_flags = SA_SIGINFO;
32357718be8SEnji Cooper 		sa.sa_sigaction = sigfpe_flt_action;
32457718be8SEnji Cooper 		sigemptyset(&sa.sa_mask);
32557718be8SEnji Cooper 		sigaction(SIGFPE, &sa, NULL);
32657718be8SEnji Cooper #ifdef HAVE_FENV
32757718be8SEnji Cooper 		feenableexcept(FE_ALL_EXCEPT);
32857718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
32957718be8SEnji Cooper 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
33057718be8SEnji Cooper #endif
33157718be8SEnji Cooper 		printf("%g\n", 1 / d);
33257718be8SEnji Cooper 	}
33357718be8SEnji Cooper 	if (fltdiv_signalled == 0)
33457718be8SEnji Cooper 		atf_tc_fail("FPE signal handler was not invoked");
33557718be8SEnji Cooper }
33657718be8SEnji Cooper 
33757718be8SEnji Cooper static sigjmp_buf sigfpe_int_env;
33857718be8SEnji Cooper static void
33957718be8SEnji Cooper sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
34057718be8SEnji Cooper {
34157718be8SEnji Cooper 
34257718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
34357718be8SEnji Cooper 
34457718be8SEnji Cooper 	if (intdiv_signalled++ != 0)
34557718be8SEnji Cooper 		atf_tc_fail("INTDIV handler called more than once");
34657718be8SEnji Cooper 
34757718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
34857718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
34957718be8SEnji Cooper 	atf_tc_expect_pass();
35057718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
35157718be8SEnji Cooper 
35257718be8SEnji Cooper 	siglongjmp(sigfpe_int_env, 1);
35357718be8SEnji Cooper }
35457718be8SEnji Cooper 
35557718be8SEnji Cooper ATF_TC(sigfpe_int);
35657718be8SEnji Cooper ATF_TC_HEAD(sigfpe_int, tc)
35757718be8SEnji Cooper {
35857718be8SEnji Cooper 
35957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
36057718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGFPE handler "
36157718be8SEnji Cooper 	    "for integer div-by-zero (PR port-i386/43655)");
36257718be8SEnji Cooper }
36357718be8SEnji Cooper 
36457718be8SEnji Cooper ATF_TC_BODY(sigfpe_int, tc)
36557718be8SEnji Cooper {
36657718be8SEnji Cooper 	struct sigaction sa;
36757718be8SEnji Cooper 	long l = strtol("0", NULL, 10);
36857718be8SEnji Cooper 
36957718be8SEnji Cooper #if defined(__powerpc__)
37057718be8SEnji Cooper 	atf_tc_skip("Test not valid on powerpc");
37157718be8SEnji Cooper #endif
37257718be8SEnji Cooper 	if (sigsetjmp(sigfpe_int_env, 0) == 0) {
37357718be8SEnji Cooper 		sa.sa_flags = SA_SIGINFO;
37457718be8SEnji Cooper 		sa.sa_sigaction = sigfpe_int_action;
37557718be8SEnji Cooper 		sigemptyset(&sa.sa_mask);
37657718be8SEnji Cooper 		sigaction(SIGFPE, &sa, NULL);
37757718be8SEnji Cooper #ifdef HAVE_FENV
37857718be8SEnji Cooper 		feenableexcept(FE_ALL_EXCEPT);
37957718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
38057718be8SEnji Cooper 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
38157718be8SEnji Cooper #endif
38257718be8SEnji Cooper 		printf("%ld\n", 1 / l);
38357718be8SEnji Cooper 	}
38457718be8SEnji Cooper 	if (intdiv_signalled == 0)
38557718be8SEnji Cooper 		atf_tc_fail("FPE signal handler was not invoked");
38657718be8SEnji Cooper }
38757718be8SEnji Cooper 
38857718be8SEnji Cooper static void
38957718be8SEnji Cooper sigsegv_action(int signo, siginfo_t *info, void *ptr)
39057718be8SEnji Cooper {
39157718be8SEnji Cooper 
39257718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
39357718be8SEnji Cooper 
39457718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
39557718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
39657718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
39757718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_addr, (void *)0);
39857718be8SEnji Cooper 
39957718be8SEnji Cooper 	atf_tc_pass();
40057718be8SEnji Cooper 	/* NOTREACHED */
40157718be8SEnji Cooper }
40257718be8SEnji Cooper 
40357718be8SEnji Cooper ATF_TC(sigsegv);
40457718be8SEnji Cooper ATF_TC_HEAD(sigsegv, tc)
40557718be8SEnji Cooper {
40657718be8SEnji Cooper 
40757718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
40857718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGSEGV handler");
40957718be8SEnji Cooper }
41057718be8SEnji Cooper 
41157718be8SEnji Cooper ATF_TC_BODY(sigsegv, tc)
41257718be8SEnji Cooper {
41357718be8SEnji Cooper 	struct sigaction sa;
41457718be8SEnji Cooper 
41557718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
41657718be8SEnji Cooper 	sa.sa_sigaction = sigsegv_action;
41757718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
41857718be8SEnji Cooper 	sigaction(SIGSEGV, &sa, NULL);
41957718be8SEnji Cooper 
42057718be8SEnji Cooper 	*(volatile long *)0 = 0;
42157718be8SEnji Cooper 	atf_tc_fail("Test did not fault as expected");
42257718be8SEnji Cooper }
42357718be8SEnji Cooper 
42457718be8SEnji Cooper static void
42557718be8SEnji Cooper sigbus_action(int signo, siginfo_t *info, void *ptr)
42657718be8SEnji Cooper {
42757718be8SEnji Cooper 
42857718be8SEnji Cooper 	printf("si_addr = %p\n", info->si_addr);
42957718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
43057718be8SEnji Cooper 
43157718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
43257718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
43357718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
43457718be8SEnji Cooper 
43557718be8SEnji Cooper #if defined(__i386__) || defined(__x86_64__)
43657718be8SEnji Cooper 	atf_tc_expect_fail("x86 architecture does not correctly "
43757718be8SEnji Cooper 	    "report the address where the unaligned access occured");
43857718be8SEnji Cooper #endif
43957718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
44057718be8SEnji Cooper 
44157718be8SEnji Cooper 	atf_tc_pass();
44257718be8SEnji Cooper 	/* NOTREACHED */
44357718be8SEnji Cooper }
44457718be8SEnji Cooper 
44557718be8SEnji Cooper ATF_TC(sigbus_adraln);
44657718be8SEnji Cooper ATF_TC_HEAD(sigbus_adraln, tc)
44757718be8SEnji Cooper {
44857718be8SEnji Cooper 
44957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
45057718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGBUS handler "
45157718be8SEnji Cooper 	    "for invalid address alignment");
45257718be8SEnji Cooper }
45357718be8SEnji Cooper 
45457718be8SEnji Cooper ATF_TC_BODY(sigbus_adraln, tc)
45557718be8SEnji Cooper {
45657718be8SEnji Cooper 	struct sigaction sa;
45757718be8SEnji Cooper 
45857718be8SEnji Cooper #if defined(__alpha__)
45957718be8SEnji Cooper 	int rv, val;
46057718be8SEnji Cooper 	size_t len = sizeof(val);
46157718be8SEnji Cooper 	rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
46257718be8SEnji Cooper 	ATF_REQUIRE(rv == 0);
46357718be8SEnji Cooper 	if (val == 0)
46457718be8SEnji Cooper 		atf_tc_skip("SIGBUS signal not enabled for unaligned accesses");
46557718be8SEnji Cooper #endif
46657718be8SEnji Cooper 
46757718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
46857718be8SEnji Cooper 	sa.sa_sigaction = sigbus_action;
46957718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
47057718be8SEnji Cooper 	sigaction(SIGBUS, &sa, NULL);
47157718be8SEnji Cooper 
47257718be8SEnji Cooper 	/* Enable alignment checks for x86. 0x40000 is PSL_AC. */
47357718be8SEnji Cooper #if defined(__i386__)
47457718be8SEnji Cooper 	__asm__("pushf; orl $0x40000, (%esp); popf");
47557718be8SEnji Cooper #elif defined(__amd64__)
47657718be8SEnji Cooper 	__asm__("pushf; orl $0x40000, (%rsp); popf");
47757718be8SEnji Cooper #endif
47857718be8SEnji Cooper 
47957718be8SEnji Cooper 	addr = calloc(2, sizeof(int));
48057718be8SEnji Cooper 	ATF_REQUIRE(addr != NULL);
48157718be8SEnji Cooper 
48257718be8SEnji Cooper 	if (isQEMU())
48357718be8SEnji Cooper 		atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
48457718be8SEnji Cooper 
48557718be8SEnji Cooper 	/* Force an unaligned access */
48657718be8SEnji Cooper 	addr++;
48757718be8SEnji Cooper 	printf("now trying to access unaligned address %p\n", addr);
48857718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
48957718be8SEnji Cooper 
49057718be8SEnji Cooper 	atf_tc_fail("Test did not fault as expected");
49157718be8SEnji Cooper }
49257718be8SEnji Cooper 
49357718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
49457718be8SEnji Cooper {
49557718be8SEnji Cooper 
49657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigalarm);
49757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_normal);
49857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_dump);
49957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_kill);
50057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigfpe_flt);
50157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigfpe_int);
50257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigsegv);
50357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigbus_adraln);
50457718be8SEnji Cooper 
50557718be8SEnji Cooper 	return atf_no_error();
50657718be8SEnji Cooper }
507