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