Home | History | Annotate | Line # | Download | only in sys
t_ptrace_wait.h revision 1.15
      1 /*	$NetBSD: t_ptrace_wait.h,v 1.15 2019/04/11 20:20:54 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 can_we_write_to_text(pid_t pid)
    557 {
    558 	int mib[3];
    559 	int paxflags;
    560 	size_t len = sizeof(int);
    561 
    562 	mib[0] = CTL_PROC;
    563 	mib[1] = pid;
    564 	mib[2] = PROC_PID_PAXFLAGS;
    565 
    566 	if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)
    567 		return false;
    568 
    569 	return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
    570 }
    571 
    572 static void __used
    573 trigger_trap(void)
    574 {
    575 
    576 	/* Software breakpoint causes CPU trap, translated to SIGTRAP */
    577 #ifdef PTRACE_BREAKPOINT_ASM
    578 	PTRACE_BREAKPOINT_ASM;
    579 #else
    580 	/* port me */
    581 #endif
    582 }
    583 
    584 static void __used
    585 trigger_segv(void)
    586 {
    587 	static volatile char *ptr = NULL;
    588 
    589 	/* Access to unmapped memory causes CPU trap, translated to SIGSEGV */
    590 	*ptr = 1;
    591 }
    592 
    593 static void __used
    594 trigger_ill(void)
    595 {
    596 
    597 	/* Illegal instruction causes CPU trap, translated to SIGILL */
    598 #ifdef PTRACE_ILLEGAL_ASM
    599 	PTRACE_ILLEGAL_ASM;
    600 #else
    601 	/* port me */
    602 #endif
    603 }
    604 
    605 static void __used
    606 trigger_fpe(void)
    607 {
    608 	volatile int a = getpid();
    609 	volatile int b = atoi("0");
    610 
    611 	/* Division by zero causes CPU trap, translated to SIGFPE */
    612 	usleep(a / b);
    613 }
    614 
    615 static void __used
    616 trigger_bus(void)
    617 {
    618 	FILE *fp;
    619 	char *p;
    620 
    621 	/* Open an empty file for writing. */
    622 	fp = tmpfile();
    623 	FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL);
    624 
    625 	/*
    626 	 * Map an empty file with mmap(2) to a pointer.
    627 	 *
    628 	 * PROT_READ handles read-modify-write sequences emitted for
    629 	 * certain combinations of CPUs and compilers (e.g. Alpha AXP).
    630 	 */
    631 	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
    632 	FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED);
    633 
    634 	/* Invalid memory access causes CPU trap, translated to SIGBUS */
    635 	*p = 'a';
    636 }
    637 
    638 #if defined(TWAIT_HAVE_PID)
    639 #define ATF_TP_ADD_TC_HAVE_PID(a,b)	ATF_TP_ADD_TC(a,b)
    640 #else
    641 #define ATF_TP_ADD_TC_HAVE_PID(a,b)
    642 #endif
    643 
    644 #if defined(HAVE_GPREGS)
    645 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)	ATF_TP_ADD_TC(a,b)
    646 #else
    647 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)
    648 #endif
    649 
    650 #if defined(HAVE_FPREGS)
    651 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)	ATF_TP_ADD_TC(a,b)
    652 #else
    653 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)
    654 #endif
    655 
    656 #if defined(HAVE_DBREGS)
    657 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b)
    658 #else
    659 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b)
    660 #endif
    661 
    662 #if defined(PT_STEP)
    663 #define ATF_TP_ADD_TC_PT_STEP(a,b)	ATF_TP_ADD_TC(a,b)
    664 #else
    665 #define ATF_TP_ADD_TC_PT_STEP(a,b)
    666 #endif
    667