xref: /freebsd-src/contrib/netbsd-tests/lib/libc/gen/t_siginfo.c (revision 57718be8fa0bd5edc11ab9a72e68cc71982939a6)
1*57718be8SEnji Cooper /* $NetBSD: t_siginfo.c,v 1.23 2014/02/09 21:26:07 jmmv Exp $ */
2*57718be8SEnji Cooper 
3*57718be8SEnji Cooper /*-
4*57718be8SEnji Cooper  * Copyright (c) 2010 The NetBSD Foundation, Inc.
5*57718be8SEnji Cooper  * All rights reserved.
6*57718be8SEnji Cooper  *
7*57718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
8*57718be8SEnji Cooper  * modification, are permitted provided that the following conditions
9*57718be8SEnji Cooper  * are met:
10*57718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
11*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
12*57718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
13*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
14*57718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
15*57718be8SEnji Cooper  *
16*57718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17*57718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18*57718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*57718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20*57718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*57718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*57718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*57718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*57718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*57718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*57718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
27*57718be8SEnji Cooper  */
28*57718be8SEnji Cooper 
29*57718be8SEnji Cooper #include <atf-c.h>
30*57718be8SEnji Cooper #include <atf-c/config.h>
31*57718be8SEnji Cooper 
32*57718be8SEnji Cooper #include <sys/inttypes.h>
33*57718be8SEnji Cooper #include <sys/resource.h>
34*57718be8SEnji Cooper #include <sys/sysctl.h>
35*57718be8SEnji Cooper #include <sys/time.h>
36*57718be8SEnji Cooper #include <sys/ucontext.h>
37*57718be8SEnji Cooper #include <sys/wait.h>
38*57718be8SEnji Cooper 
39*57718be8SEnji Cooper #include <assert.h>
40*57718be8SEnji Cooper #include <signal.h>
41*57718be8SEnji Cooper #include <stdio.h>
42*57718be8SEnji Cooper #include <stdlib.h>
43*57718be8SEnji Cooper #include <string.h>
44*57718be8SEnji Cooper #include <unistd.h>
45*57718be8SEnji Cooper #include <setjmp.h>
46*57718be8SEnji Cooper #include <float.h>
47*57718be8SEnji Cooper 
48*57718be8SEnji Cooper #ifdef HAVE_FENV
49*57718be8SEnji Cooper #include <fenv.h>
50*57718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
51*57718be8SEnji Cooper #include <ieeefp.h>
52*57718be8SEnji Cooper #endif
53*57718be8SEnji Cooper 
54*57718be8SEnji Cooper #include "isqemu.h"
55*57718be8SEnji Cooper 
56*57718be8SEnji Cooper /* for sigbus */
57*57718be8SEnji Cooper volatile char *addr;
58*57718be8SEnji Cooper 
59*57718be8SEnji Cooper /* for sigchild */
60*57718be8SEnji Cooper pid_t child;
61*57718be8SEnji Cooper int code;
62*57718be8SEnji Cooper int status;
63*57718be8SEnji Cooper 
64*57718be8SEnji Cooper /* for sigfpe */
65*57718be8SEnji Cooper sig_atomic_t fltdiv_signalled = 0;
66*57718be8SEnji Cooper sig_atomic_t intdiv_signalled = 0;
67*57718be8SEnji Cooper 
68*57718be8SEnji Cooper static void
69*57718be8SEnji Cooper sig_debug(int signo, siginfo_t *info, ucontext_t *ctx)
70*57718be8SEnji Cooper {
71*57718be8SEnji Cooper 	unsigned int i;
72*57718be8SEnji Cooper 
73*57718be8SEnji Cooper 	printf("%d %p %p\n", signo, info, ctx);
74*57718be8SEnji Cooper 	if (info != NULL) {
75*57718be8SEnji Cooper 		printf("si_signo=%d\n", info->si_signo);
76*57718be8SEnji Cooper 		printf("si_errno=%d\n", info->si_errno);
77*57718be8SEnji Cooper 		printf("si_code=%d\n", info->si_code);
78*57718be8SEnji Cooper 		printf("si_value.sival_int=%d\n", info->si_value.sival_int);
79*57718be8SEnji Cooper 	}
80*57718be8SEnji Cooper 	if (ctx != NULL) {
81*57718be8SEnji Cooper 		printf("uc_flags 0x%x\n", ctx->uc_flags);
82*57718be8SEnji Cooper 		printf("uc_link %p\n", ctx->uc_link);
83*57718be8SEnji Cooper 		for (i = 0; i < __arraycount(ctx->uc_sigmask.__bits); i++)
84*57718be8SEnji Cooper 			printf("uc_sigmask[%d] 0x%x\n", i,
85*57718be8SEnji Cooper 			    ctx->uc_sigmask.__bits[i]);
86*57718be8SEnji Cooper 		printf("uc_stack %p %lu 0x%x\n", ctx->uc_stack.ss_sp,
87*57718be8SEnji Cooper 		    (unsigned long)ctx->uc_stack.ss_size,
88*57718be8SEnji Cooper 		    ctx->uc_stack.ss_flags);
89*57718be8SEnji Cooper 		for (i = 0; i < __arraycount(ctx->uc_mcontext.__gregs); i++)
90*57718be8SEnji Cooper 			printf("uc_mcontext.greg[%d] 0x%lx\n", i,
91*57718be8SEnji Cooper 			    (long)ctx->uc_mcontext.__gregs[i]);
92*57718be8SEnji Cooper 	}
93*57718be8SEnji Cooper }
94*57718be8SEnji Cooper 
95*57718be8SEnji Cooper static void
96*57718be8SEnji Cooper sigalrm_action(int signo, siginfo_t *info, void *ptr)
97*57718be8SEnji Cooper {
98*57718be8SEnji Cooper 
99*57718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
100*57718be8SEnji Cooper 
101*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGALRM);
102*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, SI_TIMER);
103*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_value.sival_int, ITIMER_REAL);
104*57718be8SEnji Cooper 
105*57718be8SEnji Cooper 	atf_tc_pass();
106*57718be8SEnji Cooper 	/* NOTREACHED */
107*57718be8SEnji Cooper }
108*57718be8SEnji Cooper 
109*57718be8SEnji Cooper ATF_TC(sigalarm);
110*57718be8SEnji Cooper 
111*57718be8SEnji Cooper ATF_TC_HEAD(sigalarm, tc)
112*57718be8SEnji Cooper {
113*57718be8SEnji Cooper 
114*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
115*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGALRM handler");
116*57718be8SEnji Cooper }
117*57718be8SEnji Cooper 
118*57718be8SEnji Cooper ATF_TC_BODY(sigalarm, tc)
119*57718be8SEnji Cooper {
120*57718be8SEnji Cooper 	struct sigaction sa;
121*57718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
122*57718be8SEnji Cooper 	sa.sa_sigaction = sigalrm_action;
123*57718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
124*57718be8SEnji Cooper 	sigaction(SIGALRM, &sa, NULL);
125*57718be8SEnji Cooper 	for (;;) {
126*57718be8SEnji Cooper 		alarm(1);
127*57718be8SEnji Cooper 		sleep(1);
128*57718be8SEnji Cooper 	}
129*57718be8SEnji Cooper 	atf_tc_fail("SIGALRM handler wasn't called");
130*57718be8SEnji Cooper }
131*57718be8SEnji Cooper 
132*57718be8SEnji Cooper static void
133*57718be8SEnji Cooper sigchild_action(int signo, siginfo_t *info, void *ptr)
134*57718be8SEnji Cooper {
135*57718be8SEnji Cooper 	if (info != NULL) {
136*57718be8SEnji Cooper 		printf("info=%p\n", info);
137*57718be8SEnji Cooper 		printf("ptr=%p\n", ptr);
138*57718be8SEnji Cooper 		printf("si_signo=%d\n", info->si_signo);
139*57718be8SEnji Cooper 		printf("si_errno=%d\n", info->si_errno);
140*57718be8SEnji Cooper 		printf("si_code=%d\n", info->si_code);
141*57718be8SEnji Cooper 		printf("si_uid=%d\n", info->si_uid);
142*57718be8SEnji Cooper 		printf("si_pid=%d\n", info->si_pid);
143*57718be8SEnji Cooper 		printf("si_status=%d\n", info->si_status);
144*57718be8SEnji Cooper 		printf("si_utime=%lu\n", (unsigned long int)info->si_utime);
145*57718be8SEnji Cooper 		printf("si_stime=%lu\n", (unsigned long int)info->si_stime);
146*57718be8SEnji Cooper 	}
147*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, code);
148*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGCHLD);
149*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_uid, getuid());
150*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_pid, child);
151*57718be8SEnji Cooper 	if (WIFEXITED(info->si_status))
152*57718be8SEnji Cooper 		ATF_REQUIRE_EQ(WEXITSTATUS(info->si_status), status);
153*57718be8SEnji Cooper 	else if (WIFSTOPPED(info->si_status))
154*57718be8SEnji Cooper 		ATF_REQUIRE_EQ(WSTOPSIG(info->si_status), status);
155*57718be8SEnji Cooper 	else if (WIFSIGNALED(info->si_status))
156*57718be8SEnji Cooper 		ATF_REQUIRE_EQ(WTERMSIG(info->si_status), status);
157*57718be8SEnji Cooper }
158*57718be8SEnji Cooper 
159*57718be8SEnji Cooper static void
160*57718be8SEnji Cooper setchildhandler(void (*action)(int, siginfo_t *, void *))
161*57718be8SEnji Cooper {
162*57718be8SEnji Cooper 	struct sigaction sa;
163*57718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
164*57718be8SEnji Cooper 	sa.sa_sigaction = action;
165*57718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
166*57718be8SEnji Cooper 	sigaction(SIGCHLD, &sa, NULL);
167*57718be8SEnji Cooper }
168*57718be8SEnji Cooper 
169*57718be8SEnji Cooper static void
170*57718be8SEnji Cooper sigchild_setup(void)
171*57718be8SEnji Cooper {
172*57718be8SEnji Cooper 	sigset_t set;
173*57718be8SEnji Cooper 	struct rlimit rlim;
174*57718be8SEnji Cooper 
175*57718be8SEnji Cooper 	(void)getrlimit(RLIMIT_CORE, &rlim);
176*57718be8SEnji Cooper 	rlim.rlim_cur = rlim.rlim_max;
177*57718be8SEnji Cooper 	(void)setrlimit(RLIMIT_CORE, &rlim);
178*57718be8SEnji Cooper 
179*57718be8SEnji Cooper 	setchildhandler(sigchild_action);
180*57718be8SEnji Cooper 	sigemptyset(&set);
181*57718be8SEnji Cooper 	sigaddset(&set, SIGCHLD);
182*57718be8SEnji Cooper 	sigprocmask(SIG_BLOCK, &set, NULL);
183*57718be8SEnji Cooper }
184*57718be8SEnji Cooper 
185*57718be8SEnji Cooper ATF_TC(sigchild_normal);
186*57718be8SEnji Cooper ATF_TC_HEAD(sigchild_normal, tc)
187*57718be8SEnji Cooper {
188*57718be8SEnji Cooper 
189*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
190*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
191*57718be8SEnji Cooper 	    "when child exits normally");
192*57718be8SEnji Cooper }
193*57718be8SEnji Cooper 
194*57718be8SEnji Cooper ATF_TC_BODY(sigchild_normal, tc)
195*57718be8SEnji Cooper {
196*57718be8SEnji Cooper 	sigset_t set;
197*57718be8SEnji Cooper 
198*57718be8SEnji Cooper 	sigchild_setup();
199*57718be8SEnji Cooper 
200*57718be8SEnji Cooper 	status = 25;
201*57718be8SEnji Cooper 	code = CLD_EXITED;
202*57718be8SEnji Cooper 
203*57718be8SEnji Cooper 	switch ((child = fork())) {
204*57718be8SEnji Cooper 	case 0:
205*57718be8SEnji Cooper 		sleep(1);
206*57718be8SEnji Cooper 		exit(status);
207*57718be8SEnji Cooper 	case -1:
208*57718be8SEnji Cooper 		atf_tc_fail("fork failed");
209*57718be8SEnji Cooper 	default:
210*57718be8SEnji Cooper 		sigemptyset(&set);
211*57718be8SEnji Cooper 		sigsuspend(&set);
212*57718be8SEnji Cooper 	}
213*57718be8SEnji Cooper }
214*57718be8SEnji Cooper 
215*57718be8SEnji Cooper ATF_TC(sigchild_dump);
216*57718be8SEnji Cooper ATF_TC_HEAD(sigchild_dump, tc)
217*57718be8SEnji Cooper {
218*57718be8SEnji Cooper 
219*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
220*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
221*57718be8SEnji Cooper 	    "when child segfaults");
222*57718be8SEnji Cooper }
223*57718be8SEnji Cooper 
224*57718be8SEnji Cooper ATF_TC_BODY(sigchild_dump, tc)
225*57718be8SEnji Cooper {
226*57718be8SEnji Cooper 	sigset_t set;
227*57718be8SEnji Cooper 
228*57718be8SEnji Cooper 	sigchild_setup();
229*57718be8SEnji Cooper 
230*57718be8SEnji Cooper 	status = SIGSEGV;
231*57718be8SEnji Cooper 	code = CLD_DUMPED;
232*57718be8SEnji Cooper 
233*57718be8SEnji Cooper 	switch ((child = fork())) {
234*57718be8SEnji Cooper 	case 0:
235*57718be8SEnji Cooper 		sleep(1);
236*57718be8SEnji Cooper 		*(volatile long *)0 = 0;
237*57718be8SEnji Cooper 		atf_tc_fail("Child did not segfault");
238*57718be8SEnji Cooper 		/* NOTREACHED */
239*57718be8SEnji Cooper 	case -1:
240*57718be8SEnji Cooper 		atf_tc_fail("fork failed");
241*57718be8SEnji Cooper 	default:
242*57718be8SEnji Cooper 		sigemptyset(&set);
243*57718be8SEnji Cooper 		sigsuspend(&set);
244*57718be8SEnji Cooper 	}
245*57718be8SEnji Cooper }
246*57718be8SEnji Cooper 
247*57718be8SEnji Cooper ATF_TC(sigchild_kill);
248*57718be8SEnji Cooper ATF_TC_HEAD(sigchild_kill, tc)
249*57718be8SEnji Cooper {
250*57718be8SEnji Cooper 
251*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
252*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGCHLD handler "
253*57718be8SEnji Cooper 	    "when child is killed");
254*57718be8SEnji Cooper }
255*57718be8SEnji Cooper 
256*57718be8SEnji Cooper ATF_TC_BODY(sigchild_kill, tc)
257*57718be8SEnji Cooper {
258*57718be8SEnji Cooper 	sigset_t set;
259*57718be8SEnji Cooper 
260*57718be8SEnji Cooper 	sigchild_setup();
261*57718be8SEnji Cooper 
262*57718be8SEnji Cooper 	status = SIGPIPE;
263*57718be8SEnji Cooper 	code = CLD_KILLED;
264*57718be8SEnji Cooper 
265*57718be8SEnji Cooper 	switch ((child = fork())) {
266*57718be8SEnji Cooper 	case 0:
267*57718be8SEnji Cooper 		sigemptyset(&set);
268*57718be8SEnji Cooper 		sigsuspend(&set);
269*57718be8SEnji Cooper 		break;
270*57718be8SEnji Cooper 	case -1:
271*57718be8SEnji Cooper 		atf_tc_fail("fork failed");
272*57718be8SEnji Cooper 	default:
273*57718be8SEnji Cooper 		kill(child, SIGPIPE);
274*57718be8SEnji Cooper 		sigemptyset(&set);
275*57718be8SEnji Cooper 		sigsuspend(&set);
276*57718be8SEnji Cooper 	}
277*57718be8SEnji Cooper }
278*57718be8SEnji Cooper 
279*57718be8SEnji Cooper static sigjmp_buf sigfpe_flt_env;
280*57718be8SEnji Cooper static void
281*57718be8SEnji Cooper sigfpe_flt_action(int signo, siginfo_t *info, void *ptr)
282*57718be8SEnji Cooper {
283*57718be8SEnji Cooper 
284*57718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
285*57718be8SEnji Cooper 
286*57718be8SEnji Cooper 	if (fltdiv_signalled++ != 0)
287*57718be8SEnji Cooper 		atf_tc_fail("FPE handler called more than once");
288*57718be8SEnji Cooper 
289*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
290*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, FPE_FLTDIV);
291*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
292*57718be8SEnji Cooper 
293*57718be8SEnji Cooper 	siglongjmp(sigfpe_flt_env, 1);
294*57718be8SEnji Cooper }
295*57718be8SEnji Cooper 
296*57718be8SEnji Cooper ATF_TC(sigfpe_flt);
297*57718be8SEnji Cooper ATF_TC_HEAD(sigfpe_flt, tc)
298*57718be8SEnji Cooper {
299*57718be8SEnji Cooper 
300*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
301*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGFPE handler "
302*57718be8SEnji Cooper 	    "for floating div-by-zero");
303*57718be8SEnji Cooper }
304*57718be8SEnji Cooper 
305*57718be8SEnji Cooper ATF_TC_BODY(sigfpe_flt, tc)
306*57718be8SEnji Cooper {
307*57718be8SEnji Cooper 	struct sigaction sa;
308*57718be8SEnji Cooper 	double d = strtod("0", NULL);
309*57718be8SEnji Cooper 
310*57718be8SEnji Cooper 	if (isQEMU())
311*57718be8SEnji Cooper 		atf_tc_skip("Test does not run correctly under QEMU");
312*57718be8SEnji Cooper #if defined(__powerpc__)
313*57718be8SEnji Cooper 	atf_tc_skip("Test not valid on powerpc");
314*57718be8SEnji Cooper #endif
315*57718be8SEnji Cooper 	if (sigsetjmp(sigfpe_flt_env, 0) == 0) {
316*57718be8SEnji Cooper 		sa.sa_flags = SA_SIGINFO;
317*57718be8SEnji Cooper 		sa.sa_sigaction = sigfpe_flt_action;
318*57718be8SEnji Cooper 		sigemptyset(&sa.sa_mask);
319*57718be8SEnji Cooper 		sigaction(SIGFPE, &sa, NULL);
320*57718be8SEnji Cooper #ifdef HAVE_FENV
321*57718be8SEnji Cooper 		feenableexcept(FE_ALL_EXCEPT);
322*57718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
323*57718be8SEnji Cooper 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
324*57718be8SEnji Cooper #endif
325*57718be8SEnji Cooper 		printf("%g\n", 1 / d);
326*57718be8SEnji Cooper 	}
327*57718be8SEnji Cooper 	if (fltdiv_signalled == 0)
328*57718be8SEnji Cooper 		atf_tc_fail("FPE signal handler was not invoked");
329*57718be8SEnji Cooper }
330*57718be8SEnji Cooper 
331*57718be8SEnji Cooper static sigjmp_buf sigfpe_int_env;
332*57718be8SEnji Cooper static void
333*57718be8SEnji Cooper sigfpe_int_action(int signo, siginfo_t *info, void *ptr)
334*57718be8SEnji Cooper {
335*57718be8SEnji Cooper 
336*57718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
337*57718be8SEnji Cooper 
338*57718be8SEnji Cooper 	if (intdiv_signalled++ != 0)
339*57718be8SEnji Cooper 		atf_tc_fail("INTDIV handler called more than once");
340*57718be8SEnji Cooper 
341*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGFPE);
342*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, FPE_INTDIV);
343*57718be8SEnji Cooper 	atf_tc_expect_pass();
344*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
345*57718be8SEnji Cooper 
346*57718be8SEnji Cooper 	siglongjmp(sigfpe_int_env, 1);
347*57718be8SEnji Cooper }
348*57718be8SEnji Cooper 
349*57718be8SEnji Cooper ATF_TC(sigfpe_int);
350*57718be8SEnji Cooper ATF_TC_HEAD(sigfpe_int, tc)
351*57718be8SEnji Cooper {
352*57718be8SEnji Cooper 
353*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
354*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGFPE handler "
355*57718be8SEnji Cooper 	    "for integer div-by-zero (PR port-i386/43655)");
356*57718be8SEnji Cooper }
357*57718be8SEnji Cooper 
358*57718be8SEnji Cooper ATF_TC_BODY(sigfpe_int, tc)
359*57718be8SEnji Cooper {
360*57718be8SEnji Cooper 	struct sigaction sa;
361*57718be8SEnji Cooper 	long l = strtol("0", NULL, 10);
362*57718be8SEnji Cooper 
363*57718be8SEnji Cooper #if defined(__powerpc__)
364*57718be8SEnji Cooper 	atf_tc_skip("Test not valid on powerpc");
365*57718be8SEnji Cooper #endif
366*57718be8SEnji Cooper 	if (sigsetjmp(sigfpe_int_env, 0) == 0) {
367*57718be8SEnji Cooper 		sa.sa_flags = SA_SIGINFO;
368*57718be8SEnji Cooper 		sa.sa_sigaction = sigfpe_int_action;
369*57718be8SEnji Cooper 		sigemptyset(&sa.sa_mask);
370*57718be8SEnji Cooper 		sigaction(SIGFPE, &sa, NULL);
371*57718be8SEnji Cooper #ifdef HAVE_FENV
372*57718be8SEnji Cooper 		feenableexcept(FE_ALL_EXCEPT);
373*57718be8SEnji Cooper #elif defined(_FLOAT_IEEE754)
374*57718be8SEnji Cooper 		fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
375*57718be8SEnji Cooper #endif
376*57718be8SEnji Cooper 		printf("%ld\n", 1 / l);
377*57718be8SEnji Cooper 	}
378*57718be8SEnji Cooper 	if (intdiv_signalled == 0)
379*57718be8SEnji Cooper 		atf_tc_fail("FPE signal handler was not invoked");
380*57718be8SEnji Cooper }
381*57718be8SEnji Cooper 
382*57718be8SEnji Cooper static void
383*57718be8SEnji Cooper sigsegv_action(int signo, siginfo_t *info, void *ptr)
384*57718be8SEnji Cooper {
385*57718be8SEnji Cooper 
386*57718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
387*57718be8SEnji Cooper 
388*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGSEGV);
389*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
390*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, SEGV_MAPERR);
391*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_addr, (void *)0);
392*57718be8SEnji Cooper 
393*57718be8SEnji Cooper 	atf_tc_pass();
394*57718be8SEnji Cooper 	/* NOTREACHED */
395*57718be8SEnji Cooper }
396*57718be8SEnji Cooper 
397*57718be8SEnji Cooper ATF_TC(sigsegv);
398*57718be8SEnji Cooper ATF_TC_HEAD(sigsegv, tc)
399*57718be8SEnji Cooper {
400*57718be8SEnji Cooper 
401*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
402*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGSEGV handler");
403*57718be8SEnji Cooper }
404*57718be8SEnji Cooper 
405*57718be8SEnji Cooper ATF_TC_BODY(sigsegv, tc)
406*57718be8SEnji Cooper {
407*57718be8SEnji Cooper 	struct sigaction sa;
408*57718be8SEnji Cooper 
409*57718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
410*57718be8SEnji Cooper 	sa.sa_sigaction = sigsegv_action;
411*57718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
412*57718be8SEnji Cooper 	sigaction(SIGSEGV, &sa, NULL);
413*57718be8SEnji Cooper 
414*57718be8SEnji Cooper 	*(volatile long *)0 = 0;
415*57718be8SEnji Cooper 	atf_tc_fail("Test did not fault as expected");
416*57718be8SEnji Cooper }
417*57718be8SEnji Cooper 
418*57718be8SEnji Cooper static void
419*57718be8SEnji Cooper sigbus_action(int signo, siginfo_t *info, void *ptr)
420*57718be8SEnji Cooper {
421*57718be8SEnji Cooper 
422*57718be8SEnji Cooper 	printf("si_addr = %p\n", info->si_addr);
423*57718be8SEnji Cooper 	sig_debug(signo, info, (ucontext_t *)ptr);
424*57718be8SEnji Cooper 
425*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
426*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_errno, 0);
427*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
428*57718be8SEnji Cooper 
429*57718be8SEnji Cooper #if defined(__i386__) || defined(__x86_64__)
430*57718be8SEnji Cooper 	atf_tc_expect_fail("x86 architecture does not correctly "
431*57718be8SEnji Cooper 	    "report the address where the unaligned access occured");
432*57718be8SEnji Cooper #endif
433*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(info->si_addr, (volatile void *)addr);
434*57718be8SEnji Cooper 
435*57718be8SEnji Cooper 	atf_tc_pass();
436*57718be8SEnji Cooper 	/* NOTREACHED */
437*57718be8SEnji Cooper }
438*57718be8SEnji Cooper 
439*57718be8SEnji Cooper ATF_TC(sigbus_adraln);
440*57718be8SEnji Cooper ATF_TC_HEAD(sigbus_adraln, tc)
441*57718be8SEnji Cooper {
442*57718be8SEnji Cooper 
443*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
444*57718be8SEnji Cooper 	    "Checks that signal trampoline correctly calls SIGBUS handler "
445*57718be8SEnji Cooper 	    "for invalid address alignment");
446*57718be8SEnji Cooper }
447*57718be8SEnji Cooper 
448*57718be8SEnji Cooper ATF_TC_BODY(sigbus_adraln, tc)
449*57718be8SEnji Cooper {
450*57718be8SEnji Cooper 	struct sigaction sa;
451*57718be8SEnji Cooper 
452*57718be8SEnji Cooper #if defined(__alpha__)
453*57718be8SEnji Cooper 	int rv, val;
454*57718be8SEnji Cooper 	size_t len = sizeof(val);
455*57718be8SEnji Cooper 	rv = sysctlbyname("machdep.unaligned_sigbus", &val, &len, NULL, 0);
456*57718be8SEnji Cooper 	ATF_REQUIRE(rv == 0);
457*57718be8SEnji Cooper 	if (val == 0)
458*57718be8SEnji Cooper 		atf_tc_skip("SIGBUS signal not enabled for unaligned accesses");
459*57718be8SEnji Cooper #endif
460*57718be8SEnji Cooper 
461*57718be8SEnji Cooper 	sa.sa_flags = SA_SIGINFO;
462*57718be8SEnji Cooper 	sa.sa_sigaction = sigbus_action;
463*57718be8SEnji Cooper 	sigemptyset(&sa.sa_mask);
464*57718be8SEnji Cooper 	sigaction(SIGBUS, &sa, NULL);
465*57718be8SEnji Cooper 
466*57718be8SEnji Cooper 	/* Enable alignment checks for x86. 0x40000 is PSL_AC. */
467*57718be8SEnji Cooper #if defined(__i386__)
468*57718be8SEnji Cooper 	__asm__("pushf; orl $0x40000, (%esp); popf");
469*57718be8SEnji Cooper #elif defined(__amd64__)
470*57718be8SEnji Cooper 	__asm__("pushf; orl $0x40000, (%rsp); popf");
471*57718be8SEnji Cooper #endif
472*57718be8SEnji Cooper 
473*57718be8SEnji Cooper 	addr = calloc(2, sizeof(int));
474*57718be8SEnji Cooper 	ATF_REQUIRE(addr != NULL);
475*57718be8SEnji Cooper 
476*57718be8SEnji Cooper 	if (isQEMU())
477*57718be8SEnji Cooper 		atf_tc_expect_fail("QEMU fails to trap unaligned accesses");
478*57718be8SEnji Cooper 
479*57718be8SEnji Cooper 	/* Force an unaligned access */
480*57718be8SEnji Cooper 	addr++;
481*57718be8SEnji Cooper 	printf("now trying to access unaligned address %p\n", addr);
482*57718be8SEnji Cooper 	ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
483*57718be8SEnji Cooper 
484*57718be8SEnji Cooper 	atf_tc_fail("Test did not fault as expected");
485*57718be8SEnji Cooper }
486*57718be8SEnji Cooper 
487*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
488*57718be8SEnji Cooper {
489*57718be8SEnji Cooper 
490*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigalarm);
491*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_normal);
492*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_dump);
493*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigchild_kill);
494*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigfpe_flt);
495*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigfpe_int);
496*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigsegv);
497*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sigbus_adraln);
498*57718be8SEnji Cooper 
499*57718be8SEnji Cooper 	return atf_no_error();
500*57718be8SEnji Cooper }
501