1 /* $NetBSD: t_ptrace_wait.h,v 1.17 2019/05/25 03:22:53 kamil Exp $ */ 2 3 /*- 4 * Copyright (c) 2016, 2017, 2018, 2019 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 /* Detect plain wait(2) use-case */ 30 #if !defined(TWAIT_WAITPID) && \ 31 !defined(TWAIT_WAITID) && \ 32 !defined(TWAIT_WAIT3) && \ 33 !defined(TWAIT_WAIT4) && \ 34 !defined(TWAIT_WAIT6) 35 #define TWAIT_WAIT 36 #endif 37 38 /* 39 * There are two classes of wait(2)-like functions: 40 * - wait4(2)-like accepting pid_t, optional options parameter, struct rusage* 41 * - wait6(2)-like accepting idtype_t, id_t, struct wrusage, mandatory options 42 * 43 * The TWAIT_FNAME value is to be used for convenience in debug messages. 44 * 45 * The TWAIT_GENERIC() macro is designed to reuse the same unmodified 46 * code with as many wait(2)-like functions as possible. 47 * 48 * In a common use-case wait4(2) and wait6(2)-like function can work the almost 49 * the same way, however there are few important differences: 50 * wait6(2) must specify P_PID for idtype to match wpid from wait4(2). 51 * To behave like wait4(2), wait6(2) the 'options' to wait must include 52 * WEXITED|WTRUNCATED. 53 * 54 * There are two helper macros (they purpose it to mach more than one 55 * wait(2)-like function): 56 * The TWAIT_HAVE_STATUS - specifies whether a function can retrieve 57 * status (as integer value). 58 * The TWAIT_HAVE_PID - specifies whether a function can request 59 * exact process identifier 60 * The TWAIT_HAVE_RUSAGE - specifies whether a function can request 61 * the struct rusage value 62 * 63 */ 64 65 #if defined(TWAIT_WAIT) 66 # define TWAIT_FNAME "wait" 67 # define TWAIT_WAIT4TYPE(a,b,c,d) wait((b)) 68 # define TWAIT_GENERIC(a,b,c) wait((b)) 69 # define TWAIT_HAVE_STATUS 1 70 #elif defined(TWAIT_WAITPID) 71 # define TWAIT_FNAME "waitpid" 72 # define TWAIT_WAIT4TYPE(a,b,c,d) waitpid((a),(b),(c)) 73 # define TWAIT_GENERIC(a,b,c) waitpid((a),(b),(c)) 74 # define TWAIT_HAVE_PID 1 75 # define TWAIT_HAVE_STATUS 1 76 #elif defined(TWAIT_WAITID) 77 # define TWAIT_FNAME "waitid" 78 # define TWAIT_GENERIC(a,b,c) \ 79 waitid(P_PID,(a),NULL,(c)|WEXITED|WTRAPPED) 80 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) waitid((a),(b),(f),(d)) 81 # define TWAIT_HAVE_PID 1 82 #elif defined(TWAIT_WAIT3) 83 # define TWAIT_FNAME "wait3" 84 # define TWAIT_WAIT4TYPE(a,b,c,d) wait3((b),(c),(d)) 85 # define TWAIT_GENERIC(a,b,c) wait3((b),(c),NULL) 86 # define TWAIT_HAVE_STATUS 1 87 # define TWAIT_HAVE_RUSAGE 1 88 #elif defined(TWAIT_WAIT4) 89 # define TWAIT_FNAME "wait4" 90 # define TWAIT_WAIT4TYPE(a,b,c,d) wait4((a),(b),(c),(d)) 91 # define TWAIT_GENERIC(a,b,c) wait4((a),(b),(c),NULL) 92 # define TWAIT_HAVE_PID 1 93 # define TWAIT_HAVE_STATUS 1 94 # define TWAIT_HAVE_RUSAGE 1 95 #elif defined(TWAIT_WAIT6) 96 # define TWAIT_FNAME "wait6" 97 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) wait6((a),(b),(c),(d),(e),(f)) 98 # define TWAIT_GENERIC(a,b,c) \ 99 wait6(P_PID,(a),(b),(c)|WEXITED|WTRAPPED,NULL,NULL) 100 # define TWAIT_HAVE_PID 1 101 # define TWAIT_HAVE_STATUS 1 102 #endif 103 104 /* 105 * There are 3 groups of tests: 106 * - TWAIT_GENERIC() (wait, wait2, waitpid, wait3, wait4, wait6) 107 * - TWAIT_WAIT4TYPE() (wait2, waitpid, wait3, wait4) 108 * - TWAIT_WAIT6TYPE() (waitid, wait6) 109 * 110 * Tests only in the above categories are allowed. However some tests are not 111 * possible in the context requested functionality to be verified, therefore 112 * there are helper macros: 113 * - TWAIT_HAVE_PID (wait2, waitpid, waitid, wait4, wait6) 114 * - TWAIT_HAVE_STATUS (wait, wait2, waitpid, wait3, wait4, wait6) 115 * - TWAIT_HAVE_RUSAGE (wait3, wait4) 116 * - TWAIT_HAVE_RETPID (wait, wait2, waitpid, wait3, wait4, wait6) 117 * 118 * If there is an intention to test e.g. wait6(2) specific features in the 119 * ptrace(2) context, find the most matching group and with #ifdefs reduce 120 * functionality of less featured than wait6(2) interface (TWAIT_WAIT6TYPE). 121 * 122 * For clarity never use negative preprocessor checks, like: 123 * #if !defined(TWAIT_WAIT4) 124 * always refer to checks for positive values. 125 */ 126 127 #define TEST_REQUIRE_EQ(x, y) \ 128 do { \ 129 uintmax_t vx = (x); \ 130 uintmax_t vy = (y); \ 131 int ret = vx == vy; \ 132 if (!ret) \ 133 ATF_REQUIRE_EQ_MSG(vx, vy, "%s(%ju) == %s(%ju)", \ 134 #x, vx, #y, vy); \ 135 } while (/*CONSTCOND*/0) 136 137 /* 138 * A child process cannot call atf functions and expect them to magically 139 * work like in the parent. 140 * The printf(3) messaging from a child will not work out of the box as well 141 * without estabilishing a communication protocol with its parent. To not 142 * overcomplicate the tests - do not log from a child and use err(3)/errx(3) 143 * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work. 144 */ 145 #define FORKEE_ASSERT_EQ(x, y) \ 146 do { \ 147 uintmax_t vx = (x); \ 148 uintmax_t vy = (y); \ 149 int ret = vx == vy; \ 150 if (!ret) \ 151 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \ 152 "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__, \ 153 #x, vx, #y, vy); \ 154 } while (/*CONSTCOND*/0) 155 156 #define FORKEE_ASSERT_NEQ(x, y) \ 157 do { \ 158 uintmax_t vx = (x); \ 159 uintmax_t vy = (y); \ 160 int ret = vx != vy; \ 161 if (!ret) \ 162 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \ 163 "%s(%ju) != %s(%ju)", __FILE__, __LINE__, __func__, \ 164 #x, vx, #y, vy); \ 165 } while (/*CONSTCOND*/0) 166 167 #define FORKEE_ASSERTX(x) \ 168 do { \ 169 int ret = (x); \ 170 if (!ret) \ 171 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\ 172 __FILE__, __LINE__, __func__, #x); \ 173 } while (/*CONSTCOND*/0) 174 175 #define FORKEE_ASSERT(x) \ 176 do { \ 177 int ret = (x); \ 178 if (!ret) \ 179 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\ 180 __FILE__, __LINE__, __func__, #x); \ 181 } while (/*CONSTCOND*/0) 182 183 /* 184 * Simplify logic for functions using general purpose registers add HAVE_GPREGS 185 * 186 * For platforms that do not implement all needed calls for simplicity assume 187 * that they are unsupported at all. 188 */ 189 #if defined(PT_GETREGS) \ 190 && defined(PT_SETREGS) \ 191 && defined(PTRACE_REG_PC) \ 192 && defined(PTRACE_REG_SET_PC) \ 193 && defined(PTRACE_REG_SP) \ 194 && defined(PTRACE_REG_INTRV) 195 #define HAVE_GPREGS 196 #endif 197 198 /* Add guards for floating point registers */ 199 #if defined(PT_GETFPREGS) \ 200 && defined(PT_SETFPREGS) 201 #define HAVE_FPREGS 202 #endif 203 204 /* Add guards for cpu debug registers */ 205 #if defined(PT_GETDBREGS) \ 206 && defined(PT_SETDBREGS) 207 #define HAVE_DBREGS 208 #endif 209 210 /* 211 * If waitid(2) returns because one or more processes have a state change to 212 * report, 0 is returned. If an error is detected, a value of -1 is returned 213 * and errno is set to indicate the error. If WNOHANG is specified and there 214 * are no stopped, continued or exited children, 0 is returned. 215 */ 216 #if defined(TWAIT_WAITID) 217 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), 0) 218 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1) 219 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, 0) 220 #define FORKEE_REQUIRE_FAILURE(a,b) \ 221 FORKEE_ASSERTX(((a) == errno) && ((b) == -1)) 222 #else 223 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), (b)) 224 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1) 225 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, b) 226 #define FORKEE_REQUIRE_FAILURE(a,b) \ 227 FORKEE_ASSERTX(((a) == errno) && ((b) == -1)) 228 #endif 229 230 /* 231 * Helper tools to verify whether status reports exited value 232 */ 233 #if TWAIT_HAVE_STATUS 234 static void __used 235 validate_status_exited(int status, int expected) 236 { 237 ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process"); 238 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 239 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 240 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 241 242 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected, 243 "The process has exited with invalid value %d != %d", 244 WEXITSTATUS(status), expected); 245 } 246 247 static void __used 248 forkee_status_exited(int status, int expected) 249 { 250 FORKEE_ASSERTX(WIFEXITED(status)); 251 FORKEE_ASSERTX(!WIFCONTINUED(status)); 252 FORKEE_ASSERTX(!WIFSIGNALED(status)); 253 FORKEE_ASSERTX(!WIFSTOPPED(status)); 254 255 FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected); 256 } 257 258 static void __used 259 validate_status_continued(int status) 260 { 261 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 262 ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process"); 263 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 264 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 265 } 266 267 static void __used 268 forkee_status_continued(int status) 269 { 270 FORKEE_ASSERTX(!WIFEXITED(status)); 271 FORKEE_ASSERTX(WIFCONTINUED(status)); 272 FORKEE_ASSERTX(!WIFSIGNALED(status)); 273 FORKEE_ASSERTX(!WIFSTOPPED(status)); 274 } 275 276 static void __used 277 validate_status_signaled(int status, int expected_termsig, int expected_core) 278 { 279 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 280 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 281 ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process"); 282 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 283 284 ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig, 285 "Unexpected signal received"); 286 287 ATF_REQUIRE_EQ_MSG(!!WCOREDUMP(status), expected_core, 288 "Unexpectedly core file %s generated", expected_core ? "not" : ""); 289 } 290 291 static void __used 292 forkee_status_signaled(int status, int expected_termsig, int expected_core) 293 { 294 FORKEE_ASSERTX(!WIFEXITED(status)); 295 FORKEE_ASSERTX(!WIFCONTINUED(status)); 296 FORKEE_ASSERTX(WIFSIGNALED(status)); 297 FORKEE_ASSERTX(!WIFSTOPPED(status)); 298 299 FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig); 300 FORKEE_ASSERT_EQ(!!WCOREDUMP(status), expected_core); 301 } 302 303 static void __used 304 validate_status_stopped(int status, int expected) 305 { 306 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 307 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 308 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 309 ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process"); 310 311 char st[128], ex[128]; 312 strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st)); 313 strlcpy(ex, strsignal(expected), sizeof(ex)); 314 315 ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected, 316 "Unexpected stop signal received [%s] != [%s]", st, ex); 317 } 318 319 static void __used 320 forkee_status_stopped(int status, int expected) 321 { 322 FORKEE_ASSERTX(!WIFEXITED(status)); 323 FORKEE_ASSERTX(!WIFCONTINUED(status)); 324 FORKEE_ASSERTX(!WIFSIGNALED(status)); 325 FORKEE_ASSERTX(WIFSTOPPED(status)); 326 327 FORKEE_ASSERT_EQ(WSTOPSIG(status), expected); 328 } 329 #else 330 #define validate_status_exited(a,b) 331 #define forkee_status_exited(a,b) 332 #define validate_status_continued(a,b) 333 #define forkee_status_continued(a,b) 334 #define validate_status_signaled(a,b,c) 335 #define forkee_status_signaled(a,b,c) 336 #define validate_status_stopped(a,b) 337 #define forkee_status_stopped(a,b) 338 #endif 339 340 /* This function is currently designed to be run in the main/parent process */ 341 static void __used 342 await_zombie_raw(pid_t process, useconds_t ms) 343 { 344 struct kinfo_proc2 p; 345 size_t len = sizeof(p); 346 347 const int name[] = { 348 [0] = CTL_KERN, 349 [1] = KERN_PROC2, 350 [2] = KERN_PROC_PID, 351 [3] = process, 352 [4] = sizeof(p), 353 [5] = 1 354 }; 355 356 const size_t namelen = __arraycount(name); 357 358 /* Await the process becoming a zombie */ 359 while(1) { 360 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0); 361 362 if (p.p_stat == LSZOMB) 363 break; 364 365 if (ms > 0) { 366 ATF_REQUIRE(usleep(ms) == 0); 367 } 368 } 369 } 370 371 static void __used 372 await_zombie(pid_t process) 373 { 374 375 await_zombie_raw(process, 1000); 376 } 377 378 static void __used 379 await_stopped(pid_t process) 380 { 381 struct kinfo_proc2 p; 382 size_t len = sizeof(p); 383 384 const int name[] = { 385 [0] = CTL_KERN, 386 [1] = KERN_PROC2, 387 [2] = KERN_PROC_PID, 388 [3] = process, 389 [4] = sizeof(p), 390 [5] = 1 391 }; 392 393 const size_t namelen = __arraycount(name); 394 395 /* Await the process becoming a zombie */ 396 while(1) { 397 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0); 398 399 if (p.p_stat == LSSTOP) 400 break; 401 402 ATF_REQUIRE(usleep(1000) == 0); 403 } 404 } 405 406 static pid_t __used 407 await_stopped_child(pid_t process) 408 { 409 struct kinfo_proc2 *p = NULL; 410 size_t i, len; 411 pid_t child = -1; 412 413 int name[] = { 414 [0] = CTL_KERN, 415 [1] = KERN_PROC2, 416 [2] = KERN_PROC_ALL, 417 [3] = 0, 418 [4] = sizeof(struct kinfo_proc2), 419 [5] = 0 420 }; 421 422 const size_t namelen = __arraycount(name); 423 424 /* Await the process becoming a zombie */ 425 while(1) { 426 name[5] = 0; 427 428 FORKEE_ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0); 429 430 FORKEE_ASSERT_EQ(reallocarr(&p, 431 len, 432 sizeof(struct kinfo_proc2)), 0); 433 434 name[5] = len; 435 436 FORKEE_ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0); 437 438 for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) { 439 if (p[i].p_pid == getpid()) 440 continue; 441 if (p[i].p_ppid != process) 442 continue; 443 if (p[i].p_stat != LSSTOP) 444 continue; 445 child = p[i].p_pid; 446 break; 447 } 448 449 if (child != -1) 450 break; 451 452 FORKEE_ASSERT_EQ(usleep(1000), 0); 453 } 454 455 /* Free the buffer */ 456 FORKEE_ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0); 457 458 return child; 459 } 460 461 /* Happy number sequence -- this function is used to just consume cpu cycles */ 462 #define HAPPY_NUMBER 1 463 464 /* If n is not happy then its sequence ends in the cycle: 465 * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */ 466 #define SAD_NUMBER 4 467 468 /* Calculate the sum of the squares of the digits of n */ 469 static unsigned __used 470 dsum(unsigned n) 471 { 472 unsigned sum, x; 473 for (sum = 0; n; n /= 10) { 474 x = n % 10; 475 sum += x * x; 476 } 477 return sum; 478 } 479 480 /* 481 * XXX: Disabled optimization is required to make tests for hardware assisted 482 * traps in .text functional 483 * 484 * Tested with GCC 5.4 on NetBSD 7.99.47 amd64 485 */ 486 static int __used 487 #ifdef __clang__ 488 __attribute__((__optnone__)) 489 #else 490 __attribute__((__optimize__("O0"))) 491 #endif 492 check_happy(unsigned n) 493 { 494 for (;;) { 495 unsigned total = dsum(n); 496 497 if (total == HAPPY_NUMBER) 498 return 1; 499 if (total == SAD_NUMBER) 500 return 0; 501 502 n = total; 503 } 504 } 505 506 static void * __used 507 infinite_thread(void *arg __unused) 508 { 509 510 while (true) 511 continue; 512 513 __unreachable(); 514 } 515 516 static int __used 517 clone_func(void *arg) 518 { 519 int ret; 520 521 ret = (int)(intptr_t)arg; 522 523 return ret; 524 } 525 526 #if defined(HAVE_DBREGS) 527 static bool __used 528 can_we_set_dbregs(void) 529 { 530 static long euid = -1; 531 static int user_set_dbregs = -1; 532 size_t user_set_dbregs_len = sizeof(user_set_dbregs); 533 534 if (euid == -1) 535 euid = geteuid(); 536 537 if (euid == 0) 538 return true; 539 540 if (user_set_dbregs == -1) { 541 if (sysctlbyname("security.models.extensions.user_set_dbregs", 542 &user_set_dbregs, &user_set_dbregs_len, NULL, 0) 543 == -1) { 544 return false; 545 } 546 } 547 548 if (user_set_dbregs > 0) 549 return true; 550 else 551 return false; 552 } 553 #endif 554 555 static bool __used 556 get_user_va0_disable(void) 557 { 558 static int user_va0_disable = -1; 559 size_t user_va0_disable_len = sizeof(user_va0_disable); 560 561 if (user_va0_disable == -1) { 562 if (sysctlbyname("vm.user_va0_disable", 563 &user_va0_disable, &user_va0_disable_len, NULL, 0) 564 == -1) { 565 return true; 566 } 567 } 568 569 if (user_va0_disable > 0) 570 return true; 571 else 572 return false; 573 } 574 575 static bool __used 576 can_we_write_to_text(pid_t pid) 577 { 578 int mib[3]; 579 int paxflags; 580 size_t len = sizeof(int); 581 582 mib[0] = CTL_PROC; 583 mib[1] = pid; 584 mib[2] = PROC_PID_PAXFLAGS; 585 586 if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1) 587 return false; 588 589 return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT); 590 } 591 592 static void __used 593 trigger_trap(void) 594 { 595 596 /* Software breakpoint causes CPU trap, translated to SIGTRAP */ 597 #ifdef PTRACE_BREAKPOINT_ASM 598 PTRACE_BREAKPOINT_ASM; 599 #else 600 /* port me */ 601 #endif 602 } 603 604 static void __used 605 trigger_segv(void) 606 { 607 static volatile char *ptr = NULL; 608 609 /* Access to unmapped memory causes CPU trap, translated to SIGSEGV */ 610 *ptr = 1; 611 } 612 613 static void __used 614 trigger_ill(void) 615 { 616 617 /* Illegal instruction causes CPU trap, translated to SIGILL */ 618 #ifdef PTRACE_ILLEGAL_ASM 619 PTRACE_ILLEGAL_ASM; 620 #else 621 /* port me */ 622 #endif 623 } 624 625 static bool __used 626 are_fpu_exceptions_supported(void) 627 { 628 #if (__arm__ && !__SOFTFP__) || __aarch64__ 629 /* 630 * Some NEON fpus do not trap on IEEE 754 FP exceptions. 631 * Skip these tests if running on them and compiled for 632 * hard float. 633 */ 634 if (0 == fpsetmask(fpsetmask(FP_X_INV))) 635 return false; 636 #endif 637 return true; 638 } 639 640 static void __used 641 trigger_fpe(void) 642 { 643 volatile int a = getpid(); 644 volatile int b = atoi("0"); 645 646 #ifdef __HAVE_FENV 647 feenableexcept(FE_ALL_EXCEPT); 648 #endif 649 650 /* Division by zero causes CPU trap, translated to SIGFPE */ 651 usleep(a / b); 652 } 653 654 static void __used 655 trigger_bus(void) 656 { 657 FILE *fp; 658 char *p; 659 660 /* Open an empty file for writing. */ 661 fp = tmpfile(); 662 FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL); 663 664 /* 665 * Map an empty file with mmap(2) to a pointer. 666 * 667 * PROT_READ handles read-modify-write sequences emitted for 668 * certain combinations of CPUs and compilers (e.g. Alpha AXP). 669 */ 670 p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 671 FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED); 672 673 /* Invalid memory access causes CPU trap, translated to SIGBUS */ 674 *p = 'a'; 675 } 676 677 #if defined(TWAIT_HAVE_PID) 678 #define ATF_TP_ADD_TC_HAVE_PID(a,b) ATF_TP_ADD_TC(a,b) 679 #else 680 #define ATF_TP_ADD_TC_HAVE_PID(a,b) 681 #endif 682 683 #if defined(HAVE_GPREGS) 684 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) ATF_TP_ADD_TC(a,b) 685 #else 686 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) 687 #endif 688 689 #if defined(HAVE_FPREGS) 690 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) ATF_TP_ADD_TC(a,b) 691 #else 692 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) 693 #endif 694 695 #if defined(HAVE_DBREGS) 696 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b) 697 #else 698 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) 699 #endif 700 701 #if defined(PT_STEP) 702 #define ATF_TP_ADD_TC_PT_STEP(a,b) ATF_TP_ADD_TC(a,b) 703 #else 704 #define ATF_TP_ADD_TC_PT_STEP(a,b) 705 #endif 706