1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_siginfo.c,v 1.29 2015/02/17 09:47:08 isaki Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*-
411be35a1SLionel Sambuc * Copyright (c) 2010 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc * All rights reserved.
611be35a1SLionel Sambuc *
711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc * are met:
1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc *
1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1711be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1811be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1911be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2011be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2111be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2211be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2311be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2411be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2511be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2611be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
2711be35a1SLionel Sambuc */
2811be35a1SLionel Sambuc
2911be35a1SLionel Sambuc #include <atf-c.h>
3011be35a1SLionel Sambuc
3111be35a1SLionel Sambuc #include <sys/inttypes.h>
3211be35a1SLionel Sambuc #include <sys/resource.h>
3311be35a1SLionel Sambuc #include <sys/sysctl.h>
3411be35a1SLionel Sambuc #include <sys/time.h>
3511be35a1SLionel Sambuc #include <sys/ucontext.h>
3611be35a1SLionel Sambuc #include <sys/wait.h>
3711be35a1SLionel Sambuc
3811be35a1SLionel Sambuc #include <assert.h>
3911be35a1SLionel Sambuc #include <signal.h>
4011be35a1SLionel Sambuc #include <stdio.h>
4111be35a1SLionel Sambuc #include <stdlib.h>
4211be35a1SLionel Sambuc #include <string.h>
4311be35a1SLionel Sambuc #include <unistd.h>
4411be35a1SLionel Sambuc #include <setjmp.h>
4511be35a1SLionel Sambuc #include <float.h>
4611be35a1SLionel Sambuc
47*0a6a1f1dSLionel Sambuc #ifdef HAVE_FENV
48*0a6a1f1dSLionel Sambuc #include <fenv.h>
49*0a6a1f1dSLionel Sambuc #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
50*0a6a1f1dSLionel Sambuc #elif defined(_FLOAT_IEEE754)
5111be35a1SLionel Sambuc #include <ieeefp.h>
5211be35a1SLionel Sambuc #endif
5311be35a1SLionel Sambuc
5411be35a1SLionel Sambuc #include "isqemu.h"
5511be35a1SLionel Sambuc
5611be35a1SLionel Sambuc /* for sigbus */
5711be35a1SLionel Sambuc volatile char *addr;
5811be35a1SLionel Sambuc
5911be35a1SLionel Sambuc /* for sigchild */
6011be35a1SLionel Sambuc pid_t child;
6111be35a1SLionel Sambuc int code;
6211be35a1SLionel Sambuc int status;
6311be35a1SLionel Sambuc
6411be35a1SLionel Sambuc /* for sigfpe */
6511be35a1SLionel Sambuc sig_atomic_t fltdiv_signalled = 0;
6611be35a1SLionel Sambuc sig_atomic_t intdiv_signalled = 0;
6711be35a1SLionel Sambuc
6811be35a1SLionel Sambuc static void
sig_debug(int signo,siginfo_t * info,ucontext_t * ctx)6911be35a1SLionel Sambuc sig_debug(int signo, siginfo_t *info, ucontext_t *ctx)
7011be35a1SLionel Sambuc {
7111be35a1SLionel Sambuc unsigned int i;
7211be35a1SLionel Sambuc
7311be35a1SLionel Sambuc printf("%d %p %p\n", signo, info, ctx);
7411be35a1SLionel Sambuc if (info != NULL) {
7511be35a1SLionel Sambuc printf("si_signo=%d\n", info->si_signo);
7611be35a1SLionel Sambuc printf("si_errno=%d\n", info->si_errno);
7711be35a1SLionel Sambuc printf("si_code=%d\n", info->si_code);
7811be35a1SLionel Sambuc printf("si_value.sival_int=%d\n", info->si_value.sival_int);
7911be35a1SLionel Sambuc }
8011be35a1SLionel Sambuc if (ctx != NULL) {
8111be35a1SLionel Sambuc printf("uc_flags 0x%x\n", ctx->uc_flags);
8211be35a1SLionel Sambuc printf("uc_link %p\n", ctx->uc_link);
8311be35a1SLionel Sambuc for (i = 0; i < __arraycount(ctx->uc_sigmask.__bits); i++)
8411be35a1SLionel Sambuc printf("uc_sigmask[%d] 0x%x\n", i,
8511be35a1SLionel Sambuc ctx->uc_sigmask.__bits[i]);
8611be35a1SLionel Sambuc printf("uc_stack %p %lu 0x%x\n", ctx->uc_stack.ss_sp,
8711be35a1SLionel Sambuc (unsigned long)ctx->uc_stack.ss_size,
8811be35a1SLionel Sambuc ctx->uc_stack.ss_flags);
8911be35a1SLionel Sambuc for (i = 0; i < __arraycount(ctx->uc_mcontext.__gregs); i++)
9011be35a1SLionel Sambuc printf("uc_mcontext.greg[%d] 0x%lx\n", i,
9111be35a1SLionel Sambuc (long)ctx->uc_mcontext.__gregs[i]);
9211be35a1SLionel Sambuc }
9311be35a1SLionel Sambuc }
9411be35a1SLionel Sambuc
9511be35a1SLionel Sambuc static void
sigalrm_action(int signo,siginfo_t * info,void * ptr)9611be35a1SLionel Sambuc sigalrm_action(int signo, siginfo_t *info, void *ptr)
9711be35a1SLionel Sambuc {
9811be35a1SLionel Sambuc
9911be35a1SLionel Sambuc sig_debug(signo, info, (ucontext_t *)ptr);
10011be35a1SLionel Sambuc
10111be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGALRM);
10211be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, SI_TIMER);
10311be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_value.sival_int, ITIMER_REAL);
10411be35a1SLionel Sambuc
10511be35a1SLionel Sambuc atf_tc_pass();
10611be35a1SLionel Sambuc /* NOTREACHED */
10711be35a1SLionel Sambuc }
10811be35a1SLionel Sambuc
10911be35a1SLionel Sambuc ATF_TC(sigalarm);
11011be35a1SLionel Sambuc
ATF_TC_HEAD(sigalarm,tc)11111be35a1SLionel Sambuc ATF_TC_HEAD(sigalarm, tc)
11211be35a1SLionel Sambuc {
11311be35a1SLionel Sambuc
11411be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
11511be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGALRM handler");
11611be35a1SLionel Sambuc }
11711be35a1SLionel Sambuc
ATF_TC_BODY(sigalarm,tc)11811be35a1SLionel Sambuc ATF_TC_BODY(sigalarm, tc)
11911be35a1SLionel Sambuc {
12011be35a1SLionel Sambuc struct sigaction sa;
12111be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
12211be35a1SLionel Sambuc sa.sa_sigaction = sigalrm_action;
12311be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
12411be35a1SLionel Sambuc sigaction(SIGALRM, &sa, NULL);
12511be35a1SLionel Sambuc for (;;) {
12611be35a1SLionel Sambuc alarm(1);
12711be35a1SLionel Sambuc sleep(1);
12811be35a1SLionel Sambuc }
12911be35a1SLionel Sambuc atf_tc_fail("SIGALRM handler wasn't called");
13011be35a1SLionel Sambuc }
13111be35a1SLionel Sambuc
13211be35a1SLionel Sambuc static void
sigchild_action(int signo,siginfo_t * info,void * ptr)13311be35a1SLionel Sambuc sigchild_action(int signo, siginfo_t *info, void *ptr)
13411be35a1SLionel Sambuc {
13511be35a1SLionel Sambuc if (info != NULL) {
13611be35a1SLionel Sambuc printf("info=%p\n", info);
13711be35a1SLionel Sambuc printf("ptr=%p\n", ptr);
13811be35a1SLionel Sambuc printf("si_signo=%d\n", info->si_signo);
13911be35a1SLionel Sambuc printf("si_errno=%d\n", info->si_errno);
14011be35a1SLionel Sambuc printf("si_code=%d\n", info->si_code);
14111be35a1SLionel Sambuc printf("si_uid=%d\n", info->si_uid);
14211be35a1SLionel Sambuc printf("si_pid=%d\n", info->si_pid);
14311be35a1SLionel Sambuc printf("si_status=%d\n", info->si_status);
14411be35a1SLionel Sambuc printf("si_utime=%lu\n", (unsigned long int)info->si_utime);
14511be35a1SLionel Sambuc printf("si_stime=%lu\n", (unsigned long int)info->si_stime);
14611be35a1SLionel Sambuc }
14711be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, code);
14811be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGCHLD);
14911be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_uid, getuid());
15011be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_pid, child);
15111be35a1SLionel Sambuc if (WIFEXITED(info->si_status))
15211be35a1SLionel Sambuc ATF_REQUIRE_EQ(WEXITSTATUS(info->si_status), status);
15311be35a1SLionel Sambuc else if (WIFSTOPPED(info->si_status))
15411be35a1SLionel Sambuc ATF_REQUIRE_EQ(WSTOPSIG(info->si_status), status);
15511be35a1SLionel Sambuc else if (WIFSIGNALED(info->si_status))
15611be35a1SLionel Sambuc ATF_REQUIRE_EQ(WTERMSIG(info->si_status), status);
15711be35a1SLionel Sambuc }
15811be35a1SLionel Sambuc
15911be35a1SLionel Sambuc static void
setchildhandler(void (* action)(int,siginfo_t *,void *))16011be35a1SLionel Sambuc setchildhandler(void (*action)(int, siginfo_t *, void *))
16111be35a1SLionel Sambuc {
16211be35a1SLionel Sambuc struct sigaction sa;
16311be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
16411be35a1SLionel Sambuc sa.sa_sigaction = action;
16511be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
16611be35a1SLionel Sambuc sigaction(SIGCHLD, &sa, NULL);
16711be35a1SLionel Sambuc }
16811be35a1SLionel Sambuc
16911be35a1SLionel Sambuc static void
sigchild_setup(void)17011be35a1SLionel Sambuc sigchild_setup(void)
17111be35a1SLionel Sambuc {
17211be35a1SLionel Sambuc sigset_t set;
17311be35a1SLionel Sambuc struct rlimit rlim;
17411be35a1SLionel Sambuc
17511be35a1SLionel Sambuc (void)getrlimit(RLIMIT_CORE, &rlim);
17611be35a1SLionel Sambuc rlim.rlim_cur = rlim.rlim_max;
17711be35a1SLionel Sambuc (void)setrlimit(RLIMIT_CORE, &rlim);
17811be35a1SLionel Sambuc
17911be35a1SLionel Sambuc setchildhandler(sigchild_action);
18011be35a1SLionel Sambuc sigemptyset(&set);
18111be35a1SLionel Sambuc sigaddset(&set, SIGCHLD);
18211be35a1SLionel Sambuc sigprocmask(SIG_BLOCK, &set, NULL);
18311be35a1SLionel Sambuc }
18411be35a1SLionel Sambuc
18511be35a1SLionel Sambuc ATF_TC(sigchild_normal);
ATF_TC_HEAD(sigchild_normal,tc)18611be35a1SLionel Sambuc ATF_TC_HEAD(sigchild_normal, tc)
18711be35a1SLionel Sambuc {
18811be35a1SLionel Sambuc
18911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
19011be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGCHLD handler "
19111be35a1SLionel Sambuc "when child exits normally");
19211be35a1SLionel Sambuc }
19311be35a1SLionel Sambuc
ATF_TC_BODY(sigchild_normal,tc)19411be35a1SLionel Sambuc ATF_TC_BODY(sigchild_normal, tc)
19511be35a1SLionel Sambuc {
19611be35a1SLionel Sambuc sigset_t set;
19711be35a1SLionel Sambuc
19811be35a1SLionel Sambuc sigchild_setup();
19911be35a1SLionel Sambuc
20011be35a1SLionel Sambuc status = 25;
20111be35a1SLionel Sambuc code = CLD_EXITED;
20211be35a1SLionel Sambuc
20311be35a1SLionel Sambuc switch ((child = fork())) {
20411be35a1SLionel Sambuc case 0:
20511be35a1SLionel Sambuc sleep(1);
20611be35a1SLionel Sambuc exit(status);
20711be35a1SLionel Sambuc case -1:
20811be35a1SLionel Sambuc atf_tc_fail("fork failed");
20911be35a1SLionel Sambuc default:
21011be35a1SLionel Sambuc sigemptyset(&set);
21111be35a1SLionel Sambuc sigsuspend(&set);
21211be35a1SLionel Sambuc }
21311be35a1SLionel Sambuc }
21411be35a1SLionel Sambuc
21511be35a1SLionel Sambuc ATF_TC(sigchild_dump);
ATF_TC_HEAD(sigchild_dump,tc)21611be35a1SLionel Sambuc ATF_TC_HEAD(sigchild_dump, tc)
21711be35a1SLionel Sambuc {
21811be35a1SLionel Sambuc
21911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
22011be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGCHLD handler "
22111be35a1SLionel Sambuc "when child segfaults");
22211be35a1SLionel Sambuc }
22311be35a1SLionel Sambuc
ATF_TC_BODY(sigchild_dump,tc)22411be35a1SLionel Sambuc ATF_TC_BODY(sigchild_dump, tc)
22511be35a1SLionel Sambuc {
22611be35a1SLionel Sambuc sigset_t set;
22711be35a1SLionel Sambuc
22811be35a1SLionel Sambuc sigchild_setup();
22911be35a1SLionel Sambuc
23011be35a1SLionel Sambuc status = SIGSEGV;
23111be35a1SLionel Sambuc code = CLD_DUMPED;
23211be35a1SLionel Sambuc
23311be35a1SLionel Sambuc switch ((child = fork())) {
23411be35a1SLionel Sambuc case 0:
23511be35a1SLionel Sambuc sleep(1);
23611be35a1SLionel Sambuc *(volatile long *)0 = 0;
23711be35a1SLionel Sambuc atf_tc_fail("Child did not segfault");
23811be35a1SLionel Sambuc /* NOTREACHED */
23911be35a1SLionel Sambuc case -1:
24011be35a1SLionel Sambuc atf_tc_fail("fork failed");
24111be35a1SLionel Sambuc default:
24211be35a1SLionel Sambuc sigemptyset(&set);
24311be35a1SLionel Sambuc sigsuspend(&set);
24411be35a1SLionel Sambuc }
24511be35a1SLionel Sambuc }
24611be35a1SLionel Sambuc
24711be35a1SLionel Sambuc ATF_TC(sigchild_kill);
ATF_TC_HEAD(sigchild_kill,tc)24811be35a1SLionel Sambuc ATF_TC_HEAD(sigchild_kill, tc)
24911be35a1SLionel Sambuc {
25011be35a1SLionel Sambuc
25111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
25211be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGCHLD handler "
25311be35a1SLionel Sambuc "when child is killed");
25411be35a1SLionel Sambuc }
25511be35a1SLionel Sambuc
ATF_TC_BODY(sigchild_kill,tc)25611be35a1SLionel Sambuc ATF_TC_BODY(sigchild_kill, tc)
25711be35a1SLionel Sambuc {
25811be35a1SLionel Sambuc sigset_t set;
25911be35a1SLionel Sambuc
26011be35a1SLionel Sambuc sigchild_setup();
26111be35a1SLionel Sambuc
26211be35a1SLionel Sambuc status = SIGPIPE;
26311be35a1SLionel Sambuc code = CLD_KILLED;
26411be35a1SLionel Sambuc
26511be35a1SLionel Sambuc switch ((child = fork())) {
26611be35a1SLionel Sambuc case 0:
26711be35a1SLionel Sambuc sigemptyset(&set);
26811be35a1SLionel Sambuc sigsuspend(&set);
26911be35a1SLionel Sambuc break;
27011be35a1SLionel Sambuc case -1:
27111be35a1SLionel Sambuc atf_tc_fail("fork failed");
27211be35a1SLionel Sambuc default:
27311be35a1SLionel Sambuc kill(child, SIGPIPE);
27411be35a1SLionel Sambuc sigemptyset(&set);
27511be35a1SLionel Sambuc sigsuspend(&set);
27611be35a1SLionel Sambuc }
27711be35a1SLionel Sambuc }
27811be35a1SLionel Sambuc
27911be35a1SLionel Sambuc static sigjmp_buf sigfpe_flt_env;
28011be35a1SLionel Sambuc static void
sigfpe_flt_action(int signo,siginfo_t * info,void * ptr)28111be35a1SLionel Sambuc sigfpe_flt_action(int signo, siginfo_t *info, void *ptr)
28211be35a1SLionel Sambuc {
28311be35a1SLionel Sambuc
28411be35a1SLionel Sambuc sig_debug(signo, info, (ucontext_t *)ptr);
28511be35a1SLionel Sambuc
28611be35a1SLionel Sambuc if (fltdiv_signalled++ != 0)
28711be35a1SLionel Sambuc atf_tc_fail("FPE handler called more than once");
28811be35a1SLionel Sambuc
28911be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
29011be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, FPE_FLTDIV);
29111be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_errno, 0);
29211be35a1SLionel Sambuc
29311be35a1SLionel Sambuc siglongjmp(sigfpe_flt_env, 1);
29411be35a1SLionel Sambuc }
29511be35a1SLionel Sambuc
29611be35a1SLionel Sambuc ATF_TC(sigfpe_flt);
ATF_TC_HEAD(sigfpe_flt,tc)29711be35a1SLionel Sambuc ATF_TC_HEAD(sigfpe_flt, tc)
29811be35a1SLionel Sambuc {
29911be35a1SLionel Sambuc
30011be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
30111be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGFPE handler "
30211be35a1SLionel Sambuc "for floating div-by-zero");
30311be35a1SLionel Sambuc }
30411be35a1SLionel Sambuc
ATF_TC_BODY(sigfpe_flt,tc)30511be35a1SLionel Sambuc ATF_TC_BODY(sigfpe_flt, tc)
30611be35a1SLionel Sambuc {
30711be35a1SLionel Sambuc struct sigaction sa;
30811be35a1SLionel Sambuc double d = strtod("0", NULL);
30911be35a1SLionel Sambuc
31011be35a1SLionel Sambuc if (isQEMU())
31111be35a1SLionel Sambuc atf_tc_skip("Test does not run correctly under QEMU");
312*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
31311be35a1SLionel Sambuc atf_tc_skip("Test not valid on powerpc");
314*0a6a1f1dSLionel Sambuc #elif defined(__arm__) && !__SOFTFP__
315*0a6a1f1dSLionel Sambuc /*
316*0a6a1f1dSLionel Sambuc * Some NEON fpus do not implement IEEE exception handling,
317*0a6a1f1dSLionel Sambuc * skip these tests if running on them and compiled for
318*0a6a1f1dSLionel Sambuc * hard float.
319*0a6a1f1dSLionel Sambuc */
320*0a6a1f1dSLionel Sambuc if (0 == fpsetmask(fpsetmask(FP_X_INV)))
321*0a6a1f1dSLionel Sambuc atf_tc_skip("FPU does not implement exception handling");
322*0a6a1f1dSLionel Sambuc #endif
32311be35a1SLionel Sambuc if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
32411be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
32511be35a1SLionel Sambuc sa.sa_sigaction = sigfpe_flt_action;
32611be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
32711be35a1SLionel Sambuc sigaction(SIGFPE, &sa, NULL);
328*0a6a1f1dSLionel Sambuc #ifdef HAVE_FENV
329*0a6a1f1dSLionel Sambuc feenableexcept(FE_ALL_EXCEPT);
330*0a6a1f1dSLionel Sambuc #elif defined(_FLOAT_IEEE754)
33111be35a1SLionel Sambuc fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
33211be35a1SLionel Sambuc #endif
33311be35a1SLionel Sambuc printf("%g\n", 1 / d);
33411be35a1SLionel Sambuc }
33511be35a1SLionel Sambuc if (fltdiv_signalled == 0)
33611be35a1SLionel Sambuc atf_tc_fail("FPE signal handler was not invoked");
33711be35a1SLionel Sambuc }
33811be35a1SLionel Sambuc
33911be35a1SLionel Sambuc static sigjmp_buf sigfpe_int_env;
34011be35a1SLionel Sambuc static void
sigfpe_int_action(int signo,siginfo_t * info,void * ptr)34111be35a1SLionel Sambuc sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
34211be35a1SLionel Sambuc {
34311be35a1SLionel Sambuc
34411be35a1SLionel Sambuc sig_debug(signo, info, (ucontext_t *)ptr);
34511be35a1SLionel Sambuc
34611be35a1SLionel Sambuc if (intdiv_signalled++ != 0)
34711be35a1SLionel Sambuc atf_tc_fail("INTDIV handler called more than once");
34811be35a1SLionel Sambuc
34911be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
35011be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
35111be35a1SLionel Sambuc atf_tc_expect_pass();
35211be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_errno, 0);
35311be35a1SLionel Sambuc
35411be35a1SLionel Sambuc siglongjmp(sigfpe_int_env, 1);
35511be35a1SLionel Sambuc }
35611be35a1SLionel Sambuc
35711be35a1SLionel Sambuc ATF_TC(sigfpe_int);
ATF_TC_HEAD(sigfpe_int,tc)35811be35a1SLionel Sambuc ATF_TC_HEAD(sigfpe_int, tc)
35911be35a1SLionel Sambuc {
36011be35a1SLionel Sambuc
36111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
36211be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGFPE handler "
36311be35a1SLionel Sambuc "for integer div-by-zero (PR port-i386/43655)");
36411be35a1SLionel Sambuc }
36511be35a1SLionel Sambuc
ATF_TC_BODY(sigfpe_int,tc)36611be35a1SLionel Sambuc ATF_TC_BODY(sigfpe_int, tc)
36711be35a1SLionel Sambuc {
36811be35a1SLionel Sambuc struct sigaction sa;
36911be35a1SLionel Sambuc long l = strtol("0", NULL, 10);
37011be35a1SLionel Sambuc
371*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
37211be35a1SLionel Sambuc atf_tc_skip("Test not valid on powerpc");
373*0a6a1f1dSLionel Sambuc #endif
37411be35a1SLionel Sambuc if (sigsetjmp(sigfpe_int_env, 0) == 0) {
37511be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
37611be35a1SLionel Sambuc sa.sa_sigaction = sigfpe_int_action;
37711be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
37811be35a1SLionel Sambuc sigaction(SIGFPE, &sa, NULL);
379*0a6a1f1dSLionel Sambuc #ifdef HAVE_FENV
380*0a6a1f1dSLionel Sambuc feenableexcept(FE_ALL_EXCEPT);
381*0a6a1f1dSLionel Sambuc #elif defined(_FLOAT_IEEE754)
38211be35a1SLionel Sambuc fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
38311be35a1SLionel Sambuc #endif
38411be35a1SLionel Sambuc printf("%ld\n", 1 / l);
38511be35a1SLionel Sambuc }
38611be35a1SLionel Sambuc if (intdiv_signalled == 0)
38711be35a1SLionel Sambuc atf_tc_fail("FPE signal handler was not invoked");
38811be35a1SLionel Sambuc }
38911be35a1SLionel Sambuc
39011be35a1SLionel Sambuc static void
sigsegv_action(int signo,siginfo_t * info,void * ptr)39111be35a1SLionel Sambuc sigsegv_action(int signo, siginfo_t *info, void *ptr)
39211be35a1SLionel Sambuc {
39311be35a1SLionel Sambuc
39411be35a1SLionel Sambuc sig_debug(signo, info, (ucontext_t *)ptr);
39511be35a1SLionel Sambuc
39611be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
39711be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_errno, 0);
39811be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
39911be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_addr, (void *)0);
40011be35a1SLionel Sambuc
40111be35a1SLionel Sambuc atf_tc_pass();
40211be35a1SLionel Sambuc /* NOTREACHED */
40311be35a1SLionel Sambuc }
40411be35a1SLionel Sambuc
40511be35a1SLionel Sambuc ATF_TC(sigsegv);
ATF_TC_HEAD(sigsegv,tc)40611be35a1SLionel Sambuc ATF_TC_HEAD(sigsegv, tc)
40711be35a1SLionel Sambuc {
40811be35a1SLionel Sambuc
40911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
41011be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGSEGV handler");
41111be35a1SLionel Sambuc }
41211be35a1SLionel Sambuc
ATF_TC_BODY(sigsegv,tc)41311be35a1SLionel Sambuc ATF_TC_BODY(sigsegv, tc)
41411be35a1SLionel Sambuc {
41511be35a1SLionel Sambuc struct sigaction sa;
41611be35a1SLionel Sambuc
41711be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
41811be35a1SLionel Sambuc sa.sa_sigaction = sigsegv_action;
41911be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
42011be35a1SLionel Sambuc sigaction(SIGSEGV, &sa, NULL);
42111be35a1SLionel Sambuc
42211be35a1SLionel Sambuc *(volatile long *)0 = 0;
42311be35a1SLionel Sambuc atf_tc_fail("Test did not fault as expected");
42411be35a1SLionel Sambuc }
42511be35a1SLionel Sambuc
42611be35a1SLionel Sambuc static void
sigbus_action(int signo,siginfo_t * info,void * ptr)42711be35a1SLionel Sambuc sigbus_action(int signo, siginfo_t *info, void *ptr)
42811be35a1SLionel Sambuc {
42911be35a1SLionel Sambuc
43011be35a1SLionel Sambuc printf("si_addr = %p\n", info->si_addr);
43111be35a1SLionel Sambuc sig_debug(signo, info, (ucontext_t *)ptr);
43211be35a1SLionel Sambuc
43311be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
43411be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_errno, 0);
43511be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
43611be35a1SLionel Sambuc
437*0a6a1f1dSLionel Sambuc #if defined(__i386__) || defined(__x86_64__)
43811be35a1SLionel Sambuc atf_tc_expect_fail("x86 architecture does not correctly "
43911be35a1SLionel Sambuc "report the address where the unaligned access occured");
440*0a6a1f1dSLionel Sambuc #endif
44111be35a1SLionel Sambuc ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
44211be35a1SLionel Sambuc
44311be35a1SLionel Sambuc atf_tc_pass();
44411be35a1SLionel Sambuc /* NOTREACHED */
44511be35a1SLionel Sambuc }
44611be35a1SLionel Sambuc
44711be35a1SLionel Sambuc ATF_TC(sigbus_adraln);
ATF_TC_HEAD(sigbus_adraln,tc)44811be35a1SLionel Sambuc ATF_TC_HEAD(sigbus_adraln, tc)
44911be35a1SLionel Sambuc {
45011be35a1SLionel Sambuc
45111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
45211be35a1SLionel Sambuc "Checks that signal trampoline correctly calls SIGBUS handler "
45311be35a1SLionel Sambuc "for invalid address alignment");
45411be35a1SLionel Sambuc }
45511be35a1SLionel Sambuc
ATF_TC_BODY(sigbus_adraln,tc)45611be35a1SLionel Sambuc ATF_TC_BODY(sigbus_adraln, tc)
45711be35a1SLionel Sambuc {
45811be35a1SLionel Sambuc struct sigaction sa;
45911be35a1SLionel Sambuc
460*0a6a1f1dSLionel Sambuc #if defined(__alpha__) || defined(__arm__)
46111be35a1SLionel Sambuc int rv, val;
46211be35a1SLionel Sambuc size_t len = sizeof(val);
463*0a6a1f1dSLionel Sambuc rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
46411be35a1SLionel Sambuc ATF_REQUIRE(rv == 0);
46511be35a1SLionel Sambuc if (val == 0)
466*0a6a1f1dSLionel Sambuc atf_tc_skip("No SIGBUS signal for unaligned accesses");
467*0a6a1f1dSLionel Sambuc #endif
46811be35a1SLionel Sambuc
469*0a6a1f1dSLionel Sambuc /* m68k (except sun2) never issue SIGBUS (PR lib/49653) */
470*0a6a1f1dSLionel Sambuc if (strcmp(MACHINE_ARCH, "m68k") == 0)
471*0a6a1f1dSLionel Sambuc atf_tc_skip("No SIGBUS signal for unaligned accesses");
47211be35a1SLionel Sambuc
47311be35a1SLionel Sambuc sa.sa_flags = SA_SIGINFO;
47411be35a1SLionel Sambuc sa.sa_sigaction = sigbus_action;
47511be35a1SLionel Sambuc sigemptyset(&sa.sa_mask);
47611be35a1SLionel Sambuc sigaction(SIGBUS, &sa, NULL);
47711be35a1SLionel Sambuc
478*0a6a1f1dSLionel Sambuc /* Enable alignment checks for x86. 0x40000 is PSL_AC. */
47911be35a1SLionel Sambuc #if defined(__i386__)
48011be35a1SLionel Sambuc __asm__("pushf; orl $0x40000, (%esp); popf");
48111be35a1SLionel Sambuc #elif defined(__amd64__)
48211be35a1SLionel Sambuc __asm__("pushf; orl $0x40000, (%rsp); popf");
48311be35a1SLionel Sambuc #endif
48411be35a1SLionel Sambuc
48511be35a1SLionel Sambuc addr = calloc(2, sizeof(int));
48611be35a1SLionel Sambuc ATF_REQUIRE(addr != NULL);
48711be35a1SLionel Sambuc
48811be35a1SLionel Sambuc if (isQEMU())
48911be35a1SLionel Sambuc atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
49011be35a1SLionel Sambuc
49111be35a1SLionel Sambuc /* Force an unaligned access */
49211be35a1SLionel Sambuc addr++;
49311be35a1SLionel Sambuc printf("now trying to access unaligned address %p\n", addr);
49411be35a1SLionel Sambuc ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
49511be35a1SLionel Sambuc
49611be35a1SLionel Sambuc atf_tc_fail("Test did not fault as expected");
49711be35a1SLionel Sambuc }
49811be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)49911be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
50011be35a1SLionel Sambuc {
50111be35a1SLionel Sambuc
50211be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigalarm);
50311be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigchild_normal);
50411be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigchild_dump);
50511be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigchild_kill);
50611be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigfpe_flt);
50711be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigfpe_int);
50811be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigsegv);
50911be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, sigbus_adraln);
51011be35a1SLionel Sambuc
51111be35a1SLionel Sambuc return atf_no_error();
51211be35a1SLionel Sambuc }
513