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