t_signal_and_sp.c revision 1.10 1 /* $NetBSD: t_signal_and_sp.c,v 1.10 2025/04/21 12:06:08 riastradh Exp $ */
2
3 /*
4 * Copyright (c) 2024 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
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
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: t_signal_and_sp.c,v 1.10 2025/04/21 12:06:08 riastradh Exp $");
31
32 #include <sys/wait.h>
33
34 #include <machine/param.h>
35
36 #include <atf-c.h>
37 #include <limits.h>
38 #include <poll.h>
39 #include <pthread.h>
40 #include <signal.h>
41 #include <stdint.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <time.h>
46 #include <ucontext.h>
47 #include <unistd.h>
48
49 #include "h_execsp.h"
50 #include "h_macros.h"
51
52 #ifdef HAVE_STACK_POINTER_H
53 # include "stack_pointer.h"
54 #endif
55
56 #ifdef HAVE_SIGNALSPHANDLER
57 void signalsphandler(int); /* signalsphandler.S assembly routine */
58 #endif
59
60 void *volatile signalsp;
61
62 static void
63 test_execsp(const struct atf_tc *tc, const char *prog)
64 {
65 #ifdef STACK_ALIGNBYTES
66 char h_execsp[PATH_MAX];
67 struct execsp execsp;
68 int fd[2];
69 pid_t pid;
70 struct pollfd pollfd;
71 int nfds;
72 ssize_t nread;
73 int status;
74
75 /*
76 * Determine the full path to the helper program.
77 */
78 RL(snprintf(h_execsp, sizeof(h_execsp), "%s/%s",
79 atf_tc_get_config_var(tc, "srcdir"), prog));
80
81 /*
82 * Create a pipe to read a bundle of stack pointer samples from
83 * the child, and fork the child.
84 */
85 RL(pipe(fd));
86 RL(pid = vfork());
87 if (pid == 0) { /* child */
88 char *const argv[] = {h_execsp, NULL};
89
90 if (dup2(fd[1], STDOUT_FILENO) == -1)
91 _exit(1);
92 if (closefrom(STDERR_FILENO + 1) == -1)
93 _exit(2);
94 if (execve(argv[0], argv, NULL) == -1)
95 _exit(3);
96 _exit(4);
97 }
98
99 /*
100 * Close the writing end so, if something goes wrong in the
101 * child, we don't hang indefinitely waiting for output.
102 */
103 RL(close(fd[1]));
104
105 /*
106 * Wait up to 5sec for the child to return an answer. Any more
107 * than that, and we kill it. The child is mostly hand-written
108 * assembly routines where lots can go wrong, so don't bother
109 * waiting if it gets stuck in a loop.
110 */
111 pollfd.fd = fd[0];
112 pollfd.events = POLLIN;
113 RL(nfds = poll(&pollfd, 1, 5*1000/*ms*/));
114 if (nfds == 0) {
115 fprintf(stderr, "child hung, killing\n");
116 RL(kill(pid, SIGKILL));
117 }
118
119 /*
120 * Read a bundle of stack pointer samples from the child.
121 */
122 RL(nread = read(fd[0], &execsp, sizeof(execsp)));
123 ATF_CHECK_MSG((size_t)nread == sizeof(execsp),
124 "nread=%zu sizeof(execsp)=%zu",
125 (size_t)nread, sizeof(execsp));
126
127 /*
128 * Wait for the child to terminate and report failure if it
129 * didn't exit cleanly.
130 */
131 RL(waitpid(pid, &status, 0));
132 if (WIFSIGNALED(status)) {
133 atf_tc_fail_nonfatal("child exited on signal %d (%s)",
134 WTERMSIG(status), strsignal(WTERMSIG(status)));
135 } else if (!WIFEXITED(status)) {
136 atf_tc_fail_nonfatal("child exited status=0x%x", status);
137 } else {
138 ATF_CHECK_MSG(WEXITSTATUS(status) == 0,
139 "child exited with code %d",
140 WEXITSTATUS(status));
141 }
142
143 /*
144 * Now that we have reaped the child, stop here if the stack
145 * pointer samples are bogus; otherwise verify they are all
146 * aligned.
147 */
148 if ((size_t)nread != sizeof(execsp))
149 return; /* failed already */
150
151 printf("start sp @ %p\n", execsp.startsp);
152 printf("ctor sp @ %p\n", execsp.ctorsp);
153 printf("main sp @ %p\n", execsp.mainsp);
154 printf("dtor sp @ %p\n", execsp.dtorsp);
155
156 ATF_CHECK_MSG(((uintptr_t)execsp.startsp & STACK_ALIGNBYTES) == 0,
157 "elf entry point was called with misaligned sp: %p",
158 execsp.startsp);
159
160 ATF_CHECK_MSG(((uintptr_t)execsp.ctorsp & STACK_ALIGNBYTES) == 0,
161 "elf constructor was called with misaligned sp: %p",
162 execsp.ctorsp);
163
164 ATF_CHECK_MSG(((uintptr_t)execsp.mainsp & STACK_ALIGNBYTES) == 0,
165 "main function was called with misaligned sp: %p",
166 execsp.mainsp);
167
168 ATF_CHECK_MSG(((uintptr_t)execsp.dtorsp & STACK_ALIGNBYTES) == 0,
169 "elf destructor was called with misaligned sp: %p",
170 execsp.dtorsp);
171
172 /*
173 * Leave a reminder on architectures for which we haven't
174 * implemented execsp_start.S.
175 */
176 if (execsp.startsp == NULL ||
177 execsp.ctorsp == NULL ||
178 execsp.mainsp == NULL ||
179 execsp.dtorsp == NULL)
180 atf_tc_skip("Not fully supported on this architecture");
181 #else
182 atf_tc_skip("Unknown STACK_ALIGNBYTES on this architecture");
183 #endif
184 }
185
186 ATF_TC(execsp_dynamic);
187 ATF_TC_HEAD(execsp_dynamic, tc)
188 {
189 atf_tc_set_md_var(tc, "descr",
190 "Verify stack pointer is aligned on dynamic program start");
191 }
192 ATF_TC_BODY(execsp_dynamic, tc)
193 {
194 test_execsp(tc, "h_execsp_dynamic");
195 }
196
197 ATF_TC(execsp_static);
198 ATF_TC_HEAD(execsp_static, tc)
199 {
200 atf_tc_set_md_var(tc, "descr",
201 "Verify stack pointer is aligned on static program start");
202 }
203 ATF_TC_BODY(execsp_static, tc)
204 {
205 test_execsp(tc, "h_execsp_static");
206 }
207
208 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC
209 void *volatile contextsp; /* set by contextspfunc.S */
210 static ucontext_t return_context;
211 static volatile bool test_context_done;
212
213 void contextspfunc(void); /* contextspfunc.S assembly routine */
214
215 static void
216 contextnoop(void)
217 {
218
219 fprintf(stderr, "contextnoop\n");
220 /* control will return to contextspfunc via uc_link */
221 }
222
223 void contextdone(void); /* called by contextspfunc.S */
224 void
225 contextdone(void)
226 {
227
228 fprintf(stderr, "contextdone\n");
229 ATF_REQUIRE(!test_context_done);
230 test_context_done = true;
231 RL(setcontext(&return_context));
232 atf_tc_fail("setcontext returned");
233 }
234 #endif
235
236 ATF_TC(contextsp);
237 ATF_TC_HEAD(contextsp, tc)
238 {
239 atf_tc_set_md_var(tc, "descr",
240 "Verify stack pointer is aligned on makecontext entry");
241 }
242 ATF_TC_BODY(contextsp, tc)
243 {
244 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC
245 ucontext_t uc;
246 char *stack;
247 unsigned i;
248
249 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL);
250 fprintf(stderr, "stack @ [%p,%p)\n", stack,
251 stack + SIGSTKSZ + STACK_ALIGNBYTES);
252
253 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
254 contextsp = NULL;
255 test_context_done = false;
256
257 RL(getcontext(&uc));
258 uc.uc_stack.ss_sp = stack;
259 uc.uc_stack.ss_size = SIGSTKSZ + i;
260 makecontext(&uc, &contextspfunc, 0);
261
262 fprintf(stderr, "[%u] swapcontext\n", i);
263 RL(swapcontext(&return_context, &uc));
264
265 ATF_CHECK(contextsp != NULL);
266 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)contextsp &&
267 (uintptr_t)contextsp <= (uintptr_t)stack + SIGSTKSZ + i,
268 "contextsp=%p", contextsp);
269 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0,
270 "[%u] makecontext function called with misaligned sp %p",
271 i, contextsp);
272 }
273
274 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
275 contextsp = NULL;
276 test_context_done = false;
277
278 RL(getcontext(&uc));
279 uc.uc_stack.ss_sp = stack + i;
280 uc.uc_stack.ss_size = SIGSTKSZ;
281 makecontext(&uc, &contextspfunc, 0);
282
283 fprintf(stderr, "[%u] swapcontext\n", i);
284 RL(swapcontext(&return_context, &uc));
285
286 ATF_CHECK(contextsp != NULL);
287 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)contextsp &&
288 (uintptr_t)contextsp <= (uintptr_t)stack + i + SIGSTKSZ,
289 "contextsp=%p", contextsp);
290 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0,
291 "[%u] makecontext function called with misaligned sp %p",
292 i, contextsp);
293 }
294 #else
295 atf_tc_skip("Not implemented on this platform");
296 #endif
297 }
298
299 ATF_TC(contextsplink);
300 ATF_TC_HEAD(contextsplink, tc)
301 {
302 atf_tc_set_md_var(tc, "descr",
303 "Verify stack pointer is aligned on makecontext link entry");
304 }
305 ATF_TC_BODY(contextsplink, tc)
306 {
307 #if defined STACK_ALIGNBYTES && defined HAVE_CONTEXTSPFUNC
308 ucontext_t uc1, uc2;
309 char *stack1, *stack2;
310 unsigned i;
311
312 REQUIRE_LIBC(stack1 = malloc(SIGSTKSZ), NULL);
313 fprintf(stderr, "stack1 @ [%p,%p)\n", stack1, stack1 + SIGSTKSZ);
314 REQUIRE_LIBC(stack2 = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL);
315 fprintf(stderr, "stack2 @ [%p,%p)\n",
316 stack2, stack2 + SIGSTKSZ + STACK_ALIGNBYTES);
317
318 #ifdef __mips_n64
319 atf_tc_expect_fail("PR kern/59327:"
320 " user stack pointer is not aligned properly");
321 #endif
322
323 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
324 contextsp = NULL;
325 test_context_done = false;
326
327 RL(getcontext(&uc1));
328 uc1.uc_stack.ss_sp = stack1;
329 uc1.uc_stack.ss_size = SIGSTKSZ;
330 uc1.uc_link = &uc2;
331 makecontext(&uc1, &contextnoop, 0);
332
333 RL(getcontext(&uc2));
334 uc2.uc_stack.ss_sp = stack2;
335 uc2.uc_stack.ss_size = SIGSTKSZ + i;
336 makecontext(&uc2, &contextspfunc, 0);
337
338 fprintf(stderr, "[%u] swapcontext\n", i);
339 RL(swapcontext(&return_context, &uc1));
340
341 ATF_CHECK(contextsp != NULL);
342 ATF_CHECK_MSG((uintptr_t)stack2 <= (uintptr_t)contextsp &&
343 (uintptr_t)contextsp <= (uintptr_t)stack2 + SIGSTKSZ + i,
344 "contextsp=%p", contextsp);
345 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0,
346 "[%u] makecontext function called with misaligned sp %p",
347 i, contextsp);
348 }
349
350 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
351 contextsp = NULL;
352 test_context_done = false;
353
354 RL(getcontext(&uc1));
355 uc1.uc_stack.ss_sp = stack1;
356 uc1.uc_stack.ss_size = SIGSTKSZ;
357 uc1.uc_link = &uc2;
358 makecontext(&uc1, &contextnoop, 0);
359
360 RL(getcontext(&uc2));
361 uc2.uc_stack.ss_sp = stack2 + i;
362 uc2.uc_stack.ss_size = SIGSTKSZ;
363 makecontext(&uc2, &contextspfunc, 0);
364
365 fprintf(stderr, "[%u] swapcontext\n", i);
366 RL(swapcontext(&return_context, &uc1));
367
368 ATF_CHECK(contextsp != NULL);
369 ATF_CHECK_MSG((uintptr_t)stack2 + i <= (uintptr_t)contextsp &&
370 (uintptr_t)contextsp <= (uintptr_t)stack2 + SIGSTKSZ + i,
371 "contextsp=%p", contextsp);
372 ATF_CHECK_MSG(((uintptr_t)contextsp & STACK_ALIGNBYTES) == 0,
373 "[%u] makecontext function called with misaligned sp %p",
374 i, contextsp);
375 }
376 #else
377 atf_tc_skip("Not implemented on this platform");
378 #endif
379 }
380
381 ATF_TC(signalsp);
382 ATF_TC_HEAD(signalsp, tc)
383 {
384 atf_tc_set_md_var(tc, "descr",
385 "Verify stack pointer is aligned on entry to signal handler");
386 }
387 ATF_TC_BODY(signalsp, tc)
388 {
389 #if defined STACK_ALIGNBYTES && defined HAVE_SIGNALSPHANDLER
390 struct sigaction sa;
391
392 memset(&sa, 0, sizeof(sa));
393 sa.sa_handler = &signalsphandler;
394 RL(sigaction(SIGUSR1, &sa, NULL));
395 RL(raise(SIGUSR1));
396
397 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0,
398 "signal handler was called with a misaligned sp: %p",
399 signalsp);
400 #else
401 atf_tc_skip("Not implemented on this platform");
402 #endif
403 }
404
405 ATF_TC(signalsp_sigaltstack);
406 ATF_TC_HEAD(signalsp_sigaltstack, tc)
407 {
408 atf_tc_set_md_var(tc, "descr",
409 "Verify stack pointer is aligned on entry to signal handler"
410 " with maximally misaligned sigaltstack");
411 }
412 ATF_TC_BODY(signalsp_sigaltstack, tc)
413 {
414 #if defined STACK_ALIGNBYTES && HAVE_SIGNALSPHANDLER
415 char *stack;
416 struct sigaction sa;
417 struct sigaltstack ss;
418 unsigned i;
419
420 memset(&sa, 0, sizeof(sa));
421 sa.sa_handler = &signalsphandler;
422 sa.sa_flags = SA_ONSTACK;
423 RL(sigaction(SIGUSR1, &sa, NULL));
424
425 /*
426 * Allocate a signal stack with enough slop to try all possible
427 * misalignments of the stack pointer. Print it to stderr so
428 * it always appears in atf output before shenanigans happen.
429 */
430 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL);
431 fprintf(stderr, "stack @ [%p, %p)\n",
432 stack, stack + SIGSTKSZ + STACK_ALIGNBYTES);
433
434 #if defined __alpha__ || defined __i386__ || defined __mips__
435 atf_tc_expect_fail("PR kern/59327:"
436 " user stack pointer is not aligned properly");
437 #endif
438
439 /*
440 * Try with all alignments of high addresses.
441 */
442 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
443 ss.ss_sp = stack;
444 ss.ss_size = SIGSTKSZ + i;
445 ss.ss_flags = 0;
446 RL(sigaltstack(&ss, NULL));
447
448 signalsp = NULL;
449 RL(raise(SIGUSR1));
450 ATF_CHECK(signalsp != NULL);
451 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)signalsp &&
452 (uintptr_t)signalsp <= (uintptr_t)stack + SIGSTKSZ + i,
453 "signalsp=%p", signalsp);
454 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0,
455 "[%u] signal handler was called with a misaligned sp: %p",
456 i, signalsp);
457 }
458
459 /*
460 * Try with all alignments of low addresses.
461 */
462 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
463 ss.ss_sp = stack + i;
464 ss.ss_size = SIGSTKSZ;
465 ss.ss_flags = 0;
466 RL(sigaltstack(&ss, NULL));
467
468 signalsp = NULL;
469 RL(raise(SIGUSR1));
470 ATF_CHECK(signalsp != NULL);
471 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)signalsp &&
472 (uintptr_t)signalsp <= (uintptr_t)stack + i + SIGSTKSZ,
473 "signalsp=%p", signalsp);
474 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0,
475 "[%u] signal handler was called with a misaligned sp: %p",
476 i, signalsp);
477 }
478 #else
479 atf_tc_skip("Not implemented on this platform");
480 #endif
481 }
482
483 #if defined STACK_ALIGNBYTES && defined HAVE_THREADSPFUNC
484 void *threadspfunc(void *); /* threadspfunc.S assembly routine */
485 #endif
486
487 ATF_TC(threadsp);
488 ATF_TC_HEAD(threadsp, tc)
489 {
490 atf_tc_set_md_var(tc, "descr",
491 "Verify stack pointer is aligned on thread start");
492 }
493 ATF_TC_BODY(threadsp, tc)
494 {
495 #if defined STACK_ALIGNBYTES && defined HAVE_THREADSPFUNC
496 char *stack;
497 unsigned i;
498
499 REQUIRE_LIBC(stack = malloc(SIGSTKSZ + STACK_ALIGNBYTES), NULL);
500 fprintf(stderr, "stack @ [%p,%p)\n", stack,
501 stack + SIGSTKSZ + STACK_ALIGNBYTES);
502
503 #ifdef __hppa__
504 atf_tc_expect_signal(SIGBUS, "PR kern/59327:"
505 " user stack pointer is not aligned properly");
506 #endif
507 #ifdef __mips__
508 atf_tc_expect_fail("PR kern/59327:"
509 " user stack pointer is not aligned properly");
510 #endif
511
512 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
513 pthread_t t;
514 pthread_attr_t attr;
515 void *sp;
516
517 RZ(pthread_attr_init(&attr));
518 RZ(pthread_attr_setstack(&attr, stack, SIGSTKSZ + i));
519 RZ(pthread_create(&t, &attr, &threadspfunc, NULL));
520 RZ(pthread_attr_destroy(&attr));
521
522 alarm(1);
523 RZ(pthread_join(t, &sp));
524 alarm(0);
525
526 ATF_CHECK(sp != NULL);
527 ATF_CHECK_MSG((uintptr_t)stack <= (uintptr_t)sp &&
528 (uintptr_t)sp <= (uintptr_t)stack + SIGSTKSZ + i,
529 "sp=%p", sp);
530 ATF_CHECK_MSG(((uintptr_t)sp & STACK_ALIGNBYTES) == 0,
531 "[%u] thread called with misaligned sp: %p", i, sp);
532 }
533
534 for (i = 0; i <= STACK_ALIGNBYTES; i++) {
535 pthread_t t;
536 pthread_attr_t attr;
537 void *sp;
538
539 RZ(pthread_attr_init(&attr));
540 RZ(pthread_attr_setstack(&attr, stack + i, SIGSTKSZ));
541 RZ(pthread_create(&t, &attr, &threadspfunc, NULL));
542 RZ(pthread_attr_destroy(&attr));
543
544 alarm(1);
545 RZ(pthread_join(t, &sp));
546 alarm(0);
547
548 ATF_CHECK(sp != NULL);
549 ATF_CHECK_MSG((uintptr_t)stack + i <= (uintptr_t)sp &&
550 (uintptr_t)sp <= (uintptr_t)stack + i + SIGSTKSZ,
551 "sp=%p", sp);
552 ATF_CHECK_MSG(((uintptr_t)sp & STACK_ALIGNBYTES) == 0,
553 "[%u] thread called with misaligned sp: %p", i, sp);
554 }
555 #else
556 atf_tc_skip("Not implemented on this platform");
557 #endif
558 }
559
560 ATF_TC(misaligned_sp_and_signal);
561 ATF_TC_HEAD(misaligned_sp_and_signal, tc)
562 {
563 atf_tc_set_md_var(tc, "descr", "process can return from a signal"
564 " handler even if the stack pointer is misaligned when a signal"
565 " arrives");
566 }
567 ATF_TC_BODY(misaligned_sp_and_signal, tc)
568 {
569 #if defined STACK_ALIGNBYTES && defined HAVE_STACK_POINTER_H
570 /*
571 * Set up a handler for SIGALRM.
572 */
573 struct sigaction sa;
574 memset(&sa, 0, sizeof(sa));
575 sa.sa_handler = &signalsphandler;
576 RL(sigaction(SIGALRM, &sa, NULL));
577
578 #if defined __alpha__ || defined __i386__ || defined __mips__
579 atf_tc_expect_fail("PR kern/58149:"
580 " Cannot return from a signal handler"
581 " if SP was misaligned when the signal arrived");
582 #endif
583
584 /*
585 * Set up an interval timer so that we receive SIGALRM after 50 ms.
586 */
587 struct itimerval itv;
588 memset(&itv, 0, sizeof(itv));
589 itv.it_value.tv_usec = 1000 * 50;
590 RL(setitimer(ITIMER_MONOTONIC, &itv, NULL));
591
592 /*
593 * Now misalign the SP. Wait for the signal to arrive and see what
594 * happens. This should be fine as long as we don't use it to
595 * access memory.
596 */
597 MISALIGN_SP;
598 while (signalsp == NULL) {
599 /*
600 * Make sure the compiler does not optimize this busy loop
601 * away.
602 */
603 __asm__("" ::: "memory");
604 }
605 /*
606 * We could successfully return from a signal handler. Now we
607 * should fix the SP before calling any functions.
608 */
609 FIX_SP;
610
611 /*
612 * But was the stack pointer aligned when we were on the signal
613 * handler?
614 */
615 ATF_CHECK_MSG(((uintptr_t)signalsp & STACK_ALIGNBYTES) == 0,
616 "signal handler was called with a misaligned sp: %p",
617 signalsp);
618 #else
619 atf_tc_skip("Not implemented for this platform");
620 #endif
621 }
622
623 ATF_TP_ADD_TCS(tp)
624 {
625
626 ATF_TP_ADD_TC(tp, contextsp);
627 ATF_TP_ADD_TC(tp, contextsplink);
628 ATF_TP_ADD_TC(tp, execsp_dynamic);
629 ATF_TP_ADD_TC(tp, execsp_static);
630 ATF_TP_ADD_TC(tp, misaligned_sp_and_signal);
631 ATF_TP_ADD_TC(tp, signalsp);
632 ATF_TP_ADD_TC(tp, signalsp_sigaltstack);
633 ATF_TP_ADD_TC(tp, threadsp);
634 return atf_no_error();
635 }
636