t_ptrace_wait.c revision 1.43
11.42Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.43 2018/05/16 02:47:25 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.42Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.43 2018/05/16 02:47:25 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.1Skamil#include <sched.h>
471.1Skamil#include <signal.h>
481.1Skamil#include <stdint.h>
491.1Skamil#include <stdio.h>
501.1Skamil#include <stdlib.h>
511.1Skamil#include <strings.h>
521.26Skamil#include <time.h>
531.1Skamil#include <unistd.h>
541.1Skamil
551.1Skamil#include <atf-c.h>
561.1Skamil
571.1Skamil#include "h_macros.h"
581.1Skamil
591.1Skamil#include "t_ptrace_wait.h"
601.1Skamil#include "msg.h"
611.1Skamil
621.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
631.13Schristos    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0)
641.1Skamil
651.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
661.1Skamil    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
671.1Skamil
681.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
691.1Skamil    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
721.13Schristos    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
731.13Schristos
741.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
751.13Schristos    strerror(errno))
761.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
771.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
781.13Schristos
791.13Schristosstatic int debug = 0;
801.13Schristos
811.13Schristos#define DPRINTF(a, ...)	do  \
821.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
831.13Schristos    while (/*CONSTCOND*/0)
841.1Skamil
851.34Skamil/// ----------------------------------------------------------------------------
861.34Skamil
871.33Skamilstatic void
881.33Skamiltraceme_raise(int sigval)
891.1Skamil{
901.1Skamil	const int exitval = 5;
911.1Skamil	pid_t child, wpid;
921.1Skamil#if defined(TWAIT_HAVE_STATUS)
931.1Skamil	int status;
941.1Skamil#endif
951.1Skamil
961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
981.1Skamil	if (child == 0) {
991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1011.1Skamil
1021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1041.1Skamil
1051.36Skamil		switch (sigval) {
1061.36Skamil		case SIGKILL:
1071.36Skamil			/* NOTREACHED */
1081.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1091.36Skamil		default:
1101.36Skamil			DPRINTF("Before exiting of the child process\n");
1111.36Skamil			_exit(exitval);
1121.36Skamil		}
1131.1Skamil	}
1141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1151.1Skamil
1161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1181.1Skamil
1191.36Skamil	switch (sigval) {
1201.36Skamil	case SIGKILL:
1211.36Skamil		validate_status_signaled(status, sigval, 0);
1221.36Skamil		break;
1231.36Skamil	default:
1241.36Skamil		validate_status_stopped(status, sigval);
1251.1Skamil
1261.36Skamil		DPRINTF("Before resuming the child process where it left off "
1271.36Skamil		    "and without signal to be sent\n");
1281.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1291.1Skamil
1301.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1311.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1321.36Skamil		                      child);
1331.36Skamil		break;
1341.36Skamil	}
1351.1Skamil
1361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1381.1Skamil}
1391.1Skamil
1401.33Skamil#define TRACEME_RAISE(test, sig)						\
1411.33SkamilATF_TC(test);									\
1421.33SkamilATF_TC_HEAD(test, tc)								\
1431.33Skamil{										\
1441.33Skamil	atf_tc_set_md_var(tc, "descr",						\
1451.33Skamil	    "Verify " #sig " followed by _exit(2) in a child");			\
1461.33Skamil}										\
1471.33Skamil										\
1481.33SkamilATF_TC_BODY(test, tc)								\
1491.33Skamil{										\
1501.33Skamil										\
1511.33Skamil	traceme_raise(sig);							\
1521.33Skamil}
1531.33Skamil
1541.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1551.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1561.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1571.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1581.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1591.33Skamil
1601.34Skamil/// ----------------------------------------------------------------------------
1611.1Skamil
1621.1Skamilstatic void
1631.34Skamiltraceme_sighandler_catch(int sigsent, void (*sah)(int arg), int *traceme_caught)
1641.1Skamil{
1651.1Skamil	const int exitval = 5;
1661.34Skamil	const int sigval = SIGSTOP;
1671.1Skamil	pid_t child, wpid;
1681.1Skamil	struct sigaction sa;
1691.1Skamil#if defined(TWAIT_HAVE_STATUS)
1701.1Skamil	int status;
1711.1Skamil#endif
1721.1Skamil
1731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1751.1Skamil	if (child == 0) {
1761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1781.1Skamil
1791.34Skamil		sa.sa_handler = sah;
1801.1Skamil		sa.sa_flags = SA_SIGINFO;
1811.1Skamil		sigemptyset(&sa.sa_mask);
1821.1Skamil
1831.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
1841.1Skamil
1851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1871.1Skamil
1881.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
1891.1Skamil
1901.13Schristos		DPRINTF("Before exiting of the child process\n");
1911.1Skamil		_exit(exitval);
1921.1Skamil	}
1931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1941.1Skamil
1951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1971.1Skamil
1981.1Skamil	validate_status_stopped(status, sigval);
1991.1Skamil
2001.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2011.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2031.1Skamil
2041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2061.1Skamil
2071.1Skamil	validate_status_exited(status, exitval);
2081.1Skamil
2091.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2111.1Skamil}
2121.1Skamil
2131.34Skamil#define TRACEME_SIGHANDLER_CATCH(test, sig)					\
2141.34SkamilATF_TC(test);									\
2151.34SkamilATF_TC_HEAD(test, tc)								\
2161.34Skamil{										\
2171.34Skamil	atf_tc_set_md_var(tc, "descr",						\
2181.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
2191.34Skamil	    "handled correctly and caught by a signal handler");		\
2201.34Skamil}										\
2211.34Skamil										\
2221.34Skamilstatic int test##_caught = 0;							\
2231.34Skamil										\
2241.34Skamilstatic void									\
2251.34Skamiltest##_sighandler(int arg)							\
2261.34Skamil{										\
2271.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
2281.34Skamil										\
2291.34Skamil	++ test##_caught;							\
2301.34Skamil}										\
2311.34Skamil										\
2321.34SkamilATF_TC_BODY(test, tc)								\
2331.34Skamil{										\
2341.34Skamil										\
2351.34Skamil	traceme_sighandler_catch(sig, test##_sighandler, & test##_caught);	\
2361.34Skamil}
2371.34Skamil
2381.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
2391.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch1, SIGABRT) /* abort trap */
2401.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch2, SIGHUP)  /* hangup */
2411.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch3, SIGCONT) /* continued? */
2421.34Skamil
2431.34Skamil/// ----------------------------------------------------------------------------
2441.34Skamil
2451.35Skamilstatic void
2461.35Skamiltraceme_signal_nohandler(int sigsent)
2471.1Skamil{
2481.35Skamil	const int sigval = SIGSTOP;
2491.35Skamil	int exitval = 0;
2501.1Skamil	pid_t child, wpid;
2511.1Skamil#if defined(TWAIT_HAVE_STATUS)
2521.1Skamil	int status;
2531.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
2541.1Skamil#endif
2551.1Skamil
2561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2581.1Skamil	if (child == 0) {
2591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2611.1Skamil
2621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2641.1Skamil
2651.35Skamil		switch (sigsent) {
2661.35Skamil		case SIGCONT:
2671.35Skamil			_exit(exitval);
2681.35Skamil		default:
2691.35Skamil			/* NOTREACHED */
2701.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2711.35Skamil		}
2721.1Skamil	}
2731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2741.1Skamil
2751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2771.1Skamil
2781.1Skamil	validate_status_stopped(status, sigval);
2791.1Skamil
2801.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2811.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2831.1Skamil
2841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2861.1Skamil
2871.35Skamil	switch (sigsent) {
2881.35Skamil	case SIGCONT:
2891.35Skamil		validate_status_exited(status, exitval);
2901.35Skamil		break;
2911.35Skamil	default:
2921.35Skamil		validate_status_signaled(status, sigsent, expect_core);
2931.35Skamil		break;
2941.35Skamil	}
2951.1Skamil
2961.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2981.1Skamil}
2991.1Skamil
3001.35Skamil#define TRACEME_SIGNAL_NOHANDLER(test, sig)					\
3011.35SkamilATF_TC(test);									\
3021.35SkamilATF_TC_HEAD(test, tc)								\
3031.35Skamil{										\
3041.35Skamil	atf_tc_set_md_var(tc, "descr",						\
3051.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3061.35Skamil	    "handled correctly in a child without a signal handler");		\
3071.35Skamil}										\
3081.35Skamil										\
3091.35SkamilATF_TC_BODY(test, tc)								\
3101.35Skamil{										\
3111.35Skamil										\
3121.35Skamil	traceme_signal_nohandler(sig);						\
3131.35Skamil}
3141.35Skamil
3151.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler1, SIGKILL) /* non-maskable */
3161.35Skamil//TRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler2, SIGSTOP) /* non-maskable */
3171.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler3, SIGABRT) /* abort trap */
3181.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler4, SIGHUP)  /* hangup */
3191.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler5, SIGCONT) /* continued? */
3201.35Skamil
3211.35Skamil/// ----------------------------------------------------------------------------
3221.35Skamil
3231.37SkamilATF_TC(traceme_pid1_parent);
3241.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
3251.37Skamil{
3261.37Skamil	atf_tc_set_md_var(tc, "descr",
3271.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
3281.37Skamil}
3291.37Skamil
3301.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
3311.37Skamil{
3321.37Skamil	struct msg_fds parent_child;
3331.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
3341.37Skamil	pid_t child1, child2, wpid;
3351.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3361.37Skamil#if defined(TWAIT_HAVE_STATUS)
3371.37Skamil	int status;
3381.37Skamil#endif
3391.37Skamil
3401.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
3411.37Skamil
3421.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3431.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
3441.37Skamil	if (child1 == 0) {
3451.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
3461.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
3471.37Skamil		if (child2 != 0) {
3481.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
3491.37Skamil			        getpid(), child2);
3501.37Skamil			_exit(exitval_child1);
3511.37Skamil		}
3521.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
3531.37Skamil
3541.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
3551.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
3561.37Skamil
3571.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3581.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
3591.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
3601.37Skamil
3611.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
3621.37Skamil
3631.37Skamil		_exit(exitval_child2);
3641.37Skamil	}
3651.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
3661.37Skamil
3671.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
3691.37Skamil	                      child1);
3701.37Skamil
3711.37Skamil	validate_status_exited(status, exitval_child1);
3721.37Skamil
3731.37Skamil	DPRINTF("Notify that child1 is dead\n");
3741.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
3751.37Skamil
3761.37Skamil	DPRINTF("Wait for exiting of child2\n");
3771.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
3781.37Skamil}
3791.37Skamil
3801.37Skamil/// ----------------------------------------------------------------------------
3811.37Skamil
3821.40Skamilstatic void
3831.40Skamiltraceme_vfork_raise(int sigval)
3841.40Skamil{
3851.40Skamil	const int exitval = 5;
3861.40Skamil	pid_t child, wpid;
3871.40Skamil#if defined(TWAIT_HAVE_STATUS)
3881.40Skamil	int status;
3891.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
3901.40Skamil#endif
3911.40Skamil
3921.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3931.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
3941.40Skamil	if (child == 0) {
3951.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3961.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3971.40Skamil
3981.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3991.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4001.40Skamil
4011.40Skamil		switch (sigval) {
4021.40Skamil		case SIGKILL:
4031.40Skamil		case SIGABRT:
4041.40Skamil		case SIGHUP:
4051.40Skamil			/* NOTREACHED */
4061.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4071.40Skamil		default:
4081.40Skamil			DPRINTF("Before exiting of the child process\n");
4091.40Skamil			_exit(exitval);
4101.40Skamil		}
4111.40Skamil	}
4121.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4131.40Skamil
4141.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4151.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4161.40Skamil
4171.40Skamil	switch (sigval) {
4181.40Skamil	case SIGKILL:
4191.40Skamil	case SIGABRT:
4201.40Skamil	case SIGHUP:
4211.40Skamil		validate_status_signaled(status, sigval, expect_core);
4221.40Skamil		break;
4231.40Skamil	case SIGSTOP:
4241.40Skamil	case SIGCONT:
4251.40Skamil		validate_status_exited(status, exitval);
4261.40Skamil		break;
4271.40Skamil	default:
4281.40Skamil		/* NOTREACHED */
4291.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
4301.40Skamil		break;
4311.40Skamil	}
4321.40Skamil
4331.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4341.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4351.40Skamil}
4361.40Skamil
4371.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
4381.40SkamilATF_TC(test);									\
4391.40SkamilATF_TC_HEAD(test, tc)								\
4401.40Skamil{										\
4411.40Skamil	atf_tc_set_md_var(tc, "descr",						\
4421.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
4431.42Skamil	    "child");								\
4441.40Skamil}										\
4451.40Skamil										\
4461.40SkamilATF_TC_BODY(test, tc)								\
4471.40Skamil{										\
4481.40Skamil										\
4491.40Skamil	traceme_vfork_raise(sig);						\
4501.40Skamil}
4511.40Skamil
4521.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
4531.40Skamil// TRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ // TODO
4541.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGABRT) /* regular abort trap */
4551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGHUP)  /* hangup */
4561.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGCONT) /* continued? */
4571.40Skamil
4581.40Skamil/// ----------------------------------------------------------------------------
4591.40Skamil
4601.41SkamilATF_TC(traceme_vfork_breakpoint);
4611.41SkamilATF_TC_HEAD(traceme_vfork_breakpoint, tc)
4621.41Skamil{
4631.41Skamil	atf_tc_set_md_var(tc, "descr",
4641.41Skamil	    "Verify software breakpoint in a vfork(2)ed child");
4651.41Skamil}
4661.41Skamil
4671.41SkamilATF_TC_BODY(traceme_vfork_breakpoint, tc)
4681.41Skamil{
4691.41Skamil	pid_t child, wpid;
4701.41Skamil#if defined(TWAIT_HAVE_STATUS)
4711.41Skamil	int status;
4721.41Skamil#endif
4731.41Skamil
4741.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4751.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
4761.41Skamil	if (child == 0) {
4771.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4781.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4791.41Skamil
4801.41Skamil		DPRINTF("Before executing a software breakpoint\n");
4811.41Skamil#ifdef PTRACE_BREAKPOINT_ASM
4821.41Skamil		PTRACE_BREAKPOINT_ASM;
4831.41Skamil#else
4841.41Skamil		/* port me */
4851.41Skamil#endif
4861.41Skamil
4871.41Skamil		/* NOTREACHED */
4881.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4891.41Skamil	}
4901.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4911.41Skamil
4921.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4931.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4941.41Skamil
4951.41Skamil	validate_status_signaled(status, SIGTRAP, 1);
4961.41Skamil
4971.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4981.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4991.41Skamil}
5001.41Skamil
5011.41Skamil/// ----------------------------------------------------------------------------
5021.41Skamil
5031.43SkamilATF_TC(traceme_vfork_exec);
5041.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
5051.43Skamil{
5061.43Skamil	atf_tc_set_md_var(tc, "descr",
5071.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
5081.43Skamil}
5091.43Skamil
5101.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
5111.43Skamil{
5121.43Skamil	const int sigval = SIGTRAP;
5131.43Skamil	pid_t child, wpid;
5141.43Skamil#if defined(TWAIT_HAVE_STATUS)
5151.43Skamil	int status;
5161.43Skamil#endif
5171.43Skamil
5181.43Skamil	struct ptrace_siginfo info;
5191.43Skamil	memset(&info, 0, sizeof(info));
5201.43Skamil
5211.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5221.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
5231.43Skamil	if (child == 0) {
5241.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5251.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5261.43Skamil
5271.43Skamil		DPRINTF("Before calling execve(2) from child\n");
5281.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
5291.43Skamil
5301.43Skamil		/* NOTREACHED */
5311.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
5321.43Skamil	}
5331.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5341.43Skamil
5351.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5361.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5371.43Skamil
5381.43Skamil	validate_status_stopped(status, sigval);
5391.43Skamil
5401.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5411.43Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5421.43Skamil
5431.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5441.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5451.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5461.43Skamil	    info.psi_siginfo.si_errno);
5471.43Skamil
5481.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5491.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
5501.43Skamil
5511.43Skamil	DPRINTF("Before resuming the child process where it left off and "
5521.43Skamil	    "without signal to be sent\n");
5531.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5541.43Skamil
5551.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5561.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5571.43Skamil
5581.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5591.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5601.43Skamil}
5611.43Skamil
5621.43Skamil/// ----------------------------------------------------------------------------
5631.43Skamil
5641.1Skamil#if defined(TWAIT_HAVE_PID)
5651.1SkamilATF_TC(attach1);
5661.1SkamilATF_TC_HEAD(attach1, tc)
5671.1Skamil{
5681.1Skamil	atf_tc_set_md_var(tc, "descr",
5691.1Skamil	    "Assert that tracer sees process termination before the parent");
5701.1Skamil}
5711.1Skamil
5721.26Skamilstatic void
5731.26Skamilattach1_raw(bool raw)
5741.1Skamil{
5751.1Skamil	struct msg_fds parent_tracee, parent_tracer;
5761.1Skamil	const int exitval_tracee = 5;
5771.1Skamil	const int exitval_tracer = 10;
5781.1Skamil	pid_t tracee, tracer, wpid;
5791.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5801.1Skamil#if defined(TWAIT_HAVE_STATUS)
5811.1Skamil	int status;
5821.1Skamil#endif
5831.1Skamil
5841.13Schristos	DPRINTF("Spawn tracee\n");
5851.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
5861.1Skamil	tracee = atf_utils_fork();
5871.1Skamil	if (tracee == 0) {
5881.1Skamil		// Wait for parent to let us exit
5891.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
5901.1Skamil		_exit(exitval_tracee);
5911.1Skamil	}
5921.1Skamil
5931.13Schristos	DPRINTF("Spawn debugger\n");
5941.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
5951.1Skamil	tracer = atf_utils_fork();
5961.1Skamil	if (tracer == 0) {
5971.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
5981.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
5991.1Skamil
6001.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6011.1Skamil		FORKEE_REQUIRE_SUCCESS(
6021.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6031.1Skamil
6041.1Skamil		forkee_status_stopped(status, SIGSTOP);
6051.1Skamil
6061.1Skamil		/* Resume tracee with PT_CONTINUE */
6071.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6081.1Skamil
6091.1Skamil		/* Inform parent that tracer has attached to tracee */
6101.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
6111.1Skamil
6121.1Skamil		/* Wait for parent to tell use that tracee should have exited */
6131.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
6141.1Skamil
6151.1Skamil		/* Wait for tracee and assert that it exited */
6161.1Skamil		FORKEE_REQUIRE_SUCCESS(
6171.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6181.1Skamil
6191.1Skamil		forkee_status_exited(status, exitval_tracee);
6201.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
6211.1Skamil
6221.13Schristos		DPRINTF("Before exiting of the tracer process\n");
6231.1Skamil		_exit(exitval_tracer);
6241.1Skamil	}
6251.1Skamil
6261.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
6271.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
6281.1Skamil
6291.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
6301.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
6311.1Skamil
6321.13Schristos	DPRINTF("Detect that tracee is zombie\n");
6331.26Skamil	if (raw)
6341.26Skamil		await_zombie_raw(tracee, 0);
6351.26Skamil	else
6361.26Skamil		await_zombie(tracee);
6371.1Skamil
6381.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
6391.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
6401.1Skamil	    TWAIT_FNAME);
6411.1Skamil	TWAIT_REQUIRE_SUCCESS(
6421.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
6431.1Skamil
6441.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
6451.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
6461.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
6471.1Skamil	    TWAIT_FNAME);
6481.1Skamil
6491.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
6501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
6511.1Skamil	    tracer);
6521.1Skamil
6531.1Skamil	validate_status_exited(status, exitval_tracer);
6541.1Skamil
6551.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
6561.1Skamil	    TWAIT_FNAME);
6571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
6581.1Skamil	    tracee);
6591.1Skamil
6601.1Skamil	validate_status_exited(status, exitval_tracee);
6611.1Skamil
6621.1Skamil	msg_close(&parent_tracer);
6631.1Skamil	msg_close(&parent_tracee);
6641.1Skamil}
6651.26Skamil
6661.26SkamilATF_TC_BODY(attach1, tc)
6671.26Skamil{
6681.26Skamil
6691.26Skamil	/* Reuse this test with race1 */
6701.26Skamil	attach1_raw(false);
6711.26Skamil}
6721.26Skamil
6731.1Skamil#endif
6741.1Skamil
6751.1Skamil#if defined(TWAIT_HAVE_PID)
6761.1SkamilATF_TC(attach2);
6771.1SkamilATF_TC_HEAD(attach2, tc)
6781.1Skamil{
6791.1Skamil	atf_tc_set_md_var(tc, "descr",
6801.1Skamil	    "Assert that any tracer sees process termination before its "
6811.1Skamil	    "parent");
6821.1Skamil}
6831.1Skamil
6841.1SkamilATF_TC_BODY(attach2, tc)
6851.1Skamil{
6861.1Skamil	struct msg_fds parent_tracer, parent_tracee;
6871.1Skamil	const int exitval_tracee = 5;
6881.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
6891.1Skamil	pid_t tracee, tracer, wpid;
6901.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6911.1Skamil#if defined(TWAIT_HAVE_STATUS)
6921.1Skamil	int status;
6931.1Skamil#endif
6941.1Skamil
6951.13Schristos	DPRINTF("Spawn tracee\n");
6961.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6971.1Skamil	tracee = atf_utils_fork();
6981.1Skamil	if (tracee == 0) {
6991.1Skamil		/* Wait for message from the parent */
7001.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7011.1Skamil		_exit(exitval_tracee);
7021.1Skamil	}
7031.1Skamil
7041.13Schristos	DPRINTF("Spawn debugger\n");
7051.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
7061.1Skamil	tracer = atf_utils_fork();
7071.1Skamil	if (tracer == 0) {
7081.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
7091.1Skamil		tracer = atf_utils_fork();
7101.1Skamil		if (tracer != 0)
7111.1Skamil			_exit(exitval_tracer1);
7121.1Skamil
7131.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
7141.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
7151.1Skamil
7161.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
7171.1Skamil		FORKEE_REQUIRE_SUCCESS(
7181.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7191.1Skamil
7201.1Skamil		forkee_status_stopped(status, SIGSTOP);
7211.1Skamil
7221.1Skamil		/* Resume tracee with PT_CONTINUE */
7231.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
7241.1Skamil
7251.1Skamil		/* Inform parent that tracer has attached to tracee */
7261.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
7271.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
7281.1Skamil
7291.1Skamil		/* Wait for tracee and assert that it exited */
7301.1Skamil		FORKEE_REQUIRE_SUCCESS(
7311.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7321.1Skamil
7331.1Skamil		forkee_status_exited(status, exitval_tracee);
7341.1Skamil
7351.13Schristos		DPRINTF("Before exiting of the tracer process\n");
7361.1Skamil		_exit(exitval_tracer2);
7371.1Skamil	}
7381.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
7391.1Skamil	    "%s()\n", TWAIT_FNAME);
7401.1Skamil	TWAIT_REQUIRE_SUCCESS(
7411.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
7421.1Skamil
7431.1Skamil	validate_status_exited(status, exitval_tracer1);
7441.1Skamil
7451.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
7461.1Skamil	    TWAIT_FNAME);
7471.1Skamil	TWAIT_REQUIRE_SUCCESS(
7481.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
7491.1Skamil
7501.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
7511.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
7521.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
7531.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
7541.1Skamil
7551.13Schristos	DPRINTF("Detect that tracee is zombie\n");
7561.1Skamil	await_zombie(tracee);
7571.1Skamil
7581.13Schristos	DPRINTF("Assert that there is no status about tracee - "
7591.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
7601.1Skamil	TWAIT_REQUIRE_SUCCESS(
7611.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
7621.1Skamil
7631.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
7641.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
7651.1Skamil
7661.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7671.1Skamil	    TWAIT_FNAME);
7681.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
7691.1Skamil	    tracee);
7701.1Skamil
7711.1Skamil	validate_status_exited(status, exitval_tracee);
7721.1Skamil
7731.1Skamil	msg_close(&parent_tracer);
7741.1Skamil	msg_close(&parent_tracee);
7751.1Skamil}
7761.1Skamil#endif
7771.1Skamil
7781.1SkamilATF_TC(attach3);
7791.1SkamilATF_TC_HEAD(attach3, tc)
7801.1Skamil{
7811.1Skamil	atf_tc_set_md_var(tc, "descr",
7821.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
7831.1Skamil}
7841.1Skamil
7851.1SkamilATF_TC_BODY(attach3, tc)
7861.1Skamil{
7871.1Skamil	struct msg_fds parent_tracee;
7881.1Skamil	const int exitval_tracee = 5;
7891.1Skamil	pid_t tracee, wpid;
7901.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7911.1Skamil#if defined(TWAIT_HAVE_STATUS)
7921.1Skamil	int status;
7931.1Skamil#endif
7941.1Skamil
7951.13Schristos	DPRINTF("Spawn tracee\n");
7961.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7971.1Skamil	tracee = atf_utils_fork();
7981.1Skamil	if (tracee == 0) {
7991.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8001.13Schristos		DPRINTF("Parent should now attach to tracee\n");
8011.1Skamil
8021.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
8031.1Skamil		/* Wait for message from the parent */
8041.1Skamil		_exit(exitval_tracee);
8051.1Skamil	}
8061.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8071.1Skamil
8081.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
8091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8101.1Skamil
8111.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
8121.1Skamil	    TWAIT_FNAME);
8131.1Skamil	TWAIT_REQUIRE_SUCCESS(
8141.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8151.1Skamil
8161.1Skamil	validate_status_stopped(status, SIGSTOP);
8171.1Skamil
8181.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
8191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8201.1Skamil
8211.13Schristos	DPRINTF("Let the tracee exit now\n");
8221.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
8231.1Skamil
8241.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
8251.1Skamil	TWAIT_REQUIRE_SUCCESS(
8261.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8271.1Skamil
8281.1Skamil	validate_status_exited(status, exitval_tracee);
8291.1Skamil
8301.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
8311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8321.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
8331.1Skamil
8341.1Skamil	msg_close(&parent_tracee);
8351.1Skamil}
8361.1Skamil
8371.1SkamilATF_TC(attach4);
8381.1SkamilATF_TC_HEAD(attach4, tc)
8391.1Skamil{
8401.1Skamil	atf_tc_set_md_var(tc, "descr",
8411.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
8421.1Skamil}
8431.1Skamil
8441.1SkamilATF_TC_BODY(attach4, tc)
8451.1Skamil{
8461.1Skamil	struct msg_fds parent_tracee;
8471.1Skamil	const int exitval_tracer = 5;
8481.1Skamil	pid_t tracer, wpid;
8491.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8501.1Skamil#if defined(TWAIT_HAVE_STATUS)
8511.1Skamil	int status;
8521.1Skamil#endif
8531.1Skamil
8541.13Schristos	DPRINTF("Spawn tracer\n");
8551.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
8561.1Skamil	tracer = atf_utils_fork();
8571.1Skamil	if (tracer == 0) {
8581.1Skamil
8591.1Skamil		/* Wait for message from the parent */
8601.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8611.1Skamil
8621.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
8631.1Skamil		    getppid());
8641.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
8651.1Skamil
8661.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
8671.1Skamil		    TWAIT_FNAME);
8681.1Skamil		FORKEE_REQUIRE_SUCCESS(
8691.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
8701.1Skamil
8711.1Skamil		forkee_status_stopped(status, SIGSTOP);
8721.1Skamil
8731.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
8741.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
8751.1Skamil		    != -1);
8761.1Skamil
8771.1Skamil		/* Tell parent we are ready */
8781.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
8791.1Skamil
8801.1Skamil		_exit(exitval_tracer);
8811.1Skamil	}
8821.1Skamil
8831.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
8841.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8851.13Schristos	DPRINTF("Allow the tracer to exit now\n");
8861.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
8871.1Skamil
8881.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
8891.1Skamil	TWAIT_REQUIRE_SUCCESS(
8901.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
8911.1Skamil
8921.1Skamil	validate_status_exited(status, exitval_tracer);
8931.1Skamil
8941.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
8951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8961.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
8971.1Skamil
8981.1Skamil	msg_close(&parent_tracee);
8991.1Skamil}
9001.1Skamil
9011.1Skamil#if defined(TWAIT_HAVE_PID)
9021.1SkamilATF_TC(attach5);
9031.1SkamilATF_TC_HEAD(attach5, tc)
9041.1Skamil{
9051.1Skamil	atf_tc_set_md_var(tc, "descr",
9061.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
9071.1Skamil	    "(check getppid(2))");
9081.1Skamil}
9091.1Skamil
9101.1SkamilATF_TC_BODY(attach5, tc)
9111.1Skamil{
9121.1Skamil	struct msg_fds parent_tracer, parent_tracee;
9131.1Skamil	const int exitval_tracee = 5;
9141.1Skamil	const int exitval_tracer = 10;
9151.1Skamil	pid_t parent, tracee, tracer, wpid;
9161.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9171.1Skamil#if defined(TWAIT_HAVE_STATUS)
9181.1Skamil	int status;
9191.1Skamil#endif
9201.1Skamil
9211.13Schristos	DPRINTF("Spawn tracee\n");
9221.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9231.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9241.1Skamil	tracee = atf_utils_fork();
9251.1Skamil	if (tracee == 0) {
9261.1Skamil		parent = getppid();
9271.1Skamil
9281.1Skamil		/* Emit message to the parent */
9291.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
9301.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
9311.1Skamil
9321.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
9331.1Skamil
9341.1Skamil		_exit(exitval_tracee);
9351.1Skamil	}
9361.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9371.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
9381.1Skamil
9391.13Schristos	DPRINTF("Spawn debugger\n");
9401.1Skamil	tracer = atf_utils_fork();
9411.1Skamil	if (tracer == 0) {
9421.1Skamil		/* No IPC to communicate with the child */
9431.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
9441.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
9451.1Skamil
9461.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
9471.1Skamil		FORKEE_REQUIRE_SUCCESS(
9481.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9491.1Skamil
9501.1Skamil		forkee_status_stopped(status, SIGSTOP);
9511.1Skamil
9521.1Skamil		/* Resume tracee with PT_CONTINUE */
9531.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
9541.1Skamil
9551.1Skamil		/* Inform parent that tracer has attached to tracee */
9561.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
9571.1Skamil
9581.1Skamil		/* Wait for parent to tell use that tracee should have exited */
9591.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
9601.1Skamil
9611.1Skamil		/* Wait for tracee and assert that it exited */
9621.1Skamil		FORKEE_REQUIRE_SUCCESS(
9631.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9641.1Skamil
9651.1Skamil		forkee_status_exited(status, exitval_tracee);
9661.1Skamil
9671.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9681.1Skamil		_exit(exitval_tracer);
9691.1Skamil	}
9701.1Skamil
9711.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9721.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
9731.1Skamil
9741.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9751.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
9761.1Skamil
9771.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9781.1Skamil	await_zombie(tracee);
9791.1Skamil
9801.13Schristos	DPRINTF("Assert that there is no status about tracee - "
9811.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
9821.1Skamil	TWAIT_REQUIRE_SUCCESS(
9831.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9841.1Skamil
9851.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
9861.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
9871.1Skamil
9881.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
9891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9901.1Skamil	    tracer);
9911.1Skamil
9921.1Skamil	validate_status_exited(status, exitval_tracer);
9931.1Skamil
9941.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
9951.1Skamil	    TWAIT_FNAME);
9961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
9971.1Skamil	    tracee);
9981.1Skamil
9991.1Skamil	validate_status_exited(status, exitval_tracee);
10001.1Skamil
10011.1Skamil	msg_close(&parent_tracer);
10021.1Skamil	msg_close(&parent_tracee);
10031.1Skamil}
10041.1Skamil#endif
10051.1Skamil
10061.1Skamil#if defined(TWAIT_HAVE_PID)
10071.1SkamilATF_TC(attach6);
10081.1SkamilATF_TC_HEAD(attach6, tc)
10091.1Skamil{
10101.1Skamil	atf_tc_set_md_var(tc, "descr",
10111.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
10121.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
10131.1Skamil}
10141.1Skamil
10151.1SkamilATF_TC_BODY(attach6, tc)
10161.1Skamil{
10171.1Skamil	struct msg_fds parent_tracee, parent_tracer;
10181.1Skamil	const int exitval_tracee = 5;
10191.1Skamil	const int exitval_tracer = 10;
10201.1Skamil	pid_t parent, tracee, tracer, wpid;
10211.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10221.1Skamil#if defined(TWAIT_HAVE_STATUS)
10231.1Skamil	int status;
10241.1Skamil#endif
10251.1Skamil	int name[CTL_MAXNAME];
10261.1Skamil	struct kinfo_proc2 kp;
10271.1Skamil	size_t len = sizeof(kp);
10281.1Skamil	unsigned int namelen;
10291.1Skamil
10301.13Schristos	DPRINTF("Spawn tracee\n");
10311.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10321.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10331.1Skamil	tracee = atf_utils_fork();
10341.1Skamil	if (tracee == 0) {
10351.1Skamil		parent = getppid();
10361.1Skamil
10371.1Skamil		/* Emit message to the parent */
10381.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
10391.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
10401.1Skamil
10411.1Skamil		namelen = 0;
10421.1Skamil		name[namelen++] = CTL_KERN;
10431.1Skamil		name[namelen++] = KERN_PROC2;
10441.1Skamil		name[namelen++] = KERN_PROC_PID;
10451.1Skamil		name[namelen++] = getpid();
10461.1Skamil		name[namelen++] = len;
10471.1Skamil		name[namelen++] = 1;
10481.1Skamil
10491.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
10501.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
10511.1Skamil
10521.1Skamil		_exit(exitval_tracee);
10531.1Skamil	}
10541.1Skamil
10551.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
10561.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
10571.1Skamil
10581.13Schristos	DPRINTF("Spawn debugger\n");
10591.1Skamil	tracer = atf_utils_fork();
10601.1Skamil	if (tracer == 0) {
10611.1Skamil		/* No IPC to communicate with the child */
10621.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10631.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10641.1Skamil
10651.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10661.1Skamil		FORKEE_REQUIRE_SUCCESS(
10671.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10681.1Skamil
10691.1Skamil		forkee_status_stopped(status, SIGSTOP);
10701.1Skamil
10711.1Skamil		/* Resume tracee with PT_CONTINUE */
10721.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10731.1Skamil
10741.1Skamil		/* Inform parent that tracer has attached to tracee */
10751.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
10761.1Skamil
10771.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
10781.1Skamil
10791.1Skamil		/* Wait for tracee and assert that it exited */
10801.1Skamil		FORKEE_REQUIRE_SUCCESS(
10811.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10821.1Skamil
10831.1Skamil		forkee_status_exited(status, exitval_tracee);
10841.1Skamil
10851.13Schristos		DPRINTF("Before exiting of the tracer process\n");
10861.1Skamil		_exit(exitval_tracer);
10871.1Skamil	}
10881.1Skamil
10891.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
10901.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
10911.1Skamil
10921.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
10931.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
10941.1Skamil
10951.13Schristos	DPRINTF("Detect that tracee is zombie\n");
10961.1Skamil	await_zombie(tracee);
10971.1Skamil
10981.13Schristos	DPRINTF("Assert that there is no status about tracee - "
10991.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
11001.1Skamil	TWAIT_REQUIRE_SUCCESS(
11011.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
11021.1Skamil
11031.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
11041.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11051.1Skamil
11061.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
11071.1Skamil	    TWAIT_FNAME);
11081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
11091.1Skamil	    tracer);
11101.1Skamil
11111.1Skamil	validate_status_exited(status, exitval_tracer);
11121.1Skamil
11131.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11141.1Skamil	    TWAIT_FNAME);
11151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
11161.1Skamil	    tracee);
11171.1Skamil
11181.1Skamil	validate_status_exited(status, exitval_tracee);
11191.1Skamil
11201.1Skamil	msg_close(&parent_tracee);
11211.1Skamil	msg_close(&parent_tracer);
11221.1Skamil}
11231.1Skamil#endif
11241.1Skamil
11251.1Skamil#if defined(TWAIT_HAVE_PID)
11261.1SkamilATF_TC(attach7);
11271.1SkamilATF_TC_HEAD(attach7, tc)
11281.1Skamil{
11291.1Skamil	atf_tc_set_md_var(tc, "descr",
11301.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
11311.1Skamil	    "(check /proc/curproc/status 3rd column)");
11321.1Skamil}
11331.1Skamil
11341.1SkamilATF_TC_BODY(attach7, tc)
11351.1Skamil{
11361.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11371.1Skamil	int rv;
11381.1Skamil	const int exitval_tracee = 5;
11391.1Skamil	const int exitval_tracer = 10;
11401.1Skamil	pid_t parent, tracee, tracer, wpid;
11411.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11421.1Skamil#if defined(TWAIT_HAVE_STATUS)
11431.1Skamil	int status;
11441.1Skamil#endif
11451.1Skamil	FILE *fp;
11461.1Skamil	struct stat st;
11471.1Skamil	const char *fname = "/proc/curproc/status";
11481.1Skamil	char s_executable[MAXPATHLEN];
11491.1Skamil	int s_pid, s_ppid;
11501.1Skamil	/*
11511.1Skamil	 * Format:
11521.1Skamil	 *  EXECUTABLE PID PPID ...
11531.1Skamil	 */
11541.1Skamil
11551.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
11561.1Skamil	if (rv != 0) {
11571.1Skamil		atf_tc_skip("/proc/curproc/status not found");
11581.1Skamil	}
11591.1Skamil
11601.13Schristos	DPRINTF("Spawn tracee\n");
11611.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11621.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11631.1Skamil	tracee = atf_utils_fork();
11641.1Skamil	if (tracee == 0) {
11651.1Skamil		parent = getppid();
11661.1Skamil
11671.1Skamil		// Wait for parent to let us exit
11681.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
11691.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
11701.1Skamil
11711.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
11721.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
11731.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
11741.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
11751.1Skamil
11761.1Skamil		_exit(exitval_tracee);
11771.1Skamil	}
11781.1Skamil
11791.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
11801.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
11811.1Skamil
11821.13Schristos	DPRINTF("Spawn debugger\n");
11831.1Skamil	tracer = atf_utils_fork();
11841.1Skamil	if (tracer == 0) {
11851.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11861.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11871.1Skamil
11881.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11891.1Skamil		FORKEE_REQUIRE_SUCCESS(
11901.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11911.1Skamil
11921.1Skamil		forkee_status_stopped(status, SIGSTOP);
11931.1Skamil
11941.1Skamil		/* Resume tracee with PT_CONTINUE */
11951.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11961.1Skamil
11971.1Skamil		/* Inform parent that tracer has attached to tracee */
11981.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
11991.1Skamil
12001.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12011.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12021.1Skamil
12031.1Skamil		/* Wait for tracee and assert that it exited */
12041.1Skamil		FORKEE_REQUIRE_SUCCESS(
12051.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12061.1Skamil
12071.1Skamil		forkee_status_exited(status, exitval_tracee);
12081.1Skamil
12091.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12101.1Skamil		_exit(exitval_tracer);
12111.1Skamil	}
12121.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12131.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12141.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12151.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
12161.1Skamil
12171.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12181.1Skamil	await_zombie(tracee);
12191.1Skamil
12201.13Schristos	DPRINTF("Assert that there is no status about tracee - "
12211.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
12221.1Skamil	TWAIT_REQUIRE_SUCCESS(
12231.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
12241.1Skamil
12251.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
12261.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
12271.1Skamil
12281.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
12291.1Skamil	    TWAIT_FNAME);
12301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
12311.1Skamil	    tracer);
12321.1Skamil
12331.1Skamil	validate_status_exited(status, exitval_tracer);
12341.1Skamil
12351.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
12361.1Skamil	    TWAIT_FNAME);
12371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
12381.1Skamil	    tracee);
12391.1Skamil
12401.1Skamil	validate_status_exited(status, exitval_tracee);
12411.1Skamil
12421.1Skamil	msg_close(&parent_tracee);
12431.1Skamil	msg_close(&parent_tracer);
12441.1Skamil}
12451.1Skamil#endif
12461.1Skamil
12471.1SkamilATF_TC(eventmask1);
12481.1SkamilATF_TC_HEAD(eventmask1, tc)
12491.1Skamil{
12501.1Skamil	atf_tc_set_md_var(tc, "descr",
12511.1Skamil	    "Verify that empty EVENT_MASK is preserved");
12521.1Skamil}
12531.1Skamil
12541.1SkamilATF_TC_BODY(eventmask1, tc)
12551.1Skamil{
12561.1Skamil	const int exitval = 5;
12571.1Skamil	const int sigval = SIGSTOP;
12581.1Skamil	pid_t child, wpid;
12591.1Skamil#if defined(TWAIT_HAVE_STATUS)
12601.1Skamil	int status;
12611.1Skamil#endif
12621.1Skamil	ptrace_event_t set_event, get_event;
12631.1Skamil	const int len = sizeof(ptrace_event_t);
12641.1Skamil
12651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12671.1Skamil	if (child == 0) {
12681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12701.1Skamil
12711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12731.1Skamil
12741.13Schristos		DPRINTF("Before exiting of the child process\n");
12751.1Skamil		_exit(exitval);
12761.1Skamil	}
12771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12781.1Skamil
12791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12811.1Skamil
12821.1Skamil	validate_status_stopped(status, sigval);
12831.1Skamil
12841.1Skamil	set_event.pe_set_event = 0;
12851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12871.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12881.1Skamil
12891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12901.1Skamil	    "without signal to be sent\n");
12911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12921.1Skamil
12931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12951.1Skamil
12961.1Skamil	validate_status_exited(status, exitval);
12971.1Skamil
12981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13001.1Skamil}
13011.1Skamil
13021.1SkamilATF_TC(eventmask2);
13031.1SkamilATF_TC_HEAD(eventmask2, tc)
13041.1Skamil{
13051.1Skamil	atf_tc_set_md_var(tc, "descr",
13061.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
13071.1Skamil}
13081.1Skamil
13091.1SkamilATF_TC_BODY(eventmask2, tc)
13101.1Skamil{
13111.1Skamil	const int exitval = 5;
13121.1Skamil	const int sigval = SIGSTOP;
13131.1Skamil	pid_t child, wpid;
13141.1Skamil#if defined(TWAIT_HAVE_STATUS)
13151.1Skamil	int status;
13161.1Skamil#endif
13171.1Skamil	ptrace_event_t set_event, get_event;
13181.1Skamil	const int len = sizeof(ptrace_event_t);
13191.1Skamil
13201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13221.1Skamil	if (child == 0) {
13231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13251.1Skamil
13261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13281.1Skamil
13291.13Schristos		DPRINTF("Before exiting of the child process\n");
13301.1Skamil		_exit(exitval);
13311.1Skamil	}
13321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13331.1Skamil
13341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13361.1Skamil
13371.1Skamil	validate_status_stopped(status, sigval);
13381.1Skamil
13391.1Skamil	set_event.pe_set_event = PTRACE_FORK;
13401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13421.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13431.1Skamil
13441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13451.1Skamil	    "without signal to be sent\n");
13461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13471.1Skamil
13481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13501.1Skamil
13511.1Skamil	validate_status_exited(status, exitval);
13521.1Skamil
13531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13551.1Skamil}
13561.1Skamil
13571.1SkamilATF_TC(eventmask3);
13581.1SkamilATF_TC_HEAD(eventmask3, tc)
13591.1Skamil{
13601.1Skamil	atf_tc_set_md_var(tc, "descr",
13611.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
13621.1Skamil}
13631.1Skamil
13641.1SkamilATF_TC_BODY(eventmask3, tc)
13651.1Skamil{
13661.1Skamil	const int exitval = 5;
13671.1Skamil	const int sigval = SIGSTOP;
13681.1Skamil	pid_t child, wpid;
13691.1Skamil#if defined(TWAIT_HAVE_STATUS)
13701.1Skamil	int status;
13711.1Skamil#endif
13721.1Skamil	ptrace_event_t set_event, get_event;
13731.1Skamil	const int len = sizeof(ptrace_event_t);
13741.1Skamil
13751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13771.1Skamil	if (child == 0) {
13781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13801.1Skamil
13811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13831.1Skamil
13841.13Schristos		DPRINTF("Before exiting of the child process\n");
13851.1Skamil		_exit(exitval);
13861.1Skamil	}
13871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13881.1Skamil
13891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13911.1Skamil
13921.1Skamil	validate_status_stopped(status, sigval);
13931.1Skamil
13941.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
13951.38Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13971.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13981.1Skamil
13991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14001.1Skamil	    "without signal to be sent\n");
14011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14021.1Skamil
14031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14051.1Skamil
14061.1Skamil	validate_status_exited(status, exitval);
14071.1Skamil
14081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14101.1Skamil}
14111.1Skamil
14121.1SkamilATF_TC(eventmask4);
14131.1SkamilATF_TC_HEAD(eventmask4, tc)
14141.1Skamil{
14151.1Skamil	atf_tc_set_md_var(tc, "descr",
14161.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
14171.1Skamil}
14181.1Skamil
14191.1SkamilATF_TC_BODY(eventmask4, tc)
14201.1Skamil{
14211.1Skamil	const int exitval = 5;
14221.1Skamil	const int sigval = SIGSTOP;
14231.1Skamil	pid_t child, wpid;
14241.1Skamil#if defined(TWAIT_HAVE_STATUS)
14251.1Skamil	int status;
14261.1Skamil#endif
14271.1Skamil	ptrace_event_t set_event, get_event;
14281.1Skamil	const int len = sizeof(ptrace_event_t);
14291.1Skamil
14301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14321.1Skamil	if (child == 0) {
14331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14351.1Skamil
14361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14381.1Skamil
14391.13Schristos		DPRINTF("Before exiting of the child process\n");
14401.1Skamil		_exit(exitval);
14411.1Skamil	}
14421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14431.1Skamil
14441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14461.1Skamil
14471.1Skamil	validate_status_stopped(status, sigval);
14481.1Skamil
14491.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
14501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14521.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14531.1Skamil
14541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14551.1Skamil	    "without signal to be sent\n");
14561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14571.1Skamil
14581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14601.1Skamil
14611.1Skamil	validate_status_exited(status, exitval);
14621.1Skamil
14631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14651.1Skamil}
14661.1Skamil
14671.1SkamilATF_TC(eventmask5);
14681.1SkamilATF_TC_HEAD(eventmask5, tc)
14691.1Skamil{
14701.1Skamil	atf_tc_set_md_var(tc, "descr",
14711.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
14721.1Skamil}
14731.1Skamil
14741.1SkamilATF_TC_BODY(eventmask5, tc)
14751.1Skamil{
14761.1Skamil	const int exitval = 5;
14771.1Skamil	const int sigval = SIGSTOP;
14781.1Skamil	pid_t child, wpid;
14791.1Skamil#if defined(TWAIT_HAVE_STATUS)
14801.1Skamil	int status;
14811.1Skamil#endif
14821.1Skamil	ptrace_event_t set_event, get_event;
14831.1Skamil	const int len = sizeof(ptrace_event_t);
14841.1Skamil
14851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14871.1Skamil	if (child == 0) {
14881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14901.1Skamil
14911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14931.1Skamil
14941.13Schristos		DPRINTF("Before exiting of the child process\n");
14951.1Skamil		_exit(exitval);
14961.1Skamil	}
14971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14981.1Skamil
14991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15011.1Skamil
15021.1Skamil	validate_status_stopped(status, sigval);
15031.1Skamil
15041.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
15051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15071.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15081.1Skamil
15091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15101.1Skamil	    "without signal to be sent\n");
15111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15121.1Skamil
15131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15151.1Skamil
15161.1Skamil	validate_status_exited(status, exitval);
15171.1Skamil
15181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15201.1Skamil}
15211.1Skamil
15221.1SkamilATF_TC(eventmask6);
15231.1SkamilATF_TC_HEAD(eventmask6, tc)
15241.1Skamil{
15251.1Skamil	atf_tc_set_md_var(tc, "descr",
15261.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
15271.1Skamil}
15281.1Skamil
15291.1SkamilATF_TC_BODY(eventmask6, tc)
15301.1Skamil{
15311.1Skamil	const int exitval = 5;
15321.1Skamil	const int sigval = SIGSTOP;
15331.1Skamil	pid_t child, wpid;
15341.1Skamil#if defined(TWAIT_HAVE_STATUS)
15351.1Skamil	int status;
15361.1Skamil#endif
15371.1Skamil	ptrace_event_t set_event, get_event;
15381.1Skamil	const int len = sizeof(ptrace_event_t);
15391.1Skamil
15401.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15411.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15421.1Skamil	if (child == 0) {
15431.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15441.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15451.1Skamil
15461.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15471.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15481.1Skamil
15491.13Schristos		DPRINTF("Before exiting of the child process\n");
15501.1Skamil		_exit(exitval);
15511.1Skamil	}
15521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15531.1Skamil
15541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15561.1Skamil
15571.1Skamil	validate_status_stopped(status, sigval);
15581.1Skamil
15591.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
15601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15621.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15631.1Skamil
15641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15651.1Skamil	    "without signal to be sent\n");
15661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15671.1Skamil
15681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15701.1Skamil
15711.1Skamil	validate_status_exited(status, exitval);
15721.1Skamil
15731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15751.1Skamil}
15761.1Skamil
15771.28Skamilstatic void
15781.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
15791.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
15801.1Skamil{
15811.1Skamil	const int exitval = 5;
15821.1Skamil	const int exitval2 = 15;
15831.1Skamil	const int sigval = SIGSTOP;
15841.31Skamil	pid_t child, child2 = 0, wpid;
15851.1Skamil#if defined(TWAIT_HAVE_STATUS)
15861.1Skamil	int status;
15871.1Skamil#endif
15881.1Skamil	ptrace_state_t state;
15891.1Skamil	const int slen = sizeof(state);
15901.1Skamil	ptrace_event_t event;
15911.1Skamil	const int elen = sizeof(event);
15921.1Skamil
15931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15951.1Skamil	if (child == 0) {
15961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15981.1Skamil
15991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
16001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
16011.1Skamil
16021.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
16031.1Skamil
16041.1Skamil		if (child2 == 0)
16051.1Skamil			_exit(exitval2);
16061.1Skamil
16071.1Skamil		FORKEE_REQUIRE_SUCCESS
16081.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
16091.1Skamil
16101.1Skamil		forkee_status_exited(status, exitval2);
16111.1Skamil
16121.13Schristos		DPRINTF("Before exiting of the child process\n");
16131.1Skamil		_exit(exitval);
16141.1Skamil	}
16151.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16161.1Skamil
16171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16191.1Skamil
16201.1Skamil	validate_status_stopped(status, sigval);
16211.1Skamil
16221.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
16231.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
16241.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
16251.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
16261.30Skamil	event.pe_set_event = 0;
16271.30Skamil	if (trackfork)
16281.30Skamil		event.pe_set_event |= PTRACE_FORK;
16291.30Skamil	if (trackvfork)
16301.30Skamil		event.pe_set_event |= PTRACE_VFORK;
16311.30Skamil	if (trackvforkdone)
16321.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
16331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
16341.1Skamil
16351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16361.1Skamil	    "without signal to be sent\n");
16371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16381.1Skamil
16391.29Skamil#if defined(TWAIT_HAVE_PID)
16401.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
16411.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16421.29Skamil		        child);
16431.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16441.29Skamil		                      child);
16451.1Skamil
16461.29Skamil		validate_status_stopped(status, SIGTRAP);
16471.1Skamil
16481.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
16491.29Skamil		                       slen) != -1);
16501.31Skamil		if (trackfork && fn == fork) {
16511.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16521.30Skamil			       PTRACE_FORK);
16531.30Skamil		}
16541.31Skamil		if (trackvfork && fn == vfork) {
16551.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16561.30Skamil			       PTRACE_VFORK);
16571.30Skamil		}
16581.29Skamil
16591.29Skamil		child2 = state.pe_other_pid;
16601.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
16611.29Skamil
16621.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
16631.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
16641.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16651.29Skamil		    child2);
16661.1Skamil
16671.29Skamil		validate_status_stopped(status, SIGTRAP);
16681.1Skamil
16691.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
16701.29Skamil		                       slen) != -1);
16711.31Skamil		if (trackfork && fn == fork) {
16721.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16731.30Skamil			       PTRACE_FORK);
16741.30Skamil		}
16751.31Skamil		if (trackvfork && fn == vfork) {
16761.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16771.30Skamil			       PTRACE_VFORK);
16781.30Skamil		}
16791.30Skamil
16801.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
16811.29Skamil
16821.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
16831.29Skamil		    "and without signal to be sent\n");
16841.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
16851.29Skamil		                != -1);
16861.29Skamil
16871.29Skamil		DPRINTF("Before resuming the child process where it left off "
16881.29Skamil		        "and without signal to be sent\n");
16891.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16901.30Skamil	}
16911.30Skamil#endif
16921.30Skamil
16931.31Skamil	if (trackvforkdone && fn == vfork) {
16941.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16951.30Skamil		        child);
16961.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16971.30Skamil		                      child);
16981.30Skamil
16991.30Skamil		validate_status_stopped(status, SIGTRAP);
17001.30Skamil
17011.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
17021.30Skamil		                       slen) != -1);
17031.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
17041.30Skamil
17051.30Skamil		child2 = state.pe_other_pid;
17061.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
17071.30Skamil		        child2);
17081.30Skamil
17091.30Skamil		DPRINTF("Before resuming the child process where it left off "
17101.30Skamil		        "and without signal to be sent\n");
17111.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17121.30Skamil	}
17131.29Skamil
17141.30Skamil#if defined(TWAIT_HAVE_PID)
17151.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
17161.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
17171.29Skamil		        "\n", TWAIT_FNAME);
17181.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
17191.29Skamil		    child2);
17201.29Skamil
17211.29Skamil		validate_status_exited(status, exitval2);
17221.29Skamil
17231.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
17241.29Skamil		        "process\n", TWAIT_FNAME);
17251.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
17261.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
17271.29Skamil	}
17281.29Skamil#endif
17291.1Skamil
17301.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
17311.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
17321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17331.1Skamil
17341.1Skamil	validate_status_stopped(status, SIGCHLD);
17351.1Skamil
17361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17371.1Skamil	    "without signal to be sent\n");
17381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17391.1Skamil
17401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
17411.1Skamil	    TWAIT_FNAME);
17421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17431.1Skamil
17441.1Skamil	validate_status_exited(status, exitval);
17451.1Skamil
17461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
17471.1Skamil	    TWAIT_FNAME);
17481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17491.1Skamil}
17501.28Skamil
17511.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
17521.32SkamilATF_TC(name);									\
17531.32SkamilATF_TC_HEAD(name, tc)								\
17541.32Skamil{										\
17551.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
17561.32Skamil}										\
17571.32Skamil										\
17581.32SkamilATF_TC_BODY(name, tc)								\
17591.32Skamil{										\
17601.32Skamil										\
17611.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
17621.32Skamil}
17631.32Skamil
17641.32Skamil#define F false
17651.32Skamil#define T true
17661.32Skamil
17671.32Skamil#define F_IF__0(x)
17681.32Skamil#define F_IF__1(x) x
17691.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
17701.32Skamil#define F_IF_(x,y) F_IF__(x,y)
17711.32Skamil#define F_IF(x,y) F_IF_(x,y)
17721.32Skamil
17731.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
17741.32Skamil        "Verify " #function "(2) called with 0"					\
17751.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
17761.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
17771.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
17781.32Skamil        " in EVENT_MASK."							\
17791.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
17801.32Skamil        F_IF(dparentbit," Detach parent in this test.")
17811.1Skamil
17821.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
17831.31Skamil#if defined(TWAIT_HAVE_PID)
17841.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
17851.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
17861.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
17871.31Skamil#endif
17881.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
17891.31Skamil#if defined(TWAIT_HAVE_PID)
17901.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
17911.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
17921.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
17931.31Skamil#endif
17941.1Skamil
17951.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
17961.31Skamil#if defined(TWAIT_HAVE_PID)
17971.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
17981.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
17991.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
18001.31Skamil#endif
18011.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
18021.31Skamil#if defined(TWAIT_HAVE_PID)
18031.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
18041.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
18051.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
18061.31Skamil#endif
18071.31Skamil
18081.31Skamil
18091.31Skamil
18101.1Skamil
18111.1SkamilATF_TC(io_read_d1);
18121.1SkamilATF_TC_HEAD(io_read_d1, tc)
18131.1Skamil{
18141.1Skamil	atf_tc_set_md_var(tc, "descr",
18151.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
18161.1Skamil}
18171.1Skamil
18181.1SkamilATF_TC_BODY(io_read_d1, tc)
18191.1Skamil{
18201.1Skamil	const int exitval = 5;
18211.1Skamil	const int sigval = SIGSTOP;
18221.1Skamil	pid_t child, wpid;
18231.1Skamil	uint8_t lookup_me = 0;
18241.1Skamil	const uint8_t magic = 0xab;
18251.1Skamil	struct ptrace_io_desc io = {
18261.1Skamil		.piod_op = PIOD_READ_D,
18271.1Skamil		.piod_offs = &lookup_me,
18281.1Skamil		.piod_addr = &lookup_me,
18291.1Skamil		.piod_len = sizeof(lookup_me)
18301.1Skamil	};
18311.1Skamil#if defined(TWAIT_HAVE_STATUS)
18321.1Skamil	int status;
18331.1Skamil#endif
18341.1Skamil
18351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18371.1Skamil	if (child == 0) {
18381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18401.1Skamil
18411.1Skamil		lookup_me = magic;
18421.1Skamil
18431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18451.1Skamil
18461.13Schristos		DPRINTF("Before exiting of the child process\n");
18471.1Skamil		_exit(exitval);
18481.1Skamil	}
18491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18501.1Skamil
18511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18531.1Skamil
18541.1Skamil	validate_status_stopped(status, sigval);
18551.1Skamil
18561.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
18571.1Skamil	    child, getpid());
18581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
18591.1Skamil
18601.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18611.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
18621.1Skamil
18631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18641.1Skamil	    "without signal to be sent\n");
18651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18661.1Skamil
18671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18691.1Skamil
18701.1Skamil	validate_status_exited(status, exitval);
18711.1Skamil
18721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18741.1Skamil}
18751.1Skamil
18761.1SkamilATF_TC(io_read_d2);
18771.1SkamilATF_TC_HEAD(io_read_d2, tc)
18781.1Skamil{
18791.1Skamil	atf_tc_set_md_var(tc, "descr",
18801.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
18811.1Skamil}
18821.1Skamil
18831.1SkamilATF_TC_BODY(io_read_d2, tc)
18841.1Skamil{
18851.1Skamil	const int exitval = 5;
18861.1Skamil	const int sigval = SIGSTOP;
18871.1Skamil	pid_t child, wpid;
18881.1Skamil	uint16_t lookup_me = 0;
18891.1Skamil	const uint16_t magic = 0x1234;
18901.1Skamil	struct ptrace_io_desc io = {
18911.1Skamil		.piod_op = PIOD_READ_D,
18921.1Skamil		.piod_offs = &lookup_me,
18931.1Skamil		.piod_addr = &lookup_me,
18941.1Skamil		.piod_len = sizeof(lookup_me)
18951.1Skamil	};
18961.1Skamil#if defined(TWAIT_HAVE_STATUS)
18971.1Skamil	int status;
18981.1Skamil#endif
18991.1Skamil
19001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19021.1Skamil	if (child == 0) {
19031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19051.1Skamil
19061.1Skamil		lookup_me = magic;
19071.1Skamil
19081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19101.1Skamil
19111.13Schristos		DPRINTF("Before exiting of the child process\n");
19121.1Skamil		_exit(exitval);
19131.1Skamil	}
19141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19151.1Skamil
19161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19181.1Skamil
19191.1Skamil	validate_status_stopped(status, sigval);
19201.1Skamil
19211.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19221.1Skamil	    child, getpid());
19231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19241.1Skamil
19251.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19261.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
19271.1Skamil
19281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19291.1Skamil	    "without signal to be sent\n");
19301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19311.1Skamil
19321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19341.1Skamil
19351.1Skamil	validate_status_exited(status, exitval);
19361.1Skamil
19371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19391.1Skamil}
19401.1Skamil
19411.1SkamilATF_TC(io_read_d3);
19421.1SkamilATF_TC_HEAD(io_read_d3, tc)
19431.1Skamil{
19441.1Skamil	atf_tc_set_md_var(tc, "descr",
19451.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
19461.1Skamil}
19471.1Skamil
19481.1SkamilATF_TC_BODY(io_read_d3, tc)
19491.1Skamil{
19501.1Skamil	const int exitval = 5;
19511.1Skamil	const int sigval = SIGSTOP;
19521.1Skamil	pid_t child, wpid;
19531.1Skamil	uint32_t lookup_me = 0;
19541.1Skamil	const uint32_t magic = 0x1234abcd;
19551.1Skamil	struct ptrace_io_desc io = {
19561.1Skamil		.piod_op = PIOD_READ_D,
19571.1Skamil		.piod_offs = &lookup_me,
19581.1Skamil		.piod_addr = &lookup_me,
19591.1Skamil		.piod_len = sizeof(lookup_me)
19601.1Skamil	};
19611.1Skamil#if defined(TWAIT_HAVE_STATUS)
19621.1Skamil	int status;
19631.1Skamil#endif
19641.1Skamil
19651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19671.1Skamil	if (child == 0) {
19681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19701.1Skamil
19711.1Skamil		lookup_me = magic;
19721.1Skamil
19731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19751.1Skamil
19761.13Schristos		DPRINTF("Before exiting of the child process\n");
19771.1Skamil		_exit(exitval);
19781.1Skamil	}
19791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19801.1Skamil
19811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19831.1Skamil
19841.1Skamil	validate_status_stopped(status, sigval);
19851.1Skamil
19861.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19871.1Skamil	    child, getpid());
19881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19891.1Skamil
19901.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19911.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
19921.1Skamil
19931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19941.1Skamil	    "without signal to be sent\n");
19951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19961.1Skamil
19971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19991.1Skamil
20001.1Skamil	validate_status_exited(status, exitval);
20011.1Skamil
20021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20041.1Skamil}
20051.1Skamil
20061.1SkamilATF_TC(io_read_d4);
20071.1SkamilATF_TC_HEAD(io_read_d4, tc)
20081.1Skamil{
20091.1Skamil	atf_tc_set_md_var(tc, "descr",
20101.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
20111.1Skamil}
20121.1Skamil
20131.1SkamilATF_TC_BODY(io_read_d4, tc)
20141.1Skamil{
20151.1Skamil	const int exitval = 5;
20161.1Skamil	const int sigval = SIGSTOP;
20171.1Skamil	pid_t child, wpid;
20181.1Skamil	uint64_t lookup_me = 0;
20191.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
20201.1Skamil	struct ptrace_io_desc io = {
20211.1Skamil		.piod_op = PIOD_READ_D,
20221.1Skamil		.piod_offs = &lookup_me,
20231.1Skamil		.piod_addr = &lookup_me,
20241.1Skamil		.piod_len = sizeof(lookup_me)
20251.1Skamil	};
20261.1Skamil#if defined(TWAIT_HAVE_STATUS)
20271.1Skamil	int status;
20281.1Skamil#endif
20291.1Skamil
20301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20321.1Skamil	if (child == 0) {
20331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20351.1Skamil
20361.1Skamil		lookup_me = magic;
20371.1Skamil
20381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20401.1Skamil
20411.13Schristos		DPRINTF("Before exiting of the child process\n");
20421.1Skamil		_exit(exitval);
20431.1Skamil	}
20441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20451.1Skamil
20461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20481.1Skamil
20491.1Skamil	validate_status_stopped(status, sigval);
20501.1Skamil
20511.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
20521.1Skamil	    child, getpid());
20531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20541.1Skamil
20551.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
20561.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
20571.1Skamil
20581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20591.1Skamil	    "without signal to be sent\n");
20601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20611.1Skamil
20621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20641.1Skamil
20651.1Skamil	validate_status_exited(status, exitval);
20661.1Skamil
20671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20691.1Skamil}
20701.1Skamil
20711.1SkamilATF_TC(io_write_d1);
20721.1SkamilATF_TC_HEAD(io_write_d1, tc)
20731.1Skamil{
20741.1Skamil	atf_tc_set_md_var(tc, "descr",
20751.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
20761.1Skamil}
20771.1Skamil
20781.1SkamilATF_TC_BODY(io_write_d1, tc)
20791.1Skamil{
20801.1Skamil	const int exitval = 5;
20811.1Skamil	const int sigval = SIGSTOP;
20821.1Skamil	pid_t child, wpid;
20831.1Skamil	uint8_t lookup_me = 0;
20841.1Skamil	const uint8_t magic = 0xab;
20851.1Skamil	struct ptrace_io_desc io = {
20861.1Skamil		.piod_op = PIOD_WRITE_D,
20871.1Skamil		.piod_offs = &lookup_me,
20881.1Skamil		.piod_addr = &lookup_me,
20891.1Skamil		.piod_len = sizeof(lookup_me)
20901.1Skamil	};
20911.1Skamil#if defined(TWAIT_HAVE_STATUS)
20921.1Skamil	int status;
20931.1Skamil#endif
20941.1Skamil
20951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20971.1Skamil	if (child == 0) {
20981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21001.1Skamil
21011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21031.1Skamil
21041.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21051.1Skamil
21061.13Schristos		DPRINTF("Before exiting of the child process\n");
21071.1Skamil		_exit(exitval);
21081.1Skamil	}
21091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21101.1Skamil
21111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21131.1Skamil
21141.1Skamil	validate_status_stopped(status, sigval);
21151.1Skamil
21161.1Skamil	lookup_me = magic;
21171.1Skamil
21181.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21191.1Skamil	    child, getpid());
21201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21211.1Skamil
21221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21231.1Skamil	    "without signal to be sent\n");
21241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21251.1Skamil
21261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21281.1Skamil
21291.1Skamil	validate_status_exited(status, exitval);
21301.1Skamil
21311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21331.1Skamil}
21341.1Skamil
21351.1SkamilATF_TC(io_write_d2);
21361.1SkamilATF_TC_HEAD(io_write_d2, tc)
21371.1Skamil{
21381.1Skamil	atf_tc_set_md_var(tc, "descr",
21391.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
21401.1Skamil}
21411.1Skamil
21421.1SkamilATF_TC_BODY(io_write_d2, tc)
21431.1Skamil{
21441.1Skamil	const int exitval = 5;
21451.1Skamil	const int sigval = SIGSTOP;
21461.1Skamil	pid_t child, wpid;
21471.1Skamil	uint16_t lookup_me = 0;
21481.1Skamil	const uint16_t magic = 0xab12;
21491.1Skamil	struct ptrace_io_desc io = {
21501.1Skamil		.piod_op = PIOD_WRITE_D,
21511.1Skamil		.piod_offs = &lookup_me,
21521.1Skamil		.piod_addr = &lookup_me,
21531.1Skamil		.piod_len = sizeof(lookup_me)
21541.1Skamil	};
21551.1Skamil#if defined(TWAIT_HAVE_STATUS)
21561.1Skamil	int status;
21571.1Skamil#endif
21581.1Skamil
21591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21611.1Skamil	if (child == 0) {
21621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21641.1Skamil
21651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21671.1Skamil
21681.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21691.1Skamil
21701.13Schristos		DPRINTF("Before exiting of the child process\n");
21711.1Skamil		_exit(exitval);
21721.1Skamil	}
21731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21741.1Skamil
21751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21771.1Skamil
21781.1Skamil	validate_status_stopped(status, sigval);
21791.1Skamil
21801.1Skamil	lookup_me = magic;
21811.1Skamil
21821.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21831.1Skamil	    child, getpid());
21841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21851.1Skamil
21861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21871.1Skamil	    "without signal to be sent\n");
21881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21891.1Skamil
21901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21921.1Skamil
21931.1Skamil	validate_status_exited(status, exitval);
21941.1Skamil
21951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21971.1Skamil}
21981.1Skamil
21991.1SkamilATF_TC(io_write_d3);
22001.1SkamilATF_TC_HEAD(io_write_d3, tc)
22011.1Skamil{
22021.1Skamil	atf_tc_set_md_var(tc, "descr",
22031.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
22041.1Skamil}
22051.1Skamil
22061.1SkamilATF_TC_BODY(io_write_d3, tc)
22071.1Skamil{
22081.1Skamil	const int exitval = 5;
22091.1Skamil	const int sigval = SIGSTOP;
22101.1Skamil	pid_t child, wpid;
22111.1Skamil	uint32_t lookup_me = 0;
22121.1Skamil	const uint32_t magic = 0xab127643;
22131.1Skamil	struct ptrace_io_desc io = {
22141.1Skamil		.piod_op = PIOD_WRITE_D,
22151.1Skamil		.piod_offs = &lookup_me,
22161.1Skamil		.piod_addr = &lookup_me,
22171.1Skamil		.piod_len = sizeof(lookup_me)
22181.1Skamil	};
22191.1Skamil#if defined(TWAIT_HAVE_STATUS)
22201.1Skamil	int status;
22211.1Skamil#endif
22221.1Skamil
22231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22251.1Skamil	if (child == 0) {
22261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22281.1Skamil
22291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22311.1Skamil
22321.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22331.1Skamil
22341.13Schristos		DPRINTF("Before exiting of the child process\n");
22351.1Skamil		_exit(exitval);
22361.1Skamil	}
22371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22381.1Skamil
22391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22411.1Skamil
22421.1Skamil	validate_status_stopped(status, sigval);
22431.1Skamil
22441.1Skamil	lookup_me = magic;
22451.1Skamil
22461.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22471.1Skamil	    child, getpid());
22481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22491.1Skamil
22501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22511.1Skamil	    "without signal to be sent\n");
22521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22531.1Skamil
22541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22561.1Skamil
22571.1Skamil	validate_status_exited(status, exitval);
22581.1Skamil
22591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22611.1Skamil}
22621.1Skamil
22631.1SkamilATF_TC(io_write_d4);
22641.1SkamilATF_TC_HEAD(io_write_d4, tc)
22651.1Skamil{
22661.1Skamil	atf_tc_set_md_var(tc, "descr",
22671.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
22681.1Skamil}
22691.1Skamil
22701.1SkamilATF_TC_BODY(io_write_d4, tc)
22711.1Skamil{
22721.1Skamil	const int exitval = 5;
22731.1Skamil	const int sigval = SIGSTOP;
22741.1Skamil	pid_t child, wpid;
22751.1Skamil	uint64_t lookup_me = 0;
22761.1Skamil	const uint64_t magic = 0xab12764376490123;
22771.1Skamil	struct ptrace_io_desc io = {
22781.1Skamil		.piod_op = PIOD_WRITE_D,
22791.1Skamil		.piod_offs = &lookup_me,
22801.1Skamil		.piod_addr = &lookup_me,
22811.1Skamil		.piod_len = sizeof(lookup_me)
22821.1Skamil	};
22831.1Skamil#if defined(TWAIT_HAVE_STATUS)
22841.1Skamil	int status;
22851.1Skamil#endif
22861.1Skamil
22871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22891.1Skamil	if (child == 0) {
22901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22921.1Skamil
22931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22951.1Skamil
22961.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22971.1Skamil
22981.13Schristos		DPRINTF("Before exiting of the child process\n");
22991.1Skamil		_exit(exitval);
23001.1Skamil	}
23011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23021.1Skamil
23031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23051.1Skamil
23061.1Skamil	validate_status_stopped(status, sigval);
23071.1Skamil
23081.1Skamil	lookup_me = magic;
23091.1Skamil
23101.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
23111.1Skamil	    child, getpid());
23121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23131.1Skamil
23141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23151.1Skamil	    "without signal to be sent\n");
23161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23171.1Skamil
23181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23201.1Skamil
23211.1Skamil	validate_status_exited(status, exitval);
23221.1Skamil
23231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23251.1Skamil}
23261.1Skamil
23271.1SkamilATF_TC(io_read_auxv1);
23281.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
23291.1Skamil{
23301.1Skamil	atf_tc_set_md_var(tc, "descr",
23311.1Skamil	    "Verify PT_READ_AUXV called for tracee");
23321.1Skamil}
23331.1Skamil
23341.1SkamilATF_TC_BODY(io_read_auxv1, tc)
23351.1Skamil{
23361.1Skamil	const int exitval = 5;
23371.1Skamil	const int sigval = SIGSTOP;
23381.1Skamil	pid_t child, wpid;
23391.1Skamil#if defined(TWAIT_HAVE_STATUS)
23401.1Skamil	int status;
23411.1Skamil#endif
23421.1Skamil	AuxInfo ai[100], *aip;
23431.1Skamil	struct ptrace_io_desc io = {
23441.1Skamil		.piod_op = PIOD_READ_AUXV,
23451.1Skamil		.piod_offs = 0,
23461.1Skamil		.piod_addr = ai,
23471.1Skamil		.piod_len = sizeof(ai)
23481.1Skamil	};
23491.1Skamil
23501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23521.1Skamil	if (child == 0) {
23531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23551.1Skamil
23561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23581.1Skamil
23591.13Schristos		DPRINTF("Before exiting of the child process\n");
23601.1Skamil		_exit(exitval);
23611.1Skamil	}
23621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23631.1Skamil
23641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23661.1Skamil
23671.1Skamil	validate_status_stopped(status, sigval);
23681.1Skamil
23691.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
23701.1Skamil	    child, getpid());
23711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23721.1Skamil
23731.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
23741.1Skamil	ATF_REQUIRE(io.piod_len > 0);
23751.1Skamil
23761.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
23771.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
23781.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
23791.1Skamil
23801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23811.1Skamil	    "without signal to be sent\n");
23821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23831.1Skamil
23841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23861.1Skamil
23871.1Skamil	validate_status_exited(status, exitval);
23881.1Skamil
23891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23911.1Skamil}
23921.1Skamil
23931.1SkamilATF_TC(read_d1);
23941.1SkamilATF_TC_HEAD(read_d1, tc)
23951.1Skamil{
23961.1Skamil	atf_tc_set_md_var(tc, "descr",
23971.1Skamil	    "Verify PT_READ_D called once");
23981.1Skamil}
23991.1Skamil
24001.1SkamilATF_TC_BODY(read_d1, tc)
24011.1Skamil{
24021.1Skamil	const int exitval = 5;
24031.1Skamil	const int sigval = SIGSTOP;
24041.1Skamil	pid_t child, wpid;
24051.1Skamil	int lookup_me = 0;
24061.1Skamil	const int magic = (int)random();
24071.1Skamil#if defined(TWAIT_HAVE_STATUS)
24081.1Skamil	int status;
24091.1Skamil#endif
24101.1Skamil
24111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24131.1Skamil	if (child == 0) {
24141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24161.1Skamil
24171.1Skamil		lookup_me = magic;
24181.1Skamil
24191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24211.1Skamil
24221.13Schristos		DPRINTF("Before exiting of the child process\n");
24231.1Skamil		_exit(exitval);
24241.1Skamil	}
24251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24261.1Skamil
24271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24291.1Skamil
24301.1Skamil	validate_status_stopped(status, sigval);
24311.1Skamil
24321.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
24331.1Skamil	    child, getpid());
24341.1Skamil	errno = 0;
24351.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
24361.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24371.1Skamil
24381.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
24391.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
24401.1Skamil
24411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24421.1Skamil	    "without signal to be sent\n");
24431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24441.1Skamil
24451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24471.1Skamil
24481.1Skamil	validate_status_exited(status, exitval);
24491.1Skamil
24501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24521.1Skamil}
24531.1Skamil
24541.1SkamilATF_TC(read_d2);
24551.1SkamilATF_TC_HEAD(read_d2, tc)
24561.1Skamil{
24571.1Skamil	atf_tc_set_md_var(tc, "descr",
24581.1Skamil	    "Verify PT_READ_D called twice");
24591.1Skamil}
24601.1Skamil
24611.1SkamilATF_TC_BODY(read_d2, tc)
24621.1Skamil{
24631.1Skamil	const int exitval = 5;
24641.1Skamil	const int sigval = SIGSTOP;
24651.1Skamil	pid_t child, wpid;
24661.1Skamil	int lookup_me1 = 0;
24671.1Skamil	int lookup_me2 = 0;
24681.1Skamil	const int magic1 = (int)random();
24691.1Skamil	const int magic2 = (int)random();
24701.1Skamil#if defined(TWAIT_HAVE_STATUS)
24711.1Skamil	int status;
24721.1Skamil#endif
24731.1Skamil
24741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24761.1Skamil	if (child == 0) {
24771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24791.1Skamil
24801.1Skamil		lookup_me1 = magic1;
24811.1Skamil		lookup_me2 = magic2;
24821.1Skamil
24831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24851.1Skamil
24861.13Schristos		DPRINTF("Before exiting of the child process\n");
24871.1Skamil		_exit(exitval);
24881.1Skamil	}
24891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24901.1Skamil
24911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24931.1Skamil
24941.1Skamil	validate_status_stopped(status, sigval);
24951.1Skamil
24961.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
24971.1Skamil	    child, getpid());
24981.1Skamil	errno = 0;
24991.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25001.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25011.1Skamil
25021.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25031.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25041.1Skamil
25051.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25061.1Skamil	    child, getpid());
25071.1Skamil	errno = 0;
25081.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25091.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25101.1Skamil
25111.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25121.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25131.1Skamil
25141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25151.1Skamil	    "without signal to be sent\n");
25161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25171.1Skamil
25181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25201.1Skamil
25211.1Skamil	validate_status_exited(status, exitval);
25221.1Skamil
25231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25251.1Skamil}
25261.1Skamil
25271.1SkamilATF_TC(read_d3);
25281.1SkamilATF_TC_HEAD(read_d3, tc)
25291.1Skamil{
25301.1Skamil	atf_tc_set_md_var(tc, "descr",
25311.1Skamil	    "Verify PT_READ_D called three times");
25321.1Skamil}
25331.1Skamil
25341.1SkamilATF_TC_BODY(read_d3, tc)
25351.1Skamil{
25361.1Skamil	const int exitval = 5;
25371.1Skamil	const int sigval = SIGSTOP;
25381.1Skamil	pid_t child, wpid;
25391.1Skamil	int lookup_me1 = 0;
25401.1Skamil	int lookup_me2 = 0;
25411.1Skamil	int lookup_me3 = 0;
25421.1Skamil	const int magic1 = (int)random();
25431.1Skamil	const int magic2 = (int)random();
25441.1Skamil	const int magic3 = (int)random();
25451.1Skamil#if defined(TWAIT_HAVE_STATUS)
25461.1Skamil	int status;
25471.1Skamil#endif
25481.1Skamil
25491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25511.1Skamil	if (child == 0) {
25521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25541.1Skamil
25551.1Skamil		lookup_me1 = magic1;
25561.1Skamil		lookup_me2 = magic2;
25571.1Skamil		lookup_me3 = magic3;
25581.1Skamil
25591.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25601.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25611.1Skamil
25621.13Schristos		DPRINTF("Before exiting of the child process\n");
25631.1Skamil		_exit(exitval);
25641.1Skamil	}
25651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25661.1Skamil
25671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25691.1Skamil
25701.1Skamil	validate_status_stopped(status, sigval);
25711.1Skamil
25721.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25731.1Skamil	    child, getpid());
25741.1Skamil	errno = 0;
25751.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25761.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25771.1Skamil
25781.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25791.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25801.1Skamil
25811.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25821.1Skamil	    child, getpid());
25831.1Skamil	errno = 0;
25841.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25851.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25861.1Skamil
25871.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25881.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25891.1Skamil
25901.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
25911.1Skamil	    child, getpid());
25921.1Skamil	errno = 0;
25931.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
25941.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25951.1Skamil
25961.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
25971.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
25981.1Skamil
25991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26001.1Skamil	    "without signal to be sent\n");
26011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26021.1Skamil
26031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26051.1Skamil
26061.1Skamil	validate_status_exited(status, exitval);
26071.1Skamil
26081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26101.1Skamil}
26111.1Skamil
26121.1SkamilATF_TC(read_d4);
26131.1SkamilATF_TC_HEAD(read_d4, tc)
26141.1Skamil{
26151.1Skamil	atf_tc_set_md_var(tc, "descr",
26161.1Skamil	    "Verify PT_READ_D called four times");
26171.1Skamil}
26181.1Skamil
26191.1SkamilATF_TC_BODY(read_d4, tc)
26201.1Skamil{
26211.1Skamil	const int exitval = 5;
26221.1Skamil	const int sigval = SIGSTOP;
26231.1Skamil	pid_t child, wpid;
26241.1Skamil	int lookup_me1 = 0;
26251.1Skamil	int lookup_me2 = 0;
26261.1Skamil	int lookup_me3 = 0;
26271.1Skamil	int lookup_me4 = 0;
26281.1Skamil	const int magic1 = (int)random();
26291.1Skamil	const int magic2 = (int)random();
26301.1Skamil	const int magic3 = (int)random();
26311.1Skamil	const int magic4 = (int)random();
26321.1Skamil#if defined(TWAIT_HAVE_STATUS)
26331.1Skamil	int status;
26341.1Skamil#endif
26351.1Skamil
26361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26381.1Skamil	if (child == 0) {
26391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26411.1Skamil
26421.1Skamil		lookup_me1 = magic1;
26431.1Skamil		lookup_me2 = magic2;
26441.1Skamil		lookup_me3 = magic3;
26451.1Skamil		lookup_me4 = magic4;
26461.1Skamil
26471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26491.1Skamil
26501.13Schristos		DPRINTF("Before exiting of the child process\n");
26511.1Skamil		_exit(exitval);
26521.1Skamil	}
26531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26541.1Skamil
26551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26571.1Skamil
26581.1Skamil	validate_status_stopped(status, sigval);
26591.1Skamil
26601.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
26611.1Skamil	    child, getpid());
26621.1Skamil	errno = 0;
26631.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26641.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26651.1Skamil
26661.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26671.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26681.1Skamil
26691.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26701.1Skamil	    child, getpid());
26711.1Skamil	errno = 0;
26721.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26731.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26741.1Skamil
26751.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26761.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26771.1Skamil
26781.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26791.1Skamil	    child, getpid());
26801.1Skamil	errno = 0;
26811.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26821.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26831.1Skamil
26841.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26851.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26861.1Skamil
26871.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
26881.1Skamil	    child, getpid());
26891.1Skamil	errno = 0;
26901.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
26911.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26921.1Skamil
26931.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
26941.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
26951.1Skamil
26961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26971.1Skamil	    "without signal to be sent\n");
26981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26991.1Skamil
27001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27021.1Skamil
27031.1Skamil	validate_status_exited(status, exitval);
27041.1Skamil
27051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27071.1Skamil}
27081.1Skamil
27091.1SkamilATF_TC(write_d1);
27101.1SkamilATF_TC_HEAD(write_d1, tc)
27111.1Skamil{
27121.1Skamil	atf_tc_set_md_var(tc, "descr",
27131.1Skamil	    "Verify PT_WRITE_D called once");
27141.1Skamil}
27151.1Skamil
27161.1SkamilATF_TC_BODY(write_d1, tc)
27171.1Skamil{
27181.1Skamil	const int exitval = 5;
27191.1Skamil	const int sigval = SIGSTOP;
27201.1Skamil	pid_t child, wpid;
27211.1Skamil	int lookup_me = 0;
27221.1Skamil	const int magic = (int)random();
27231.1Skamil#if defined(TWAIT_HAVE_STATUS)
27241.1Skamil	int status;
27251.1Skamil#endif
27261.1Skamil
27271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27291.1Skamil	if (child == 0) {
27301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27321.1Skamil
27331.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27341.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27351.1Skamil
27361.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
27371.1Skamil
27381.13Schristos		DPRINTF("Before exiting of the child process\n");
27391.1Skamil		_exit(exitval);
27401.1Skamil	}
27411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27421.1Skamil
27431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27451.1Skamil
27461.1Skamil	validate_status_stopped(status, sigval);
27471.1Skamil
27481.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
27491.1Skamil	    child, getpid());
27501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
27511.1Skamil
27521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27531.1Skamil	    "without signal to be sent\n");
27541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27551.1Skamil
27561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27581.1Skamil
27591.1Skamil	validate_status_exited(status, exitval);
27601.1Skamil
27611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27631.1Skamil}
27641.1Skamil
27651.1SkamilATF_TC(write_d2);
27661.1SkamilATF_TC_HEAD(write_d2, tc)
27671.1Skamil{
27681.1Skamil	atf_tc_set_md_var(tc, "descr",
27691.1Skamil	    "Verify PT_WRITE_D called twice");
27701.1Skamil}
27711.1Skamil
27721.1SkamilATF_TC_BODY(write_d2, tc)
27731.1Skamil{
27741.1Skamil	const int exitval = 5;
27751.1Skamil	const int sigval = SIGSTOP;
27761.1Skamil	pid_t child, wpid;
27771.1Skamil	int lookup_me1 = 0;
27781.1Skamil	int lookup_me2 = 0;
27791.1Skamil	const int magic1 = (int)random();
27801.1Skamil	const int magic2 = (int)random();
27811.1Skamil#if defined(TWAIT_HAVE_STATUS)
27821.1Skamil	int status;
27831.1Skamil#endif
27841.1Skamil
27851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27871.1Skamil	if (child == 0) {
27881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27901.1Skamil
27911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27931.1Skamil
27941.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27951.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
27961.1Skamil
27971.13Schristos		DPRINTF("Before exiting of the child process\n");
27981.1Skamil		_exit(exitval);
27991.1Skamil	}
28001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28011.1Skamil
28021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28041.1Skamil
28051.1Skamil	validate_status_stopped(status, sigval);
28061.1Skamil
28071.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28081.1Skamil	    child, getpid());
28091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28101.1Skamil
28111.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28121.1Skamil	    child, getpid());
28131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28141.1Skamil
28151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28161.1Skamil	    "without signal to be sent\n");
28171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28181.1Skamil
28191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28211.1Skamil
28221.1Skamil	validate_status_exited(status, exitval);
28231.1Skamil
28241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28261.1Skamil}
28271.1Skamil
28281.1SkamilATF_TC(write_d3);
28291.1SkamilATF_TC_HEAD(write_d3, tc)
28301.1Skamil{
28311.1Skamil	atf_tc_set_md_var(tc, "descr",
28321.1Skamil	    "Verify PT_WRITE_D called three times");
28331.1Skamil}
28341.1Skamil
28351.1SkamilATF_TC_BODY(write_d3, tc)
28361.1Skamil{
28371.1Skamil	const int exitval = 5;
28381.1Skamil	const int sigval = SIGSTOP;
28391.1Skamil	pid_t child, wpid;
28401.1Skamil	int lookup_me1 = 0;
28411.1Skamil	int lookup_me2 = 0;
28421.1Skamil	int lookup_me3 = 0;
28431.1Skamil	const int magic1 = (int)random();
28441.1Skamil	const int magic2 = (int)random();
28451.1Skamil	const int magic3 = (int)random();
28461.1Skamil#if defined(TWAIT_HAVE_STATUS)
28471.1Skamil	int status;
28481.1Skamil#endif
28491.1Skamil
28501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28521.1Skamil	if (child == 0) {
28531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28551.1Skamil
28561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28581.1Skamil
28591.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28601.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28611.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28621.1Skamil
28631.13Schristos		DPRINTF("Before exiting of the child process\n");
28641.1Skamil		_exit(exitval);
28651.1Skamil	}
28661.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28671.1Skamil
28681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28701.1Skamil
28711.1Skamil	validate_status_stopped(status, sigval);
28721.1Skamil
28731.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28741.1Skamil	    child, getpid());
28751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28761.1Skamil
28771.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28781.1Skamil	    child, getpid());
28791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28801.1Skamil
28811.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28821.1Skamil	    child, getpid());
28831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28841.1Skamil
28851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28861.1Skamil	    "without signal to be sent\n");
28871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28881.1Skamil
28891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28911.1Skamil
28921.1Skamil	validate_status_exited(status, exitval);
28931.1Skamil
28941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28961.1Skamil}
28971.1Skamil
28981.1SkamilATF_TC(write_d4);
28991.1SkamilATF_TC_HEAD(write_d4, tc)
29001.1Skamil{
29011.1Skamil	atf_tc_set_md_var(tc, "descr",
29021.1Skamil	    "Verify PT_WRITE_D called four times");
29031.1Skamil}
29041.1Skamil
29051.1SkamilATF_TC_BODY(write_d4, tc)
29061.1Skamil{
29071.1Skamil	const int exitval = 5;
29081.1Skamil	const int sigval = SIGSTOP;
29091.1Skamil	pid_t child, wpid;
29101.1Skamil	int lookup_me1 = 0;
29111.1Skamil	int lookup_me2 = 0;
29121.1Skamil	int lookup_me3 = 0;
29131.1Skamil	int lookup_me4 = 0;
29141.1Skamil	const int magic1 = (int)random();
29151.1Skamil	const int magic2 = (int)random();
29161.1Skamil	const int magic3 = (int)random();
29171.1Skamil	const int magic4 = (int)random();
29181.1Skamil#if defined(TWAIT_HAVE_STATUS)
29191.1Skamil	int status;
29201.1Skamil#endif
29211.1Skamil
29221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29241.1Skamil	if (child == 0) {
29251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29271.1Skamil
29281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29301.1Skamil
29311.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
29321.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
29331.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
29341.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
29351.1Skamil
29361.13Schristos		DPRINTF("Before exiting of the child process\n");
29371.1Skamil		_exit(exitval);
29381.1Skamil	}
29391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29401.1Skamil
29411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29431.1Skamil
29441.1Skamil	validate_status_stopped(status, sigval);
29451.1Skamil
29461.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
29471.1Skamil	    child, getpid());
29481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
29491.1Skamil
29501.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
29511.1Skamil	    child, getpid());
29521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
29531.1Skamil
29541.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
29551.1Skamil	    child, getpid());
29561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
29571.1Skamil
29581.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
29591.1Skamil	    child, getpid());
29601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
29611.1Skamil
29621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29631.1Skamil	    "without signal to be sent\n");
29641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29651.1Skamil
29661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29681.1Skamil
29691.1Skamil	validate_status_exited(status, exitval);
29701.1Skamil
29711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29731.1Skamil}
29741.1Skamil
29751.1SkamilATF_TC(io_read_d_write_d_handshake1);
29761.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
29771.1Skamil{
29781.1Skamil	atf_tc_set_md_var(tc, "descr",
29791.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
29801.1Skamil}
29811.1Skamil
29821.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
29831.1Skamil{
29841.1Skamil	const int exitval = 5;
29851.1Skamil	const int sigval = SIGSTOP;
29861.1Skamil	pid_t child, wpid;
29871.1Skamil	uint8_t lookup_me_fromtracee = 0;
29881.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
29891.1Skamil	uint8_t lookup_me_totracee = 0;
29901.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
29911.1Skamil	struct ptrace_io_desc io_fromtracee = {
29921.1Skamil		.piod_op = PIOD_READ_D,
29931.1Skamil		.piod_offs = &lookup_me_fromtracee,
29941.1Skamil		.piod_addr = &lookup_me_fromtracee,
29951.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
29961.1Skamil	};
29971.1Skamil	struct ptrace_io_desc io_totracee = {
29981.1Skamil		.piod_op = PIOD_WRITE_D,
29991.1Skamil		.piod_offs = &lookup_me_totracee,
30001.1Skamil		.piod_addr = &lookup_me_totracee,
30011.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30021.1Skamil	};
30031.1Skamil#if defined(TWAIT_HAVE_STATUS)
30041.1Skamil	int status;
30051.1Skamil#endif
30061.1Skamil
30071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30091.1Skamil	if (child == 0) {
30101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30121.1Skamil
30131.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30141.1Skamil
30151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30171.1Skamil
30181.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30191.1Skamil
30201.13Schristos		DPRINTF("Before exiting of the child process\n");
30211.1Skamil		_exit(exitval);
30221.1Skamil	}
30231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30241.1Skamil
30251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30271.1Skamil
30281.1Skamil	validate_status_stopped(status, sigval);
30291.1Skamil
30301.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30311.1Skamil	    child, getpid());
30321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30331.1Skamil
30341.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30351.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30361.1Skamil	    magic_fromtracee);
30371.1Skamil
30381.1Skamil	lookup_me_totracee = magic_totracee;
30391.1Skamil
30401.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30411.1Skamil	    child, getpid());
30421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30431.1Skamil
30441.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30451.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30461.1Skamil	    magic_totracee);
30471.1Skamil
30481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30491.1Skamil	    "without signal to be sent\n");
30501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30511.1Skamil
30521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30541.1Skamil
30551.1Skamil	validate_status_exited(status, exitval);
30561.1Skamil
30571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30591.1Skamil}
30601.1Skamil
30611.1SkamilATF_TC(io_read_d_write_d_handshake2);
30621.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
30631.1Skamil{
30641.1Skamil	atf_tc_set_md_var(tc, "descr",
30651.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
30661.1Skamil}
30671.1Skamil
30681.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
30691.1Skamil{
30701.1Skamil	const int exitval = 5;
30711.1Skamil	const int sigval = SIGSTOP;
30721.1Skamil	pid_t child, wpid;
30731.1Skamil	uint8_t lookup_me_fromtracee = 0;
30741.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30751.1Skamil	uint8_t lookup_me_totracee = 0;
30761.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30771.1Skamil	struct ptrace_io_desc io_fromtracee = {
30781.1Skamil		.piod_op = PIOD_READ_D,
30791.1Skamil		.piod_offs = &lookup_me_fromtracee,
30801.1Skamil		.piod_addr = &lookup_me_fromtracee,
30811.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30821.1Skamil	};
30831.1Skamil	struct ptrace_io_desc io_totracee = {
30841.1Skamil		.piod_op = PIOD_WRITE_D,
30851.1Skamil		.piod_offs = &lookup_me_totracee,
30861.1Skamil		.piod_addr = &lookup_me_totracee,
30871.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30881.1Skamil	};
30891.1Skamil#if defined(TWAIT_HAVE_STATUS)
30901.1Skamil	int status;
30911.1Skamil#endif
30921.1Skamil
30931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30951.1Skamil	if (child == 0) {
30961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30981.1Skamil
30991.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31001.1Skamil
31011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31031.1Skamil
31041.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31051.1Skamil
31061.13Schristos		DPRINTF("Before exiting of the child process\n");
31071.1Skamil		_exit(exitval);
31081.1Skamil	}
31091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31101.1Skamil
31111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31131.1Skamil
31141.1Skamil	validate_status_stopped(status, sigval);
31151.1Skamil
31161.1Skamil	lookup_me_totracee = magic_totracee;
31171.1Skamil
31181.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
31191.1Skamil	    child, getpid());
31201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
31211.1Skamil
31221.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
31231.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
31241.1Skamil	    magic_totracee);
31251.1Skamil
31261.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31271.1Skamil	    child, getpid());
31281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
31291.1Skamil
31301.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31311.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
31321.1Skamil	    magic_fromtracee);
31331.1Skamil
31341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31351.1Skamil	    "without signal to be sent\n");
31361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31371.1Skamil
31381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31401.1Skamil
31411.1Skamil	validate_status_exited(status, exitval);
31421.1Skamil
31431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31451.1Skamil}
31461.1Skamil
31471.1SkamilATF_TC(read_d_write_d_handshake1);
31481.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
31491.1Skamil{
31501.1Skamil	atf_tc_set_md_var(tc, "descr",
31511.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
31521.1Skamil}
31531.1Skamil
31541.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
31551.1Skamil{
31561.1Skamil	const int exitval = 5;
31571.1Skamil	const int sigval = SIGSTOP;
31581.1Skamil	pid_t child, wpid;
31591.1Skamil	int lookup_me_fromtracee = 0;
31601.1Skamil	const int magic_fromtracee = (int)random();
31611.1Skamil	int lookup_me_totracee = 0;
31621.1Skamil	const int magic_totracee = (int)random();
31631.1Skamil#if defined(TWAIT_HAVE_STATUS)
31641.1Skamil	int status;
31651.1Skamil#endif
31661.1Skamil
31671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31691.1Skamil	if (child == 0) {
31701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31721.1Skamil
31731.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31741.1Skamil
31751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31771.1Skamil
31781.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31791.1Skamil
31801.13Schristos		DPRINTF("Before exiting of the child process\n");
31811.1Skamil		_exit(exitval);
31821.1Skamil	}
31831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31841.1Skamil
31851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31871.1Skamil
31881.1Skamil	validate_status_stopped(status, sigval);
31891.1Skamil
31901.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31911.1Skamil	    child, getpid());
31921.1Skamil	errno = 0;
31931.1Skamil	lookup_me_fromtracee =
31941.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
31951.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
31961.1Skamil
31971.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31981.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
31991.1Skamil	    magic_fromtracee);
32001.1Skamil
32011.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32021.1Skamil	    child, getpid());
32031.1Skamil	ATF_REQUIRE
32041.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32051.1Skamil	    != -1);
32061.1Skamil
32071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32081.1Skamil	    "without signal to be sent\n");
32091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32101.1Skamil
32111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32131.1Skamil
32141.1Skamil	validate_status_exited(status, exitval);
32151.1Skamil
32161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32181.1Skamil}
32191.1Skamil
32201.1SkamilATF_TC(read_d_write_d_handshake2);
32211.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
32221.1Skamil{
32231.1Skamil	atf_tc_set_md_var(tc, "descr",
32241.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
32251.1Skamil}
32261.1Skamil
32271.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
32281.1Skamil{
32291.1Skamil	const int exitval = 5;
32301.1Skamil	const int sigval = SIGSTOP;
32311.1Skamil	pid_t child, wpid;
32321.1Skamil	int lookup_me_fromtracee = 0;
32331.1Skamil	const int magic_fromtracee = (int)random();
32341.1Skamil	int lookup_me_totracee = 0;
32351.1Skamil	const int magic_totracee = (int)random();
32361.1Skamil#if defined(TWAIT_HAVE_STATUS)
32371.1Skamil	int status;
32381.1Skamil#endif
32391.1Skamil
32401.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32411.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32421.1Skamil	if (child == 0) {
32431.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32441.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32451.1Skamil
32461.1Skamil		lookup_me_fromtracee = magic_fromtracee;
32471.1Skamil
32481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32501.1Skamil
32511.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
32521.1Skamil
32531.13Schristos		DPRINTF("Before exiting of the child process\n");
32541.1Skamil		_exit(exitval);
32551.1Skamil	}
32561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32571.1Skamil
32581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32601.1Skamil
32611.1Skamil	validate_status_stopped(status, sigval);
32621.1Skamil
32631.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32641.1Skamil	    child, getpid());
32651.1Skamil	ATF_REQUIRE
32661.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32671.1Skamil	    != -1);
32681.1Skamil
32691.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32701.1Skamil	    child, getpid());
32711.1Skamil	errno = 0;
32721.1Skamil	lookup_me_fromtracee =
32731.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32741.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32751.1Skamil
32761.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32771.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32781.1Skamil	    magic_fromtracee);
32791.1Skamil
32801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32811.1Skamil	    "without signal to be sent\n");
32821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32831.1Skamil
32841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32861.1Skamil
32871.1Skamil	validate_status_exited(status, exitval);
32881.1Skamil
32891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32911.1Skamil}
32921.1Skamil
32931.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
32941.1Skamilstatic int __used
32951.1Skamildummy_fn1(int a, int b, int c, int d)
32961.1Skamil{
32971.1Skamil
32981.1Skamil	a *= 1;
32991.1Skamil	b += 2;
33001.1Skamil	c -= 3;
33011.1Skamil	d /= 4;
33021.1Skamil
33031.1Skamil	return a + b * c - d;
33041.1Skamil}
33051.1Skamil
33061.1Skamilstatic int __used
33071.1Skamildummy_fn2(int a, int b, int c, int d)
33081.1Skamil{
33091.1Skamil
33101.1Skamil	a *= 4;
33111.1Skamil	b += 3;
33121.1Skamil	c -= 2;
33131.1Skamil	d /= 1;
33141.1Skamil
33151.1Skamil	return a + b * c - d;
33161.1Skamil}
33171.1Skamil
33181.1Skamilstatic int __used
33191.1Skamildummy_fn3(int a, int b, int c, int d)
33201.1Skamil{
33211.1Skamil
33221.1Skamil	a *= 10;
33231.1Skamil	b += 20;
33241.1Skamil	c -= 30;
33251.1Skamil	d /= 40;
33261.1Skamil
33271.1Skamil	return a + b * c - d;
33281.1Skamil}
33291.1Skamil
33301.1Skamilstatic int __used
33311.1Skamildummy_fn4(int a, int b, int c, int d)
33321.1Skamil{
33331.1Skamil
33341.1Skamil	a *= 40;
33351.1Skamil	b += 30;
33361.1Skamil	c -= 20;
33371.1Skamil	d /= 10;
33381.1Skamil
33391.1Skamil	return a + b * c - d;
33401.1Skamil}
33411.1Skamil
33421.1SkamilATF_TC(io_read_i1);
33431.1SkamilATF_TC_HEAD(io_read_i1, tc)
33441.1Skamil{
33451.1Skamil	atf_tc_set_md_var(tc, "descr",
33461.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
33471.1Skamil}
33481.1Skamil
33491.1SkamilATF_TC_BODY(io_read_i1, tc)
33501.1Skamil{
33511.1Skamil	const int exitval = 5;
33521.1Skamil	const int sigval = SIGSTOP;
33531.1Skamil	pid_t child, wpid;
33541.1Skamil	uint8_t lookup_me = 0;
33551.1Skamil	uint8_t magic;
33561.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
33571.1Skamil	struct ptrace_io_desc io = {
33581.1Skamil		.piod_op = PIOD_READ_I,
33591.1Skamil		.piod_offs = dummy_fn1,
33601.1Skamil		.piod_addr = &lookup_me,
33611.1Skamil		.piod_len = sizeof(lookup_me)
33621.1Skamil	};
33631.1Skamil#if defined(TWAIT_HAVE_STATUS)
33641.1Skamil	int status;
33651.1Skamil#endif
33661.1Skamil
33671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33691.1Skamil	if (child == 0) {
33701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33721.1Skamil
33731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33751.1Skamil
33761.13Schristos		DPRINTF("Before exiting of the child process\n");
33771.1Skamil		_exit(exitval);
33781.1Skamil	}
33791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33801.1Skamil
33811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33831.1Skamil
33841.1Skamil	validate_status_stopped(status, sigval);
33851.1Skamil
33861.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33871.1Skamil	    child, getpid());
33881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33891.1Skamil
33901.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33911.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
33921.1Skamil
33931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33941.1Skamil	    "without signal to be sent\n");
33951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33961.1Skamil
33971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33991.1Skamil
34001.1Skamil	validate_status_exited(status, exitval);
34011.1Skamil
34021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34041.1Skamil}
34051.1Skamil
34061.1SkamilATF_TC(io_read_i2);
34071.1SkamilATF_TC_HEAD(io_read_i2, tc)
34081.1Skamil{
34091.1Skamil	atf_tc_set_md_var(tc, "descr",
34101.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
34111.1Skamil}
34121.1Skamil
34131.1SkamilATF_TC_BODY(io_read_i2, tc)
34141.1Skamil{
34151.1Skamil	const int exitval = 5;
34161.1Skamil	const int sigval = SIGSTOP;
34171.1Skamil	pid_t child, wpid;
34181.1Skamil	uint16_t lookup_me = 0;
34191.1Skamil	uint16_t magic;
34201.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34211.1Skamil	struct ptrace_io_desc io = {
34221.1Skamil		.piod_op = PIOD_READ_I,
34231.1Skamil		.piod_offs = dummy_fn1,
34241.1Skamil		.piod_addr = &lookup_me,
34251.1Skamil		.piod_len = sizeof(lookup_me)
34261.1Skamil	};
34271.1Skamil#if defined(TWAIT_HAVE_STATUS)
34281.1Skamil	int status;
34291.1Skamil#endif
34301.1Skamil
34311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34331.1Skamil	if (child == 0) {
34341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34361.1Skamil
34371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34391.1Skamil
34401.13Schristos		DPRINTF("Before exiting of the child process\n");
34411.1Skamil		_exit(exitval);
34421.1Skamil	}
34431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34441.1Skamil
34451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34471.1Skamil
34481.1Skamil	validate_status_stopped(status, sigval);
34491.1Skamil
34501.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34511.1Skamil	    child, getpid());
34521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34531.1Skamil
34541.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34551.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
34561.1Skamil
34571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34581.1Skamil	    "without signal to be sent\n");
34591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34601.1Skamil
34611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34631.1Skamil
34641.1Skamil	validate_status_exited(status, exitval);
34651.1Skamil
34661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34681.1Skamil}
34691.1Skamil
34701.1SkamilATF_TC(io_read_i3);
34711.1SkamilATF_TC_HEAD(io_read_i3, tc)
34721.1Skamil{
34731.1Skamil	atf_tc_set_md_var(tc, "descr",
34741.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
34751.1Skamil}
34761.1Skamil
34771.1SkamilATF_TC_BODY(io_read_i3, tc)
34781.1Skamil{
34791.1Skamil	const int exitval = 5;
34801.1Skamil	const int sigval = SIGSTOP;
34811.1Skamil	pid_t child, wpid;
34821.1Skamil	uint32_t lookup_me = 0;
34831.1Skamil	uint32_t magic;
34841.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34851.1Skamil	struct ptrace_io_desc io = {
34861.1Skamil		.piod_op = PIOD_READ_I,
34871.1Skamil		.piod_offs = dummy_fn1,
34881.1Skamil		.piod_addr = &lookup_me,
34891.1Skamil		.piod_len = sizeof(lookup_me)
34901.1Skamil	};
34911.1Skamil#if defined(TWAIT_HAVE_STATUS)
34921.1Skamil	int status;
34931.1Skamil#endif
34941.1Skamil
34951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34971.1Skamil	if (child == 0) {
34981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35001.1Skamil
35011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35031.1Skamil
35041.13Schristos		DPRINTF("Before exiting of the child process\n");
35051.1Skamil		_exit(exitval);
35061.1Skamil	}
35071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35081.1Skamil
35091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35111.1Skamil
35121.1Skamil	validate_status_stopped(status, sigval);
35131.1Skamil
35141.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35151.1Skamil	    child, getpid());
35161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35171.1Skamil
35181.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35191.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
35201.1Skamil
35211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35221.1Skamil	    "without signal to be sent\n");
35231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35241.1Skamil
35251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35271.1Skamil
35281.1Skamil	validate_status_exited(status, exitval);
35291.1Skamil
35301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35321.1Skamil}
35331.1Skamil
35341.1SkamilATF_TC(io_read_i4);
35351.1SkamilATF_TC_HEAD(io_read_i4, tc)
35361.1Skamil{
35371.1Skamil	atf_tc_set_md_var(tc, "descr",
35381.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
35391.1Skamil}
35401.1Skamil
35411.1SkamilATF_TC_BODY(io_read_i4, tc)
35421.1Skamil{
35431.1Skamil	const int exitval = 5;
35441.1Skamil	const int sigval = SIGSTOP;
35451.1Skamil	pid_t child, wpid;
35461.1Skamil	uint64_t lookup_me = 0;
35471.1Skamil	uint64_t magic;
35481.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35491.1Skamil	struct ptrace_io_desc io = {
35501.1Skamil		.piod_op = PIOD_READ_I,
35511.1Skamil		.piod_offs = dummy_fn1,
35521.1Skamil		.piod_addr = &lookup_me,
35531.1Skamil		.piod_len = sizeof(lookup_me)
35541.1Skamil	};
35551.1Skamil#if defined(TWAIT_HAVE_STATUS)
35561.1Skamil	int status;
35571.1Skamil#endif
35581.1Skamil
35591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35611.1Skamil	if (child == 0) {
35621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35641.1Skamil
35651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35671.1Skamil
35681.13Schristos		DPRINTF("Before exiting of the child process\n");
35691.1Skamil		_exit(exitval);
35701.1Skamil	}
35711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35721.1Skamil
35731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35751.1Skamil
35761.1Skamil	validate_status_stopped(status, sigval);
35771.1Skamil
35781.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35791.1Skamil	    child, getpid());
35801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35811.1Skamil
35821.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35831.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
35841.1Skamil
35851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35861.1Skamil	    "without signal to be sent\n");
35871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35881.1Skamil
35891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35911.1Skamil
35921.1Skamil	validate_status_exited(status, exitval);
35931.1Skamil
35941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35961.1Skamil}
35971.1Skamil
35981.1SkamilATF_TC(read_i1);
35991.1SkamilATF_TC_HEAD(read_i1, tc)
36001.1Skamil{
36011.1Skamil	atf_tc_set_md_var(tc, "descr",
36021.1Skamil	    "Verify PT_READ_I called once");
36031.1Skamil}
36041.1Skamil
36051.1SkamilATF_TC_BODY(read_i1, tc)
36061.1Skamil{
36071.1Skamil	const int exitval = 5;
36081.1Skamil	const int sigval = SIGSTOP;
36091.1Skamil	pid_t child, wpid;
36101.1Skamil	int lookup_me = 0;
36111.1Skamil	int magic;
36121.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
36131.1Skamil#if defined(TWAIT_HAVE_STATUS)
36141.1Skamil	int status;
36151.1Skamil#endif
36161.1Skamil
36171.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36181.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36191.1Skamil	if (child == 0) {
36201.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36211.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36221.1Skamil
36231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36251.1Skamil
36261.13Schristos		DPRINTF("Before exiting of the child process\n");
36271.1Skamil		_exit(exitval);
36281.1Skamil	}
36291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36301.1Skamil
36311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36331.1Skamil
36341.1Skamil	validate_status_stopped(status, sigval);
36351.1Skamil
36361.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
36371.1Skamil	    child, getpid());
36381.1Skamil	errno = 0;
36391.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
36401.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36411.1Skamil
36421.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36431.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
36441.1Skamil
36451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36461.1Skamil	    "without signal to be sent\n");
36471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36481.1Skamil
36491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36511.1Skamil
36521.1Skamil	validate_status_exited(status, exitval);
36531.1Skamil
36541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36561.1Skamil}
36571.1Skamil
36581.1SkamilATF_TC(read_i2);
36591.1SkamilATF_TC_HEAD(read_i2, tc)
36601.1Skamil{
36611.1Skamil	atf_tc_set_md_var(tc, "descr",
36621.1Skamil	    "Verify PT_READ_I called twice");
36631.1Skamil}
36641.1Skamil
36651.1SkamilATF_TC_BODY(read_i2, tc)
36661.1Skamil{
36671.1Skamil	const int exitval = 5;
36681.1Skamil	const int sigval = SIGSTOP;
36691.1Skamil	pid_t child, wpid;
36701.1Skamil	int lookup_me1 = 0;
36711.1Skamil	int lookup_me2 = 0;
36721.1Skamil	int magic1;
36731.1Skamil	int magic2;
36741.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36751.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36761.1Skamil#if defined(TWAIT_HAVE_STATUS)
36771.1Skamil	int status;
36781.1Skamil#endif
36791.1Skamil
36801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36821.1Skamil	if (child == 0) {
36831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36851.1Skamil
36861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36881.1Skamil
36891.13Schristos		DPRINTF("Before exiting of the child process\n");
36901.1Skamil		_exit(exitval);
36911.1Skamil	}
36921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36931.1Skamil
36941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36961.1Skamil
36971.1Skamil	validate_status_stopped(status, sigval);
36981.1Skamil
36991.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37001.1Skamil	    child, getpid());
37011.1Skamil	errno = 0;
37021.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37031.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37041.1Skamil
37051.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37061.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37071.1Skamil
37081.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37091.1Skamil	    child, getpid());
37101.1Skamil	errno = 0;
37111.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37131.1Skamil
37141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37151.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37161.1Skamil
37171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37181.1Skamil	    "without signal to be sent\n");
37191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37201.1Skamil
37211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37231.1Skamil
37241.1Skamil	validate_status_exited(status, exitval);
37251.1Skamil
37261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37281.1Skamil}
37291.1Skamil
37301.1SkamilATF_TC(read_i3);
37311.1SkamilATF_TC_HEAD(read_i3, tc)
37321.1Skamil{
37331.1Skamil	atf_tc_set_md_var(tc, "descr",
37341.1Skamil	    "Verify PT_READ_I called three times");
37351.1Skamil}
37361.1Skamil
37371.1SkamilATF_TC_BODY(read_i3, tc)
37381.1Skamil{
37391.1Skamil	const int exitval = 5;
37401.1Skamil	const int sigval = SIGSTOP;
37411.1Skamil	pid_t child, wpid;
37421.1Skamil	int lookup_me1 = 0;
37431.1Skamil	int lookup_me2 = 0;
37441.1Skamil	int lookup_me3 = 0;
37451.1Skamil	int magic1;
37461.1Skamil	int magic2;
37471.1Skamil	int magic3;
37481.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37491.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37501.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37511.1Skamil#if defined(TWAIT_HAVE_STATUS)
37521.1Skamil	int status;
37531.1Skamil#endif
37541.1Skamil
37551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37571.1Skamil	if (child == 0) {
37581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37601.1Skamil
37611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37631.1Skamil
37641.13Schristos		DPRINTF("Before exiting of the child process\n");
37651.1Skamil		_exit(exitval);
37661.1Skamil	}
37671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37681.1Skamil
37691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37711.1Skamil
37721.1Skamil	validate_status_stopped(status, sigval);
37731.1Skamil
37741.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37751.1Skamil	    child, getpid());
37761.1Skamil	errno = 0;
37771.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37781.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37791.1Skamil
37801.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37811.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37821.1Skamil
37831.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37841.1Skamil	    child, getpid());
37851.1Skamil	errno = 0;
37861.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37871.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37881.1Skamil
37891.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37901.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37911.1Skamil
37921.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
37931.1Skamil	    child, getpid());
37941.1Skamil	errno = 0;
37951.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
37961.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37971.1Skamil
37981.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
37991.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38001.1Skamil
38011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38021.1Skamil	    "without signal to be sent\n");
38031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38041.1Skamil
38051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38071.1Skamil
38081.1Skamil	validate_status_exited(status, exitval);
38091.1Skamil
38101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38121.1Skamil}
38131.1Skamil
38141.1SkamilATF_TC(read_i4);
38151.1SkamilATF_TC_HEAD(read_i4, tc)
38161.1Skamil{
38171.1Skamil	atf_tc_set_md_var(tc, "descr",
38181.1Skamil	    "Verify PT_READ_I called four times");
38191.1Skamil}
38201.1Skamil
38211.1SkamilATF_TC_BODY(read_i4, tc)
38221.1Skamil{
38231.1Skamil	const int exitval = 5;
38241.1Skamil	const int sigval = SIGSTOP;
38251.1Skamil	pid_t child, wpid;
38261.1Skamil	int lookup_me1 = 0;
38271.1Skamil	int lookup_me2 = 0;
38281.1Skamil	int lookup_me3 = 0;
38291.1Skamil	int lookup_me4 = 0;
38301.1Skamil	int magic1;
38311.1Skamil	int magic2;
38321.1Skamil	int magic3;
38331.1Skamil	int magic4;
38341.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
38351.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
38361.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
38371.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
38381.1Skamil#if defined(TWAIT_HAVE_STATUS)
38391.1Skamil	int status;
38401.1Skamil#endif
38411.1Skamil
38421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38441.1Skamil	if (child == 0) {
38451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38471.1Skamil
38481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38501.1Skamil
38511.13Schristos		DPRINTF("Before exiting of the child process\n");
38521.1Skamil		_exit(exitval);
38531.1Skamil	}
38541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38551.1Skamil
38561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38581.1Skamil
38591.1Skamil	validate_status_stopped(status, sigval);
38601.1Skamil
38611.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38621.1Skamil	    child, getpid());
38631.1Skamil	errno = 0;
38641.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38651.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38661.1Skamil
38671.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38681.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38691.1Skamil
38701.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38711.1Skamil	    child, getpid());
38721.1Skamil	errno = 0;
38731.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38741.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38751.1Skamil
38761.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38771.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38781.1Skamil
38791.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38801.1Skamil	    child, getpid());
38811.1Skamil	errno = 0;
38821.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38831.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38841.1Skamil
38851.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38861.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38871.1Skamil
38881.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
38891.1Skamil	    child, getpid());
38901.1Skamil	errno = 0;
38911.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
38921.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38931.1Skamil
38941.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
38951.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
38961.1Skamil
38971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38981.1Skamil	    "without signal to be sent\n");
38991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39001.1Skamil
39011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39031.1Skamil
39041.1Skamil	validate_status_exited(status, exitval);
39051.1Skamil
39061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39081.1Skamil}
39091.1Skamil
39101.1Skamil#if defined(HAVE_GPREGS)
39111.1SkamilATF_TC(regs1);
39121.1SkamilATF_TC_HEAD(regs1, tc)
39131.1Skamil{
39141.1Skamil	atf_tc_set_md_var(tc, "descr",
39151.1Skamil	    "Verify plain PT_GETREGS call without further steps");
39161.1Skamil}
39171.1Skamil
39181.1SkamilATF_TC_BODY(regs1, tc)
39191.1Skamil{
39201.1Skamil	const int exitval = 5;
39211.1Skamil	const int sigval = SIGSTOP;
39221.1Skamil	pid_t child, wpid;
39231.1Skamil#if defined(TWAIT_HAVE_STATUS)
39241.1Skamil	int status;
39251.1Skamil#endif
39261.1Skamil	struct reg r;
39271.1Skamil
39281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39301.1Skamil	if (child == 0) {
39311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39331.1Skamil
39341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39361.1Skamil
39371.13Schristos		DPRINTF("Before exiting of the child process\n");
39381.1Skamil		_exit(exitval);
39391.1Skamil	}
39401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39411.1Skamil
39421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39441.1Skamil
39451.1Skamil	validate_status_stopped(status, sigval);
39461.1Skamil
39471.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39491.1Skamil
39501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39511.1Skamil	    "without signal to be sent\n");
39521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39531.1Skamil
39541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39561.1Skamil
39571.1Skamil	validate_status_exited(status, exitval);
39581.1Skamil
39591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39611.1Skamil}
39621.1Skamil#endif
39631.1Skamil
39641.1Skamil#if defined(HAVE_GPREGS)
39651.1SkamilATF_TC(regs2);
39661.1SkamilATF_TC_HEAD(regs2, tc)
39671.1Skamil{
39681.1Skamil	atf_tc_set_md_var(tc, "descr",
39691.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
39701.1Skamil}
39711.1Skamil
39721.1SkamilATF_TC_BODY(regs2, tc)
39731.1Skamil{
39741.1Skamil	const int exitval = 5;
39751.1Skamil	const int sigval = SIGSTOP;
39761.1Skamil	pid_t child, wpid;
39771.1Skamil#if defined(TWAIT_HAVE_STATUS)
39781.1Skamil	int status;
39791.1Skamil#endif
39801.1Skamil	struct reg r;
39811.1Skamil
39821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39841.1Skamil	if (child == 0) {
39851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39871.1Skamil
39881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39901.1Skamil
39911.13Schristos		DPRINTF("Before exiting of the child process\n");
39921.1Skamil		_exit(exitval);
39931.1Skamil	}
39941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39951.1Skamil
39961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39981.1Skamil
39991.1Skamil	validate_status_stopped(status, sigval);
40001.1Skamil
40011.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40031.1Skamil
40041.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
40051.1Skamil
40061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40071.1Skamil	    "without signal to be sent\n");
40081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40091.1Skamil
40101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40121.1Skamil
40131.1Skamil	validate_status_exited(status, exitval);
40141.1Skamil
40151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40171.1Skamil}
40181.1Skamil#endif
40191.1Skamil
40201.1Skamil#if defined(HAVE_GPREGS)
40211.1SkamilATF_TC(regs3);
40221.1SkamilATF_TC_HEAD(regs3, tc)
40231.1Skamil{
40241.1Skamil	atf_tc_set_md_var(tc, "descr",
40251.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
40261.1Skamil}
40271.1Skamil
40281.1SkamilATF_TC_BODY(regs3, tc)
40291.1Skamil{
40301.1Skamil	const int exitval = 5;
40311.1Skamil	const int sigval = SIGSTOP;
40321.1Skamil	pid_t child, wpid;
40331.1Skamil#if defined(TWAIT_HAVE_STATUS)
40341.1Skamil	int status;
40351.1Skamil#endif
40361.1Skamil	struct reg r;
40371.1Skamil
40381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40401.1Skamil	if (child == 0) {
40411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40431.1Skamil
40441.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40451.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40461.1Skamil
40471.13Schristos		DPRINTF("Before exiting of the child process\n");
40481.1Skamil		_exit(exitval);
40491.1Skamil	}
40501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40511.1Skamil
40521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40541.1Skamil
40551.1Skamil	validate_status_stopped(status, sigval);
40561.1Skamil
40571.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40591.1Skamil
40601.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
40611.1Skamil
40621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40631.1Skamil	    "without signal to be sent\n");
40641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40651.1Skamil
40661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40681.1Skamil
40691.1Skamil	validate_status_exited(status, exitval);
40701.1Skamil
40711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40731.1Skamil}
40741.1Skamil#endif
40751.1Skamil
40761.1Skamil#if defined(HAVE_GPREGS)
40771.1SkamilATF_TC(regs4);
40781.1SkamilATF_TC_HEAD(regs4, tc)
40791.1Skamil{
40801.1Skamil	atf_tc_set_md_var(tc, "descr",
40811.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
40821.1Skamil}
40831.1Skamil
40841.1SkamilATF_TC_BODY(regs4, tc)
40851.1Skamil{
40861.1Skamil	const int exitval = 5;
40871.1Skamil	const int sigval = SIGSTOP;
40881.1Skamil	pid_t child, wpid;
40891.1Skamil#if defined(TWAIT_HAVE_STATUS)
40901.1Skamil	int status;
40911.1Skamil#endif
40921.1Skamil	struct reg r;
40931.1Skamil
40941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40961.1Skamil	if (child == 0) {
40971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40991.1Skamil
41001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41021.1Skamil
41031.13Schristos		DPRINTF("Before exiting of the child process\n");
41041.1Skamil		_exit(exitval);
41051.1Skamil	}
41061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41071.1Skamil
41081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41101.1Skamil
41111.1Skamil	validate_status_stopped(status, sigval);
41121.1Skamil
41131.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41151.1Skamil
41161.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
41171.1Skamil
41181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41191.1Skamil	    "without signal to be sent\n");
41201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41211.1Skamil
41221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41241.1Skamil
41251.1Skamil	validate_status_exited(status, exitval);
41261.1Skamil
41271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41291.1Skamil}
41301.1Skamil#endif
41311.1Skamil
41321.1Skamil#if defined(HAVE_GPREGS)
41331.1SkamilATF_TC(regs5);
41341.1SkamilATF_TC_HEAD(regs5, tc)
41351.1Skamil{
41361.1Skamil	atf_tc_set_md_var(tc, "descr",
41371.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
41381.1Skamil}
41391.1Skamil
41401.1SkamilATF_TC_BODY(regs5, tc)
41411.1Skamil{
41421.1Skamil	const int exitval = 5;
41431.1Skamil	const int sigval = SIGSTOP;
41441.1Skamil	pid_t child, wpid;
41451.1Skamil#if defined(TWAIT_HAVE_STATUS)
41461.1Skamil	int status;
41471.1Skamil#endif
41481.1Skamil	struct reg r;
41491.1Skamil
41501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41521.1Skamil	if (child == 0) {
41531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41551.1Skamil
41561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41581.1Skamil
41591.13Schristos		DPRINTF("Before exiting of the child process\n");
41601.1Skamil		_exit(exitval);
41611.1Skamil	}
41621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41631.1Skamil
41641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41661.1Skamil
41671.1Skamil	validate_status_stopped(status, sigval);
41681.1Skamil
41691.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41711.1Skamil
41721.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
41731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41741.1Skamil
41751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41761.1Skamil	    "without signal to be sent\n");
41771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41781.1Skamil
41791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41811.1Skamil
41821.1Skamil	validate_status_exited(status, exitval);
41831.1Skamil
41841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41861.1Skamil}
41871.1Skamil#endif
41881.1Skamil
41891.1Skamil#if defined(HAVE_FPREGS)
41901.1SkamilATF_TC(fpregs1);
41911.1SkamilATF_TC_HEAD(fpregs1, tc)
41921.1Skamil{
41931.1Skamil	atf_tc_set_md_var(tc, "descr",
41941.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
41951.1Skamil}
41961.1Skamil
41971.1SkamilATF_TC_BODY(fpregs1, tc)
41981.1Skamil{
41991.1Skamil	const int exitval = 5;
42001.1Skamil	const int sigval = SIGSTOP;
42011.1Skamil	pid_t child, wpid;
42021.1Skamil#if defined(TWAIT_HAVE_STATUS)
42031.1Skamil	int status;
42041.1Skamil#endif
42051.1Skamil	struct fpreg r;
42061.1Skamil
42071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42091.1Skamil	if (child == 0) {
42101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42121.1Skamil
42131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42151.1Skamil
42161.13Schristos		DPRINTF("Before exiting of the child process\n");
42171.1Skamil		_exit(exitval);
42181.1Skamil	}
42191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42201.1Skamil
42211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42231.1Skamil
42241.1Skamil	validate_status_stopped(status, sigval);
42251.1Skamil
42261.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42281.1Skamil
42291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42301.1Skamil	    "without signal to be sent\n");
42311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42321.1Skamil
42331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42351.1Skamil
42361.1Skamil	validate_status_exited(status, exitval);
42371.1Skamil
42381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42401.1Skamil}
42411.1Skamil#endif
42421.1Skamil
42431.1Skamil#if defined(HAVE_FPREGS)
42441.1SkamilATF_TC(fpregs2);
42451.1SkamilATF_TC_HEAD(fpregs2, tc)
42461.1Skamil{
42471.1Skamil	atf_tc_set_md_var(tc, "descr",
42481.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
42491.1Skamil	    "regs");
42501.1Skamil}
42511.1Skamil
42521.1SkamilATF_TC_BODY(fpregs2, tc)
42531.1Skamil{
42541.1Skamil	const int exitval = 5;
42551.1Skamil	const int sigval = SIGSTOP;
42561.1Skamil	pid_t child, wpid;
42571.1Skamil#if defined(TWAIT_HAVE_STATUS)
42581.1Skamil	int status;
42591.1Skamil#endif
42601.1Skamil	struct fpreg r;
42611.1Skamil
42621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42641.1Skamil	if (child == 0) {
42651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42671.1Skamil
42681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42701.1Skamil
42711.13Schristos		DPRINTF("Before exiting of the child process\n");
42721.1Skamil		_exit(exitval);
42731.1Skamil	}
42741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42751.1Skamil
42761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42781.1Skamil
42791.1Skamil	validate_status_stopped(status, sigval);
42801.1Skamil
42811.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42831.1Skamil
42841.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
42851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
42861.1Skamil
42871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42881.1Skamil	    "without signal to be sent\n");
42891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42901.1Skamil
42911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42931.1Skamil
42941.1Skamil	validate_status_exited(status, exitval);
42951.1Skamil
42961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42981.1Skamil}
42991.1Skamil#endif
43001.1Skamil
43011.1Skamil#if defined(PT_STEP)
43021.1Skamilstatic void
43031.2Skamilptrace_step(int N, int setstep)
43041.1Skamil{
43051.1Skamil	const int exitval = 5;
43061.1Skamil	const int sigval = SIGSTOP;
43071.1Skamil	pid_t child, wpid;
43081.1Skamil#if defined(TWAIT_HAVE_STATUS)
43091.1Skamil	int status;
43101.1Skamil#endif
43111.1Skamil	int happy;
43121.1Skamil
43131.1Skamil#if defined(__arm__)
43141.1Skamil	/* PT_STEP not supported on arm 32-bit */
43151.1Skamil	atf_tc_expect_fail("PR kern/52119");
43161.1Skamil#endif
43171.1Skamil
43181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43201.1Skamil	if (child == 0) {
43211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43231.1Skamil
43241.1Skamil		happy = check_happy(999);
43251.1Skamil
43261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43281.1Skamil
43291.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
43301.1Skamil
43311.13Schristos		DPRINTF("Before exiting of the child process\n");
43321.1Skamil		_exit(exitval);
43331.1Skamil	}
43341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43351.1Skamil
43361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43381.1Skamil
43391.1Skamil	validate_status_stopped(status, sigval);
43401.1Skamil
43411.1Skamil	while (N --> 0) {
43421.2Skamil		if (setstep) {
43431.13Schristos			DPRINTF("Before resuming the child process where it "
43441.2Skamil			    "left off and without signal to be sent (use "
43451.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
43461.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
43471.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
43481.2Skamil			    != -1);
43491.2Skamil		} else {
43501.13Schristos			DPRINTF("Before resuming the child process where it "
43511.2Skamil			    "left off and without signal to be sent (use "
43521.2Skamil			    "PT_STEP)\n");
43531.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
43541.2Skamil			    != -1);
43551.2Skamil		}
43561.1Skamil
43571.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43581.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43591.1Skamil		    child);
43601.1Skamil
43611.1Skamil		validate_status_stopped(status, SIGTRAP);
43621.2Skamil
43631.2Skamil		if (setstep) {
43641.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43651.2Skamil		}
43661.1Skamil	}
43671.1Skamil
43681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43691.1Skamil	    "without signal to be sent\n");
43701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43711.1Skamil
43721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43741.1Skamil
43751.1Skamil	validate_status_exited(status, exitval);
43761.1Skamil
43771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43791.1Skamil}
43801.1Skamil#endif
43811.1Skamil
43821.1Skamil#if defined(PT_STEP)
43831.1SkamilATF_TC(step1);
43841.1SkamilATF_TC_HEAD(step1, tc)
43851.1Skamil{
43861.1Skamil	atf_tc_set_md_var(tc, "descr",
43871.1Skamil	    "Verify single PT_STEP call");
43881.1Skamil}
43891.1Skamil
43901.1SkamilATF_TC_BODY(step1, tc)
43911.1Skamil{
43921.2Skamil	ptrace_step(1, 0);
43931.1Skamil}
43941.1Skamil#endif
43951.1Skamil
43961.1Skamil#if defined(PT_STEP)
43971.1SkamilATF_TC(step2);
43981.1SkamilATF_TC_HEAD(step2, tc)
43991.1Skamil{
44001.1Skamil	atf_tc_set_md_var(tc, "descr",
44011.1Skamil	    "Verify PT_STEP called twice");
44021.1Skamil}
44031.1Skamil
44041.1SkamilATF_TC_BODY(step2, tc)
44051.1Skamil{
44061.2Skamil	ptrace_step(2, 0);
44071.1Skamil}
44081.1Skamil#endif
44091.1Skamil
44101.1Skamil#if defined(PT_STEP)
44111.1SkamilATF_TC(step3);
44121.1SkamilATF_TC_HEAD(step3, tc)
44131.1Skamil{
44141.1Skamil	atf_tc_set_md_var(tc, "descr",
44151.1Skamil	    "Verify PT_STEP called three times");
44161.1Skamil}
44171.1Skamil
44181.1SkamilATF_TC_BODY(step3, tc)
44191.1Skamil{
44201.2Skamil	ptrace_step(3, 0);
44211.1Skamil}
44221.1Skamil#endif
44231.1Skamil
44241.1Skamil#if defined(PT_STEP)
44251.1SkamilATF_TC(step4);
44261.1SkamilATF_TC_HEAD(step4, tc)
44271.1Skamil{
44281.1Skamil	atf_tc_set_md_var(tc, "descr",
44291.1Skamil	    "Verify PT_STEP called four times");
44301.1Skamil}
44311.1Skamil
44321.1SkamilATF_TC_BODY(step4, tc)
44331.1Skamil{
44341.2Skamil	ptrace_step(4, 0);
44351.2Skamil}
44361.2Skamil#endif
44371.2Skamil
44381.2Skamil#if defined(PT_STEP)
44391.2SkamilATF_TC(setstep1);
44401.2SkamilATF_TC_HEAD(setstep1, tc)
44411.2Skamil{
44421.2Skamil	atf_tc_set_md_var(tc, "descr",
44431.2Skamil	    "Verify single PT_SETSTEP call");
44441.2Skamil}
44451.2Skamil
44461.2SkamilATF_TC_BODY(setstep1, tc)
44471.2Skamil{
44481.2Skamil	ptrace_step(1, 1);
44491.2Skamil}
44501.2Skamil#endif
44511.2Skamil
44521.2Skamil#if defined(PT_STEP)
44531.2SkamilATF_TC(setstep2);
44541.2SkamilATF_TC_HEAD(setstep2, tc)
44551.2Skamil{
44561.2Skamil	atf_tc_set_md_var(tc, "descr",
44571.2Skamil	    "Verify PT_SETSTEP called twice");
44581.2Skamil}
44591.2Skamil
44601.2SkamilATF_TC_BODY(setstep2, tc)
44611.2Skamil{
44621.2Skamil	ptrace_step(2, 1);
44631.2Skamil}
44641.2Skamil#endif
44651.2Skamil
44661.2Skamil#if defined(PT_STEP)
44671.2SkamilATF_TC(setstep3);
44681.2SkamilATF_TC_HEAD(setstep3, tc)
44691.2Skamil{
44701.2Skamil	atf_tc_set_md_var(tc, "descr",
44711.2Skamil	    "Verify PT_SETSTEP called three times");
44721.2Skamil}
44731.2Skamil
44741.2SkamilATF_TC_BODY(setstep3, tc)
44751.2Skamil{
44761.2Skamil	ptrace_step(3, 1);
44771.2Skamil}
44781.2Skamil#endif
44791.2Skamil
44801.2Skamil#if defined(PT_STEP)
44811.2SkamilATF_TC(setstep4);
44821.2SkamilATF_TC_HEAD(setstep4, tc)
44831.2Skamil{
44841.2Skamil	atf_tc_set_md_var(tc, "descr",
44851.2Skamil	    "Verify PT_SETSTEP called four times");
44861.2Skamil}
44871.2Skamil
44881.2SkamilATF_TC_BODY(setstep4, tc)
44891.2Skamil{
44901.2Skamil	ptrace_step(4, 1);
44911.1Skamil}
44921.1Skamil#endif
44931.1Skamil
44941.1SkamilATF_TC(kill1);
44951.1SkamilATF_TC_HEAD(kill1, tc)
44961.1Skamil{
44971.1Skamil	atf_tc_set_md_var(tc, "descr",
44981.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
44991.1Skamil}
45001.1Skamil
45011.1SkamilATF_TC_BODY(kill1, tc)
45021.1Skamil{
45031.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
45041.1Skamil	pid_t child, wpid;
45051.1Skamil#if defined(TWAIT_HAVE_STATUS)
45061.1Skamil	int status;
45071.1Skamil#endif
45081.1Skamil
45091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45111.1Skamil	if (child == 0) {
45121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45141.1Skamil
45151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45171.1Skamil
45181.1Skamil		/* NOTREACHED */
45191.1Skamil		FORKEE_ASSERTX(0 &&
45201.1Skamil		    "Child should be terminated by a signal from its parent");
45211.1Skamil	}
45221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45231.1Skamil
45241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45261.1Skamil
45271.1Skamil	validate_status_stopped(status, sigval);
45281.1Skamil
45291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45301.1Skamil	    "without signal to be sent\n");
45311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
45321.1Skamil
45331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45351.1Skamil
45361.1Skamil	validate_status_signaled(status, sigsent, 0);
45371.1Skamil
45381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45401.1Skamil}
45411.1Skamil
45421.1SkamilATF_TC(kill2);
45431.1SkamilATF_TC_HEAD(kill2, tc)
45441.1Skamil{
45451.1Skamil	atf_tc_set_md_var(tc, "descr",
45461.1Skamil	    "Verify that PT_KILL terminates child");
45471.1Skamil}
45481.1Skamil
45491.1SkamilATF_TC_BODY(kill2, tc)
45501.1Skamil{
45511.1Skamil	const int sigval = SIGSTOP;
45521.1Skamil	pid_t child, wpid;
45531.1Skamil#if defined(TWAIT_HAVE_STATUS)
45541.1Skamil	int status;
45551.1Skamil#endif
45561.1Skamil
45571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45591.1Skamil	if (child == 0) {
45601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45621.1Skamil
45631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45651.1Skamil
45661.1Skamil		/* NOTREACHED */
45671.1Skamil		FORKEE_ASSERTX(0 &&
45681.1Skamil		    "Child should be terminated by a signal from its parent");
45691.1Skamil	}
45701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45711.1Skamil
45721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45741.1Skamil
45751.1Skamil	validate_status_stopped(status, sigval);
45761.1Skamil
45771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45781.1Skamil	    "without signal to be sent\n");
45791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
45801.1Skamil
45811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45831.1Skamil
45841.1Skamil	validate_status_signaled(status, SIGKILL, 0);
45851.1Skamil
45861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45881.1Skamil}
45891.1Skamil
45901.1SkamilATF_TC(lwpinfo1);
45911.1SkamilATF_TC_HEAD(lwpinfo1, tc)
45921.1Skamil{
45931.1Skamil	atf_tc_set_md_var(tc, "descr",
45941.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
45951.1Skamil}
45961.1Skamil
45971.1SkamilATF_TC_BODY(lwpinfo1, tc)
45981.1Skamil{
45991.1Skamil	const int exitval = 5;
46001.1Skamil	const int sigval = SIGSTOP;
46011.1Skamil	pid_t child, wpid;
46021.1Skamil#if defined(TWAIT_HAVE_STATUS)
46031.1Skamil	int status;
46041.1Skamil#endif
46051.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46061.1Skamil
46071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46091.1Skamil	if (child == 0) {
46101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46121.1Skamil
46131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46151.1Skamil
46161.13Schristos		DPRINTF("Before exiting of the child process\n");
46171.1Skamil		_exit(exitval);
46181.1Skamil	}
46191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46201.1Skamil
46211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46231.1Skamil
46241.1Skamil	validate_status_stopped(status, sigval);
46251.1Skamil
46261.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46281.1Skamil
46291.13Schristos	DPRINTF("Assert that there exists a thread\n");
46301.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
46311.1Skamil
46321.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
46331.1Skamil	    info.pl_lwpid);
46341.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
46351.1Skamil	    "Received event %d != expected event %d",
46361.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
46371.1Skamil
46381.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46401.1Skamil
46411.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
46421.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
46431.1Skamil
46441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46451.1Skamil	    "without signal to be sent\n");
46461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46471.1Skamil
46481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46501.1Skamil
46511.1Skamil	validate_status_exited(status, exitval);
46521.1Skamil
46531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46551.1Skamil}
46561.1Skamil
46571.1Skamil#if defined(TWAIT_HAVE_PID)
46581.1SkamilATF_TC(lwpinfo2);
46591.1SkamilATF_TC_HEAD(lwpinfo2, tc)
46601.1Skamil{
46611.1Skamil	atf_tc_set_md_var(tc, "descr",
46621.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
46631.1Skamil	    "tracer)");
46641.1Skamil}
46651.1Skamil
46661.1SkamilATF_TC_BODY(lwpinfo2, tc)
46671.1Skamil{
46681.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46691.1Skamil	const int exitval_tracee = 5;
46701.1Skamil	const int exitval_tracer = 10;
46711.1Skamil	pid_t tracee, tracer, wpid;
46721.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46731.1Skamil#if defined(TWAIT_HAVE_STATUS)
46741.1Skamil	int status;
46751.1Skamil#endif
46761.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46771.1Skamil
46781.13Schristos	DPRINTF("Spawn tracee\n");
46791.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
46801.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
46811.1Skamil	tracee = atf_utils_fork();
46821.1Skamil	if (tracee == 0) {
46831.1Skamil
46841.1Skamil		/* Wait for message from the parent */
46851.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
46861.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
46871.1Skamil
46881.1Skamil		_exit(exitval_tracee);
46891.1Skamil	}
46901.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
46911.1Skamil
46921.13Schristos	DPRINTF("Spawn debugger\n");
46931.1Skamil	tracer = atf_utils_fork();
46941.1Skamil	if (tracer == 0) {
46951.1Skamil		/* No IPC to communicate with the child */
46961.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
46971.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
46981.1Skamil
46991.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
47001.1Skamil		FORKEE_REQUIRE_SUCCESS(
47011.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47021.1Skamil
47031.1Skamil		forkee_status_stopped(status, SIGSTOP);
47041.1Skamil
47051.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47061.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47071.1Skamil		    != -1);
47081.1Skamil
47091.13Schristos		DPRINTF("Assert that there exists a thread\n");
47101.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
47111.1Skamil
47121.13Schristos		DPRINTF("Assert that lwp thread %d received event "
47131.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
47141.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
47151.1Skamil
47161.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47171.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47181.1Skamil		    != -1);
47191.1Skamil
47201.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
47211.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
47221.1Skamil
47231.1Skamil		/* Resume tracee with PT_CONTINUE */
47241.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
47251.1Skamil
47261.1Skamil		/* Inform parent that tracer has attached to tracee */
47271.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
47281.1Skamil		/* Wait for parent */
47291.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
47301.1Skamil
47311.1Skamil		/* Wait for tracee and assert that it exited */
47321.1Skamil		FORKEE_REQUIRE_SUCCESS(
47331.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47341.1Skamil
47351.1Skamil		forkee_status_exited(status, exitval_tracee);
47361.1Skamil
47371.13Schristos		DPRINTF("Before exiting of the tracer process\n");
47381.1Skamil		_exit(exitval_tracer);
47391.1Skamil	}
47401.1Skamil
47411.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
47421.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
47431.1Skamil
47441.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
47451.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
47461.1Skamil
47471.13Schristos	DPRINTF("Detect that tracee is zombie\n");
47481.1Skamil	await_zombie(tracee);
47491.1Skamil
47501.13Schristos	DPRINTF("Assert that there is no status about tracee - "
47511.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
47521.1Skamil	TWAIT_REQUIRE_SUCCESS(
47531.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
47541.1Skamil
47551.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
47561.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
47571.1Skamil
47581.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
47591.1Skamil	    TWAIT_FNAME);
47601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
47611.1Skamil	    tracer);
47621.1Skamil
47631.1Skamil	validate_status_exited(status, exitval_tracer);
47641.1Skamil
47651.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
47661.1Skamil	    TWAIT_FNAME);
47671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
47681.1Skamil	    tracee);
47691.1Skamil
47701.1Skamil	validate_status_exited(status, exitval_tracee);
47711.1Skamil
47721.1Skamil	msg_close(&parent_tracer);
47731.1Skamil	msg_close(&parent_tracee);
47741.1Skamil}
47751.1Skamil#endif
47761.1Skamil
47771.1SkamilATF_TC(siginfo1);
47781.1SkamilATF_TC_HEAD(siginfo1, tc)
47791.1Skamil{
47801.1Skamil	atf_tc_set_md_var(tc, "descr",
47811.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
47821.1Skamil}
47831.1Skamil
47841.1SkamilATF_TC_BODY(siginfo1, tc)
47851.1Skamil{
47861.1Skamil	const int exitval = 5;
47871.1Skamil	const int sigval = SIGTRAP;
47881.1Skamil	pid_t child, wpid;
47891.1Skamil#if defined(TWAIT_HAVE_STATUS)
47901.1Skamil	int status;
47911.1Skamil#endif
47921.1Skamil	struct ptrace_siginfo info;
47931.1Skamil	memset(&info, 0, sizeof(info));
47941.1Skamil
47951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47971.1Skamil	if (child == 0) {
47981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48001.1Skamil
48011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48031.1Skamil
48041.13Schristos		DPRINTF("Before exiting of the child process\n");
48051.1Skamil		_exit(exitval);
48061.1Skamil	}
48071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48081.1Skamil
48091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48111.1Skamil
48121.1Skamil	validate_status_stopped(status, sigval);
48131.1Skamil
48141.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48161.1Skamil
48171.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48181.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48191.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48201.1Skamil	    info.psi_siginfo.si_errno);
48211.1Skamil
48221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48231.1Skamil	    "without signal to be sent\n");
48241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48251.1Skamil
48261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48281.1Skamil
48291.1Skamil	validate_status_exited(status, exitval);
48301.1Skamil
48311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48331.1Skamil}
48341.1Skamil
48351.1SkamilATF_TC(siginfo2);
48361.1SkamilATF_TC_HEAD(siginfo2, tc)
48371.1Skamil{
48381.1Skamil	atf_tc_set_md_var(tc, "descr",
48391.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
48401.1Skamil	    "modification of SIGINT from tracee");
48411.1Skamil}
48421.1Skamil
48431.1Skamilstatic int siginfo2_caught = 0;
48441.1Skamil
48451.1Skamilstatic void
48461.1Skamilsiginfo2_sighandler(int sig)
48471.1Skamil{
48481.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
48491.1Skamil
48501.1Skamil	++siginfo2_caught;
48511.1Skamil}
48521.1Skamil
48531.1SkamilATF_TC_BODY(siginfo2, tc)
48541.1Skamil{
48551.1Skamil	const int exitval = 5;
48561.1Skamil	const int sigval = SIGINT;
48571.1Skamil	pid_t child, wpid;
48581.1Skamil	struct sigaction sa;
48591.1Skamil#if defined(TWAIT_HAVE_STATUS)
48601.1Skamil	int status;
48611.1Skamil#endif
48621.1Skamil	struct ptrace_siginfo info;
48631.1Skamil	memset(&info, 0, sizeof(info));
48641.1Skamil
48651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48671.1Skamil	if (child == 0) {
48681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48701.1Skamil
48711.1Skamil		sa.sa_handler = siginfo2_sighandler;
48721.1Skamil		sa.sa_flags = SA_SIGINFO;
48731.1Skamil		sigemptyset(&sa.sa_mask);
48741.1Skamil
48751.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48761.1Skamil
48771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48791.1Skamil
48801.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
48811.1Skamil
48821.13Schristos		DPRINTF("Before exiting of the child process\n");
48831.1Skamil		_exit(exitval);
48841.1Skamil	}
48851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48861.1Skamil
48871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48891.1Skamil
48901.1Skamil	validate_status_stopped(status, sigval);
48911.1Skamil
48921.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48941.1Skamil
48951.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48961.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48971.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48981.1Skamil	    info.psi_siginfo.si_errno);
48991.1Skamil
49001.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49021.1Skamil
49031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49041.1Skamil	    "without signal to be sent\n");
49051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
49061.1Skamil
49071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49091.1Skamil
49101.1Skamil	validate_status_exited(status, exitval);
49111.1Skamil
49121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49141.1Skamil}
49151.1Skamil
49161.1SkamilATF_TC(siginfo3);
49171.1SkamilATF_TC_HEAD(siginfo3, tc)
49181.1Skamil{
49191.1Skamil	atf_tc_set_md_var(tc, "descr",
49201.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
49211.1Skamil	    "setting signal to new value");
49221.1Skamil}
49231.1Skamil
49241.1Skamilstatic int siginfo3_caught = 0;
49251.1Skamil
49261.1Skamilstatic void
49271.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
49281.1Skamil{
49291.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
49301.1Skamil
49311.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
49321.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
49331.1Skamil
49341.1Skamil	++siginfo3_caught;
49351.1Skamil}
49361.1Skamil
49371.1SkamilATF_TC_BODY(siginfo3, tc)
49381.1Skamil{
49391.1Skamil	const int exitval = 5;
49401.1Skamil	const int sigval = SIGINT;
49411.1Skamil	const int sigfaked = SIGTRAP;
49421.1Skamil	const int sicodefaked = TRAP_BRKPT;
49431.1Skamil	pid_t child, wpid;
49441.1Skamil	struct sigaction sa;
49451.1Skamil#if defined(TWAIT_HAVE_STATUS)
49461.1Skamil	int status;
49471.1Skamil#endif
49481.1Skamil	struct ptrace_siginfo info;
49491.1Skamil	memset(&info, 0, sizeof(info));
49501.1Skamil
49511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49531.1Skamil	if (child == 0) {
49541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49561.1Skamil
49571.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
49581.1Skamil		sa.sa_flags = SA_SIGINFO;
49591.1Skamil		sigemptyset(&sa.sa_mask);
49601.1Skamil
49611.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
49621.1Skamil
49631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49651.1Skamil
49661.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
49671.1Skamil
49681.13Schristos		DPRINTF("Before exiting of the child process\n");
49691.1Skamil		_exit(exitval);
49701.1Skamil	}
49711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49721.1Skamil
49731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49751.1Skamil
49761.1Skamil	validate_status_stopped(status, sigval);
49771.1Skamil
49781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49801.1Skamil
49811.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49821.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49831.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49841.1Skamil	    info.psi_siginfo.si_errno);
49851.1Skamil
49861.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
49871.1Skamil	    sigfaked, sicodefaked);
49881.1Skamil	info.psi_siginfo.si_signo = sigfaked;
49891.1Skamil	info.psi_siginfo.si_code = sicodefaked;
49901.1Skamil
49911.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49931.1Skamil
49941.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49961.1Skamil
49971.13Schristos	DPRINTF("Before checking siginfo_t\n");
49981.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
49991.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
50001.1Skamil
50011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50021.1Skamil	    "without signal to be sent\n");
50031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
50041.1Skamil
50051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50071.1Skamil
50081.1Skamil	validate_status_exited(status, exitval);
50091.1Skamil
50101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50121.1Skamil}
50131.1Skamil
50141.1SkamilATF_TC(siginfo4);
50151.1SkamilATF_TC_HEAD(siginfo4, tc)
50161.1Skamil{
50171.1Skamil	atf_tc_set_md_var(tc, "descr",
50181.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
50191.1Skamil}
50201.1Skamil
50211.1SkamilATF_TC_BODY(siginfo4, tc)
50221.1Skamil{
50231.1Skamil	const int sigval = SIGTRAP;
50241.1Skamil	pid_t child, wpid;
50251.1Skamil#if defined(TWAIT_HAVE_STATUS)
50261.1Skamil	int status;
50271.1Skamil#endif
50281.1Skamil
50291.1Skamil	struct ptrace_siginfo info;
50301.1Skamil	memset(&info, 0, sizeof(info));
50311.1Skamil
50321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50341.1Skamil	if (child == 0) {
50351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50371.1Skamil
50381.13Schristos		DPRINTF("Before calling execve(2) from child\n");
50391.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
50401.1Skamil
50411.1Skamil		FORKEE_ASSERT(0 && "Not reached");
50421.1Skamil	}
50431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50441.1Skamil
50451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50471.1Skamil
50481.1Skamil	validate_status_stopped(status, sigval);
50491.1Skamil
50501.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50521.1Skamil
50531.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50541.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50551.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50561.1Skamil	    info.psi_siginfo.si_errno);
50571.1Skamil
50581.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50591.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
50601.1Skamil
50611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50621.1Skamil	    "without signal to be sent\n");
50631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50641.1Skamil
50651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50671.1Skamil
50681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50701.1Skamil}
50711.1Skamil
50721.1Skamil#if defined(TWAIT_HAVE_PID)
50731.1SkamilATF_TC(siginfo5);
50741.1SkamilATF_TC_HEAD(siginfo5, tc)
50751.1Skamil{
50761.1Skamil	atf_tc_set_md_var(tc, "descr",
50771.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
50781.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
50791.1Skamil}
50801.1Skamil
50811.1SkamilATF_TC_BODY(siginfo5, tc)
50821.1Skamil{
50831.1Skamil	const int exitval = 5;
50841.1Skamil	const int exitval2 = 15;
50851.1Skamil	const int sigval = SIGSTOP;
50861.1Skamil	pid_t child, child2, wpid;
50871.1Skamil#if defined(TWAIT_HAVE_STATUS)
50881.1Skamil	int status;
50891.1Skamil#endif
50901.1Skamil	ptrace_state_t state;
50911.1Skamil	const int slen = sizeof(state);
50921.1Skamil	ptrace_event_t event;
50931.1Skamil	const int elen = sizeof(event);
50941.1Skamil	struct ptrace_siginfo info;
50951.1Skamil
50961.1Skamil	memset(&info, 0, sizeof(info));
50971.1Skamil
50981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51001.1Skamil	if (child == 0) {
51011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51031.1Skamil
51041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51061.1Skamil
51071.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
51081.1Skamil
51091.1Skamil		if (child2 == 0)
51101.1Skamil			_exit(exitval2);
51111.1Skamil
51121.1Skamil		FORKEE_REQUIRE_SUCCESS
51131.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
51141.1Skamil
51151.1Skamil		forkee_status_exited(status, exitval2);
51161.1Skamil
51171.13Schristos		DPRINTF("Before exiting of the child process\n");
51181.1Skamil		_exit(exitval);
51191.1Skamil	}
51201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51211.1Skamil
51221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51241.1Skamil
51251.1Skamil	validate_status_stopped(status, sigval);
51261.1Skamil
51271.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51291.1Skamil
51301.13Schristos	DPRINTF("Before checking siginfo_t\n");
51311.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51321.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
51331.1Skamil
51341.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
51351.1Skamil	event.pe_set_event = PTRACE_FORK;
51361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51371.1Skamil
51381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51391.1Skamil	    "without signal to be sent\n");
51401.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
51411.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
51421.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
51431.1Skamil                "state.pe_other_pid=child)\n", child);
51441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51451.1Skamil
51461.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
51471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51481.1Skamil
51491.1Skamil	validate_status_stopped(status, SIGTRAP);
51501.1Skamil
51511.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51531.1Skamil
51541.13Schristos	DPRINTF("Before checking siginfo_t\n");
51551.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51561.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51571.1Skamil
51581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51591.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51601.1Skamil
51611.1Skamil	child2 = state.pe_other_pid;
51621.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
51631.1Skamil
51641.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
51651.1Skamil	    TWAIT_FNAME, child2, child);
51661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51671.1Skamil	    child2);
51681.1Skamil
51691.1Skamil	validate_status_stopped(status, SIGTRAP);
51701.1Skamil
51711.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51731.1Skamil
51741.13Schristos	DPRINTF("Before checking siginfo_t\n");
51751.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51771.1Skamil
51781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
51791.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51801.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
51811.1Skamil
51821.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
51831.1Skamil	    "without signal to be sent\n");
51841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
51851.1Skamil
51861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51871.1Skamil	    "without signal to be sent\n");
51881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51891.1Skamil
51901.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
51911.1Skamil	    TWAIT_FNAME);
51921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51931.1Skamil	    child2);
51941.1Skamil
51951.1Skamil	validate_status_exited(status, exitval2);
51961.1Skamil
51971.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
51981.1Skamil	    TWAIT_FNAME);
51991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
52001.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
52011.1Skamil
52021.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52031.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
52041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52051.1Skamil
52061.1Skamil	validate_status_stopped(status, SIGCHLD);
52071.1Skamil
52081.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52101.1Skamil
52111.13Schristos	DPRINTF("Before checking siginfo_t\n");
52121.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
52131.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
52141.1Skamil
52151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52161.1Skamil	    "without signal to be sent\n");
52171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52181.1Skamil
52191.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52201.1Skamil	    TWAIT_FNAME);
52211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52221.1Skamil
52231.1Skamil	validate_status_exited(status, exitval);
52241.1Skamil
52251.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52261.1Skamil	    TWAIT_FNAME);
52271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52281.1Skamil}
52291.1Skamil#endif
52301.1Skamil
52311.1Skamil#if defined(PT_STEP)
52321.1SkamilATF_TC(siginfo6);
52331.1SkamilATF_TC_HEAD(siginfo6, tc)
52341.1Skamil{
52351.1Skamil	atf_tc_set_md_var(tc, "descr",
52361.1Skamil	    "Verify single PT_STEP call with signal information check");
52371.1Skamil}
52381.1Skamil
52391.1SkamilATF_TC_BODY(siginfo6, tc)
52401.1Skamil{
52411.1Skamil	const int exitval = 5;
52421.1Skamil	const int sigval = SIGSTOP;
52431.1Skamil	pid_t child, wpid;
52441.1Skamil#if defined(TWAIT_HAVE_STATUS)
52451.1Skamil	int status;
52461.1Skamil#endif
52471.1Skamil	int happy;
52481.1Skamil	struct ptrace_siginfo info;
52491.1Skamil
52501.1Skamil#if defined(__arm__)
52511.1Skamil	/* PT_STEP not supported on arm 32-bit */
52521.1Skamil	atf_tc_expect_fail("PR kern/52119");
52531.1Skamil#endif
52541.1Skamil
52551.1Skamil	memset(&info, 0, sizeof(info));
52561.1Skamil
52571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52591.1Skamil	if (child == 0) {
52601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52621.1Skamil
52631.1Skamil		happy = check_happy(100);
52641.1Skamil
52651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52671.1Skamil
52681.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
52691.1Skamil
52701.13Schristos		DPRINTF("Before exiting of the child process\n");
52711.1Skamil		_exit(exitval);
52721.1Skamil	}
52731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52741.1Skamil
52751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52771.1Skamil
52781.1Skamil	validate_status_stopped(status, sigval);
52791.1Skamil
52801.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52821.1Skamil
52831.13Schristos	DPRINTF("Before checking siginfo_t\n");
52841.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52851.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52861.1Skamil
52871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52881.1Skamil	    "without signal to be sent (use PT_STEP)\n");
52891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
52901.1Skamil
52911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52931.1Skamil
52941.1Skamil	validate_status_stopped(status, SIGTRAP);
52951.1Skamil
52961.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52981.1Skamil
52991.13Schristos	DPRINTF("Before checking siginfo_t\n");
53001.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
53011.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
53021.1Skamil
53031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53041.1Skamil	    "without signal to be sent\n");
53051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53061.1Skamil
53071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53091.1Skamil
53101.1Skamil	validate_status_exited(status, exitval);
53111.1Skamil
53121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53141.1Skamil}
53151.1Skamil#endif
53161.1Skamil
53171.1Skamilvolatile lwpid_t the_lwp_id = 0;
53181.1Skamil
53191.1Skamilstatic void
53201.1Skamillwp_main_func(void *arg)
53211.1Skamil{
53221.1Skamil	the_lwp_id = _lwp_self();
53231.1Skamil	_lwp_exit();
53241.1Skamil}
53251.1Skamil
53261.1SkamilATF_TC(lwp_create1);
53271.1SkamilATF_TC_HEAD(lwp_create1, tc)
53281.1Skamil{
53291.1Skamil	atf_tc_set_md_var(tc, "descr",
53301.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53311.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
53321.1Skamil}
53331.1Skamil
53341.1SkamilATF_TC_BODY(lwp_create1, tc)
53351.1Skamil{
53361.1Skamil	const int exitval = 5;
53371.1Skamil	const int sigval = SIGSTOP;
53381.1Skamil	pid_t child, wpid;
53391.1Skamil#if defined(TWAIT_HAVE_STATUS)
53401.1Skamil	int status;
53411.1Skamil#endif
53421.1Skamil	ptrace_state_t state;
53431.1Skamil	const int slen = sizeof(state);
53441.1Skamil	ptrace_event_t event;
53451.1Skamil	const int elen = sizeof(event);
53461.1Skamil	ucontext_t uc;
53471.1Skamil	lwpid_t lid;
53481.1Skamil	static const size_t ssize = 16*1024;
53491.1Skamil	void *stack;
53501.1Skamil
53511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53531.1Skamil	if (child == 0) {
53541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53561.1Skamil
53571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53591.1Skamil
53601.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53611.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53621.1Skamil
53631.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53641.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53651.1Skamil
53661.13Schristos		DPRINTF("Before creating new in child\n");
53671.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53681.1Skamil
53691.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53701.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53711.1Skamil
53721.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53731.1Skamil		    "are the same\n", lid, the_lwp_id);
53741.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53751.1Skamil
53761.13Schristos		DPRINTF("Before exiting of the child process\n");
53771.1Skamil		_exit(exitval);
53781.1Skamil	}
53791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53801.1Skamil
53811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53831.1Skamil
53841.1Skamil	validate_status_stopped(status, sigval);
53851.1Skamil
53861.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
53871.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
53881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53891.1Skamil
53901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53911.1Skamil	    "without signal to be sent\n");
53921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53931.1Skamil
53941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53951.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
53961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53971.1Skamil
53981.1Skamil	validate_status_stopped(status, SIGTRAP);
53991.1Skamil
54001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54011.1Skamil
54021.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
54031.1Skamil
54041.1Skamil	lid = state.pe_lwp;
54051.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54061.1Skamil
54071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54081.1Skamil	    "without signal to be sent\n");
54091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54101.1Skamil
54111.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54121.1Skamil	    TWAIT_FNAME);
54131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54141.1Skamil
54151.1Skamil	validate_status_exited(status, exitval);
54161.1Skamil
54171.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54181.1Skamil	    TWAIT_FNAME);
54191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54201.1Skamil}
54211.1Skamil
54221.1SkamilATF_TC(lwp_exit1);
54231.1SkamilATF_TC_HEAD(lwp_exit1, tc)
54241.1Skamil{
54251.1Skamil	atf_tc_set_md_var(tc, "descr",
54261.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
54271.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
54281.1Skamil}
54291.1Skamil
54301.1SkamilATF_TC_BODY(lwp_exit1, tc)
54311.1Skamil{
54321.1Skamil	const int exitval = 5;
54331.1Skamil	const int sigval = SIGSTOP;
54341.1Skamil	pid_t child, wpid;
54351.1Skamil#if defined(TWAIT_HAVE_STATUS)
54361.1Skamil	int status;
54371.1Skamil#endif
54381.1Skamil	ptrace_state_t state;
54391.1Skamil	const int slen = sizeof(state);
54401.1Skamil	ptrace_event_t event;
54411.1Skamil	const int elen = sizeof(event);
54421.1Skamil	ucontext_t uc;
54431.1Skamil	lwpid_t lid;
54441.1Skamil	static const size_t ssize = 16*1024;
54451.1Skamil	void *stack;
54461.1Skamil
54471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54491.1Skamil	if (child == 0) {
54501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54521.1Skamil
54531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54551.1Skamil
54561.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54571.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54581.1Skamil
54591.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54601.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54611.1Skamil
54621.13Schristos		DPRINTF("Before creating new in child\n");
54631.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54641.1Skamil
54651.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54661.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54671.1Skamil
54681.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54691.1Skamil		    "are the same\n", lid, the_lwp_id);
54701.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54711.1Skamil
54721.13Schristos		DPRINTF("Before exiting of the child process\n");
54731.1Skamil		_exit(exitval);
54741.1Skamil	}
54751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54761.1Skamil
54771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54791.1Skamil
54801.1Skamil	validate_status_stopped(status, sigval);
54811.1Skamil
54821.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54831.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
54841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54851.1Skamil
54861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54871.1Skamil	    "without signal to be sent\n");
54881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54891.1Skamil
54901.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54911.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54931.1Skamil
54941.1Skamil	validate_status_stopped(status, SIGTRAP);
54951.1Skamil
54961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54971.1Skamil
54981.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
54991.1Skamil
55001.1Skamil	lid = state.pe_lwp;
55011.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55021.1Skamil
55031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55041.1Skamil	    "without signal to be sent\n");
55051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55061.1Skamil
55071.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55081.1Skamil	    TWAIT_FNAME);
55091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55101.1Skamil
55111.1Skamil	validate_status_exited(status, exitval);
55121.1Skamil
55131.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55141.1Skamil	    TWAIT_FNAME);
55151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55161.1Skamil}
55171.1Skamil
55181.1SkamilATF_TC(signal1);
55191.1SkamilATF_TC_HEAD(signal1, tc)
55201.1Skamil{
55211.1Skamil	atf_tc_set_md_var(tc, "descr",
55221.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
55231.1Skamil	    "from catching other signals");
55241.1Skamil}
55251.1Skamil
55261.1SkamilATF_TC_BODY(signal1, tc)
55271.1Skamil{
55281.1Skamil	const int exitval = 5;
55291.1Skamil	const int sigval = SIGSTOP;
55301.1Skamil	const int sigmasked = SIGTRAP;
55311.1Skamil	const int signotmasked = SIGINT;
55321.1Skamil	pid_t child, wpid;
55331.1Skamil#if defined(TWAIT_HAVE_STATUS)
55341.1Skamil	int status;
55351.1Skamil#endif
55361.1Skamil	sigset_t intmask;
55371.1Skamil
55381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55401.1Skamil	if (child == 0) {
55411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55431.1Skamil
55441.1Skamil		sigemptyset(&intmask);
55451.1Skamil		sigaddset(&intmask, sigmasked);
55461.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55471.1Skamil
55481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55501.1Skamil
55511.13Schristos		DPRINTF("Before raising %s from child\n",
55521.1Skamil		    strsignal(signotmasked));
55531.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
55541.1Skamil
55551.13Schristos		DPRINTF("Before exiting of the child process\n");
55561.1Skamil		_exit(exitval);
55571.1Skamil	}
55581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55591.1Skamil
55601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55621.1Skamil
55631.1Skamil	validate_status_stopped(status, sigval);
55641.1Skamil
55651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55661.1Skamil	    "without signal to be sent\n");
55671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55681.1Skamil
55691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55711.1Skamil
55721.1Skamil	validate_status_stopped(status, signotmasked);
55731.1Skamil
55741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55751.1Skamil	    "without signal to be sent\n");
55761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55771.1Skamil
55781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55801.1Skamil
55811.1Skamil	validate_status_exited(status, exitval);
55821.1Skamil
55831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55851.1Skamil}
55861.1Skamil
55871.1SkamilATF_TC(signal2);
55881.1SkamilATF_TC_HEAD(signal2, tc)
55891.1Skamil{
55901.1Skamil	atf_tc_set_md_var(tc, "descr",
55911.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
55921.1Skamil	    "catching this raised signal");
55931.1Skamil}
55941.1Skamil
55951.1SkamilATF_TC_BODY(signal2, tc)
55961.1Skamil{
55971.1Skamil	const int exitval = 5;
55981.1Skamil	const int sigval = SIGSTOP;
55991.1Skamil	const int sigmasked = SIGTRAP;
56001.1Skamil	pid_t child, wpid;
56011.1Skamil#if defined(TWAIT_HAVE_STATUS)
56021.1Skamil	int status;
56031.1Skamil#endif
56041.1Skamil	sigset_t intmask;
56051.1Skamil
56061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56081.1Skamil	if (child == 0) {
56091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56111.1Skamil
56121.1Skamil		sigemptyset(&intmask);
56131.1Skamil		sigaddset(&intmask, sigmasked);
56141.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56151.1Skamil
56161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56181.1Skamil
56191.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
56201.1Skamil		    strsignal(sigmasked));
56211.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
56221.1Skamil
56231.13Schristos		DPRINTF("Before exiting of the child process\n");
56241.1Skamil		_exit(exitval);
56251.1Skamil	}
56261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56271.1Skamil
56281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56301.1Skamil
56311.1Skamil	validate_status_stopped(status, sigval);
56321.1Skamil
56331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56341.1Skamil	    "without signal to be sent\n");
56351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56361.1Skamil
56371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56391.1Skamil
56401.1Skamil	validate_status_exited(status, exitval);
56411.1Skamil
56421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56441.1Skamil}
56451.1Skamil
56461.1SkamilATF_TC(signal3);
56471.1SkamilATF_TC_HEAD(signal3, tc)
56481.1Skamil{
56491.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
56501.1Skamil	atf_tc_set_md_var(tc, "descr",
56511.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56521.1Skamil	    "catching software breakpoints");
56531.1Skamil}
56541.1Skamil
56551.1SkamilATF_TC_BODY(signal3, tc)
56561.1Skamil{
56571.1Skamil	const int exitval = 5;
56581.1Skamil	const int sigval = SIGSTOP;
56591.1Skamil	const int sigmasked = SIGTRAP;
56601.1Skamil	pid_t child, wpid;
56611.1Skamil#if defined(TWAIT_HAVE_STATUS)
56621.1Skamil	int status;
56631.1Skamil#endif
56641.1Skamil	sigset_t intmask;
56651.1Skamil
56661.20Skamil	atf_tc_expect_fail("PR kern/51918");
56671.20Skamil
56681.20Skamil	// This test breaks now on some ports, temporarily disable it
56691.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56701.20Skamil
56711.10Smartin#if defined(__sparc__)
56721.7Skamil	atf_tc_expect_timeout("PR kern/52167");
56731.7Skamil
56741.7Skamil	// timeout wins, failure still valid
56751.7Skamil	// atf_tc_expect_fail("PR kern/51918");
56761.7Skamil#endif
56771.1Skamil
56781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56801.1Skamil	if (child == 0) {
56811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56831.1Skamil
56841.1Skamil		sigemptyset(&intmask);
56851.1Skamil		sigaddset(&intmask, sigmasked);
56861.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56871.1Skamil
56881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56901.1Skamil
56911.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
56921.4Skamil
56931.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
56941.4Skamil		PTRACE_BREAKPOINT_ASM;
56951.1Skamil#else
56961.4Skamil		/* port me */
56971.1Skamil#endif
56981.1Skamil
56991.13Schristos		DPRINTF("Before exiting of the child process\n");
57001.1Skamil		_exit(exitval);
57011.1Skamil	}
57021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57031.1Skamil
57041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57061.1Skamil
57071.1Skamil	validate_status_stopped(status, sigval);
57081.1Skamil
57091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57101.1Skamil	    "without signal to be sent\n");
57111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57121.1Skamil
57131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57151.1Skamil
57161.1Skamil	validate_status_stopped(status, sigmasked);
57171.1Skamil
57181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57191.1Skamil	    "without signal to be sent\n");
57201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57211.1Skamil
57221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57241.1Skamil
57251.1Skamil	validate_status_exited(status, exitval);
57261.1Skamil
57271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57291.1Skamil}
57301.1Skamil
57311.1Skamil#if defined(PT_STEP)
57321.1SkamilATF_TC(signal4);
57331.1SkamilATF_TC_HEAD(signal4, tc)
57341.1Skamil{
57351.1Skamil	atf_tc_set_md_var(tc, "descr",
57361.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57371.1Skamil	    "catching single step trap");
57381.1Skamil}
57391.1Skamil
57401.1SkamilATF_TC_BODY(signal4, tc)
57411.1Skamil{
57421.1Skamil	const int exitval = 5;
57431.1Skamil	const int sigval = SIGSTOP;
57441.1Skamil	const int sigmasked = SIGTRAP;
57451.1Skamil	pid_t child, wpid;
57461.1Skamil#if defined(TWAIT_HAVE_STATUS)
57471.1Skamil	int status;
57481.1Skamil#endif
57491.1Skamil	sigset_t intmask;
57501.1Skamil	int happy;
57511.1Skamil
57521.1Skamil#if defined(__arm__)
57531.5Skamil	/* PT_STEP not supported on arm 32-bit */
57541.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
57551.1Skamil#endif
57561.1Skamil
57571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57591.1Skamil	if (child == 0) {
57601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57621.1Skamil
57631.1Skamil		happy = check_happy(100);
57641.1Skamil
57651.1Skamil		sigemptyset(&intmask);
57661.1Skamil		sigaddset(&intmask, sigmasked);
57671.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57681.1Skamil
57691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57711.1Skamil
57721.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
57731.1Skamil
57741.13Schristos		DPRINTF("Before exiting of the child process\n");
57751.1Skamil		_exit(exitval);
57761.1Skamil	}
57771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57781.1Skamil
57791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57811.1Skamil
57821.1Skamil	validate_status_stopped(status, sigval);
57831.1Skamil
57841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57851.1Skamil	    "without signal to be sent\n");
57861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
57871.1Skamil
57881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57901.1Skamil
57911.1Skamil	validate_status_stopped(status, sigmasked);
57921.1Skamil
57931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57941.1Skamil	    "without signal to be sent\n");
57951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57961.1Skamil
57971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57991.1Skamil
58001.1Skamil	validate_status_exited(status, exitval);
58011.1Skamil
58021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58041.1Skamil}
58051.1Skamil#endif
58061.1Skamil
58071.1SkamilATF_TC(signal5);
58081.1SkamilATF_TC_HEAD(signal5, tc)
58091.1Skamil{
58101.1Skamil	atf_tc_set_md_var(tc, "descr",
58111.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58121.1Skamil	    "catching exec() breakpoint");
58131.1Skamil}
58141.1Skamil
58151.1SkamilATF_TC_BODY(signal5, tc)
58161.1Skamil{
58171.1Skamil	const int exitval = 5;
58181.1Skamil	const int sigval = SIGSTOP;
58191.1Skamil	const int sigmasked = SIGTRAP;
58201.1Skamil	pid_t child, wpid;
58211.1Skamil#if defined(TWAIT_HAVE_STATUS)
58221.1Skamil	int status;
58231.1Skamil#endif
58241.1Skamil	sigset_t intmask;
58251.1Skamil
58261.14Schristos	atf_tc_expect_fail("wrong signal");
58271.14Schristos
58281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58301.1Skamil	if (child == 0) {
58311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58331.1Skamil
58341.1Skamil		sigemptyset(&intmask);
58351.1Skamil		sigaddset(&intmask, sigmasked);
58361.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58371.1Skamil
58381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58401.1Skamil
58411.13Schristos		DPRINTF("Before calling execve(2) from child\n");
58421.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
58431.1Skamil
58441.13Schristos		DPRINTF("Before exiting of the child process\n");
58451.1Skamil		_exit(exitval);
58461.1Skamil	}
58471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58481.1Skamil
58491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58511.1Skamil
58521.1Skamil	validate_status_stopped(status, sigval);
58531.1Skamil
58541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58551.1Skamil	    "without signal to be sent\n");
58561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58571.1Skamil
58581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58601.1Skamil
58611.1Skamil	validate_status_stopped(status, sigmasked);
58621.1Skamil
58631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58641.1Skamil	    "without signal to be sent\n");
58651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58661.1Skamil
58671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58691.1Skamil
58701.1Skamil	validate_status_exited(status, exitval);
58711.1Skamil
58721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58741.1Skamil}
58751.1Skamil
58761.1Skamil#if defined(TWAIT_HAVE_PID)
58771.1SkamilATF_TC(signal6);
58781.1SkamilATF_TC_HEAD(signal6, tc)
58791.1Skamil{
58801.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
58811.1Skamil	atf_tc_set_md_var(tc, "descr",
58821.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58831.1Skamil	    "catching PTRACE_FORK breakpoint");
58841.1Skamil}
58851.1Skamil
58861.1SkamilATF_TC_BODY(signal6, tc)
58871.1Skamil{
58881.1Skamil	const int exitval = 5;
58891.1Skamil	const int exitval2 = 15;
58901.1Skamil	const int sigval = SIGSTOP;
58911.1Skamil	const int sigmasked = SIGTRAP;
58921.1Skamil	pid_t child, child2, wpid;
58931.1Skamil#if defined(TWAIT_HAVE_STATUS)
58941.1Skamil	int status;
58951.1Skamil#endif
58961.1Skamil	sigset_t intmask;
58971.1Skamil	ptrace_state_t state;
58981.1Skamil	const int slen = sizeof(state);
58991.1Skamil	ptrace_event_t event;
59001.1Skamil	const int elen = sizeof(event);
59011.1Skamil
59021.38Skamil	atf_tc_expect_fail("PR kern/51918");
59031.14Schristos
59041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59061.1Skamil	if (child == 0) {
59071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59091.1Skamil
59101.1Skamil		sigemptyset(&intmask);
59111.1Skamil		sigaddset(&intmask, sigmasked);
59121.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59131.1Skamil
59141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59161.1Skamil
59171.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59181.1Skamil
59191.1Skamil		if (child2 == 0)
59201.1Skamil			_exit(exitval2);
59211.1Skamil
59221.1Skamil		FORKEE_REQUIRE_SUCCESS
59231.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59241.1Skamil
59251.1Skamil		forkee_status_exited(status, exitval2);
59261.1Skamil
59271.13Schristos		DPRINTF("Before exiting of the child process\n");
59281.1Skamil		_exit(exitval);
59291.1Skamil	}
59301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59311.1Skamil
59321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59341.1Skamil
59351.1Skamil	validate_status_stopped(status, sigval);
59361.1Skamil
59371.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
59381.1Skamil	event.pe_set_event = PTRACE_FORK;
59391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
59401.1Skamil
59411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59421.1Skamil	    "without signal to be sent\n");
59431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59441.1Skamil
59451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59471.1Skamil
59481.1Skamil	validate_status_stopped(status, sigmasked);
59491.1Skamil
59501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59511.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59521.1Skamil
59531.1Skamil	child2 = state.pe_other_pid;
59541.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
59551.1Skamil
59561.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
59571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59581.1Skamil	    child2);
59591.1Skamil
59601.1Skamil	validate_status_stopped(status, SIGTRAP);
59611.1Skamil
59621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59631.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59641.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
59651.1Skamil
59661.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
59671.1Skamil	    "without signal to be sent\n");
59681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59691.1Skamil
59701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59711.1Skamil	    "without signal to be sent\n");
59721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59731.1Skamil
59741.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
59751.1Skamil	    TWAIT_FNAME);
59761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59771.1Skamil	    child2);
59781.1Skamil
59791.1Skamil	validate_status_exited(status, exitval2);
59801.1Skamil
59811.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
59821.1Skamil	    TWAIT_FNAME);
59831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
59841.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
59851.1Skamil
59861.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59871.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
59881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59891.1Skamil
59901.1Skamil	validate_status_stopped(status, SIGCHLD);
59911.1Skamil
59921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59931.1Skamil	    "without signal to be sent\n");
59941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59951.1Skamil
59961.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59971.1Skamil	    TWAIT_FNAME);
59981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59991.1Skamil
60001.1Skamil	validate_status_exited(status, exitval);
60011.1Skamil
60021.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60031.1Skamil	    TWAIT_FNAME);
60041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60051.1Skamil}
60061.1Skamil#endif
60071.1Skamil
60081.1Skamil#if defined(TWAIT_HAVE_PID)
60091.1SkamilATF_TC(signal7);
60101.1SkamilATF_TC_HEAD(signal7, tc)
60111.1Skamil{
60121.1Skamil	atf_tc_set_md_var(tc, "descr",
60131.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60141.1Skamil	    "catching PTRACE_VFORK breakpoint");
60151.1Skamil}
60161.1Skamil
60171.1SkamilATF_TC_BODY(signal7, tc)
60181.1Skamil{
60191.1Skamil	const int exitval = 5;
60201.1Skamil	const int exitval2 = 15;
60211.1Skamil	const int sigval = SIGSTOP;
60221.1Skamil	const int sigmasked = SIGTRAP;
60231.1Skamil	pid_t child, child2, wpid;
60241.1Skamil#if defined(TWAIT_HAVE_STATUS)
60251.1Skamil	int status;
60261.1Skamil#endif
60271.1Skamil	sigset_t intmask;
60281.1Skamil	ptrace_state_t state;
60291.1Skamil	const int slen = sizeof(state);
60301.1Skamil	ptrace_event_t event;
60311.1Skamil	const int elen = sizeof(event);
60321.1Skamil
60331.38Skamil	atf_tc_expect_fail("PR kern/51918");
60341.14Schristos
60351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60371.1Skamil	if (child == 0) {
60381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60401.1Skamil
60411.1Skamil		sigemptyset(&intmask);
60421.1Skamil		sigaddset(&intmask, sigmasked);
60431.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
60441.1Skamil
60451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60471.1Skamil
60481.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
60491.1Skamil
60501.1Skamil		if (child2 == 0)
60511.1Skamil			_exit(exitval2);
60521.1Skamil
60531.1Skamil		FORKEE_REQUIRE_SUCCESS
60541.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60551.1Skamil
60561.1Skamil		forkee_status_exited(status, exitval2);
60571.1Skamil
60581.13Schristos		DPRINTF("Before exiting of the child process\n");
60591.1Skamil		_exit(exitval);
60601.1Skamil	}
60611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60621.1Skamil
60631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60651.1Skamil
60661.1Skamil	validate_status_stopped(status, sigval);
60671.1Skamil
60681.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
60691.1Skamil	event.pe_set_event = PTRACE_VFORK;
60701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
60711.1Skamil
60721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60731.1Skamil	    "without signal to be sent\n");
60741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60751.1Skamil
60761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60781.1Skamil
60791.1Skamil	validate_status_stopped(status, sigmasked);
60801.1Skamil
60811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60821.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60831.1Skamil
60841.1Skamil	child2 = state.pe_other_pid;
60851.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
60861.1Skamil
60871.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
60881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60891.1Skamil	    child2);
60901.1Skamil
60911.1Skamil	validate_status_stopped(status, SIGTRAP);
60921.1Skamil
60931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
60941.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60951.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
60961.1Skamil
60971.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
60981.1Skamil	    "without signal to be sent\n");
60991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
61001.1Skamil
61011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61021.1Skamil	    "without signal to be sent\n");
61031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61041.1Skamil
61051.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
61061.1Skamil	    TWAIT_FNAME);
61071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61081.1Skamil	    child2);
61091.1Skamil
61101.1Skamil	validate_status_exited(status, exitval2);
61111.1Skamil
61121.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
61131.1Skamil	    TWAIT_FNAME);
61141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
61151.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
61161.1Skamil
61171.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61181.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61201.1Skamil
61211.1Skamil	validate_status_stopped(status, SIGCHLD);
61221.1Skamil
61231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61241.1Skamil	    "without signal to be sent\n");
61251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61261.1Skamil
61271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61281.1Skamil	    TWAIT_FNAME);
61291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61301.1Skamil
61311.1Skamil	validate_status_exited(status, exitval);
61321.1Skamil
61331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61341.1Skamil	    TWAIT_FNAME);
61351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61361.1Skamil}
61371.1Skamil#endif
61381.1Skamil
61391.1SkamilATF_TC(signal8);
61401.1SkamilATF_TC_HEAD(signal8, tc)
61411.1Skamil{
61421.1Skamil	atf_tc_set_md_var(tc, "descr",
61431.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61441.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
61451.1Skamil}
61461.1Skamil
61471.1SkamilATF_TC_BODY(signal8, tc)
61481.1Skamil{
61491.1Skamil	const int exitval = 5;
61501.1Skamil	const int exitval2 = 15;
61511.1Skamil	const int sigval = SIGSTOP;
61521.1Skamil	const int sigmasked = SIGTRAP;
61531.1Skamil	pid_t child, child2, wpid;
61541.1Skamil#if defined(TWAIT_HAVE_STATUS)
61551.1Skamil	int status;
61561.1Skamil#endif
61571.1Skamil	sigset_t intmask;
61581.1Skamil	ptrace_state_t state;
61591.1Skamil	const int slen = sizeof(state);
61601.1Skamil	ptrace_event_t event;
61611.1Skamil	const int elen = sizeof(event);
61621.1Skamil
61631.14Schristos	atf_tc_expect_fail("PR kern/51918");
61641.14Schristos
61651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61671.1Skamil	if (child == 0) {
61681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61701.1Skamil
61711.1Skamil		sigemptyset(&intmask);
61721.1Skamil		sigaddset(&intmask, sigmasked);
61731.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61741.1Skamil
61751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61771.1Skamil
61781.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
61791.1Skamil
61801.1Skamil		if (child2 == 0)
61811.1Skamil			_exit(exitval2);
61821.1Skamil
61831.1Skamil		FORKEE_REQUIRE_SUCCESS
61841.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
61851.1Skamil
61861.1Skamil		forkee_status_exited(status, exitval2);
61871.1Skamil
61881.13Schristos		DPRINTF("Before exiting of the child process\n");
61891.1Skamil		_exit(exitval);
61901.1Skamil	}
61911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61921.1Skamil
61931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61951.1Skamil
61961.1Skamil	validate_status_stopped(status, sigval);
61971.1Skamil
61981.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
61991.1Skamil	    child);
62001.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
62011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62021.1Skamil
62031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62041.1Skamil	    "without signal to be sent\n");
62051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62061.1Skamil
62071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62091.1Skamil
62101.1Skamil	validate_status_stopped(status, sigmasked);
62111.1Skamil
62121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62131.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
62141.1Skamil
62151.1Skamil	child2 = state.pe_other_pid;
62161.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
62171.1Skamil
62181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62191.1Skamil	    "without signal to be sent\n");
62201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62211.1Skamil
62221.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62231.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
62241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62251.1Skamil
62261.1Skamil	validate_status_stopped(status, SIGCHLD);
62271.1Skamil
62281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62291.1Skamil	    "without signal to be sent\n");
62301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62311.1Skamil
62321.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62331.1Skamil	    TWAIT_FNAME);
62341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62351.1Skamil
62361.1Skamil	validate_status_exited(status, exitval);
62371.1Skamil
62381.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62391.1Skamil	    TWAIT_FNAME);
62401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62411.1Skamil}
62421.1Skamil
62431.1SkamilATF_TC(signal9);
62441.1SkamilATF_TC_HEAD(signal9, tc)
62451.1Skamil{
62461.1Skamil	atf_tc_set_md_var(tc, "descr",
62471.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62481.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
62491.1Skamil}
62501.1Skamil
62511.1SkamilATF_TC_BODY(signal9, tc)
62521.1Skamil{
62531.1Skamil	const int exitval = 5;
62541.1Skamil	const int sigval = SIGSTOP;
62551.1Skamil	const int sigmasked = SIGTRAP;
62561.1Skamil	pid_t child, wpid;
62571.1Skamil#if defined(TWAIT_HAVE_STATUS)
62581.1Skamil	int status;
62591.1Skamil#endif
62601.1Skamil	sigset_t intmask;
62611.1Skamil	ptrace_state_t state;
62621.1Skamil	const int slen = sizeof(state);
62631.1Skamil	ptrace_event_t event;
62641.1Skamil	const int elen = sizeof(event);
62651.1Skamil	ucontext_t uc;
62661.1Skamil	lwpid_t lid;
62671.1Skamil	static const size_t ssize = 16*1024;
62681.1Skamil	void *stack;
62691.1Skamil
62701.14Schristos	atf_tc_expect_fail("PR kern/51918");
62711.14Schristos
62721.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62731.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62741.1Skamil	if (child == 0) {
62751.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62761.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62771.1Skamil
62781.1Skamil		sigemptyset(&intmask);
62791.1Skamil		sigaddset(&intmask, sigmasked);
62801.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62811.1Skamil
62821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62841.1Skamil
62851.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62861.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62871.1Skamil
62881.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62891.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62901.1Skamil
62911.13Schristos		DPRINTF("Before creating new in child\n");
62921.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62931.1Skamil
62941.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62951.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62961.1Skamil
62971.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62981.1Skamil		    "are the same\n", lid, the_lwp_id);
62991.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63001.1Skamil
63011.13Schristos		DPRINTF("Before exiting of the child process\n");
63021.1Skamil		_exit(exitval);
63031.1Skamil	}
63041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63051.1Skamil
63061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63081.1Skamil
63091.1Skamil	validate_status_stopped(status, sigval);
63101.1Skamil
63111.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63121.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
63131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63141.1Skamil
63151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63161.1Skamil	    "without signal to be sent\n");
63171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63181.1Skamil
63191.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63201.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63221.1Skamil
63231.1Skamil	validate_status_stopped(status, sigmasked);
63241.1Skamil
63251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63261.1Skamil
63271.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
63281.1Skamil
63291.1Skamil	lid = state.pe_lwp;
63301.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
63311.1Skamil
63321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63331.1Skamil	    "without signal to be sent\n");
63341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63351.1Skamil
63361.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63371.1Skamil	    TWAIT_FNAME);
63381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63391.1Skamil
63401.1Skamil	validate_status_exited(status, exitval);
63411.1Skamil
63421.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63431.1Skamil	    TWAIT_FNAME);
63441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63451.1Skamil}
63461.1Skamil
63471.1SkamilATF_TC(signal10);
63481.1SkamilATF_TC_HEAD(signal10, tc)
63491.1Skamil{
63501.1Skamil	atf_tc_set_md_var(tc, "descr",
63511.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
63521.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
63531.1Skamil}
63541.1Skamil
63551.1SkamilATF_TC_BODY(signal10, tc)
63561.1Skamil{
63571.1Skamil	const int exitval = 5;
63581.1Skamil	const int sigval = SIGSTOP;
63591.1Skamil	const int sigmasked = SIGTRAP;
63601.1Skamil	pid_t child, wpid;
63611.1Skamil#if defined(TWAIT_HAVE_STATUS)
63621.1Skamil	int status;
63631.1Skamil#endif
63641.1Skamil	sigset_t intmask;
63651.1Skamil	ptrace_state_t state;
63661.1Skamil	const int slen = sizeof(state);
63671.1Skamil	ptrace_event_t event;
63681.1Skamil	const int elen = sizeof(event);
63691.1Skamil	ucontext_t uc;
63701.1Skamil	lwpid_t lid;
63711.1Skamil	static const size_t ssize = 16*1024;
63721.1Skamil	void *stack;
63731.1Skamil
63741.14Schristos	atf_tc_expect_fail("PR kern/51918");
63751.14Schristos
63761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63781.1Skamil	if (child == 0) {
63791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63811.1Skamil
63821.1Skamil		sigemptyset(&intmask);
63831.1Skamil		sigaddset(&intmask, sigmasked);
63841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63851.1Skamil
63861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63881.1Skamil
63891.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63901.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63911.1Skamil
63921.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63931.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63941.1Skamil
63951.13Schristos		DPRINTF("Before creating new in child\n");
63961.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63971.1Skamil
63981.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63991.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64001.1Skamil
64011.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64021.1Skamil		    "are the same\n", lid, the_lwp_id);
64031.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64041.1Skamil
64051.13Schristos		DPRINTF("Before exiting of the child process\n");
64061.1Skamil		_exit(exitval);
64071.1Skamil	}
64081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64091.1Skamil
64101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64121.1Skamil
64131.1Skamil	validate_status_stopped(status, sigval);
64141.1Skamil
64151.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
64161.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
64171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64181.1Skamil
64191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64201.1Skamil	    "without signal to be sent\n");
64211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64221.1Skamil
64231.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64241.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64261.1Skamil
64271.1Skamil	validate_status_stopped(status, sigmasked);
64281.1Skamil
64291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64301.1Skamil
64311.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
64321.1Skamil
64331.1Skamil	lid = state.pe_lwp;
64341.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
64351.1Skamil
64361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64371.1Skamil	    "without signal to be sent\n");
64381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64391.1Skamil
64401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64411.1Skamil	    TWAIT_FNAME);
64421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64431.1Skamil
64441.1Skamil	validate_status_exited(status, exitval);
64451.1Skamil
64461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64471.1Skamil	    TWAIT_FNAME);
64481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64491.1Skamil}
64501.1Skamil
64511.1Skamilstatic void
64521.1Skamillwp_main_stop(void *arg)
64531.1Skamil{
64541.1Skamil	the_lwp_id = _lwp_self();
64551.1Skamil
64561.1Skamil	raise(SIGTRAP);
64571.1Skamil
64581.1Skamil	_lwp_exit();
64591.1Skamil}
64601.1Skamil
64611.1SkamilATF_TC(suspend1);
64621.1SkamilATF_TC_HEAD(suspend1, tc)
64631.1Skamil{
64641.1Skamil	atf_tc_set_md_var(tc, "descr",
64651.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64661.1Skamil	    "resumed by a tracee");
64671.1Skamil}
64681.1Skamil
64691.1SkamilATF_TC_BODY(suspend1, tc)
64701.1Skamil{
64711.1Skamil	const int exitval = 5;
64721.1Skamil	const int sigval = SIGSTOP;
64731.1Skamil	pid_t child, wpid;
64741.1Skamil#if defined(TWAIT_HAVE_STATUS)
64751.1Skamil	int status;
64761.1Skamil#endif
64771.1Skamil	ucontext_t uc;
64781.1Skamil	lwpid_t lid;
64791.1Skamil	static const size_t ssize = 16*1024;
64801.1Skamil	void *stack;
64811.1Skamil	struct ptrace_lwpinfo pl;
64821.1Skamil	struct ptrace_siginfo psi;
64831.1Skamil	volatile int go = 0;
64841.1Skamil
64851.17Skamil	// Feature pending for refactoring
64861.17Skamil	atf_tc_expect_fail("PR kern/51995");
64871.17Skamil
64881.16Skamil	// Hangs with qemu
64891.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
64901.16Skamil
64911.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64921.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64931.1Skamil	if (child == 0) {
64941.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64951.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64961.1Skamil
64971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64991.1Skamil
65001.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65011.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65021.1Skamil
65031.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65041.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65051.1Skamil
65061.13Schristos		DPRINTF("Before creating new in child\n");
65071.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65081.1Skamil
65091.1Skamil		while (go == 0)
65101.1Skamil			continue;
65111.1Skamil
65121.1Skamil		raise(SIGINT);
65131.1Skamil
65141.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
65151.1Skamil
65161.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65171.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65181.1Skamil
65191.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65201.1Skamil		    "are the same\n", lid, the_lwp_id);
65211.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65221.1Skamil
65231.13Schristos		DPRINTF("Before exiting of the child process\n");
65241.1Skamil		_exit(exitval);
65251.1Skamil	}
65261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65271.1Skamil
65281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65301.1Skamil
65311.1Skamil	validate_status_stopped(status, sigval);
65321.1Skamil
65331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65341.1Skamil	    "without signal to be sent\n");
65351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65361.1Skamil
65371.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65381.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65401.1Skamil
65411.1Skamil	validate_status_stopped(status, SIGTRAP);
65421.1Skamil
65431.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65451.1Skamil
65461.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65481.1Skamil
65491.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
65501.1Skamil	    child, getpid());
65511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
65521.1Skamil
65531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65541.1Skamil	    "without signal to be sent\n");
65551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65561.1Skamil
65571.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65581.1Skamil	    "SIGINT\n", TWAIT_FNAME);
65591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65601.1Skamil
65611.1Skamil	validate_status_stopped(status, SIGINT);
65621.1Skamil
65631.1Skamil	pl.pl_lwpid = 0;
65641.1Skamil
65651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65661.1Skamil	while (pl.pl_lwpid != 0) {
65671.1Skamil
65681.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65691.1Skamil		switch (pl.pl_lwpid) {
65701.1Skamil		case 1:
65711.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65721.1Skamil			break;
65731.1Skamil		case 2:
65741.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65751.1Skamil			break;
65761.1Skamil		}
65771.1Skamil	}
65781.1Skamil
65791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65801.1Skamil	    "without signal to be sent\n");
65811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65821.1Skamil
65831.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65841.1Skamil	    TWAIT_FNAME);
65851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65861.1Skamil
65871.1Skamil	validate_status_exited(status, exitval);
65881.1Skamil
65891.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65901.1Skamil	    TWAIT_FNAME);
65911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65921.1Skamil}
65931.1Skamil
65941.1SkamilATF_TC(suspend2);
65951.1SkamilATF_TC_HEAD(suspend2, tc)
65961.1Skamil{
65971.1Skamil	atf_tc_set_md_var(tc, "descr",
65981.1Skamil	    "Verify that the while the only thread within a process is "
65991.1Skamil	    "suspended, the whole process cannot be unstopped");
66001.1Skamil}
66011.1Skamil
66021.1SkamilATF_TC_BODY(suspend2, tc)
66031.1Skamil{
66041.1Skamil	const int exitval = 5;
66051.1Skamil	const int sigval = SIGSTOP;
66061.1Skamil	pid_t child, wpid;
66071.1Skamil#if defined(TWAIT_HAVE_STATUS)
66081.1Skamil	int status;
66091.1Skamil#endif
66101.1Skamil	struct ptrace_siginfo psi;
66111.1Skamil
66121.17Skamil	// Feature pending for refactoring
66131.17Skamil	atf_tc_expect_fail("PR kern/51995");
66141.17Skamil
66151.16Skamil	// Hangs with qemu
66161.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66171.16Skamil
66181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66201.1Skamil	if (child == 0) {
66211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66231.1Skamil
66241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66261.1Skamil
66271.13Schristos		DPRINTF("Before exiting of the child process\n");
66281.1Skamil		_exit(exitval);
66291.1Skamil	}
66301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66311.1Skamil
66321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66341.1Skamil
66351.1Skamil	validate_status_stopped(status, sigval);
66361.1Skamil
66371.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66391.1Skamil
66401.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66421.1Skamil
66431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66441.1Skamil	    "without signal to be sent\n");
66451.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
66461.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
66471.1Skamil
66481.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66501.1Skamil
66511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66521.1Skamil	    "without signal to be sent\n");
66531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66541.1Skamil
66551.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66561.1Skamil	    TWAIT_FNAME);
66571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66581.1Skamil
66591.1Skamil	validate_status_exited(status, exitval);
66601.1Skamil
66611.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66621.1Skamil	    TWAIT_FNAME);
66631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66641.1Skamil}
66651.1Skamil
66661.1SkamilATF_TC(resume1);
66671.1SkamilATF_TC_HEAD(resume1, tc)
66681.1Skamil{
66691.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
66701.1Skamil	atf_tc_set_md_var(tc, "descr",
66711.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
66721.1Skamil	    "resumed by the debugger");
66731.1Skamil}
66741.1Skamil
66751.1SkamilATF_TC_BODY(resume1, tc)
66761.1Skamil{
66771.1Skamil	struct msg_fds fds;
66781.1Skamil	const int exitval = 5;
66791.1Skamil	const int sigval = SIGSTOP;
66801.1Skamil	pid_t child, wpid;
66811.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
66821.1Skamil#if defined(TWAIT_HAVE_STATUS)
66831.1Skamil	int status;
66841.1Skamil#endif
66851.1Skamil	ucontext_t uc;
66861.1Skamil	lwpid_t lid;
66871.1Skamil	static const size_t ssize = 16*1024;
66881.1Skamil	void *stack;
66891.1Skamil	struct ptrace_lwpinfo pl;
66901.1Skamil	struct ptrace_siginfo psi;
66911.1Skamil
66921.17Skamil	// Feature pending for refactoring
66931.17Skamil	atf_tc_expect_fail("PR kern/51995");
66941.17Skamil
66951.15Schristos	// Hangs with qemu
66961.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66971.1Skamil
66981.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
66991.1Skamil
67001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67021.1Skamil	if (child == 0) {
67031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67051.1Skamil
67061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67081.1Skamil
67091.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
67101.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
67111.1Skamil
67121.13Schristos		DPRINTF("Before making context for new lwp in child\n");
67131.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
67141.1Skamil
67151.13Schristos		DPRINTF("Before creating new in child\n");
67161.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
67171.1Skamil
67181.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
67191.1Skamil
67201.1Skamil		raise(SIGINT);
67211.1Skamil
67221.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
67231.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
67241.1Skamil
67251.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
67261.1Skamil		    "are the same\n", lid, the_lwp_id);
67271.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
67281.1Skamil
67291.13Schristos		DPRINTF("Before exiting of the child process\n");
67301.1Skamil		_exit(exitval);
67311.1Skamil	}
67321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67331.1Skamil
67341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67361.1Skamil
67371.1Skamil	validate_status_stopped(status, sigval);
67381.1Skamil
67391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67401.1Skamil	    "without signal to be sent\n");
67411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67421.1Skamil
67431.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67441.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
67451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67461.1Skamil
67471.1Skamil	validate_status_stopped(status, SIGTRAP);
67481.1Skamil
67491.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
67501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
67511.1Skamil
67521.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
67531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
67541.1Skamil
67551.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
67561.1Skamil
67571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67581.1Skamil	    "without signal to be sent\n");
67591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67601.1Skamil
67611.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67621.1Skamil	    "SIGINT\n", TWAIT_FNAME);
67631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67641.1Skamil
67651.1Skamil	validate_status_stopped(status, SIGINT);
67661.1Skamil
67671.1Skamil	pl.pl_lwpid = 0;
67681.1Skamil
67691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67701.1Skamil	while (pl.pl_lwpid != 0) {
67711.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67721.1Skamil		switch (pl.pl_lwpid) {
67731.1Skamil		case 1:
67741.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
67751.1Skamil			break;
67761.1Skamil		case 2:
67771.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
67781.1Skamil			break;
67791.1Skamil		}
67801.1Skamil	}
67811.1Skamil
67821.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
67831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
67841.1Skamil
67851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67861.1Skamil	    "without signal to be sent\n");
67871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67881.1Skamil
67891.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
67901.1Skamil	    TWAIT_FNAME);
67911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67921.1Skamil
67931.1Skamil	validate_status_exited(status, exitval);
67941.1Skamil
67951.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
67961.1Skamil	    TWAIT_FNAME);
67971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67981.1Skamil
67991.1Skamil	msg_close(&fds);
68001.1Skamil
68011.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
68021.1Skamil	sleep(10);
68031.1Skamil}
68041.1Skamil
68051.1SkamilATF_TC(syscall1);
68061.1SkamilATF_TC_HEAD(syscall1, tc)
68071.1Skamil{
68081.1Skamil	atf_tc_set_md_var(tc, "descr",
68091.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
68101.1Skamil}
68111.1Skamil
68121.1SkamilATF_TC_BODY(syscall1, tc)
68131.1Skamil{
68141.1Skamil	const int exitval = 5;
68151.1Skamil	const int sigval = SIGSTOP;
68161.1Skamil	pid_t child, wpid;
68171.1Skamil#if defined(TWAIT_HAVE_STATUS)
68181.1Skamil	int status;
68191.1Skamil#endif
68201.1Skamil	struct ptrace_siginfo info;
68211.1Skamil	memset(&info, 0, sizeof(info));
68221.1Skamil
68231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68251.1Skamil	if (child == 0) {
68261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68281.1Skamil
68291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68311.1Skamil
68321.1Skamil		syscall(SYS_getpid);
68331.1Skamil
68341.13Schristos		DPRINTF("Before exiting of the child process\n");
68351.1Skamil		_exit(exitval);
68361.1Skamil	}
68371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68381.1Skamil
68391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68411.1Skamil
68421.1Skamil	validate_status_stopped(status, sigval);
68431.1Skamil
68441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68451.1Skamil	    "without signal to be sent\n");
68461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68471.1Skamil
68481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68501.1Skamil
68511.1Skamil	validate_status_stopped(status, SIGTRAP);
68521.1Skamil
68531.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68551.1Skamil
68561.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68571.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68581.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68591.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
68601.1Skamil
68611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68621.1Skamil	    "without signal to be sent\n");
68631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68641.1Skamil
68651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68671.1Skamil
68681.1Skamil	validate_status_stopped(status, SIGTRAP);
68691.1Skamil
68701.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68721.1Skamil
68731.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68741.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68751.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
68771.1Skamil
68781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68791.1Skamil	    "without signal to be sent\n");
68801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68811.1Skamil
68821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68841.1Skamil
68851.1Skamil	validate_status_exited(status, exitval);
68861.1Skamil
68871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68891.1Skamil}
68901.1Skamil
68911.1SkamilATF_TC(syscallemu1);
68921.1SkamilATF_TC_HEAD(syscallemu1, tc)
68931.1Skamil{
68941.1Skamil	atf_tc_set_md_var(tc, "descr",
68951.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
68961.1Skamil}
68971.1Skamil
68981.1SkamilATF_TC_BODY(syscallemu1, tc)
68991.1Skamil{
69001.1Skamil	const int exitval = 5;
69011.1Skamil	const int sigval = SIGSTOP;
69021.1Skamil	pid_t child, wpid;
69031.1Skamil#if defined(TWAIT_HAVE_STATUS)
69041.1Skamil	int status;
69051.1Skamil#endif
69061.1Skamil
69071.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
69081.6Skamil	/* syscallemu does not work on sparc (32-bit) */
69091.6Skamil	atf_tc_expect_fail("PR kern/52166");
69101.6Skamil#endif
69111.6Skamil
69121.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
69131.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
69141.1Skamil	if (child == 0) {
69151.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
69161.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
69171.1Skamil
69181.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
69191.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
69201.1Skamil
69211.1Skamil		syscall(SYS_exit, 100);
69221.1Skamil
69231.13Schristos		DPRINTF("Before exiting of the child process\n");
69241.1Skamil		_exit(exitval);
69251.1Skamil	}
69261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
69271.1Skamil
69281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69301.1Skamil
69311.1Skamil	validate_status_stopped(status, sigval);
69321.1Skamil
69331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69341.1Skamil	    "without signal to be sent\n");
69351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69361.1Skamil
69371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69391.1Skamil
69401.1Skamil	validate_status_stopped(status, SIGTRAP);
69411.1Skamil
69421.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
69431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
69441.1Skamil
69451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69461.1Skamil	    "without signal to be sent\n");
69471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69481.1Skamil
69491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69511.1Skamil
69521.1Skamil	validate_status_stopped(status, SIGTRAP);
69531.1Skamil
69541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69551.1Skamil	    "without signal to be sent\n");
69561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69571.1Skamil
69581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69601.1Skamil
69611.1Skamil	validate_status_exited(status, exitval);
69621.1Skamil
69631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69651.1Skamil}
69661.1Skamil
69671.26Skamil#if defined(TWAIT_HAVE_PID)
69681.26SkamilATF_TC(race1);
69691.26SkamilATF_TC_HEAD(race1, tc)
69701.26Skamil{
69711.26Skamil	atf_tc_set_md_var(tc, "descr",
69721.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
69731.26Skamil	    "process and no other error is reported");
69741.26Skamil}
69751.26Skamil
69761.26SkamilATF_TC_BODY(race1, tc)
69771.26Skamil{
69781.26Skamil	time_t start, end;
69791.26Skamil	double diff;
69801.26Skamil	unsigned long N = 0;
69811.26Skamil
69821.26Skamil	/* Reuse this test with attach1 */
69831.26Skamil
69841.26Skamil	start = time(NULL);
69851.26Skamil	while (true) {
69861.26Skamil		DPRINTF("Step: %lu\n", N);
69871.26Skamil		attach1_raw(true);
69881.26Skamil		end = time(NULL);
69891.26Skamil		diff = difftime(end, start);
69901.26Skamil		if (diff >= 5.0)
69911.26Skamil			break;
69921.26Skamil		++N;
69931.26Skamil	}
69941.26Skamil	DPRINTF("Iterations: %lu\n", N);
69951.26Skamil}
69961.26Skamil#endif
69971.26Skamil
69981.1Skamil#include "t_ptrace_amd64_wait.h"
69991.1Skamil#include "t_ptrace_i386_wait.h"
70001.1Skamil#include "t_ptrace_x86_wait.h"
70011.1Skamil
70021.1SkamilATF_TP_ADD_TCS(tp)
70031.1Skamil{
70041.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
70051.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
70061.33Skamil
70071.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
70081.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
70091.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
70101.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
70111.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
70121.33Skamil
70131.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch1);
70141.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch2);
70151.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch3);
70161.34Skamil
70171.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler1);
70181.35Skamil//	ATF_TP_ADD_TC(tp, traceme_signal_nohandler2); // not yet
70191.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler3);
70201.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler4);
70211.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler5);
70221.1Skamil
70231.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
70241.37Skamil
70251.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
70261.40Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_raise2); // not yet
70271.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
70281.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
70291.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
70301.40Skamil
70311.41Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_breakpoint);
70321.41Skamil
70331.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
70341.43Skamil
70351.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
70361.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
70371.1Skamil	ATF_TP_ADD_TC(tp, attach3);
70381.1Skamil	ATF_TP_ADD_TC(tp, attach4);
70391.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
70401.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
70411.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
70421.1Skamil
70431.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
70441.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
70451.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
70461.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
70471.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
70481.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
70491.1Skamil
70501.31Skamil	ATF_TP_ADD_TC(tp, fork1);
70511.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
70521.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
70531.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
70541.31Skamil	ATF_TP_ADD_TC(tp, fork5);
70551.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
70561.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
70571.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
70581.31Skamil
70591.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
70601.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
70611.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
70621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
70631.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
70641.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
70651.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
70661.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
70671.1Skamil
70681.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
70691.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
70701.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
70711.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
70721.1Skamil
70731.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
70741.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
70751.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
70761.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
70771.1Skamil
70781.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
70791.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
70801.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
70811.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
70821.1Skamil
70831.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
70841.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
70851.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
70861.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
70871.1Skamil
70881.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
70891.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
70901.1Skamil
70911.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
70921.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
70931.1Skamil
70941.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
70951.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
70961.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
70971.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
70981.1Skamil
70991.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
71001.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
71011.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
71021.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
71031.1Skamil
71041.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
71051.1Skamil
71061.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
71071.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
71081.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
71091.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
71101.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
71111.1Skamil
71121.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
71131.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
71141.1Skamil
71151.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
71161.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
71171.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
71181.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
71191.1Skamil
71201.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
71211.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
71221.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
71231.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
71241.2Skamil
71251.1Skamil	ATF_TP_ADD_TC(tp, kill1);
71261.1Skamil	ATF_TP_ADD_TC(tp, kill2);
71271.1Skamil
71281.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
71291.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
71301.1Skamil
71311.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
71321.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
71331.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
71341.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
71351.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
71361.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
71371.1Skamil
71381.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
71391.1Skamil
71401.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
71411.1Skamil
71421.1Skamil	ATF_TP_ADD_TC(tp, signal1);
71431.1Skamil	ATF_TP_ADD_TC(tp, signal2);
71441.1Skamil	ATF_TP_ADD_TC(tp, signal3);
71451.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
71461.1Skamil	ATF_TP_ADD_TC(tp, signal5);
71471.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
71481.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
71491.1Skamil	ATF_TP_ADD_TC(tp, signal8);
71501.1Skamil	ATF_TP_ADD_TC(tp, signal9);
71511.1Skamil	ATF_TP_ADD_TC(tp, signal10);
71521.1Skamil
71531.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
71541.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
71551.1Skamil
71561.1Skamil	ATF_TP_ADD_TC(tp, resume1);
71571.1Skamil
71581.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
71591.1Skamil
71601.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
71611.1Skamil
71621.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
71631.26Skamil
71641.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
71651.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
71661.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
71671.1Skamil
71681.1Skamil	return atf_no_error();
71691.1Skamil}
7170