Home | History | Annotate | Line # | Download | only in sys
t_ptrace_wait.h revision 1.38
      1 /*	$NetBSD: t_ptrace_wait.h,v 1.38 2025/05/02 02:24:44 riastradh 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 #	define TWAIT_HAVE_OPTIONS		1
     77 #elif defined(TWAIT_WAITID)
     78 #	define TWAIT_FNAME			"waitid"
     79 #	define TWAIT_GENERIC(a,b,c)		\
     80 		waitid(P_PID,(a),NULL,(c)|WEXITED|WTRAPPED)
     81 #	define TWAIT_WAIT6TYPE(a,b,c,d,e,f)	waitid((a),(b),(f),(d))
     82 #	define TWAIT_HAVE_PID			1
     83 #	define TWAIT_HAVE_OPTIONS		1
     84 #elif defined(TWAIT_WAIT3)
     85 #	define TWAIT_FNAME			"wait3"
     86 #	define TWAIT_WAIT4TYPE(a,b,c,d)		wait3((b),(c),(d))
     87 #	define TWAIT_GENERIC(a,b,c)		wait3((b),(c),NULL)
     88 #	define TWAIT_HAVE_STATUS		1
     89 #	define TWAIT_HAVE_RUSAGE		1
     90 #	define TWAIT_HAVE_OPTIONS		1
     91 #elif defined(TWAIT_WAIT4)
     92 #	define TWAIT_FNAME			"wait4"
     93 #	define TWAIT_WAIT4TYPE(a,b,c,d)		wait4((a),(b),(c),(d))
     94 #	define TWAIT_GENERIC(a,b,c)		wait4((a),(b),(c),NULL)
     95 #	define TWAIT_HAVE_PID			1
     96 #	define TWAIT_HAVE_STATUS		1
     97 #	define TWAIT_HAVE_RUSAGE		1
     98 #	define TWAIT_HAVE_OPTIONS		1
     99 #elif defined(TWAIT_WAIT6)
    100 #	define TWAIT_FNAME			"wait6"
    101 #	define TWAIT_WAIT6TYPE(a,b,c,d,e,f)	wait6((a),(b),(c),(d),(e),(f))
    102 #	define TWAIT_GENERIC(a,b,c)		\
    103 		wait6(P_PID,(a),(b),(c)|WEXITED|WTRAPPED,NULL,NULL)
    104 #	define TWAIT_HAVE_PID			1
    105 #	define TWAIT_HAVE_STATUS		1
    106 #	define TWAIT_HAVE_OPTIONS		1
    107 #endif
    108 
    109 /*
    110  * There are 3 groups of tests:
    111  * - TWAIT_GENERIC()	(wait, wait2, waitpid, wait3, wait4, wait6)
    112  * - TWAIT_WAIT4TYPE()	(wait2, waitpid, wait3, wait4)
    113  * - TWAIT_WAIT6TYPE()	(waitid, wait6)
    114  *
    115  * Tests only in the above categories are allowed. However some tests are not
    116  * possible in the context requested functionality to be verified, therefore
    117  * there are helper macros:
    118  * - TWAIT_HAVE_PID	(wait2, waitpid, waitid, wait4, wait6)
    119  * - TWAIT_HAVE_STATUS	(wait, wait2, waitpid, wait3, wait4, wait6)
    120  * - TWAIT_HAVE_RUSAGE	(wait3, wait4)
    121  * - TWAIT_HAVE_RETPID	(wait, wait2, waitpid, wait3, wait4, wait6)
    122  *
    123  * If there is an intention to test e.g. wait6(2) specific features in the
    124  * ptrace(2) context, find the most matching group and with #ifdefs reduce
    125  * functionality of less featured than wait6(2) interface (TWAIT_WAIT6TYPE).
    126  *
    127  * For clarity never use negative preprocessor checks, like:
    128  *     #if !defined(TWAIT_WAIT4)
    129  * always refer to checks for positive values.
    130  */
    131 
    132 #define TEST_REQUIRE_EQ(x, y)						\
    133 do {									\
    134 	uintmax_t vx = (x);						\
    135 	uintmax_t vy = (y);						\
    136 	int ret = vx == vy;						\
    137 	if (!ret)							\
    138 		ATF_REQUIRE_EQ_MSG(vx, vy, "%s(%ju) == %s(%ju)", 	\
    139 		    #x, vx, #y, vy);					\
    140 } while (/*CONSTCOND*/0)
    141 
    142 /*
    143  * A child process cannot call atf functions and expect them to magically
    144  * work like in the parent.
    145  * The printf(3) messaging from a child will not work out of the box as well
    146  * without establishing a communication protocol with its parent. To not
    147  * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
    148  * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work.
    149  */
    150 #define FORKEE_ASSERT_EQ(x, y)						\
    151 do {									\
    152 	uintmax_t vx = (x);						\
    153 	uintmax_t vy = (y);						\
    154 	int ret = vx == vy;						\
    155 	if (!ret)							\
    156 		errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: "	\
    157 		    "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__,	\
    158 		    #x, vx, #y, vy);					\
    159 } while (/*CONSTCOND*/0)
    160 
    161 #define FORKEE_ASSERT_NEQ(x, y)						\
    162 do {									\
    163 	uintmax_t vx = (x);						\
    164 	uintmax_t vy = (y);						\
    165 	int ret = vx != vy;						\
    166 	if (!ret)							\
    167 		errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: "	\
    168 		    "%s(%ju) != %s(%ju)", __FILE__, __LINE__, __func__,	\
    169 		    #x, vx, #y, vy);					\
    170 } while (/*CONSTCOND*/0)
    171 
    172 __unused	/* used by FORKEE_ASSERT_MEMEQ, otherwise not used */
    173 static void
    174 hexdump(const char *title, const void *buf, size_t len)
    175 {
    176 	const unsigned char *p = buf;
    177 	size_t i;
    178 
    179 	fprintf(stderr, "%s (%zu bytes)\n", title, len);
    180 	for (i = 0; i < len; i++) {
    181 		if ((i % 8) == 0)
    182 			fprintf(stderr, " ");
    183 		fprintf(stderr, "%02hhx", p[i]);
    184 		if ((i % 16) == 0)
    185 			fprintf(stderr, "\n");
    186 	}
    187 	if (i % 16)
    188 		fprintf(stderr, "\n");
    189 }
    190 
    191 #define	FORKEE_ASSERT_MEMEQ(x, y, n)					\
    192 do {									\
    193 	const void *const vx = (x);					\
    194 	const void *const vy = (y);					\
    195 	const size_t vn = (n);						\
    196 									\
    197 	if (__predict_true(memcmp(vx, vy, vn) == 0))			\
    198 		break;							\
    199 	fprintf(stderr, "%s != %s (%s = %zu bytes)\n", #x, #y, #n, vn);	\
    200 	hexdump(#x, vx, vn);						\
    201 	hexdump(#y, vy, vn);						\
    202 } while (/*CONSTCOND*/0)
    203 
    204 #define FORKEE_ASSERTX(x)						\
    205 do {									\
    206 	int ret = (x);							\
    207 	if (!ret)							\
    208 		errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
    209 		     __FILE__, __LINE__, __func__, #x);			\
    210 } while (/*CONSTCOND*/0)
    211 
    212 #define FORKEE_ASSERT(x)						\
    213 do {									\
    214 	int ret = (x);							\
    215 	if (!ret)							\
    216 		err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
    217 		     __FILE__, __LINE__, __func__, #x);			\
    218 } while (/*CONSTCOND*/0)
    219 
    220 #define	FORKEE_PTHREAD(x)						\
    221 do {									\
    222 	int _forkee_pthread_error = (x);				\
    223 	if (_forkee_pthread_error) {					\
    224 		errno = _forkee_pthread_error;				\
    225 		err(EXIT_FAILURE, "%s:%d %s(): %s", __FILE__, __LINE__,	\
    226 		    __func__, #x);					\
    227 	}								\
    228 } while (/*CONSTCOND*/0)
    229 
    230 /*
    231  * Simplify logic for functions using general purpose registers add HAVE_GPREGS
    232  *
    233  * For platforms that do not implement all needed calls for simplicity assume
    234  * that they are unsupported at all.
    235  */
    236 #if defined(PT_GETREGS)			\
    237     && defined(PT_SETREGS)		\
    238     && defined(PTRACE_REG_PC)		\
    239     && defined(PTRACE_REG_SET_PC)	\
    240     && defined(PTRACE_REG_SP)		\
    241     && defined(PTRACE_REG_INTRV)
    242 #define HAVE_GPREGS
    243 #endif
    244 
    245 /* Add guards for floating point registers */
    246 #if defined(PT_GETFPREGS)		\
    247     && defined(PT_SETFPREGS)
    248 #define HAVE_FPREGS
    249 #endif
    250 
    251 /* Add guards for cpu debug registers */
    252 #if defined(PT_GETDBREGS)		\
    253     && defined(PT_SETDBREGS)
    254 #define HAVE_DBREGS
    255 #endif
    256 
    257 /*
    258  * If waitid(2) returns because one or more processes have a state change to
    259  * report, 0 is returned.  If an error is detected, a value of -1 is returned
    260  * and errno is set to indicate the error. If WNOHANG is specified and there
    261  * are no stopped, continued or exited children, 0 is returned.
    262  */
    263 #if defined(TWAIT_WAITID)
    264 #define TWAIT_REQUIRE_SUCCESS(a,b)	TEST_REQUIRE_EQ((a), 0)
    265 #define TWAIT_REQUIRE_FAILURE(a,b)	ATF_REQUIRE_ERRNO((a),(b) == -1)
    266 #define FORKEE_REQUIRE_SUCCESS(a,b)	FORKEE_ASSERT_EQ(a, 0)
    267 #define FORKEE_REQUIRE_FAILURE(a,b)	\
    268 	FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
    269 #else
    270 #define TWAIT_REQUIRE_SUCCESS(a,b)	TEST_REQUIRE_EQ((a), (b))
    271 #define TWAIT_REQUIRE_FAILURE(a,b)	ATF_REQUIRE_ERRNO((a),(b) == -1)
    272 #define FORKEE_REQUIRE_SUCCESS(a,b)	FORKEE_ASSERT_EQ(a, b)
    273 #define FORKEE_REQUIRE_FAILURE(a,b)	\
    274 	FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
    275 #endif
    276 
    277 /*
    278  * Helper tools to verify whether status reports exited value
    279  */
    280 #if TWAIT_HAVE_STATUS
    281 static void __used
    282 validate_status_exited(int status, int expected)
    283 {
    284         ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process");
    285         ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
    286         ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
    287         ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
    288 
    289 	ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected,
    290 	    "The process has exited with invalid value %d != %d",
    291 	    WEXITSTATUS(status), expected);
    292 }
    293 
    294 static void __used
    295 forkee_status_exited(int status, int expected)
    296 {
    297 	FORKEE_ASSERTX(WIFEXITED(status));
    298 	FORKEE_ASSERTX(!WIFCONTINUED(status));
    299 	FORKEE_ASSERTX(!WIFSIGNALED(status));
    300 	FORKEE_ASSERTX(!WIFSTOPPED(status));
    301 
    302 	FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected);
    303 }
    304 
    305 static void __used
    306 validate_status_continued(int status)
    307 {
    308 	ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
    309 	ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process");
    310 	ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
    311 	ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
    312 }
    313 
    314 static void __used
    315 forkee_status_continued(int status)
    316 {
    317 	FORKEE_ASSERTX(!WIFEXITED(status));
    318 	FORKEE_ASSERTX(WIFCONTINUED(status));
    319 	FORKEE_ASSERTX(!WIFSIGNALED(status));
    320 	FORKEE_ASSERTX(!WIFSTOPPED(status));
    321 }
    322 
    323 static void __used
    324 validate_status_signaled(int status, int expected_termsig, int expected_core)
    325 {
    326 	ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
    327 	ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
    328 	ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process");
    329 	ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
    330 
    331 	ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig,
    332 	    "Unexpected signal received");
    333 
    334 	ATF_REQUIRE_EQ_MSG(!!WCOREDUMP(status), expected_core,
    335 	    "Unexpectedly core file %s generated", expected_core ? "not" : "");
    336 }
    337 
    338 static void __used
    339 forkee_status_signaled(int status, int expected_termsig, int expected_core)
    340 {
    341 	FORKEE_ASSERTX(!WIFEXITED(status));
    342 	FORKEE_ASSERTX(!WIFCONTINUED(status));
    343 	FORKEE_ASSERTX(WIFSIGNALED(status));
    344 	FORKEE_ASSERTX(!WIFSTOPPED(status));
    345 
    346 	FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig);
    347 	FORKEE_ASSERT_EQ(!!WCOREDUMP(status), expected_core);
    348 }
    349 
    350 static void __used
    351 validate_status_stopped(int status, int expected)
    352 {
    353 	ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
    354 	ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
    355 	ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
    356 	ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process");
    357 
    358 	char st[128], ex[128];
    359 	strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st));
    360 	strlcpy(ex, strsignal(expected), sizeof(ex));
    361 
    362 	ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected,
    363 	    "Unexpected stop signal received [%s] != [%s]", st, ex);
    364 }
    365 
    366 static void __used
    367 forkee_status_stopped(int status, int expected)
    368 {
    369 	FORKEE_ASSERTX(!WIFEXITED(status));
    370 	FORKEE_ASSERTX(!WIFCONTINUED(status));
    371 	FORKEE_ASSERTX(!WIFSIGNALED(status));
    372 	FORKEE_ASSERTX(WIFSTOPPED(status));
    373 
    374 	FORKEE_ASSERT_EQ(WSTOPSIG(status), expected);
    375 }
    376 #else
    377 #define validate_status_exited(a,b)
    378 #define forkee_status_exited(a,b)
    379 #define validate_status_continued(a,b)
    380 #define forkee_status_continued(a,b)
    381 #define validate_status_signaled(a,b,c)
    382 #define forkee_status_signaled(a,b,c)
    383 #define validate_status_stopped(a,b)
    384 #define forkee_status_stopped(a,b)
    385 #endif
    386 
    387 /* This function is currently designed to be run in the main/parent process */
    388 static void __used
    389 await_zombie_raw(pid_t process, useconds_t ms)
    390 {
    391 	struct kinfo_proc2 p;
    392 	size_t len = sizeof(p);
    393 
    394 	const int name[] = {
    395 		[0] = CTL_KERN,
    396 		[1] = KERN_PROC2,
    397 		[2] = KERN_PROC_PID,
    398 		[3] = process,
    399 		[4] = sizeof(p),
    400 		[5] = 1
    401 	};
    402 
    403 	const size_t namelen = __arraycount(name);
    404 
    405 	/* Await the process becoming a zombie */
    406 	while(1) {
    407 		ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
    408 
    409 		if (p.p_stat == LSZOMB)
    410 			break;
    411 
    412 		if (ms > 0) {
    413 			ATF_REQUIRE(usleep(ms) == 0);
    414 		}
    415 	}
    416 }
    417 
    418 static void __used
    419 await_zombie(pid_t process)
    420 {
    421 
    422 	await_zombie_raw(process, 1000);
    423 }
    424 
    425 static void __used
    426 await_stopped(pid_t process)
    427 {
    428 	struct kinfo_proc2 p;
    429 	size_t len = sizeof(p);
    430 
    431 	const int name[] = {
    432 		[0] = CTL_KERN,
    433 		[1] = KERN_PROC2,
    434 		[2] = KERN_PROC_PID,
    435 		[3] = process,
    436 		[4] = sizeof(p),
    437 		[5] = 1
    438 	};
    439 
    440 	const size_t namelen = __arraycount(name);
    441 
    442 	/* Await the process becoming a zombie */
    443 	while(1) {
    444 		ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
    445 
    446 		if (p.p_stat == LSSTOP)
    447 			break;
    448 
    449 		ATF_REQUIRE(usleep(1000) == 0);
    450 	}
    451 }
    452 
    453 static pid_t __used
    454 await_stopped_child(pid_t process)
    455 {
    456 	struct kinfo_proc2 *p = NULL;
    457 	size_t i, len;
    458 	pid_t child = -1;
    459 
    460 	int name[] = {
    461 		[0] = CTL_KERN,
    462 		[1] = KERN_PROC2,
    463 		[2] = KERN_PROC_ALL,
    464 		[3] = 0,
    465 		[4] = sizeof(struct kinfo_proc2),
    466 		[5] = 0
    467 	};
    468 
    469 	const size_t namelen = __arraycount(name);
    470 
    471 	/* Await the process becoming a zombie */
    472 	while(1) {
    473 		name[5] = 0;
    474 
    475 		FORKEE_ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
    476 
    477 		FORKEE_ASSERT_EQ(reallocarr(&p,
    478 		                            len,
    479 		                            sizeof(struct kinfo_proc2)), 0);
    480 
    481 		name[5] = len;
    482 
    483 		FORKEE_ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
    484 
    485 		for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
    486 			if (p[i].p_pid == getpid())
    487 				continue;
    488 			if (p[i].p_ppid != process)
    489 				continue;
    490 			if (p[i].p_stat != LSSTOP)
    491 				continue;
    492 			child = p[i].p_pid;
    493 			break;
    494 		}
    495 
    496 		if (child != -1)
    497 			break;
    498 
    499 		FORKEE_ASSERT_EQ(usleep(1000), 0);
    500 	}
    501 
    502 	/* Free the buffer */
    503 	FORKEE_ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
    504 
    505 	return child;
    506 }
    507 
    508 static void __used
    509 await_collected(pid_t process)
    510 {
    511 	struct kinfo_proc2 p;
    512 	size_t len = sizeof(p);
    513 
    514 	const int name[] = {
    515 		[0] = CTL_KERN,
    516 		[1] = KERN_PROC2,
    517 		[2] = KERN_PROC_PID,
    518 		[3] = process,
    519 		[4] = sizeof(p),
    520 		[5] = 1
    521 	};
    522 
    523 	const size_t namelen = __arraycount(name);
    524 
    525 	/* Await the process to disappear */
    526 	while(1) {
    527 		FORKEE_ASSERT_EQ(sysctl(name, namelen, &p, &len, NULL, 0), 0);
    528 		if (len == 0)
    529 			break;
    530 
    531 		ATF_REQUIRE(usleep(1000) == 0);
    532 	}
    533 }
    534 
    535 /* Happy number sequence -- this function is used to just consume cpu cycles */
    536 #define	HAPPY_NUMBER	1
    537 
    538 /* If n is not happy then its sequence ends in the cycle:
    539  * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */
    540 #define	SAD_NUMBER	4
    541 
    542 /* Calculate the sum of the squares of the digits of n */
    543 static unsigned __used
    544 dsum(unsigned n)
    545 {
    546 	unsigned sum, x;
    547 	for (sum = 0; n; n /= 10) {
    548 		x = n % 10;
    549 		sum += x * x;
    550 	}
    551 	return sum;
    552 }
    553 
    554 /*
    555  * XXX: Disabled optimization is required to make tests for hardware assisted
    556  * traps in .text functional
    557  *
    558  * Tested with GCC 5.4 on NetBSD 7.99.47 amd64
    559  */
    560 static int __used
    561 #ifdef __clang__
    562 __attribute__((__optnone__))
    563 #else
    564 __attribute__((__optimize__("O0")))
    565 #endif
    566 check_happy(unsigned n)
    567 {
    568 	for (;;) {
    569 		unsigned total = dsum(n);
    570 
    571 		if (total == HAPPY_NUMBER)
    572 			return 1;
    573 		if (total == SAD_NUMBER)
    574 			return 0;
    575 
    576 		n = total;
    577 	}
    578 }
    579 
    580 static void * __used
    581 infinite_thread(void *arg __unused)
    582 {
    583 
    584         while (true)
    585                 continue;
    586 
    587         __unreachable();
    588 }
    589 
    590 static int __used
    591 clone_func(void *arg)
    592 {
    593 	int ret;
    594 
    595 	ret = (int)(intptr_t)arg;
    596 
    597 	return ret;
    598 }
    599 
    600 #if defined(HAVE_DBREGS)
    601 static bool __used
    602 can_we_set_dbregs(void)
    603 {
    604 	static long euid = -1;
    605 	static int user_set_dbregs  = -1;
    606 	size_t user_set_dbregs_len = sizeof(user_set_dbregs);
    607 
    608 	if (euid == -1)
    609 		euid = geteuid();
    610 
    611 	if (euid == 0)
    612 		return true;
    613 
    614 	if (user_set_dbregs == -1) {
    615 		if (sysctlbyname("security.models.extensions.user_set_dbregs",
    616 			&user_set_dbregs, &user_set_dbregs_len, NULL, 0)
    617 			== -1) {
    618 			return false;
    619 		}
    620 	}
    621 
    622 	if (user_set_dbregs > 0)
    623 		return true;
    624 	else
    625 		return false;
    626 }
    627 #endif
    628 
    629 static bool __used
    630 get_user_va0_disable(void)
    631 {
    632 	static int user_va0_disable = -1;
    633 	size_t user_va0_disable_len = sizeof(user_va0_disable);
    634 
    635 	if (user_va0_disable == -1) {
    636 		if (sysctlbyname("vm.user_va0_disable",
    637 			&user_va0_disable, &user_va0_disable_len, NULL, 0)
    638 			== -1) {
    639 			return true;
    640 		}
    641 	}
    642 
    643 	if (user_va0_disable > 0)
    644 		return true;
    645 	else
    646 		return false;
    647 }
    648 
    649 static bool __used
    650 can_we_write_to_text(pid_t pid)
    651 {
    652 	int mib[3];
    653 	int paxflags;
    654 	size_t len = sizeof(int);
    655 
    656 	mib[0] = CTL_PROC;
    657 	mib[1] = pid;
    658 	mib[2] = PROC_PID_PAXFLAGS;
    659 
    660 	if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)
    661 		return false;
    662 
    663 	return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
    664 }
    665 
    666 static void __used
    667 trigger_trap(void)
    668 {
    669 
    670 	/* Software breakpoint causes CPU trap, translated to SIGTRAP */
    671 #ifdef PTRACE_BREAKPOINT_ASM
    672 	PTRACE_BREAKPOINT_ASM;
    673 #else
    674 	/* port me */
    675 #endif
    676 }
    677 
    678 static void __used
    679 trigger_segv(void)
    680 {
    681 	static volatile char *ptr = NULL;
    682 
    683 	/* Access to unmapped memory causes CPU trap, translated to SIGSEGV */
    684 	*ptr = 1;
    685 }
    686 
    687 static void __used
    688 trigger_ill(void)
    689 {
    690 
    691 	/* Illegal instruction causes CPU trap, translated to SIGILL */
    692 #ifdef PTRACE_ILLEGAL_ASM
    693 #ifndef __mips__ /* To avoid GXemul crash */
    694 	PTRACE_ILLEGAL_ASM;
    695 #endif
    696 #else
    697 	/* port me */
    698 #endif
    699 }
    700 
    701 #include <fenv.h>
    702 
    703 #if (__arm__ && !__SOFTFP__) || __aarch64__
    704 #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
    705 
    706 static bool __used
    707 are_fpu_exceptions_supported(void)
    708 {
    709 	/*
    710 	 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
    711 	 * Skip these tests if running on them and compiled for
    712 	 * hard float.
    713 	 */
    714 	if (0 == fpsetmask(fpsetmask(FP_X_INV)))
    715 		return false;
    716 	return true;
    717 }
    718 #elif defined __riscv__
    719 #define are_fpu_exceptions_supported() 0
    720 #else
    721 #define are_fpu_exceptions_supported() 1
    722 #endif
    723 
    724 volatile double ignore_result;
    725 
    726 static void __used
    727 trigger_fpe(void)
    728 {
    729 #if __i386__ || __x86_64__
    730 	/*
    731 	 * XXX
    732 	 * Hack for QEMU bug #1668041, by which floating-point division by
    733 	 * zero is not trapped correctly. Also, assertions for si_code in
    734 	 * ptrace_signal_wait.h are commented out. Clean them up after the
    735 	 * bug is fixed.
    736 	 */
    737 	volatile int a, b;
    738 #else
    739 	volatile double a, b;
    740 #endif
    741 
    742 	a = getpid();
    743 	b = atoi("0");
    744 
    745 #ifdef __HAVE_FENV
    746 	feenableexcept(FE_ALL_EXCEPT);
    747 #endif
    748 
    749 	/* Division by zero causes CPU trap, translated to SIGFPE */
    750 	ignore_result = (int)(a / b);
    751 }
    752 
    753 static void __used
    754 trigger_bus(void)
    755 {
    756 	FILE *fp;
    757 	char *p;
    758 
    759 	/* Open an empty file for writing. */
    760 	fp = tmpfile();
    761 	FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL);
    762 
    763 	/*
    764 	 * Map an empty file with mmap(2) to a pointer.
    765 	 *
    766 	 * PROT_READ handles read-modify-write sequences emitted for
    767 	 * certain combinations of CPUs and compilers (e.g. Alpha AXP).
    768 	 */
    769 	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
    770 	FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED);
    771 
    772 	/* Invalid memory access causes CPU trap, translated to SIGBUS */
    773 	*p = 'a';
    774 }
    775 
    776 struct lwp_event_count {
    777 	lwpid_t lec_lwp;
    778 	int lec_count;
    779 };
    780 
    781 static int * __used
    782 find_event_count(struct lwp_event_count list[], lwpid_t lwp, size_t max_lwps)
    783 {
    784 	size_t i;
    785 
    786 	for (i = 0; i < max_lwps; i++) {
    787 		if (list[i].lec_lwp == 0)
    788 			list[i].lec_lwp = lwp;
    789 		if (list[i].lec_lwp == lwp)
    790 			return &list[i].lec_count;
    791 	}
    792 
    793 	atf_tc_fail("More LWPs reported than expected");
    794 }
    795 
    796 #define FIND_EVENT_COUNT(list, lwp)			\
    797 	find_event_count(list, lwp, __arraycount(list))
    798 
    799 #if defined(TWAIT_HAVE_PID)
    800 #define ATF_TP_ADD_TC_HAVE_PID(a,b)	ATF_TP_ADD_TC(a,b)
    801 #else
    802 #define ATF_TP_ADD_TC_HAVE_PID(a,b)
    803 #endif
    804 
    805 #if defined(TWAIT_HAVE_STATUS)
    806 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b)	ATF_TP_ADD_TC(a,b)
    807 #else
    808 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b)
    809 #endif
    810 
    811 #if defined(TWAIT_HAVE_STATUS) && (defined(__i386__) || defined(__x86_64__))
    812 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b)	ATF_TP_ADD_TC(a,b)
    813 #else
    814 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b)
    815 #endif
    816 
    817 #if defined(HAVE_GPREGS)
    818 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)	ATF_TP_ADD_TC(a,b)
    819 #else
    820 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)
    821 #endif
    822 
    823 #if defined(HAVE_FPREGS)
    824 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)	ATF_TP_ADD_TC(a,b)
    825 #else
    826 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)
    827 #endif
    828 
    829 #if defined(HAVE_DBREGS)
    830 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b)
    831 #else
    832 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b)
    833 #endif
    834 
    835 #if defined(PT_STEP)
    836 #define ATF_TP_ADD_TC_PT_STEP(a,b)	ATF_TP_ADD_TC(a,b)
    837 #else
    838 #define ATF_TP_ADD_TC_PT_STEP(a,b)
    839 #endif
    840