t_ptrace_wait.c revision 1.45
11.45Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.45 2018/05/16 03:52:35 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.45Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.45 2018/05/16 03:52:35 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.45Skamil	struct ptrace_siginfo info;
971.45Skamil	memset(&info, 0, sizeof(info));
981.45Skamil
991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1011.1Skamil	if (child == 0) {
1021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1041.1Skamil
1051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1071.1Skamil
1081.36Skamil		switch (sigval) {
1091.36Skamil		case SIGKILL:
1101.36Skamil			/* NOTREACHED */
1111.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1121.36Skamil		default:
1131.36Skamil			DPRINTF("Before exiting of the child process\n");
1141.36Skamil			_exit(exitval);
1151.36Skamil		}
1161.1Skamil	}
1171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1181.1Skamil
1191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1211.1Skamil
1221.36Skamil	switch (sigval) {
1231.36Skamil	case SIGKILL:
1241.36Skamil		validate_status_signaled(status, sigval, 0);
1251.36Skamil		break;
1261.36Skamil	default:
1271.36Skamil		validate_status_stopped(status, sigval);
1281.1Skamil
1291.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1301.45Skamil		        "child\n");
1311.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1321.45Skamil		                       sizeof(info)) != -1);
1331.45Skamil
1341.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1351.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1361.45Skamil		        "si_errno=%#x\n",
1371.45Skamil		        info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1381.45Skamil		        info.psi_siginfo.si_errno);
1391.45Skamil
1401.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1411.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1421.45Skamil
1431.36Skamil		DPRINTF("Before resuming the child process where it left off "
1441.36Skamil		    "and without signal to be sent\n");
1451.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1461.1Skamil
1471.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1481.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1491.36Skamil		                      child);
1501.36Skamil		break;
1511.36Skamil	}
1521.1Skamil
1531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1551.1Skamil}
1561.1Skamil
1571.33Skamil#define TRACEME_RAISE(test, sig)						\
1581.33SkamilATF_TC(test);									\
1591.33SkamilATF_TC_HEAD(test, tc)								\
1601.33Skamil{										\
1611.33Skamil	atf_tc_set_md_var(tc, "descr",						\
1621.33Skamil	    "Verify " #sig " followed by _exit(2) in a child");			\
1631.33Skamil}										\
1641.33Skamil										\
1651.33SkamilATF_TC_BODY(test, tc)								\
1661.33Skamil{										\
1671.33Skamil										\
1681.33Skamil	traceme_raise(sig);							\
1691.33Skamil}
1701.33Skamil
1711.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1721.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1731.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1741.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1751.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1761.33Skamil
1771.34Skamil/// ----------------------------------------------------------------------------
1781.1Skamil
1791.1Skamilstatic void
1801.34Skamiltraceme_sighandler_catch(int sigsent, void (*sah)(int arg), int *traceme_caught)
1811.1Skamil{
1821.1Skamil	const int exitval = 5;
1831.34Skamil	const int sigval = SIGSTOP;
1841.1Skamil	pid_t child, wpid;
1851.1Skamil	struct sigaction sa;
1861.1Skamil#if defined(TWAIT_HAVE_STATUS)
1871.1Skamil	int status;
1881.1Skamil#endif
1891.1Skamil
1901.45Skamil	struct ptrace_siginfo info;
1911.45Skamil	memset(&info, 0, sizeof(info));
1921.45Skamil
1931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1951.1Skamil	if (child == 0) {
1961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1981.1Skamil
1991.34Skamil		sa.sa_handler = sah;
2001.1Skamil		sa.sa_flags = SA_SIGINFO;
2011.1Skamil		sigemptyset(&sa.sa_mask);
2021.1Skamil
2031.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
2041.1Skamil
2051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2071.1Skamil
2081.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
2091.1Skamil
2101.13Schristos		DPRINTF("Before exiting of the child process\n");
2111.1Skamil		_exit(exitval);
2121.1Skamil	}
2131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2141.1Skamil
2151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2171.1Skamil
2181.1Skamil	validate_status_stopped(status, sigval);
2191.1Skamil
2201.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2211.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
2221.45Skamil	                != -1);
2231.45Skamil
2241.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2251.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2261.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2271.45Skamil	    info.psi_siginfo.si_errno);
2281.45Skamil
2291.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2301.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2311.45Skamil
2321.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2331.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2351.1Skamil
2361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2381.1Skamil
2391.1Skamil	validate_status_exited(status, exitval);
2401.1Skamil
2411.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2431.1Skamil}
2441.1Skamil
2451.34Skamil#define TRACEME_SIGHANDLER_CATCH(test, sig)					\
2461.34SkamilATF_TC(test);									\
2471.34SkamilATF_TC_HEAD(test, tc)								\
2481.34Skamil{										\
2491.34Skamil	atf_tc_set_md_var(tc, "descr",						\
2501.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
2511.34Skamil	    "handled correctly and caught by a signal handler");		\
2521.34Skamil}										\
2531.34Skamil										\
2541.34Skamilstatic int test##_caught = 0;							\
2551.34Skamil										\
2561.34Skamilstatic void									\
2571.34Skamiltest##_sighandler(int arg)							\
2581.34Skamil{										\
2591.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
2601.34Skamil										\
2611.34Skamil	++ test##_caught;							\
2621.34Skamil}										\
2631.34Skamil										\
2641.34SkamilATF_TC_BODY(test, tc)								\
2651.34Skamil{										\
2661.34Skamil										\
2671.34Skamil	traceme_sighandler_catch(sig, test##_sighandler, & test##_caught);	\
2681.34Skamil}
2691.34Skamil
2701.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
2711.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch1, SIGABRT) /* abort trap */
2721.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch2, SIGHUP)  /* hangup */
2731.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch3, SIGCONT) /* continued? */
2741.34Skamil
2751.34Skamil/// ----------------------------------------------------------------------------
2761.34Skamil
2771.35Skamilstatic void
2781.35Skamiltraceme_signal_nohandler(int sigsent)
2791.1Skamil{
2801.35Skamil	const int sigval = SIGSTOP;
2811.35Skamil	int exitval = 0;
2821.1Skamil	pid_t child, wpid;
2831.1Skamil#if defined(TWAIT_HAVE_STATUS)
2841.1Skamil	int status;
2851.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
2861.1Skamil#endif
2871.1Skamil
2881.45Skamil	struct ptrace_siginfo info;
2891.45Skamil	memset(&info, 0, sizeof(info));
2901.45Skamil
2911.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2921.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2931.1Skamil	if (child == 0) {
2941.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2951.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2961.1Skamil
2971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2991.1Skamil
3001.35Skamil		switch (sigsent) {
3011.35Skamil		case SIGCONT:
3021.35Skamil			_exit(exitval);
3031.35Skamil		default:
3041.35Skamil			/* NOTREACHED */
3051.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
3061.35Skamil		}
3071.1Skamil	}
3081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3091.1Skamil
3101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3121.1Skamil
3131.1Skamil	validate_status_stopped(status, sigval);
3141.1Skamil
3151.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3161.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
3171.45Skamil	                != -1);
3181.45Skamil
3191.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3201.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3211.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3221.45Skamil	    info.psi_siginfo.si_errno);
3231.45Skamil
3241.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3251.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3261.45Skamil
3271.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3281.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3301.1Skamil
3311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3331.1Skamil
3341.35Skamil	switch (sigsent) {
3351.35Skamil	case SIGCONT:
3361.35Skamil		validate_status_exited(status, exitval);
3371.35Skamil		break;
3381.35Skamil	default:
3391.35Skamil		validate_status_signaled(status, sigsent, expect_core);
3401.35Skamil		break;
3411.35Skamil	}
3421.1Skamil
3431.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3451.1Skamil}
3461.1Skamil
3471.35Skamil#define TRACEME_SIGNAL_NOHANDLER(test, sig)					\
3481.35SkamilATF_TC(test);									\
3491.35SkamilATF_TC_HEAD(test, tc)								\
3501.35Skamil{										\
3511.35Skamil	atf_tc_set_md_var(tc, "descr",						\
3521.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3531.35Skamil	    "handled correctly in a child without a signal handler");		\
3541.35Skamil}										\
3551.35Skamil										\
3561.35SkamilATF_TC_BODY(test, tc)								\
3571.35Skamil{										\
3581.35Skamil										\
3591.35Skamil	traceme_signal_nohandler(sig);						\
3601.35Skamil}
3611.35Skamil
3621.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler1, SIGKILL) /* non-maskable */
3631.35Skamil//TRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler2, SIGSTOP) /* non-maskable */
3641.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler3, SIGABRT) /* abort trap */
3651.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler4, SIGHUP)  /* hangup */
3661.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler5, SIGCONT) /* continued? */
3671.35Skamil
3681.35Skamil/// ----------------------------------------------------------------------------
3691.35Skamil
3701.37SkamilATF_TC(traceme_pid1_parent);
3711.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
3721.37Skamil{
3731.37Skamil	atf_tc_set_md_var(tc, "descr",
3741.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
3751.37Skamil}
3761.37Skamil
3771.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
3781.37Skamil{
3791.37Skamil	struct msg_fds parent_child;
3801.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
3811.37Skamil	pid_t child1, child2, wpid;
3821.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3831.37Skamil#if defined(TWAIT_HAVE_STATUS)
3841.37Skamil	int status;
3851.37Skamil#endif
3861.37Skamil
3871.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
3881.37Skamil
3891.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3901.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
3911.37Skamil	if (child1 == 0) {
3921.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
3931.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
3941.37Skamil		if (child2 != 0) {
3951.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
3961.37Skamil			        getpid(), child2);
3971.37Skamil			_exit(exitval_child1);
3981.37Skamil		}
3991.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
4001.37Skamil
4011.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
4021.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
4031.37Skamil
4041.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4051.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
4061.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
4071.37Skamil
4081.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
4091.37Skamil
4101.37Skamil		_exit(exitval_child2);
4111.37Skamil	}
4121.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
4131.37Skamil
4141.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4151.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
4161.37Skamil	                      child1);
4171.37Skamil
4181.37Skamil	validate_status_exited(status, exitval_child1);
4191.37Skamil
4201.37Skamil	DPRINTF("Notify that child1 is dead\n");
4211.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
4221.37Skamil
4231.37Skamil	DPRINTF("Wait for exiting of child2\n");
4241.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
4251.37Skamil}
4261.37Skamil
4271.37Skamil/// ----------------------------------------------------------------------------
4281.37Skamil
4291.40Skamilstatic void
4301.40Skamiltraceme_vfork_raise(int sigval)
4311.40Skamil{
4321.40Skamil	const int exitval = 5;
4331.40Skamil	pid_t child, wpid;
4341.40Skamil#if defined(TWAIT_HAVE_STATUS)
4351.40Skamil	int status;
4361.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
4371.40Skamil#endif
4381.40Skamil
4391.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4401.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
4411.40Skamil	if (child == 0) {
4421.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4431.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4441.40Skamil
4451.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4461.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4471.40Skamil
4481.40Skamil		switch (sigval) {
4491.40Skamil		case SIGKILL:
4501.40Skamil		case SIGABRT:
4511.40Skamil		case SIGHUP:
4521.40Skamil			/* NOTREACHED */
4531.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4541.40Skamil		default:
4551.40Skamil			DPRINTF("Before exiting of the child process\n");
4561.40Skamil			_exit(exitval);
4571.40Skamil		}
4581.40Skamil	}
4591.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4601.40Skamil
4611.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4621.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4631.40Skamil
4641.40Skamil	switch (sigval) {
4651.40Skamil	case SIGKILL:
4661.40Skamil	case SIGABRT:
4671.40Skamil	case SIGHUP:
4681.40Skamil		validate_status_signaled(status, sigval, expect_core);
4691.40Skamil		break;
4701.40Skamil	case SIGSTOP:
4711.40Skamil	case SIGCONT:
4721.40Skamil		validate_status_exited(status, exitval);
4731.40Skamil		break;
4741.40Skamil	default:
4751.40Skamil		/* NOTREACHED */
4761.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
4771.40Skamil		break;
4781.40Skamil	}
4791.40Skamil
4801.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4811.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4821.40Skamil}
4831.40Skamil
4841.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
4851.40SkamilATF_TC(test);									\
4861.40SkamilATF_TC_HEAD(test, tc)								\
4871.40Skamil{										\
4881.40Skamil	atf_tc_set_md_var(tc, "descr",						\
4891.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
4901.42Skamil	    "child");								\
4911.40Skamil}										\
4921.40Skamil										\
4931.40SkamilATF_TC_BODY(test, tc)								\
4941.40Skamil{										\
4951.40Skamil										\
4961.40Skamil	traceme_vfork_raise(sig);						\
4971.40Skamil}
4981.40Skamil
4991.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
5001.40Skamil// TRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ // TODO
5011.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGABRT) /* regular abort trap */
5021.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGHUP)  /* hangup */
5031.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGCONT) /* continued? */
5041.40Skamil
5051.40Skamil/// ----------------------------------------------------------------------------
5061.40Skamil
5071.41SkamilATF_TC(traceme_vfork_breakpoint);
5081.41SkamilATF_TC_HEAD(traceme_vfork_breakpoint, tc)
5091.41Skamil{
5101.41Skamil	atf_tc_set_md_var(tc, "descr",
5111.44Skamil	    "Verify PT_TRACE_ME followed by a software breakpoint in a "
5121.44Skamil	    "vfork(2)ed child");
5131.41Skamil}
5141.41Skamil
5151.41SkamilATF_TC_BODY(traceme_vfork_breakpoint, tc)
5161.41Skamil{
5171.41Skamil	pid_t child, wpid;
5181.41Skamil#if defined(TWAIT_HAVE_STATUS)
5191.41Skamil	int status;
5201.41Skamil#endif
5211.41Skamil
5221.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5231.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
5241.41Skamil	if (child == 0) {
5251.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5261.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5271.41Skamil
5281.41Skamil		DPRINTF("Before executing a software breakpoint\n");
5291.41Skamil#ifdef PTRACE_BREAKPOINT_ASM
5301.41Skamil		PTRACE_BREAKPOINT_ASM;
5311.41Skamil#else
5321.41Skamil		/* port me */
5331.41Skamil#endif
5341.41Skamil
5351.41Skamil		/* NOTREACHED */
5361.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
5371.41Skamil	}
5381.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5391.41Skamil
5401.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5411.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5421.41Skamil
5431.41Skamil	validate_status_signaled(status, SIGTRAP, 1);
5441.41Skamil
5451.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5461.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5471.41Skamil}
5481.41Skamil
5491.41Skamil/// ----------------------------------------------------------------------------
5501.41Skamil
5511.43SkamilATF_TC(traceme_vfork_exec);
5521.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
5531.43Skamil{
5541.43Skamil	atf_tc_set_md_var(tc, "descr",
5551.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
5561.43Skamil}
5571.43Skamil
5581.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
5591.43Skamil{
5601.43Skamil	const int sigval = SIGTRAP;
5611.43Skamil	pid_t child, wpid;
5621.43Skamil#if defined(TWAIT_HAVE_STATUS)
5631.43Skamil	int status;
5641.43Skamil#endif
5651.43Skamil
5661.43Skamil	struct ptrace_siginfo info;
5671.43Skamil	memset(&info, 0, sizeof(info));
5681.43Skamil
5691.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5701.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
5711.43Skamil	if (child == 0) {
5721.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5731.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5741.43Skamil
5751.43Skamil		DPRINTF("Before calling execve(2) from child\n");
5761.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
5771.43Skamil
5781.43Skamil		/* NOTREACHED */
5791.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
5801.43Skamil	}
5811.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5821.43Skamil
5831.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5841.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5851.43Skamil
5861.43Skamil	validate_status_stopped(status, sigval);
5871.43Skamil
5881.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5891.43Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5901.43Skamil
5911.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5921.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5931.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5941.43Skamil	    info.psi_siginfo.si_errno);
5951.43Skamil
5961.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5971.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
5981.43Skamil
5991.43Skamil	DPRINTF("Before resuming the child process where it left off and "
6001.43Skamil	    "without signal to be sent\n");
6011.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6021.43Skamil
6031.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6041.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6051.43Skamil
6061.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6071.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6081.43Skamil}
6091.43Skamil
6101.43Skamil/// ----------------------------------------------------------------------------
6111.43Skamil
6121.1Skamil#if defined(TWAIT_HAVE_PID)
6131.1SkamilATF_TC(attach1);
6141.1SkamilATF_TC_HEAD(attach1, tc)
6151.1Skamil{
6161.1Skamil	atf_tc_set_md_var(tc, "descr",
6171.1Skamil	    "Assert that tracer sees process termination before the parent");
6181.1Skamil}
6191.1Skamil
6201.26Skamilstatic void
6211.26Skamilattach1_raw(bool raw)
6221.1Skamil{
6231.1Skamil	struct msg_fds parent_tracee, parent_tracer;
6241.1Skamil	const int exitval_tracee = 5;
6251.1Skamil	const int exitval_tracer = 10;
6261.1Skamil	pid_t tracee, tracer, wpid;
6271.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6281.1Skamil#if defined(TWAIT_HAVE_STATUS)
6291.1Skamil	int status;
6301.1Skamil#endif
6311.1Skamil
6321.13Schristos	DPRINTF("Spawn tracee\n");
6331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6341.1Skamil	tracee = atf_utils_fork();
6351.1Skamil	if (tracee == 0) {
6361.1Skamil		// Wait for parent to let us exit
6371.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
6381.1Skamil		_exit(exitval_tracee);
6391.1Skamil	}
6401.1Skamil
6411.13Schristos	DPRINTF("Spawn debugger\n");
6421.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
6431.1Skamil	tracer = atf_utils_fork();
6441.1Skamil	if (tracer == 0) {
6451.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
6461.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
6471.1Skamil
6481.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6491.1Skamil		FORKEE_REQUIRE_SUCCESS(
6501.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6511.1Skamil
6521.1Skamil		forkee_status_stopped(status, SIGSTOP);
6531.1Skamil
6541.1Skamil		/* Resume tracee with PT_CONTINUE */
6551.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6561.1Skamil
6571.1Skamil		/* Inform parent that tracer has attached to tracee */
6581.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
6591.1Skamil
6601.1Skamil		/* Wait for parent to tell use that tracee should have exited */
6611.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
6621.1Skamil
6631.1Skamil		/* Wait for tracee and assert that it exited */
6641.1Skamil		FORKEE_REQUIRE_SUCCESS(
6651.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6661.1Skamil
6671.1Skamil		forkee_status_exited(status, exitval_tracee);
6681.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
6691.1Skamil
6701.13Schristos		DPRINTF("Before exiting of the tracer process\n");
6711.1Skamil		_exit(exitval_tracer);
6721.1Skamil	}
6731.1Skamil
6741.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
6751.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
6761.1Skamil
6771.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
6781.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
6791.1Skamil
6801.13Schristos	DPRINTF("Detect that tracee is zombie\n");
6811.26Skamil	if (raw)
6821.26Skamil		await_zombie_raw(tracee, 0);
6831.26Skamil	else
6841.26Skamil		await_zombie(tracee);
6851.1Skamil
6861.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
6871.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
6881.1Skamil	    TWAIT_FNAME);
6891.1Skamil	TWAIT_REQUIRE_SUCCESS(
6901.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
6911.1Skamil
6921.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
6931.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
6941.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
6951.1Skamil	    TWAIT_FNAME);
6961.1Skamil
6971.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
6981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
6991.1Skamil	    tracer);
7001.1Skamil
7011.1Skamil	validate_status_exited(status, exitval_tracer);
7021.1Skamil
7031.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7041.1Skamil	    TWAIT_FNAME);
7051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
7061.1Skamil	    tracee);
7071.1Skamil
7081.1Skamil	validate_status_exited(status, exitval_tracee);
7091.1Skamil
7101.1Skamil	msg_close(&parent_tracer);
7111.1Skamil	msg_close(&parent_tracee);
7121.1Skamil}
7131.26Skamil
7141.26SkamilATF_TC_BODY(attach1, tc)
7151.26Skamil{
7161.26Skamil
7171.26Skamil	/* Reuse this test with race1 */
7181.26Skamil	attach1_raw(false);
7191.26Skamil}
7201.26Skamil
7211.1Skamil#endif
7221.1Skamil
7231.1Skamil#if defined(TWAIT_HAVE_PID)
7241.1SkamilATF_TC(attach2);
7251.1SkamilATF_TC_HEAD(attach2, tc)
7261.1Skamil{
7271.1Skamil	atf_tc_set_md_var(tc, "descr",
7281.1Skamil	    "Assert that any tracer sees process termination before its "
7291.1Skamil	    "parent");
7301.1Skamil}
7311.1Skamil
7321.1SkamilATF_TC_BODY(attach2, tc)
7331.1Skamil{
7341.1Skamil	struct msg_fds parent_tracer, parent_tracee;
7351.1Skamil	const int exitval_tracee = 5;
7361.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
7371.1Skamil	pid_t tracee, tracer, wpid;
7381.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7391.1Skamil#if defined(TWAIT_HAVE_STATUS)
7401.1Skamil	int status;
7411.1Skamil#endif
7421.1Skamil
7431.13Schristos	DPRINTF("Spawn tracee\n");
7441.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7451.1Skamil	tracee = atf_utils_fork();
7461.1Skamil	if (tracee == 0) {
7471.1Skamil		/* Wait for message from the parent */
7481.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7491.1Skamil		_exit(exitval_tracee);
7501.1Skamil	}
7511.1Skamil
7521.13Schristos	DPRINTF("Spawn debugger\n");
7531.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
7541.1Skamil	tracer = atf_utils_fork();
7551.1Skamil	if (tracer == 0) {
7561.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
7571.1Skamil		tracer = atf_utils_fork();
7581.1Skamil		if (tracer != 0)
7591.1Skamil			_exit(exitval_tracer1);
7601.1Skamil
7611.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
7621.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
7631.1Skamil
7641.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
7651.1Skamil		FORKEE_REQUIRE_SUCCESS(
7661.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7671.1Skamil
7681.1Skamil		forkee_status_stopped(status, SIGSTOP);
7691.1Skamil
7701.1Skamil		/* Resume tracee with PT_CONTINUE */
7711.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
7721.1Skamil
7731.1Skamil		/* Inform parent that tracer has attached to tracee */
7741.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
7751.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
7761.1Skamil
7771.1Skamil		/* Wait for tracee and assert that it exited */
7781.1Skamil		FORKEE_REQUIRE_SUCCESS(
7791.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7801.1Skamil
7811.1Skamil		forkee_status_exited(status, exitval_tracee);
7821.1Skamil
7831.13Schristos		DPRINTF("Before exiting of the tracer process\n");
7841.1Skamil		_exit(exitval_tracer2);
7851.1Skamil	}
7861.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
7871.1Skamil	    "%s()\n", TWAIT_FNAME);
7881.1Skamil	TWAIT_REQUIRE_SUCCESS(
7891.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
7901.1Skamil
7911.1Skamil	validate_status_exited(status, exitval_tracer1);
7921.1Skamil
7931.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
7941.1Skamil	    TWAIT_FNAME);
7951.1Skamil	TWAIT_REQUIRE_SUCCESS(
7961.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
7971.1Skamil
7981.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
7991.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
8001.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
8011.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8021.1Skamil
8031.13Schristos	DPRINTF("Detect that tracee is zombie\n");
8041.1Skamil	await_zombie(tracee);
8051.1Skamil
8061.13Schristos	DPRINTF("Assert that there is no status about tracee - "
8071.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
8081.1Skamil	TWAIT_REQUIRE_SUCCESS(
8091.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
8101.1Skamil
8111.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
8121.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
8131.1Skamil
8141.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
8151.1Skamil	    TWAIT_FNAME);
8161.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
8171.1Skamil	    tracee);
8181.1Skamil
8191.1Skamil	validate_status_exited(status, exitval_tracee);
8201.1Skamil
8211.1Skamil	msg_close(&parent_tracer);
8221.1Skamil	msg_close(&parent_tracee);
8231.1Skamil}
8241.1Skamil#endif
8251.1Skamil
8261.1SkamilATF_TC(attach3);
8271.1SkamilATF_TC_HEAD(attach3, tc)
8281.1Skamil{
8291.1Skamil	atf_tc_set_md_var(tc, "descr",
8301.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
8311.1Skamil}
8321.1Skamil
8331.1SkamilATF_TC_BODY(attach3, tc)
8341.1Skamil{
8351.1Skamil	struct msg_fds parent_tracee;
8361.1Skamil	const int exitval_tracee = 5;
8371.1Skamil	pid_t tracee, wpid;
8381.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8391.1Skamil#if defined(TWAIT_HAVE_STATUS)
8401.1Skamil	int status;
8411.1Skamil#endif
8421.1Skamil
8431.13Schristos	DPRINTF("Spawn tracee\n");
8441.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
8451.1Skamil	tracee = atf_utils_fork();
8461.1Skamil	if (tracee == 0) {
8471.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8481.13Schristos		DPRINTF("Parent should now attach to tracee\n");
8491.1Skamil
8501.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
8511.1Skamil		/* Wait for message from the parent */
8521.1Skamil		_exit(exitval_tracee);
8531.1Skamil	}
8541.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8551.1Skamil
8561.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
8571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8581.1Skamil
8591.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
8601.1Skamil	    TWAIT_FNAME);
8611.1Skamil	TWAIT_REQUIRE_SUCCESS(
8621.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8631.1Skamil
8641.1Skamil	validate_status_stopped(status, SIGSTOP);
8651.1Skamil
8661.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
8671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8681.1Skamil
8691.13Schristos	DPRINTF("Let the tracee exit now\n");
8701.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
8711.1Skamil
8721.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
8731.1Skamil	TWAIT_REQUIRE_SUCCESS(
8741.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8751.1Skamil
8761.1Skamil	validate_status_exited(status, exitval_tracee);
8771.1Skamil
8781.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
8791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8801.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
8811.1Skamil
8821.1Skamil	msg_close(&parent_tracee);
8831.1Skamil}
8841.1Skamil
8851.1SkamilATF_TC(attach4);
8861.1SkamilATF_TC_HEAD(attach4, tc)
8871.1Skamil{
8881.1Skamil	atf_tc_set_md_var(tc, "descr",
8891.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
8901.1Skamil}
8911.1Skamil
8921.1SkamilATF_TC_BODY(attach4, tc)
8931.1Skamil{
8941.1Skamil	struct msg_fds parent_tracee;
8951.1Skamil	const int exitval_tracer = 5;
8961.1Skamil	pid_t tracer, wpid;
8971.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8981.1Skamil#if defined(TWAIT_HAVE_STATUS)
8991.1Skamil	int status;
9001.1Skamil#endif
9011.1Skamil
9021.13Schristos	DPRINTF("Spawn tracer\n");
9031.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9041.1Skamil	tracer = atf_utils_fork();
9051.1Skamil	if (tracer == 0) {
9061.1Skamil
9071.1Skamil		/* Wait for message from the parent */
9081.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
9091.1Skamil
9101.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
9111.1Skamil		    getppid());
9121.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
9131.1Skamil
9141.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
9151.1Skamil		    TWAIT_FNAME);
9161.1Skamil		FORKEE_REQUIRE_SUCCESS(
9171.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
9181.1Skamil
9191.1Skamil		forkee_status_stopped(status, SIGSTOP);
9201.1Skamil
9211.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
9221.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
9231.1Skamil		    != -1);
9241.1Skamil
9251.1Skamil		/* Tell parent we are ready */
9261.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
9271.1Skamil
9281.1Skamil		_exit(exitval_tracer);
9291.1Skamil	}
9301.1Skamil
9311.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
9321.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
9331.13Schristos	DPRINTF("Allow the tracer to exit now\n");
9341.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
9351.1Skamil
9361.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
9371.1Skamil	TWAIT_REQUIRE_SUCCESS(
9381.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
9391.1Skamil
9401.1Skamil	validate_status_exited(status, exitval_tracer);
9411.1Skamil
9421.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
9431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
9441.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
9451.1Skamil
9461.1Skamil	msg_close(&parent_tracee);
9471.1Skamil}
9481.1Skamil
9491.1Skamil#if defined(TWAIT_HAVE_PID)
9501.1SkamilATF_TC(attach5);
9511.1SkamilATF_TC_HEAD(attach5, tc)
9521.1Skamil{
9531.1Skamil	atf_tc_set_md_var(tc, "descr",
9541.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
9551.1Skamil	    "(check getppid(2))");
9561.1Skamil}
9571.1Skamil
9581.1SkamilATF_TC_BODY(attach5, tc)
9591.1Skamil{
9601.1Skamil	struct msg_fds parent_tracer, parent_tracee;
9611.1Skamil	const int exitval_tracee = 5;
9621.1Skamil	const int exitval_tracer = 10;
9631.1Skamil	pid_t parent, tracee, tracer, wpid;
9641.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9651.1Skamil#if defined(TWAIT_HAVE_STATUS)
9661.1Skamil	int status;
9671.1Skamil#endif
9681.1Skamil
9691.13Schristos	DPRINTF("Spawn tracee\n");
9701.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9711.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9721.1Skamil	tracee = atf_utils_fork();
9731.1Skamil	if (tracee == 0) {
9741.1Skamil		parent = getppid();
9751.1Skamil
9761.1Skamil		/* Emit message to the parent */
9771.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
9781.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
9791.1Skamil
9801.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
9811.1Skamil
9821.1Skamil		_exit(exitval_tracee);
9831.1Skamil	}
9841.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9851.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
9861.1Skamil
9871.13Schristos	DPRINTF("Spawn debugger\n");
9881.1Skamil	tracer = atf_utils_fork();
9891.1Skamil	if (tracer == 0) {
9901.1Skamil		/* No IPC to communicate with the child */
9911.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
9921.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
9931.1Skamil
9941.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
9951.1Skamil		FORKEE_REQUIRE_SUCCESS(
9961.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9971.1Skamil
9981.1Skamil		forkee_status_stopped(status, SIGSTOP);
9991.1Skamil
10001.1Skamil		/* Resume tracee with PT_CONTINUE */
10011.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10021.1Skamil
10031.1Skamil		/* Inform parent that tracer has attached to tracee */
10041.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10051.1Skamil
10061.1Skamil		/* Wait for parent to tell use that tracee should have exited */
10071.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10081.1Skamil
10091.1Skamil		/* Wait for tracee and assert that it exited */
10101.1Skamil		FORKEE_REQUIRE_SUCCESS(
10111.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10121.1Skamil
10131.1Skamil		forkee_status_exited(status, exitval_tracee);
10141.1Skamil
10151.13Schristos		DPRINTF("Before exiting of the tracer process\n");
10161.1Skamil		_exit(exitval_tracer);
10171.1Skamil	}
10181.1Skamil
10191.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
10201.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
10211.1Skamil
10221.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
10231.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
10241.1Skamil
10251.13Schristos	DPRINTF("Detect that tracee is zombie\n");
10261.1Skamil	await_zombie(tracee);
10271.1Skamil
10281.13Schristos	DPRINTF("Assert that there is no status about tracee - "
10291.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
10301.1Skamil	TWAIT_REQUIRE_SUCCESS(
10311.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
10321.1Skamil
10331.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
10341.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
10351.1Skamil
10361.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
10371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
10381.1Skamil	    tracer);
10391.1Skamil
10401.1Skamil	validate_status_exited(status, exitval_tracer);
10411.1Skamil
10421.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
10431.1Skamil	    TWAIT_FNAME);
10441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
10451.1Skamil	    tracee);
10461.1Skamil
10471.1Skamil	validate_status_exited(status, exitval_tracee);
10481.1Skamil
10491.1Skamil	msg_close(&parent_tracer);
10501.1Skamil	msg_close(&parent_tracee);
10511.1Skamil}
10521.1Skamil#endif
10531.1Skamil
10541.1Skamil#if defined(TWAIT_HAVE_PID)
10551.1SkamilATF_TC(attach6);
10561.1SkamilATF_TC_HEAD(attach6, tc)
10571.1Skamil{
10581.1Skamil	atf_tc_set_md_var(tc, "descr",
10591.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
10601.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
10611.1Skamil}
10621.1Skamil
10631.1SkamilATF_TC_BODY(attach6, tc)
10641.1Skamil{
10651.1Skamil	struct msg_fds parent_tracee, parent_tracer;
10661.1Skamil	const int exitval_tracee = 5;
10671.1Skamil	const int exitval_tracer = 10;
10681.1Skamil	pid_t parent, tracee, tracer, wpid;
10691.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10701.1Skamil#if defined(TWAIT_HAVE_STATUS)
10711.1Skamil	int status;
10721.1Skamil#endif
10731.1Skamil	int name[CTL_MAXNAME];
10741.1Skamil	struct kinfo_proc2 kp;
10751.1Skamil	size_t len = sizeof(kp);
10761.1Skamil	unsigned int namelen;
10771.1Skamil
10781.13Schristos	DPRINTF("Spawn tracee\n");
10791.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10801.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10811.1Skamil	tracee = atf_utils_fork();
10821.1Skamil	if (tracee == 0) {
10831.1Skamil		parent = getppid();
10841.1Skamil
10851.1Skamil		/* Emit message to the parent */
10861.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
10871.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
10881.1Skamil
10891.1Skamil		namelen = 0;
10901.1Skamil		name[namelen++] = CTL_KERN;
10911.1Skamil		name[namelen++] = KERN_PROC2;
10921.1Skamil		name[namelen++] = KERN_PROC_PID;
10931.1Skamil		name[namelen++] = getpid();
10941.1Skamil		name[namelen++] = len;
10951.1Skamil		name[namelen++] = 1;
10961.1Skamil
10971.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
10981.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
10991.1Skamil
11001.1Skamil		_exit(exitval_tracee);
11011.1Skamil	}
11021.1Skamil
11031.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
11041.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
11051.1Skamil
11061.13Schristos	DPRINTF("Spawn debugger\n");
11071.1Skamil	tracer = atf_utils_fork();
11081.1Skamil	if (tracer == 0) {
11091.1Skamil		/* No IPC to communicate with the child */
11101.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11111.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11121.1Skamil
11131.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11141.1Skamil		FORKEE_REQUIRE_SUCCESS(
11151.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11161.1Skamil
11171.1Skamil		forkee_status_stopped(status, SIGSTOP);
11181.1Skamil
11191.1Skamil		/* Resume tracee with PT_CONTINUE */
11201.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11211.1Skamil
11221.1Skamil		/* Inform parent that tracer has attached to tracee */
11231.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
11241.1Skamil
11251.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
11261.1Skamil
11271.1Skamil		/* Wait for tracee and assert that it exited */
11281.1Skamil		FORKEE_REQUIRE_SUCCESS(
11291.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11301.1Skamil
11311.1Skamil		forkee_status_exited(status, exitval_tracee);
11321.1Skamil
11331.13Schristos		DPRINTF("Before exiting of the tracer process\n");
11341.1Skamil		_exit(exitval_tracer);
11351.1Skamil	}
11361.1Skamil
11371.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
11381.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
11391.1Skamil
11401.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
11411.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
11421.1Skamil
11431.13Schristos	DPRINTF("Detect that tracee is zombie\n");
11441.1Skamil	await_zombie(tracee);
11451.1Skamil
11461.13Schristos	DPRINTF("Assert that there is no status about tracee - "
11471.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
11481.1Skamil	TWAIT_REQUIRE_SUCCESS(
11491.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
11501.1Skamil
11511.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
11521.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11531.1Skamil
11541.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
11551.1Skamil	    TWAIT_FNAME);
11561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
11571.1Skamil	    tracer);
11581.1Skamil
11591.1Skamil	validate_status_exited(status, exitval_tracer);
11601.1Skamil
11611.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11621.1Skamil	    TWAIT_FNAME);
11631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
11641.1Skamil	    tracee);
11651.1Skamil
11661.1Skamil	validate_status_exited(status, exitval_tracee);
11671.1Skamil
11681.1Skamil	msg_close(&parent_tracee);
11691.1Skamil	msg_close(&parent_tracer);
11701.1Skamil}
11711.1Skamil#endif
11721.1Skamil
11731.1Skamil#if defined(TWAIT_HAVE_PID)
11741.1SkamilATF_TC(attach7);
11751.1SkamilATF_TC_HEAD(attach7, tc)
11761.1Skamil{
11771.1Skamil	atf_tc_set_md_var(tc, "descr",
11781.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
11791.1Skamil	    "(check /proc/curproc/status 3rd column)");
11801.1Skamil}
11811.1Skamil
11821.1SkamilATF_TC_BODY(attach7, tc)
11831.1Skamil{
11841.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11851.1Skamil	int rv;
11861.1Skamil	const int exitval_tracee = 5;
11871.1Skamil	const int exitval_tracer = 10;
11881.1Skamil	pid_t parent, tracee, tracer, wpid;
11891.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11901.1Skamil#if defined(TWAIT_HAVE_STATUS)
11911.1Skamil	int status;
11921.1Skamil#endif
11931.1Skamil	FILE *fp;
11941.1Skamil	struct stat st;
11951.1Skamil	const char *fname = "/proc/curproc/status";
11961.1Skamil	char s_executable[MAXPATHLEN];
11971.1Skamil	int s_pid, s_ppid;
11981.1Skamil	/*
11991.1Skamil	 * Format:
12001.1Skamil	 *  EXECUTABLE PID PPID ...
12011.1Skamil	 */
12021.1Skamil
12031.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
12041.1Skamil	if (rv != 0) {
12051.1Skamil		atf_tc_skip("/proc/curproc/status not found");
12061.1Skamil	}
12071.1Skamil
12081.13Schristos	DPRINTF("Spawn tracee\n");
12091.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12101.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12111.1Skamil	tracee = atf_utils_fork();
12121.1Skamil	if (tracee == 0) {
12131.1Skamil		parent = getppid();
12141.1Skamil
12151.1Skamil		// Wait for parent to let us exit
12161.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
12171.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
12181.1Skamil
12191.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
12201.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
12211.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
12221.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
12231.1Skamil
12241.1Skamil		_exit(exitval_tracee);
12251.1Skamil	}
12261.1Skamil
12271.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
12281.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
12291.1Skamil
12301.13Schristos	DPRINTF("Spawn debugger\n");
12311.1Skamil	tracer = atf_utils_fork();
12321.1Skamil	if (tracer == 0) {
12331.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12341.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12351.1Skamil
12361.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12371.1Skamil		FORKEE_REQUIRE_SUCCESS(
12381.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12391.1Skamil
12401.1Skamil		forkee_status_stopped(status, SIGSTOP);
12411.1Skamil
12421.1Skamil		/* Resume tracee with PT_CONTINUE */
12431.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12441.1Skamil
12451.1Skamil		/* Inform parent that tracer has attached to tracee */
12461.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12471.1Skamil
12481.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12491.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12501.1Skamil
12511.1Skamil		/* Wait for tracee and assert that it exited */
12521.1Skamil		FORKEE_REQUIRE_SUCCESS(
12531.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12541.1Skamil
12551.1Skamil		forkee_status_exited(status, exitval_tracee);
12561.1Skamil
12571.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12581.1Skamil		_exit(exitval_tracer);
12591.1Skamil	}
12601.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12611.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12621.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12631.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
12641.1Skamil
12651.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12661.1Skamil	await_zombie(tracee);
12671.1Skamil
12681.13Schristos	DPRINTF("Assert that there is no status about tracee - "
12691.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
12701.1Skamil	TWAIT_REQUIRE_SUCCESS(
12711.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
12721.1Skamil
12731.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
12741.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
12751.1Skamil
12761.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
12771.1Skamil	    TWAIT_FNAME);
12781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
12791.1Skamil	    tracer);
12801.1Skamil
12811.1Skamil	validate_status_exited(status, exitval_tracer);
12821.1Skamil
12831.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
12841.1Skamil	    TWAIT_FNAME);
12851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
12861.1Skamil	    tracee);
12871.1Skamil
12881.1Skamil	validate_status_exited(status, exitval_tracee);
12891.1Skamil
12901.1Skamil	msg_close(&parent_tracee);
12911.1Skamil	msg_close(&parent_tracer);
12921.1Skamil}
12931.1Skamil#endif
12941.1Skamil
12951.1SkamilATF_TC(eventmask1);
12961.1SkamilATF_TC_HEAD(eventmask1, tc)
12971.1Skamil{
12981.1Skamil	atf_tc_set_md_var(tc, "descr",
12991.1Skamil	    "Verify that empty EVENT_MASK is preserved");
13001.1Skamil}
13011.1Skamil
13021.1SkamilATF_TC_BODY(eventmask1, tc)
13031.1Skamil{
13041.1Skamil	const int exitval = 5;
13051.1Skamil	const int sigval = SIGSTOP;
13061.1Skamil	pid_t child, wpid;
13071.1Skamil#if defined(TWAIT_HAVE_STATUS)
13081.1Skamil	int status;
13091.1Skamil#endif
13101.1Skamil	ptrace_event_t set_event, get_event;
13111.1Skamil	const int len = sizeof(ptrace_event_t);
13121.1Skamil
13131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13151.1Skamil	if (child == 0) {
13161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13181.1Skamil
13191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13211.1Skamil
13221.13Schristos		DPRINTF("Before exiting of the child process\n");
13231.1Skamil		_exit(exitval);
13241.1Skamil	}
13251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13261.1Skamil
13271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13291.1Skamil
13301.1Skamil	validate_status_stopped(status, sigval);
13311.1Skamil
13321.1Skamil	set_event.pe_set_event = 0;
13331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13351.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13361.1Skamil
13371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13381.1Skamil	    "without signal to be sent\n");
13391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13401.1Skamil
13411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13431.1Skamil
13441.1Skamil	validate_status_exited(status, exitval);
13451.1Skamil
13461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13481.1Skamil}
13491.1Skamil
13501.1SkamilATF_TC(eventmask2);
13511.1SkamilATF_TC_HEAD(eventmask2, tc)
13521.1Skamil{
13531.1Skamil	atf_tc_set_md_var(tc, "descr",
13541.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
13551.1Skamil}
13561.1Skamil
13571.1SkamilATF_TC_BODY(eventmask2, tc)
13581.1Skamil{
13591.1Skamil	const int exitval = 5;
13601.1Skamil	const int sigval = SIGSTOP;
13611.1Skamil	pid_t child, wpid;
13621.1Skamil#if defined(TWAIT_HAVE_STATUS)
13631.1Skamil	int status;
13641.1Skamil#endif
13651.1Skamil	ptrace_event_t set_event, get_event;
13661.1Skamil	const int len = sizeof(ptrace_event_t);
13671.1Skamil
13681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13701.1Skamil	if (child == 0) {
13711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13731.1Skamil
13741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13761.1Skamil
13771.13Schristos		DPRINTF("Before exiting of the child process\n");
13781.1Skamil		_exit(exitval);
13791.1Skamil	}
13801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13811.1Skamil
13821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13841.1Skamil
13851.1Skamil	validate_status_stopped(status, sigval);
13861.1Skamil
13871.1Skamil	set_event.pe_set_event = PTRACE_FORK;
13881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13901.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13911.1Skamil
13921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13931.1Skamil	    "without signal to be sent\n");
13941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13951.1Skamil
13961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13981.1Skamil
13991.1Skamil	validate_status_exited(status, exitval);
14001.1Skamil
14011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14031.1Skamil}
14041.1Skamil
14051.1SkamilATF_TC(eventmask3);
14061.1SkamilATF_TC_HEAD(eventmask3, tc)
14071.1Skamil{
14081.1Skamil	atf_tc_set_md_var(tc, "descr",
14091.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
14101.1Skamil}
14111.1Skamil
14121.1SkamilATF_TC_BODY(eventmask3, tc)
14131.1Skamil{
14141.1Skamil	const int exitval = 5;
14151.1Skamil	const int sigval = SIGSTOP;
14161.1Skamil	pid_t child, wpid;
14171.1Skamil#if defined(TWAIT_HAVE_STATUS)
14181.1Skamil	int status;
14191.1Skamil#endif
14201.1Skamil	ptrace_event_t set_event, get_event;
14211.1Skamil	const int len = sizeof(ptrace_event_t);
14221.1Skamil
14231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14251.1Skamil	if (child == 0) {
14261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14281.1Skamil
14291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14311.1Skamil
14321.13Schristos		DPRINTF("Before exiting of the child process\n");
14331.1Skamil		_exit(exitval);
14341.1Skamil	}
14351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14361.1Skamil
14371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14391.1Skamil
14401.1Skamil	validate_status_stopped(status, sigval);
14411.1Skamil
14421.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
14431.38Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14451.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14461.1Skamil
14471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14481.1Skamil	    "without signal to be sent\n");
14491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14501.1Skamil
14511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14531.1Skamil
14541.1Skamil	validate_status_exited(status, exitval);
14551.1Skamil
14561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14581.1Skamil}
14591.1Skamil
14601.1SkamilATF_TC(eventmask4);
14611.1SkamilATF_TC_HEAD(eventmask4, tc)
14621.1Skamil{
14631.1Skamil	atf_tc_set_md_var(tc, "descr",
14641.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
14651.1Skamil}
14661.1Skamil
14671.1SkamilATF_TC_BODY(eventmask4, tc)
14681.1Skamil{
14691.1Skamil	const int exitval = 5;
14701.1Skamil	const int sigval = SIGSTOP;
14711.1Skamil	pid_t child, wpid;
14721.1Skamil#if defined(TWAIT_HAVE_STATUS)
14731.1Skamil	int status;
14741.1Skamil#endif
14751.1Skamil	ptrace_event_t set_event, get_event;
14761.1Skamil	const int len = sizeof(ptrace_event_t);
14771.1Skamil
14781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14801.1Skamil	if (child == 0) {
14811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14831.1Skamil
14841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14861.1Skamil
14871.13Schristos		DPRINTF("Before exiting of the child process\n");
14881.1Skamil		_exit(exitval);
14891.1Skamil	}
14901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14911.1Skamil
14921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14941.1Skamil
14951.1Skamil	validate_status_stopped(status, sigval);
14961.1Skamil
14971.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
14981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15001.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15011.1Skamil
15021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15031.1Skamil	    "without signal to be sent\n");
15041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15051.1Skamil
15061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15081.1Skamil
15091.1Skamil	validate_status_exited(status, exitval);
15101.1Skamil
15111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15131.1Skamil}
15141.1Skamil
15151.1SkamilATF_TC(eventmask5);
15161.1SkamilATF_TC_HEAD(eventmask5, tc)
15171.1Skamil{
15181.1Skamil	atf_tc_set_md_var(tc, "descr",
15191.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
15201.1Skamil}
15211.1Skamil
15221.1SkamilATF_TC_BODY(eventmask5, tc)
15231.1Skamil{
15241.1Skamil	const int exitval = 5;
15251.1Skamil	const int sigval = SIGSTOP;
15261.1Skamil	pid_t child, wpid;
15271.1Skamil#if defined(TWAIT_HAVE_STATUS)
15281.1Skamil	int status;
15291.1Skamil#endif
15301.1Skamil	ptrace_event_t set_event, get_event;
15311.1Skamil	const int len = sizeof(ptrace_event_t);
15321.1Skamil
15331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15351.1Skamil	if (child == 0) {
15361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15381.1Skamil
15391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15411.1Skamil
15421.13Schristos		DPRINTF("Before exiting of the child process\n");
15431.1Skamil		_exit(exitval);
15441.1Skamil	}
15451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15461.1Skamil
15471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15491.1Skamil
15501.1Skamil	validate_status_stopped(status, sigval);
15511.1Skamil
15521.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
15531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15551.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15561.1Skamil
15571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15581.1Skamil	    "without signal to be sent\n");
15591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15601.1Skamil
15611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15631.1Skamil
15641.1Skamil	validate_status_exited(status, exitval);
15651.1Skamil
15661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15681.1Skamil}
15691.1Skamil
15701.1SkamilATF_TC(eventmask6);
15711.1SkamilATF_TC_HEAD(eventmask6, tc)
15721.1Skamil{
15731.1Skamil	atf_tc_set_md_var(tc, "descr",
15741.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
15751.1Skamil}
15761.1Skamil
15771.1SkamilATF_TC_BODY(eventmask6, tc)
15781.1Skamil{
15791.1Skamil	const int exitval = 5;
15801.1Skamil	const int sigval = SIGSTOP;
15811.1Skamil	pid_t child, wpid;
15821.1Skamil#if defined(TWAIT_HAVE_STATUS)
15831.1Skamil	int status;
15841.1Skamil#endif
15851.1Skamil	ptrace_event_t set_event, get_event;
15861.1Skamil	const int len = sizeof(ptrace_event_t);
15871.1Skamil
15881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15901.1Skamil	if (child == 0) {
15911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15931.1Skamil
15941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15961.1Skamil
15971.13Schristos		DPRINTF("Before exiting of the child process\n");
15981.1Skamil		_exit(exitval);
15991.1Skamil	}
16001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16011.1Skamil
16021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16041.1Skamil
16051.1Skamil	validate_status_stopped(status, sigval);
16061.1Skamil
16071.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
16081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
16091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
16101.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
16111.1Skamil
16121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16131.1Skamil	    "without signal to be sent\n");
16141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16151.1Skamil
16161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16181.1Skamil
16191.1Skamil	validate_status_exited(status, exitval);
16201.1Skamil
16211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16231.1Skamil}
16241.1Skamil
16251.28Skamilstatic void
16261.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
16271.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
16281.1Skamil{
16291.1Skamil	const int exitval = 5;
16301.1Skamil	const int exitval2 = 15;
16311.1Skamil	const int sigval = SIGSTOP;
16321.31Skamil	pid_t child, child2 = 0, wpid;
16331.1Skamil#if defined(TWAIT_HAVE_STATUS)
16341.1Skamil	int status;
16351.1Skamil#endif
16361.1Skamil	ptrace_state_t state;
16371.1Skamil	const int slen = sizeof(state);
16381.1Skamil	ptrace_event_t event;
16391.1Skamil	const int elen = sizeof(event);
16401.1Skamil
16411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
16421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
16431.1Skamil	if (child == 0) {
16441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16461.1Skamil
16471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
16481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
16491.1Skamil
16501.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
16511.1Skamil
16521.1Skamil		if (child2 == 0)
16531.1Skamil			_exit(exitval2);
16541.1Skamil
16551.1Skamil		FORKEE_REQUIRE_SUCCESS
16561.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
16571.1Skamil
16581.1Skamil		forkee_status_exited(status, exitval2);
16591.1Skamil
16601.13Schristos		DPRINTF("Before exiting of the child process\n");
16611.1Skamil		_exit(exitval);
16621.1Skamil	}
16631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16641.1Skamil
16651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16671.1Skamil
16681.1Skamil	validate_status_stopped(status, sigval);
16691.1Skamil
16701.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
16711.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
16721.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
16731.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
16741.30Skamil	event.pe_set_event = 0;
16751.30Skamil	if (trackfork)
16761.30Skamil		event.pe_set_event |= PTRACE_FORK;
16771.30Skamil	if (trackvfork)
16781.30Skamil		event.pe_set_event |= PTRACE_VFORK;
16791.30Skamil	if (trackvforkdone)
16801.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
16811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
16821.1Skamil
16831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16841.1Skamil	    "without signal to be sent\n");
16851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16861.1Skamil
16871.29Skamil#if defined(TWAIT_HAVE_PID)
16881.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
16891.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16901.29Skamil		        child);
16911.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16921.29Skamil		                      child);
16931.1Skamil
16941.29Skamil		validate_status_stopped(status, SIGTRAP);
16951.1Skamil
16961.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
16971.29Skamil		                       slen) != -1);
16981.31Skamil		if (trackfork && fn == fork) {
16991.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
17001.30Skamil			       PTRACE_FORK);
17011.30Skamil		}
17021.31Skamil		if (trackvfork && fn == vfork) {
17031.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
17041.30Skamil			       PTRACE_VFORK);
17051.30Skamil		}
17061.29Skamil
17071.29Skamil		child2 = state.pe_other_pid;
17081.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
17091.29Skamil
17101.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
17111.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
17121.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
17131.29Skamil		    child2);
17141.1Skamil
17151.29Skamil		validate_status_stopped(status, SIGTRAP);
17161.1Skamil
17171.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
17181.29Skamil		                       slen) != -1);
17191.31Skamil		if (trackfork && fn == fork) {
17201.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
17211.30Skamil			       PTRACE_FORK);
17221.30Skamil		}
17231.31Skamil		if (trackvfork && fn == vfork) {
17241.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
17251.30Skamil			       PTRACE_VFORK);
17261.30Skamil		}
17271.30Skamil
17281.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
17291.29Skamil
17301.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
17311.29Skamil		    "and without signal to be sent\n");
17321.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
17331.29Skamil		                != -1);
17341.29Skamil
17351.29Skamil		DPRINTF("Before resuming the child process where it left off "
17361.29Skamil		        "and without signal to be sent\n");
17371.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17381.30Skamil	}
17391.30Skamil#endif
17401.30Skamil
17411.31Skamil	if (trackvforkdone && fn == vfork) {
17421.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
17431.30Skamil		        child);
17441.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
17451.30Skamil		                      child);
17461.30Skamil
17471.30Skamil		validate_status_stopped(status, SIGTRAP);
17481.30Skamil
17491.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
17501.30Skamil		                       slen) != -1);
17511.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
17521.30Skamil
17531.30Skamil		child2 = state.pe_other_pid;
17541.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
17551.30Skamil		        child2);
17561.30Skamil
17571.30Skamil		DPRINTF("Before resuming the child process where it left off "
17581.30Skamil		        "and without signal to be sent\n");
17591.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17601.30Skamil	}
17611.29Skamil
17621.30Skamil#if defined(TWAIT_HAVE_PID)
17631.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
17641.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
17651.29Skamil		        "\n", TWAIT_FNAME);
17661.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
17671.29Skamil		    child2);
17681.29Skamil
17691.29Skamil		validate_status_exited(status, exitval2);
17701.29Skamil
17711.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
17721.29Skamil		        "process\n", TWAIT_FNAME);
17731.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
17741.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
17751.29Skamil	}
17761.29Skamil#endif
17771.1Skamil
17781.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
17791.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
17801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17811.1Skamil
17821.1Skamil	validate_status_stopped(status, SIGCHLD);
17831.1Skamil
17841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17851.1Skamil	    "without signal to be sent\n");
17861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17871.1Skamil
17881.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
17891.1Skamil	    TWAIT_FNAME);
17901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17911.1Skamil
17921.1Skamil	validate_status_exited(status, exitval);
17931.1Skamil
17941.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
17951.1Skamil	    TWAIT_FNAME);
17961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17971.1Skamil}
17981.28Skamil
17991.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
18001.32SkamilATF_TC(name);									\
18011.32SkamilATF_TC_HEAD(name, tc)								\
18021.32Skamil{										\
18031.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
18041.32Skamil}										\
18051.32Skamil										\
18061.32SkamilATF_TC_BODY(name, tc)								\
18071.32Skamil{										\
18081.32Skamil										\
18091.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
18101.32Skamil}
18111.32Skamil
18121.32Skamil#define F false
18131.32Skamil#define T true
18141.32Skamil
18151.32Skamil#define F_IF__0(x)
18161.32Skamil#define F_IF__1(x) x
18171.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
18181.32Skamil#define F_IF_(x,y) F_IF__(x,y)
18191.32Skamil#define F_IF(x,y) F_IF_(x,y)
18201.32Skamil
18211.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
18221.32Skamil        "Verify " #function "(2) called with 0"					\
18231.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
18241.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
18251.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
18261.32Skamil        " in EVENT_MASK."							\
18271.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
18281.32Skamil        F_IF(dparentbit," Detach parent in this test.")
18291.1Skamil
18301.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
18311.31Skamil#if defined(TWAIT_HAVE_PID)
18321.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
18331.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
18341.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
18351.31Skamil#endif
18361.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
18371.31Skamil#if defined(TWAIT_HAVE_PID)
18381.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
18391.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
18401.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
18411.31Skamil#endif
18421.1Skamil
18431.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
18441.31Skamil#if defined(TWAIT_HAVE_PID)
18451.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
18461.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
18471.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
18481.31Skamil#endif
18491.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
18501.31Skamil#if defined(TWAIT_HAVE_PID)
18511.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
18521.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
18531.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
18541.31Skamil#endif
18551.31Skamil
18561.31Skamil
18571.31Skamil
18581.1Skamil
18591.1SkamilATF_TC(io_read_d1);
18601.1SkamilATF_TC_HEAD(io_read_d1, tc)
18611.1Skamil{
18621.1Skamil	atf_tc_set_md_var(tc, "descr",
18631.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
18641.1Skamil}
18651.1Skamil
18661.1SkamilATF_TC_BODY(io_read_d1, tc)
18671.1Skamil{
18681.1Skamil	const int exitval = 5;
18691.1Skamil	const int sigval = SIGSTOP;
18701.1Skamil	pid_t child, wpid;
18711.1Skamil	uint8_t lookup_me = 0;
18721.1Skamil	const uint8_t magic = 0xab;
18731.1Skamil	struct ptrace_io_desc io = {
18741.1Skamil		.piod_op = PIOD_READ_D,
18751.1Skamil		.piod_offs = &lookup_me,
18761.1Skamil		.piod_addr = &lookup_me,
18771.1Skamil		.piod_len = sizeof(lookup_me)
18781.1Skamil	};
18791.1Skamil#if defined(TWAIT_HAVE_STATUS)
18801.1Skamil	int status;
18811.1Skamil#endif
18821.1Skamil
18831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18851.1Skamil	if (child == 0) {
18861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18881.1Skamil
18891.1Skamil		lookup_me = magic;
18901.1Skamil
18911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18931.1Skamil
18941.13Schristos		DPRINTF("Before exiting of the child process\n");
18951.1Skamil		_exit(exitval);
18961.1Skamil	}
18971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18981.1Skamil
18991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19011.1Skamil
19021.1Skamil	validate_status_stopped(status, sigval);
19031.1Skamil
19041.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19051.1Skamil	    child, getpid());
19061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19071.1Skamil
19081.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19091.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
19101.1Skamil
19111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19121.1Skamil	    "without signal to be sent\n");
19131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19141.1Skamil
19151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19171.1Skamil
19181.1Skamil	validate_status_exited(status, exitval);
19191.1Skamil
19201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19221.1Skamil}
19231.1Skamil
19241.1SkamilATF_TC(io_read_d2);
19251.1SkamilATF_TC_HEAD(io_read_d2, tc)
19261.1Skamil{
19271.1Skamil	atf_tc_set_md_var(tc, "descr",
19281.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
19291.1Skamil}
19301.1Skamil
19311.1SkamilATF_TC_BODY(io_read_d2, tc)
19321.1Skamil{
19331.1Skamil	const int exitval = 5;
19341.1Skamil	const int sigval = SIGSTOP;
19351.1Skamil	pid_t child, wpid;
19361.1Skamil	uint16_t lookup_me = 0;
19371.1Skamil	const uint16_t magic = 0x1234;
19381.1Skamil	struct ptrace_io_desc io = {
19391.1Skamil		.piod_op = PIOD_READ_D,
19401.1Skamil		.piod_offs = &lookup_me,
19411.1Skamil		.piod_addr = &lookup_me,
19421.1Skamil		.piod_len = sizeof(lookup_me)
19431.1Skamil	};
19441.1Skamil#if defined(TWAIT_HAVE_STATUS)
19451.1Skamil	int status;
19461.1Skamil#endif
19471.1Skamil
19481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19501.1Skamil	if (child == 0) {
19511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19531.1Skamil
19541.1Skamil		lookup_me = magic;
19551.1Skamil
19561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19581.1Skamil
19591.13Schristos		DPRINTF("Before exiting of the child process\n");
19601.1Skamil		_exit(exitval);
19611.1Skamil	}
19621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19631.1Skamil
19641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19661.1Skamil
19671.1Skamil	validate_status_stopped(status, sigval);
19681.1Skamil
19691.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19701.1Skamil	    child, getpid());
19711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19721.1Skamil
19731.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19741.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
19751.1Skamil
19761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19771.1Skamil	    "without signal to be sent\n");
19781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19791.1Skamil
19801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19821.1Skamil
19831.1Skamil	validate_status_exited(status, exitval);
19841.1Skamil
19851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19871.1Skamil}
19881.1Skamil
19891.1SkamilATF_TC(io_read_d3);
19901.1SkamilATF_TC_HEAD(io_read_d3, tc)
19911.1Skamil{
19921.1Skamil	atf_tc_set_md_var(tc, "descr",
19931.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
19941.1Skamil}
19951.1Skamil
19961.1SkamilATF_TC_BODY(io_read_d3, tc)
19971.1Skamil{
19981.1Skamil	const int exitval = 5;
19991.1Skamil	const int sigval = SIGSTOP;
20001.1Skamil	pid_t child, wpid;
20011.1Skamil	uint32_t lookup_me = 0;
20021.1Skamil	const uint32_t magic = 0x1234abcd;
20031.1Skamil	struct ptrace_io_desc io = {
20041.1Skamil		.piod_op = PIOD_READ_D,
20051.1Skamil		.piod_offs = &lookup_me,
20061.1Skamil		.piod_addr = &lookup_me,
20071.1Skamil		.piod_len = sizeof(lookup_me)
20081.1Skamil	};
20091.1Skamil#if defined(TWAIT_HAVE_STATUS)
20101.1Skamil	int status;
20111.1Skamil#endif
20121.1Skamil
20131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20151.1Skamil	if (child == 0) {
20161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20181.1Skamil
20191.1Skamil		lookup_me = magic;
20201.1Skamil
20211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20231.1Skamil
20241.13Schristos		DPRINTF("Before exiting of the child process\n");
20251.1Skamil		_exit(exitval);
20261.1Skamil	}
20271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20281.1Skamil
20291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20311.1Skamil
20321.1Skamil	validate_status_stopped(status, sigval);
20331.1Skamil
20341.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
20351.1Skamil	    child, getpid());
20361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20371.1Skamil
20381.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
20391.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
20401.1Skamil
20411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20421.1Skamil	    "without signal to be sent\n");
20431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20441.1Skamil
20451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20471.1Skamil
20481.1Skamil	validate_status_exited(status, exitval);
20491.1Skamil
20501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20521.1Skamil}
20531.1Skamil
20541.1SkamilATF_TC(io_read_d4);
20551.1SkamilATF_TC_HEAD(io_read_d4, tc)
20561.1Skamil{
20571.1Skamil	atf_tc_set_md_var(tc, "descr",
20581.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
20591.1Skamil}
20601.1Skamil
20611.1SkamilATF_TC_BODY(io_read_d4, tc)
20621.1Skamil{
20631.1Skamil	const int exitval = 5;
20641.1Skamil	const int sigval = SIGSTOP;
20651.1Skamil	pid_t child, wpid;
20661.1Skamil	uint64_t lookup_me = 0;
20671.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
20681.1Skamil	struct ptrace_io_desc io = {
20691.1Skamil		.piod_op = PIOD_READ_D,
20701.1Skamil		.piod_offs = &lookup_me,
20711.1Skamil		.piod_addr = &lookup_me,
20721.1Skamil		.piod_len = sizeof(lookup_me)
20731.1Skamil	};
20741.1Skamil#if defined(TWAIT_HAVE_STATUS)
20751.1Skamil	int status;
20761.1Skamil#endif
20771.1Skamil
20781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20801.1Skamil	if (child == 0) {
20811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20831.1Skamil
20841.1Skamil		lookup_me = magic;
20851.1Skamil
20861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20881.1Skamil
20891.13Schristos		DPRINTF("Before exiting of the child process\n");
20901.1Skamil		_exit(exitval);
20911.1Skamil	}
20921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20931.1Skamil
20941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20961.1Skamil
20971.1Skamil	validate_status_stopped(status, sigval);
20981.1Skamil
20991.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
21001.1Skamil	    child, getpid());
21011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21021.1Skamil
21031.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
21041.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
21051.1Skamil
21061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21071.1Skamil	    "without signal to be sent\n");
21081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21091.1Skamil
21101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21121.1Skamil
21131.1Skamil	validate_status_exited(status, exitval);
21141.1Skamil
21151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21171.1Skamil}
21181.1Skamil
21191.1SkamilATF_TC(io_write_d1);
21201.1SkamilATF_TC_HEAD(io_write_d1, tc)
21211.1Skamil{
21221.1Skamil	atf_tc_set_md_var(tc, "descr",
21231.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
21241.1Skamil}
21251.1Skamil
21261.1SkamilATF_TC_BODY(io_write_d1, tc)
21271.1Skamil{
21281.1Skamil	const int exitval = 5;
21291.1Skamil	const int sigval = SIGSTOP;
21301.1Skamil	pid_t child, wpid;
21311.1Skamil	uint8_t lookup_me = 0;
21321.1Skamil	const uint8_t magic = 0xab;
21331.1Skamil	struct ptrace_io_desc io = {
21341.1Skamil		.piod_op = PIOD_WRITE_D,
21351.1Skamil		.piod_offs = &lookup_me,
21361.1Skamil		.piod_addr = &lookup_me,
21371.1Skamil		.piod_len = sizeof(lookup_me)
21381.1Skamil	};
21391.1Skamil#if defined(TWAIT_HAVE_STATUS)
21401.1Skamil	int status;
21411.1Skamil#endif
21421.1Skamil
21431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21451.1Skamil	if (child == 0) {
21461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21481.1Skamil
21491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21511.1Skamil
21521.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21531.1Skamil
21541.13Schristos		DPRINTF("Before exiting of the child process\n");
21551.1Skamil		_exit(exitval);
21561.1Skamil	}
21571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21581.1Skamil
21591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21611.1Skamil
21621.1Skamil	validate_status_stopped(status, sigval);
21631.1Skamil
21641.1Skamil	lookup_me = magic;
21651.1Skamil
21661.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21671.1Skamil	    child, getpid());
21681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21691.1Skamil
21701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21711.1Skamil	    "without signal to be sent\n");
21721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21731.1Skamil
21741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21761.1Skamil
21771.1Skamil	validate_status_exited(status, exitval);
21781.1Skamil
21791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21811.1Skamil}
21821.1Skamil
21831.1SkamilATF_TC(io_write_d2);
21841.1SkamilATF_TC_HEAD(io_write_d2, tc)
21851.1Skamil{
21861.1Skamil	atf_tc_set_md_var(tc, "descr",
21871.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
21881.1Skamil}
21891.1Skamil
21901.1SkamilATF_TC_BODY(io_write_d2, tc)
21911.1Skamil{
21921.1Skamil	const int exitval = 5;
21931.1Skamil	const int sigval = SIGSTOP;
21941.1Skamil	pid_t child, wpid;
21951.1Skamil	uint16_t lookup_me = 0;
21961.1Skamil	const uint16_t magic = 0xab12;
21971.1Skamil	struct ptrace_io_desc io = {
21981.1Skamil		.piod_op = PIOD_WRITE_D,
21991.1Skamil		.piod_offs = &lookup_me,
22001.1Skamil		.piod_addr = &lookup_me,
22011.1Skamil		.piod_len = sizeof(lookup_me)
22021.1Skamil	};
22031.1Skamil#if defined(TWAIT_HAVE_STATUS)
22041.1Skamil	int status;
22051.1Skamil#endif
22061.1Skamil
22071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22091.1Skamil	if (child == 0) {
22101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22121.1Skamil
22131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22151.1Skamil
22161.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22171.1Skamil
22181.13Schristos		DPRINTF("Before exiting of the child process\n");
22191.1Skamil		_exit(exitval);
22201.1Skamil	}
22211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22221.1Skamil
22231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22251.1Skamil
22261.1Skamil	validate_status_stopped(status, sigval);
22271.1Skamil
22281.1Skamil	lookup_me = magic;
22291.1Skamil
22301.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22311.1Skamil	    child, getpid());
22321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22331.1Skamil
22341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22351.1Skamil	    "without signal to be sent\n");
22361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22371.1Skamil
22381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22401.1Skamil
22411.1Skamil	validate_status_exited(status, exitval);
22421.1Skamil
22431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22451.1Skamil}
22461.1Skamil
22471.1SkamilATF_TC(io_write_d3);
22481.1SkamilATF_TC_HEAD(io_write_d3, tc)
22491.1Skamil{
22501.1Skamil	atf_tc_set_md_var(tc, "descr",
22511.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
22521.1Skamil}
22531.1Skamil
22541.1SkamilATF_TC_BODY(io_write_d3, tc)
22551.1Skamil{
22561.1Skamil	const int exitval = 5;
22571.1Skamil	const int sigval = SIGSTOP;
22581.1Skamil	pid_t child, wpid;
22591.1Skamil	uint32_t lookup_me = 0;
22601.1Skamil	const uint32_t magic = 0xab127643;
22611.1Skamil	struct ptrace_io_desc io = {
22621.1Skamil		.piod_op = PIOD_WRITE_D,
22631.1Skamil		.piod_offs = &lookup_me,
22641.1Skamil		.piod_addr = &lookup_me,
22651.1Skamil		.piod_len = sizeof(lookup_me)
22661.1Skamil	};
22671.1Skamil#if defined(TWAIT_HAVE_STATUS)
22681.1Skamil	int status;
22691.1Skamil#endif
22701.1Skamil
22711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22731.1Skamil	if (child == 0) {
22741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22761.1Skamil
22771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22791.1Skamil
22801.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22811.1Skamil
22821.13Schristos		DPRINTF("Before exiting of the child process\n");
22831.1Skamil		_exit(exitval);
22841.1Skamil	}
22851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22861.1Skamil
22871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22891.1Skamil
22901.1Skamil	validate_status_stopped(status, sigval);
22911.1Skamil
22921.1Skamil	lookup_me = magic;
22931.1Skamil
22941.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22951.1Skamil	    child, getpid());
22961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22971.1Skamil
22981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22991.1Skamil	    "without signal to be sent\n");
23001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23011.1Skamil
23021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23041.1Skamil
23051.1Skamil	validate_status_exited(status, exitval);
23061.1Skamil
23071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23091.1Skamil}
23101.1Skamil
23111.1SkamilATF_TC(io_write_d4);
23121.1SkamilATF_TC_HEAD(io_write_d4, tc)
23131.1Skamil{
23141.1Skamil	atf_tc_set_md_var(tc, "descr",
23151.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
23161.1Skamil}
23171.1Skamil
23181.1SkamilATF_TC_BODY(io_write_d4, tc)
23191.1Skamil{
23201.1Skamil	const int exitval = 5;
23211.1Skamil	const int sigval = SIGSTOP;
23221.1Skamil	pid_t child, wpid;
23231.1Skamil	uint64_t lookup_me = 0;
23241.1Skamil	const uint64_t magic = 0xab12764376490123;
23251.1Skamil	struct ptrace_io_desc io = {
23261.1Skamil		.piod_op = PIOD_WRITE_D,
23271.1Skamil		.piod_offs = &lookup_me,
23281.1Skamil		.piod_addr = &lookup_me,
23291.1Skamil		.piod_len = sizeof(lookup_me)
23301.1Skamil	};
23311.1Skamil#if defined(TWAIT_HAVE_STATUS)
23321.1Skamil	int status;
23331.1Skamil#endif
23341.1Skamil
23351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23371.1Skamil	if (child == 0) {
23381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23401.1Skamil
23411.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23421.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23431.1Skamil
23441.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
23451.1Skamil
23461.13Schristos		DPRINTF("Before exiting of the child process\n");
23471.1Skamil		_exit(exitval);
23481.1Skamil	}
23491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23501.1Skamil
23511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23531.1Skamil
23541.1Skamil	validate_status_stopped(status, sigval);
23551.1Skamil
23561.1Skamil	lookup_me = magic;
23571.1Skamil
23581.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
23591.1Skamil	    child, getpid());
23601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23611.1Skamil
23621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23631.1Skamil	    "without signal to be sent\n");
23641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23651.1Skamil
23661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23681.1Skamil
23691.1Skamil	validate_status_exited(status, exitval);
23701.1Skamil
23711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23731.1Skamil}
23741.1Skamil
23751.1SkamilATF_TC(io_read_auxv1);
23761.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
23771.1Skamil{
23781.1Skamil	atf_tc_set_md_var(tc, "descr",
23791.1Skamil	    "Verify PT_READ_AUXV called for tracee");
23801.1Skamil}
23811.1Skamil
23821.1SkamilATF_TC_BODY(io_read_auxv1, tc)
23831.1Skamil{
23841.1Skamil	const int exitval = 5;
23851.1Skamil	const int sigval = SIGSTOP;
23861.1Skamil	pid_t child, wpid;
23871.1Skamil#if defined(TWAIT_HAVE_STATUS)
23881.1Skamil	int status;
23891.1Skamil#endif
23901.1Skamil	AuxInfo ai[100], *aip;
23911.1Skamil	struct ptrace_io_desc io = {
23921.1Skamil		.piod_op = PIOD_READ_AUXV,
23931.1Skamil		.piod_offs = 0,
23941.1Skamil		.piod_addr = ai,
23951.1Skamil		.piod_len = sizeof(ai)
23961.1Skamil	};
23971.1Skamil
23981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24001.1Skamil	if (child == 0) {
24011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24031.1Skamil
24041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24061.1Skamil
24071.13Schristos		DPRINTF("Before exiting of the child process\n");
24081.1Skamil		_exit(exitval);
24091.1Skamil	}
24101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24111.1Skamil
24121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24141.1Skamil
24151.1Skamil	validate_status_stopped(status, sigval);
24161.1Skamil
24171.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
24181.1Skamil	    child, getpid());
24191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
24201.1Skamil
24211.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
24221.1Skamil	ATF_REQUIRE(io.piod_len > 0);
24231.1Skamil
24241.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
24251.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
24261.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
24271.1Skamil
24281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24291.1Skamil	    "without signal to be sent\n");
24301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24311.1Skamil
24321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24341.1Skamil
24351.1Skamil	validate_status_exited(status, exitval);
24361.1Skamil
24371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24391.1Skamil}
24401.1Skamil
24411.1SkamilATF_TC(read_d1);
24421.1SkamilATF_TC_HEAD(read_d1, tc)
24431.1Skamil{
24441.1Skamil	atf_tc_set_md_var(tc, "descr",
24451.1Skamil	    "Verify PT_READ_D called once");
24461.1Skamil}
24471.1Skamil
24481.1SkamilATF_TC_BODY(read_d1, tc)
24491.1Skamil{
24501.1Skamil	const int exitval = 5;
24511.1Skamil	const int sigval = SIGSTOP;
24521.1Skamil	pid_t child, wpid;
24531.1Skamil	int lookup_me = 0;
24541.1Skamil	const int magic = (int)random();
24551.1Skamil#if defined(TWAIT_HAVE_STATUS)
24561.1Skamil	int status;
24571.1Skamil#endif
24581.1Skamil
24591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24611.1Skamil	if (child == 0) {
24621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24641.1Skamil
24651.1Skamil		lookup_me = magic;
24661.1Skamil
24671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24691.1Skamil
24701.13Schristos		DPRINTF("Before exiting of the child process\n");
24711.1Skamil		_exit(exitval);
24721.1Skamil	}
24731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24741.1Skamil
24751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24771.1Skamil
24781.1Skamil	validate_status_stopped(status, sigval);
24791.1Skamil
24801.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
24811.1Skamil	    child, getpid());
24821.1Skamil	errno = 0;
24831.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
24841.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24851.1Skamil
24861.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
24871.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
24881.1Skamil
24891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24901.1Skamil	    "without signal to be sent\n");
24911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24921.1Skamil
24931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24951.1Skamil
24961.1Skamil	validate_status_exited(status, exitval);
24971.1Skamil
24981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25001.1Skamil}
25011.1Skamil
25021.1SkamilATF_TC(read_d2);
25031.1SkamilATF_TC_HEAD(read_d2, tc)
25041.1Skamil{
25051.1Skamil	atf_tc_set_md_var(tc, "descr",
25061.1Skamil	    "Verify PT_READ_D called twice");
25071.1Skamil}
25081.1Skamil
25091.1SkamilATF_TC_BODY(read_d2, tc)
25101.1Skamil{
25111.1Skamil	const int exitval = 5;
25121.1Skamil	const int sigval = SIGSTOP;
25131.1Skamil	pid_t child, wpid;
25141.1Skamil	int lookup_me1 = 0;
25151.1Skamil	int lookup_me2 = 0;
25161.1Skamil	const int magic1 = (int)random();
25171.1Skamil	const int magic2 = (int)random();
25181.1Skamil#if defined(TWAIT_HAVE_STATUS)
25191.1Skamil	int status;
25201.1Skamil#endif
25211.1Skamil
25221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25241.1Skamil	if (child == 0) {
25251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25271.1Skamil
25281.1Skamil		lookup_me1 = magic1;
25291.1Skamil		lookup_me2 = magic2;
25301.1Skamil
25311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25331.1Skamil
25341.13Schristos		DPRINTF("Before exiting of the child process\n");
25351.1Skamil		_exit(exitval);
25361.1Skamil	}
25371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25381.1Skamil
25391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25411.1Skamil
25421.1Skamil	validate_status_stopped(status, sigval);
25431.1Skamil
25441.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25451.1Skamil	    child, getpid());
25461.1Skamil	errno = 0;
25471.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25481.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25491.1Skamil
25501.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25511.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25521.1Skamil
25531.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25541.1Skamil	    child, getpid());
25551.1Skamil	errno = 0;
25561.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25571.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25581.1Skamil
25591.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25601.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25611.1Skamil
25621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25631.1Skamil	    "without signal to be sent\n");
25641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25651.1Skamil
25661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25681.1Skamil
25691.1Skamil	validate_status_exited(status, exitval);
25701.1Skamil
25711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25731.1Skamil}
25741.1Skamil
25751.1SkamilATF_TC(read_d3);
25761.1SkamilATF_TC_HEAD(read_d3, tc)
25771.1Skamil{
25781.1Skamil	atf_tc_set_md_var(tc, "descr",
25791.1Skamil	    "Verify PT_READ_D called three times");
25801.1Skamil}
25811.1Skamil
25821.1SkamilATF_TC_BODY(read_d3, tc)
25831.1Skamil{
25841.1Skamil	const int exitval = 5;
25851.1Skamil	const int sigval = SIGSTOP;
25861.1Skamil	pid_t child, wpid;
25871.1Skamil	int lookup_me1 = 0;
25881.1Skamil	int lookup_me2 = 0;
25891.1Skamil	int lookup_me3 = 0;
25901.1Skamil	const int magic1 = (int)random();
25911.1Skamil	const int magic2 = (int)random();
25921.1Skamil	const int magic3 = (int)random();
25931.1Skamil#if defined(TWAIT_HAVE_STATUS)
25941.1Skamil	int status;
25951.1Skamil#endif
25961.1Skamil
25971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25991.1Skamil	if (child == 0) {
26001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26021.1Skamil
26031.1Skamil		lookup_me1 = magic1;
26041.1Skamil		lookup_me2 = magic2;
26051.1Skamil		lookup_me3 = magic3;
26061.1Skamil
26071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26091.1Skamil
26101.13Schristos		DPRINTF("Before exiting of the child process\n");
26111.1Skamil		_exit(exitval);
26121.1Skamil	}
26131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26141.1Skamil
26151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26171.1Skamil
26181.1Skamil	validate_status_stopped(status, sigval);
26191.1Skamil
26201.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
26211.1Skamil	    child, getpid());
26221.1Skamil	errno = 0;
26231.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26241.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26251.1Skamil
26261.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26271.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26281.1Skamil
26291.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26301.1Skamil	    child, getpid());
26311.1Skamil	errno = 0;
26321.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26331.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26341.1Skamil
26351.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26361.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26371.1Skamil
26381.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26391.1Skamil	    child, getpid());
26401.1Skamil	errno = 0;
26411.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26421.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26431.1Skamil
26441.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26451.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26461.1Skamil
26471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26481.1Skamil	    "without signal to be sent\n");
26491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26501.1Skamil
26511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26531.1Skamil
26541.1Skamil	validate_status_exited(status, exitval);
26551.1Skamil
26561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26581.1Skamil}
26591.1Skamil
26601.1SkamilATF_TC(read_d4);
26611.1SkamilATF_TC_HEAD(read_d4, tc)
26621.1Skamil{
26631.1Skamil	atf_tc_set_md_var(tc, "descr",
26641.1Skamil	    "Verify PT_READ_D called four times");
26651.1Skamil}
26661.1Skamil
26671.1SkamilATF_TC_BODY(read_d4, tc)
26681.1Skamil{
26691.1Skamil	const int exitval = 5;
26701.1Skamil	const int sigval = SIGSTOP;
26711.1Skamil	pid_t child, wpid;
26721.1Skamil	int lookup_me1 = 0;
26731.1Skamil	int lookup_me2 = 0;
26741.1Skamil	int lookup_me3 = 0;
26751.1Skamil	int lookup_me4 = 0;
26761.1Skamil	const int magic1 = (int)random();
26771.1Skamil	const int magic2 = (int)random();
26781.1Skamil	const int magic3 = (int)random();
26791.1Skamil	const int magic4 = (int)random();
26801.1Skamil#if defined(TWAIT_HAVE_STATUS)
26811.1Skamil	int status;
26821.1Skamil#endif
26831.1Skamil
26841.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26851.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26861.1Skamil	if (child == 0) {
26871.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26881.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26891.1Skamil
26901.1Skamil		lookup_me1 = magic1;
26911.1Skamil		lookup_me2 = magic2;
26921.1Skamil		lookup_me3 = magic3;
26931.1Skamil		lookup_me4 = magic4;
26941.1Skamil
26951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26971.1Skamil
26981.13Schristos		DPRINTF("Before exiting of the child process\n");
26991.1Skamil		_exit(exitval);
27001.1Skamil	}
27011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27021.1Skamil
27031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27051.1Skamil
27061.1Skamil	validate_status_stopped(status, sigval);
27071.1Skamil
27081.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
27091.1Skamil	    child, getpid());
27101.1Skamil	errno = 0;
27111.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
27121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27131.1Skamil
27141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
27151.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
27161.1Skamil
27171.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
27181.1Skamil	    child, getpid());
27191.1Skamil	errno = 0;
27201.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
27211.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27221.1Skamil
27231.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
27241.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
27251.1Skamil
27261.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
27271.1Skamil	    child, getpid());
27281.1Skamil	errno = 0;
27291.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
27301.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27311.1Skamil
27321.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
27331.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
27341.1Skamil
27351.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
27361.1Skamil	    child, getpid());
27371.1Skamil	errno = 0;
27381.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
27391.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
27401.1Skamil
27411.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
27421.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
27431.1Skamil
27441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27451.1Skamil	    "without signal to be sent\n");
27461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27471.1Skamil
27481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27501.1Skamil
27511.1Skamil	validate_status_exited(status, exitval);
27521.1Skamil
27531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27551.1Skamil}
27561.1Skamil
27571.1SkamilATF_TC(write_d1);
27581.1SkamilATF_TC_HEAD(write_d1, tc)
27591.1Skamil{
27601.1Skamil	atf_tc_set_md_var(tc, "descr",
27611.1Skamil	    "Verify PT_WRITE_D called once");
27621.1Skamil}
27631.1Skamil
27641.1SkamilATF_TC_BODY(write_d1, tc)
27651.1Skamil{
27661.1Skamil	const int exitval = 5;
27671.1Skamil	const int sigval = SIGSTOP;
27681.1Skamil	pid_t child, wpid;
27691.1Skamil	int lookup_me = 0;
27701.1Skamil	const int magic = (int)random();
27711.1Skamil#if defined(TWAIT_HAVE_STATUS)
27721.1Skamil	int status;
27731.1Skamil#endif
27741.1Skamil
27751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27771.1Skamil	if (child == 0) {
27781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27801.1Skamil
27811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27831.1Skamil
27841.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
27851.1Skamil
27861.13Schristos		DPRINTF("Before exiting of the child process\n");
27871.1Skamil		_exit(exitval);
27881.1Skamil	}
27891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27901.1Skamil
27911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27931.1Skamil
27941.1Skamil	validate_status_stopped(status, sigval);
27951.1Skamil
27961.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
27971.1Skamil	    child, getpid());
27981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
27991.1Skamil
28001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28011.1Skamil	    "without signal to be sent\n");
28021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28031.1Skamil
28041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28061.1Skamil
28071.1Skamil	validate_status_exited(status, exitval);
28081.1Skamil
28091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28111.1Skamil}
28121.1Skamil
28131.1SkamilATF_TC(write_d2);
28141.1SkamilATF_TC_HEAD(write_d2, tc)
28151.1Skamil{
28161.1Skamil	atf_tc_set_md_var(tc, "descr",
28171.1Skamil	    "Verify PT_WRITE_D called twice");
28181.1Skamil}
28191.1Skamil
28201.1SkamilATF_TC_BODY(write_d2, tc)
28211.1Skamil{
28221.1Skamil	const int exitval = 5;
28231.1Skamil	const int sigval = SIGSTOP;
28241.1Skamil	pid_t child, wpid;
28251.1Skamil	int lookup_me1 = 0;
28261.1Skamil	int lookup_me2 = 0;
28271.1Skamil	const int magic1 = (int)random();
28281.1Skamil	const int magic2 = (int)random();
28291.1Skamil#if defined(TWAIT_HAVE_STATUS)
28301.1Skamil	int status;
28311.1Skamil#endif
28321.1Skamil
28331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28351.1Skamil	if (child == 0) {
28361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28381.1Skamil
28391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28411.1Skamil
28421.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28431.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28441.1Skamil
28451.13Schristos		DPRINTF("Before exiting of the child process\n");
28461.1Skamil		_exit(exitval);
28471.1Skamil	}
28481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28491.1Skamil
28501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28521.1Skamil
28531.1Skamil	validate_status_stopped(status, sigval);
28541.1Skamil
28551.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28561.1Skamil	    child, getpid());
28571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28581.1Skamil
28591.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28601.1Skamil	    child, getpid());
28611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28621.1Skamil
28631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28641.1Skamil	    "without signal to be sent\n");
28651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28661.1Skamil
28671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28691.1Skamil
28701.1Skamil	validate_status_exited(status, exitval);
28711.1Skamil
28721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28741.1Skamil}
28751.1Skamil
28761.1SkamilATF_TC(write_d3);
28771.1SkamilATF_TC_HEAD(write_d3, tc)
28781.1Skamil{
28791.1Skamil	atf_tc_set_md_var(tc, "descr",
28801.1Skamil	    "Verify PT_WRITE_D called three times");
28811.1Skamil}
28821.1Skamil
28831.1SkamilATF_TC_BODY(write_d3, tc)
28841.1Skamil{
28851.1Skamil	const int exitval = 5;
28861.1Skamil	const int sigval = SIGSTOP;
28871.1Skamil	pid_t child, wpid;
28881.1Skamil	int lookup_me1 = 0;
28891.1Skamil	int lookup_me2 = 0;
28901.1Skamil	int lookup_me3 = 0;
28911.1Skamil	const int magic1 = (int)random();
28921.1Skamil	const int magic2 = (int)random();
28931.1Skamil	const int magic3 = (int)random();
28941.1Skamil#if defined(TWAIT_HAVE_STATUS)
28951.1Skamil	int status;
28961.1Skamil#endif
28971.1Skamil
28981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29001.1Skamil	if (child == 0) {
29011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29031.1Skamil
29041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29061.1Skamil
29071.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
29081.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
29091.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
29101.1Skamil
29111.13Schristos		DPRINTF("Before exiting of the child process\n");
29121.1Skamil		_exit(exitval);
29131.1Skamil	}
29141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29151.1Skamil
29161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29181.1Skamil
29191.1Skamil	validate_status_stopped(status, sigval);
29201.1Skamil
29211.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
29221.1Skamil	    child, getpid());
29231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
29241.1Skamil
29251.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
29261.1Skamil	    child, getpid());
29271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
29281.1Skamil
29291.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
29301.1Skamil	    child, getpid());
29311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
29321.1Skamil
29331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29341.1Skamil	    "without signal to be sent\n");
29351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29361.1Skamil
29371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29391.1Skamil
29401.1Skamil	validate_status_exited(status, exitval);
29411.1Skamil
29421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29441.1Skamil}
29451.1Skamil
29461.1SkamilATF_TC(write_d4);
29471.1SkamilATF_TC_HEAD(write_d4, tc)
29481.1Skamil{
29491.1Skamil	atf_tc_set_md_var(tc, "descr",
29501.1Skamil	    "Verify PT_WRITE_D called four times");
29511.1Skamil}
29521.1Skamil
29531.1SkamilATF_TC_BODY(write_d4, tc)
29541.1Skamil{
29551.1Skamil	const int exitval = 5;
29561.1Skamil	const int sigval = SIGSTOP;
29571.1Skamil	pid_t child, wpid;
29581.1Skamil	int lookup_me1 = 0;
29591.1Skamil	int lookup_me2 = 0;
29601.1Skamil	int lookup_me3 = 0;
29611.1Skamil	int lookup_me4 = 0;
29621.1Skamil	const int magic1 = (int)random();
29631.1Skamil	const int magic2 = (int)random();
29641.1Skamil	const int magic3 = (int)random();
29651.1Skamil	const int magic4 = (int)random();
29661.1Skamil#if defined(TWAIT_HAVE_STATUS)
29671.1Skamil	int status;
29681.1Skamil#endif
29691.1Skamil
29701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29721.1Skamil	if (child == 0) {
29731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29751.1Skamil
29761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29781.1Skamil
29791.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
29801.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
29811.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
29821.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
29831.1Skamil
29841.13Schristos		DPRINTF("Before exiting of the child process\n");
29851.1Skamil		_exit(exitval);
29861.1Skamil	}
29871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29881.1Skamil
29891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29911.1Skamil
29921.1Skamil	validate_status_stopped(status, sigval);
29931.1Skamil
29941.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
29951.1Skamil	    child, getpid());
29961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
29971.1Skamil
29981.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
29991.1Skamil	    child, getpid());
30001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
30011.1Skamil
30021.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
30031.1Skamil	    child, getpid());
30041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
30051.1Skamil
30061.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
30071.1Skamil	    child, getpid());
30081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
30091.1Skamil
30101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30111.1Skamil	    "without signal to be sent\n");
30121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30131.1Skamil
30141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30161.1Skamil
30171.1Skamil	validate_status_exited(status, exitval);
30181.1Skamil
30191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30211.1Skamil}
30221.1Skamil
30231.1SkamilATF_TC(io_read_d_write_d_handshake1);
30241.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
30251.1Skamil{
30261.1Skamil	atf_tc_set_md_var(tc, "descr",
30271.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
30281.1Skamil}
30291.1Skamil
30301.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
30311.1Skamil{
30321.1Skamil	const int exitval = 5;
30331.1Skamil	const int sigval = SIGSTOP;
30341.1Skamil	pid_t child, wpid;
30351.1Skamil	uint8_t lookup_me_fromtracee = 0;
30361.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30371.1Skamil	uint8_t lookup_me_totracee = 0;
30381.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30391.1Skamil	struct ptrace_io_desc io_fromtracee = {
30401.1Skamil		.piod_op = PIOD_READ_D,
30411.1Skamil		.piod_offs = &lookup_me_fromtracee,
30421.1Skamil		.piod_addr = &lookup_me_fromtracee,
30431.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30441.1Skamil	};
30451.1Skamil	struct ptrace_io_desc io_totracee = {
30461.1Skamil		.piod_op = PIOD_WRITE_D,
30471.1Skamil		.piod_offs = &lookup_me_totracee,
30481.1Skamil		.piod_addr = &lookup_me_totracee,
30491.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30501.1Skamil	};
30511.1Skamil#if defined(TWAIT_HAVE_STATUS)
30521.1Skamil	int status;
30531.1Skamil#endif
30541.1Skamil
30551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30571.1Skamil	if (child == 0) {
30581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30601.1Skamil
30611.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30621.1Skamil
30631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30651.1Skamil
30661.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30671.1Skamil
30681.13Schristos		DPRINTF("Before exiting of the child process\n");
30691.1Skamil		_exit(exitval);
30701.1Skamil	}
30711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30721.1Skamil
30731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30751.1Skamil
30761.1Skamil	validate_status_stopped(status, sigval);
30771.1Skamil
30781.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30791.1Skamil	    child, getpid());
30801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30811.1Skamil
30821.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30831.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30841.1Skamil	    magic_fromtracee);
30851.1Skamil
30861.1Skamil	lookup_me_totracee = magic_totracee;
30871.1Skamil
30881.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30891.1Skamil	    child, getpid());
30901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30911.1Skamil
30921.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30931.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30941.1Skamil	    magic_totracee);
30951.1Skamil
30961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30971.1Skamil	    "without signal to be sent\n");
30981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30991.1Skamil
31001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31021.1Skamil
31031.1Skamil	validate_status_exited(status, exitval);
31041.1Skamil
31051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31071.1Skamil}
31081.1Skamil
31091.1SkamilATF_TC(io_read_d_write_d_handshake2);
31101.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
31111.1Skamil{
31121.1Skamil	atf_tc_set_md_var(tc, "descr",
31131.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
31141.1Skamil}
31151.1Skamil
31161.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
31171.1Skamil{
31181.1Skamil	const int exitval = 5;
31191.1Skamil	const int sigval = SIGSTOP;
31201.1Skamil	pid_t child, wpid;
31211.1Skamil	uint8_t lookup_me_fromtracee = 0;
31221.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
31231.1Skamil	uint8_t lookup_me_totracee = 0;
31241.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
31251.1Skamil	struct ptrace_io_desc io_fromtracee = {
31261.1Skamil		.piod_op = PIOD_READ_D,
31271.1Skamil		.piod_offs = &lookup_me_fromtracee,
31281.1Skamil		.piod_addr = &lookup_me_fromtracee,
31291.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
31301.1Skamil	};
31311.1Skamil	struct ptrace_io_desc io_totracee = {
31321.1Skamil		.piod_op = PIOD_WRITE_D,
31331.1Skamil		.piod_offs = &lookup_me_totracee,
31341.1Skamil		.piod_addr = &lookup_me_totracee,
31351.1Skamil		.piod_len = sizeof(lookup_me_totracee)
31361.1Skamil	};
31371.1Skamil#if defined(TWAIT_HAVE_STATUS)
31381.1Skamil	int status;
31391.1Skamil#endif
31401.1Skamil
31411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31431.1Skamil	if (child == 0) {
31441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31461.1Skamil
31471.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31481.1Skamil
31491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31511.1Skamil
31521.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31531.1Skamil
31541.13Schristos		DPRINTF("Before exiting of the child process\n");
31551.1Skamil		_exit(exitval);
31561.1Skamil	}
31571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31581.1Skamil
31591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31611.1Skamil
31621.1Skamil	validate_status_stopped(status, sigval);
31631.1Skamil
31641.1Skamil	lookup_me_totracee = magic_totracee;
31651.1Skamil
31661.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
31671.1Skamil	    child, getpid());
31681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
31691.1Skamil
31701.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
31711.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
31721.1Skamil	    magic_totracee);
31731.1Skamil
31741.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31751.1Skamil	    child, getpid());
31761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
31771.1Skamil
31781.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31791.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
31801.1Skamil	    magic_fromtracee);
31811.1Skamil
31821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31831.1Skamil	    "without signal to be sent\n");
31841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31851.1Skamil
31861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31881.1Skamil
31891.1Skamil	validate_status_exited(status, exitval);
31901.1Skamil
31911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31931.1Skamil}
31941.1Skamil
31951.1SkamilATF_TC(read_d_write_d_handshake1);
31961.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
31971.1Skamil{
31981.1Skamil	atf_tc_set_md_var(tc, "descr",
31991.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
32001.1Skamil}
32011.1Skamil
32021.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
32031.1Skamil{
32041.1Skamil	const int exitval = 5;
32051.1Skamil	const int sigval = SIGSTOP;
32061.1Skamil	pid_t child, wpid;
32071.1Skamil	int lookup_me_fromtracee = 0;
32081.1Skamil	const int magic_fromtracee = (int)random();
32091.1Skamil	int lookup_me_totracee = 0;
32101.1Skamil	const int magic_totracee = (int)random();
32111.1Skamil#if defined(TWAIT_HAVE_STATUS)
32121.1Skamil	int status;
32131.1Skamil#endif
32141.1Skamil
32151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32171.1Skamil	if (child == 0) {
32181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32201.1Skamil
32211.1Skamil		lookup_me_fromtracee = magic_fromtracee;
32221.1Skamil
32231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32251.1Skamil
32261.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
32271.1Skamil
32281.13Schristos		DPRINTF("Before exiting of the child process\n");
32291.1Skamil		_exit(exitval);
32301.1Skamil	}
32311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32321.1Skamil
32331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32351.1Skamil
32361.1Skamil	validate_status_stopped(status, sigval);
32371.1Skamil
32381.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32391.1Skamil	    child, getpid());
32401.1Skamil	errno = 0;
32411.1Skamil	lookup_me_fromtracee =
32421.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32431.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32441.1Skamil
32451.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32461.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32471.1Skamil	    magic_fromtracee);
32481.1Skamil
32491.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32501.1Skamil	    child, getpid());
32511.1Skamil	ATF_REQUIRE
32521.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32531.1Skamil	    != -1);
32541.1Skamil
32551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32561.1Skamil	    "without signal to be sent\n");
32571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32581.1Skamil
32591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32611.1Skamil
32621.1Skamil	validate_status_exited(status, exitval);
32631.1Skamil
32641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32661.1Skamil}
32671.1Skamil
32681.1SkamilATF_TC(read_d_write_d_handshake2);
32691.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
32701.1Skamil{
32711.1Skamil	atf_tc_set_md_var(tc, "descr",
32721.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
32731.1Skamil}
32741.1Skamil
32751.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
32761.1Skamil{
32771.1Skamil	const int exitval = 5;
32781.1Skamil	const int sigval = SIGSTOP;
32791.1Skamil	pid_t child, wpid;
32801.1Skamil	int lookup_me_fromtracee = 0;
32811.1Skamil	const int magic_fromtracee = (int)random();
32821.1Skamil	int lookup_me_totracee = 0;
32831.1Skamil	const int magic_totracee = (int)random();
32841.1Skamil#if defined(TWAIT_HAVE_STATUS)
32851.1Skamil	int status;
32861.1Skamil#endif
32871.1Skamil
32881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32901.1Skamil	if (child == 0) {
32911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32931.1Skamil
32941.1Skamil		lookup_me_fromtracee = magic_fromtracee;
32951.1Skamil
32961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32981.1Skamil
32991.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
33001.1Skamil
33011.13Schristos		DPRINTF("Before exiting of the child process\n");
33021.1Skamil		_exit(exitval);
33031.1Skamil	}
33041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33051.1Skamil
33061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33081.1Skamil
33091.1Skamil	validate_status_stopped(status, sigval);
33101.1Skamil
33111.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
33121.1Skamil	    child, getpid());
33131.1Skamil	ATF_REQUIRE
33141.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
33151.1Skamil	    != -1);
33161.1Skamil
33171.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
33181.1Skamil	    child, getpid());
33191.1Skamil	errno = 0;
33201.1Skamil	lookup_me_fromtracee =
33211.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
33221.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
33231.1Skamil
33241.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
33251.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
33261.1Skamil	    magic_fromtracee);
33271.1Skamil
33281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33291.1Skamil	    "without signal to be sent\n");
33301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33311.1Skamil
33321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33341.1Skamil
33351.1Skamil	validate_status_exited(status, exitval);
33361.1Skamil
33371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33391.1Skamil}
33401.1Skamil
33411.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
33421.1Skamilstatic int __used
33431.1Skamildummy_fn1(int a, int b, int c, int d)
33441.1Skamil{
33451.1Skamil
33461.1Skamil	a *= 1;
33471.1Skamil	b += 2;
33481.1Skamil	c -= 3;
33491.1Skamil	d /= 4;
33501.1Skamil
33511.1Skamil	return a + b * c - d;
33521.1Skamil}
33531.1Skamil
33541.1Skamilstatic int __used
33551.1Skamildummy_fn2(int a, int b, int c, int d)
33561.1Skamil{
33571.1Skamil
33581.1Skamil	a *= 4;
33591.1Skamil	b += 3;
33601.1Skamil	c -= 2;
33611.1Skamil	d /= 1;
33621.1Skamil
33631.1Skamil	return a + b * c - d;
33641.1Skamil}
33651.1Skamil
33661.1Skamilstatic int __used
33671.1Skamildummy_fn3(int a, int b, int c, int d)
33681.1Skamil{
33691.1Skamil
33701.1Skamil	a *= 10;
33711.1Skamil	b += 20;
33721.1Skamil	c -= 30;
33731.1Skamil	d /= 40;
33741.1Skamil
33751.1Skamil	return a + b * c - d;
33761.1Skamil}
33771.1Skamil
33781.1Skamilstatic int __used
33791.1Skamildummy_fn4(int a, int b, int c, int d)
33801.1Skamil{
33811.1Skamil
33821.1Skamil	a *= 40;
33831.1Skamil	b += 30;
33841.1Skamil	c -= 20;
33851.1Skamil	d /= 10;
33861.1Skamil
33871.1Skamil	return a + b * c - d;
33881.1Skamil}
33891.1Skamil
33901.1SkamilATF_TC(io_read_i1);
33911.1SkamilATF_TC_HEAD(io_read_i1, tc)
33921.1Skamil{
33931.1Skamil	atf_tc_set_md_var(tc, "descr",
33941.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
33951.1Skamil}
33961.1Skamil
33971.1SkamilATF_TC_BODY(io_read_i1, tc)
33981.1Skamil{
33991.1Skamil	const int exitval = 5;
34001.1Skamil	const int sigval = SIGSTOP;
34011.1Skamil	pid_t child, wpid;
34021.1Skamil	uint8_t lookup_me = 0;
34031.1Skamil	uint8_t magic;
34041.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34051.1Skamil	struct ptrace_io_desc io = {
34061.1Skamil		.piod_op = PIOD_READ_I,
34071.1Skamil		.piod_offs = dummy_fn1,
34081.1Skamil		.piod_addr = &lookup_me,
34091.1Skamil		.piod_len = sizeof(lookup_me)
34101.1Skamil	};
34111.1Skamil#if defined(TWAIT_HAVE_STATUS)
34121.1Skamil	int status;
34131.1Skamil#endif
34141.1Skamil
34151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34171.1Skamil	if (child == 0) {
34181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34201.1Skamil
34211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34231.1Skamil
34241.13Schristos		DPRINTF("Before exiting of the child process\n");
34251.1Skamil		_exit(exitval);
34261.1Skamil	}
34271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34281.1Skamil
34291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34311.1Skamil
34321.1Skamil	validate_status_stopped(status, sigval);
34331.1Skamil
34341.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34351.1Skamil	    child, getpid());
34361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34371.1Skamil
34381.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34391.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
34401.1Skamil
34411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34421.1Skamil	    "without signal to be sent\n");
34431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
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_exited(status, exitval);
34491.1Skamil
34501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34521.1Skamil}
34531.1Skamil
34541.1SkamilATF_TC(io_read_i2);
34551.1SkamilATF_TC_HEAD(io_read_i2, tc)
34561.1Skamil{
34571.1Skamil	atf_tc_set_md_var(tc, "descr",
34581.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
34591.1Skamil}
34601.1Skamil
34611.1SkamilATF_TC_BODY(io_read_i2, tc)
34621.1Skamil{
34631.1Skamil	const int exitval = 5;
34641.1Skamil	const int sigval = SIGSTOP;
34651.1Skamil	pid_t child, wpid;
34661.1Skamil	uint16_t lookup_me = 0;
34671.1Skamil	uint16_t magic;
34681.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34691.1Skamil	struct ptrace_io_desc io = {
34701.1Skamil		.piod_op = PIOD_READ_I,
34711.1Skamil		.piod_offs = dummy_fn1,
34721.1Skamil		.piod_addr = &lookup_me,
34731.1Skamil		.piod_len = sizeof(lookup_me)
34741.1Skamil	};
34751.1Skamil#if defined(TWAIT_HAVE_STATUS)
34761.1Skamil	int status;
34771.1Skamil#endif
34781.1Skamil
34791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34811.1Skamil	if (child == 0) {
34821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34841.1Skamil
34851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34871.1Skamil
34881.13Schristos		DPRINTF("Before exiting of the child process\n");
34891.1Skamil		_exit(exitval);
34901.1Skamil	}
34911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34921.1Skamil
34931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34951.1Skamil
34961.1Skamil	validate_status_stopped(status, sigval);
34971.1Skamil
34981.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34991.1Skamil	    child, getpid());
35001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35011.1Skamil
35021.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35031.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
35041.1Skamil
35051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35061.1Skamil	    "without signal to be sent\n");
35071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
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_exited(status, exitval);
35131.1Skamil
35141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35161.1Skamil}
35171.1Skamil
35181.1SkamilATF_TC(io_read_i3);
35191.1SkamilATF_TC_HEAD(io_read_i3, tc)
35201.1Skamil{
35211.1Skamil	atf_tc_set_md_var(tc, "descr",
35221.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
35231.1Skamil}
35241.1Skamil
35251.1SkamilATF_TC_BODY(io_read_i3, tc)
35261.1Skamil{
35271.1Skamil	const int exitval = 5;
35281.1Skamil	const int sigval = SIGSTOP;
35291.1Skamil	pid_t child, wpid;
35301.1Skamil	uint32_t lookup_me = 0;
35311.1Skamil	uint32_t magic;
35321.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35331.1Skamil	struct ptrace_io_desc io = {
35341.1Skamil		.piod_op = PIOD_READ_I,
35351.1Skamil		.piod_offs = dummy_fn1,
35361.1Skamil		.piod_addr = &lookup_me,
35371.1Skamil		.piod_len = sizeof(lookup_me)
35381.1Skamil	};
35391.1Skamil#if defined(TWAIT_HAVE_STATUS)
35401.1Skamil	int status;
35411.1Skamil#endif
35421.1Skamil
35431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35451.1Skamil	if (child == 0) {
35461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35481.1Skamil
35491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35511.1Skamil
35521.13Schristos		DPRINTF("Before exiting of the child process\n");
35531.1Skamil		_exit(exitval);
35541.1Skamil	}
35551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35561.1Skamil
35571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35591.1Skamil
35601.1Skamil	validate_status_stopped(status, sigval);
35611.1Skamil
35621.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35631.1Skamil	    child, getpid());
35641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35651.1Skamil
35661.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35671.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
35681.1Skamil
35691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35701.1Skamil	    "without signal to be sent\n");
35711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
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_exited(status, exitval);
35771.1Skamil
35781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35801.1Skamil}
35811.1Skamil
35821.1SkamilATF_TC(io_read_i4);
35831.1SkamilATF_TC_HEAD(io_read_i4, tc)
35841.1Skamil{
35851.1Skamil	atf_tc_set_md_var(tc, "descr",
35861.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
35871.1Skamil}
35881.1Skamil
35891.1SkamilATF_TC_BODY(io_read_i4, tc)
35901.1Skamil{
35911.1Skamil	const int exitval = 5;
35921.1Skamil	const int sigval = SIGSTOP;
35931.1Skamil	pid_t child, wpid;
35941.1Skamil	uint64_t lookup_me = 0;
35951.1Skamil	uint64_t magic;
35961.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35971.1Skamil	struct ptrace_io_desc io = {
35981.1Skamil		.piod_op = PIOD_READ_I,
35991.1Skamil		.piod_offs = dummy_fn1,
36001.1Skamil		.piod_addr = &lookup_me,
36011.1Skamil		.piod_len = sizeof(lookup_me)
36021.1Skamil	};
36031.1Skamil#if defined(TWAIT_HAVE_STATUS)
36041.1Skamil	int status;
36051.1Skamil#endif
36061.1Skamil
36071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36091.1Skamil	if (child == 0) {
36101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36121.1Skamil
36131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36151.1Skamil
36161.13Schristos		DPRINTF("Before exiting of the child process\n");
36171.1Skamil		_exit(exitval);
36181.1Skamil	}
36191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36201.1Skamil
36211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36231.1Skamil
36241.1Skamil	validate_status_stopped(status, sigval);
36251.1Skamil
36261.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
36271.1Skamil	    child, getpid());
36281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
36291.1Skamil
36301.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36311.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
36321.1Skamil
36331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36341.1Skamil	    "without signal to be sent\n");
36351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36361.1Skamil
36371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36391.1Skamil
36401.1Skamil	validate_status_exited(status, exitval);
36411.1Skamil
36421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36441.1Skamil}
36451.1Skamil
36461.1SkamilATF_TC(read_i1);
36471.1SkamilATF_TC_HEAD(read_i1, tc)
36481.1Skamil{
36491.1Skamil	atf_tc_set_md_var(tc, "descr",
36501.1Skamil	    "Verify PT_READ_I called once");
36511.1Skamil}
36521.1Skamil
36531.1SkamilATF_TC_BODY(read_i1, tc)
36541.1Skamil{
36551.1Skamil	const int exitval = 5;
36561.1Skamil	const int sigval = SIGSTOP;
36571.1Skamil	pid_t child, wpid;
36581.1Skamil	int lookup_me = 0;
36591.1Skamil	int magic;
36601.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
36611.1Skamil#if defined(TWAIT_HAVE_STATUS)
36621.1Skamil	int status;
36631.1Skamil#endif
36641.1Skamil
36651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36671.1Skamil	if (child == 0) {
36681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36701.1Skamil
36711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36731.1Skamil
36741.13Schristos		DPRINTF("Before exiting of the child process\n");
36751.1Skamil		_exit(exitval);
36761.1Skamil	}
36771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36781.1Skamil
36791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36811.1Skamil
36821.1Skamil	validate_status_stopped(status, sigval);
36831.1Skamil
36841.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
36851.1Skamil	    child, getpid());
36861.1Skamil	errno = 0;
36871.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
36881.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36891.1Skamil
36901.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36911.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
36921.1Skamil
36931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36941.1Skamil	    "without signal to be sent\n");
36951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36961.1Skamil
36971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36991.1Skamil
37001.1Skamil	validate_status_exited(status, exitval);
37011.1Skamil
37021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37041.1Skamil}
37051.1Skamil
37061.1SkamilATF_TC(read_i2);
37071.1SkamilATF_TC_HEAD(read_i2, tc)
37081.1Skamil{
37091.1Skamil	atf_tc_set_md_var(tc, "descr",
37101.1Skamil	    "Verify PT_READ_I called twice");
37111.1Skamil}
37121.1Skamil
37131.1SkamilATF_TC_BODY(read_i2, tc)
37141.1Skamil{
37151.1Skamil	const int exitval = 5;
37161.1Skamil	const int sigval = SIGSTOP;
37171.1Skamil	pid_t child, wpid;
37181.1Skamil	int lookup_me1 = 0;
37191.1Skamil	int lookup_me2 = 0;
37201.1Skamil	int magic1;
37211.1Skamil	int magic2;
37221.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37231.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37241.1Skamil#if defined(TWAIT_HAVE_STATUS)
37251.1Skamil	int status;
37261.1Skamil#endif
37271.1Skamil
37281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37301.1Skamil	if (child == 0) {
37311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37331.1Skamil
37341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37361.1Skamil
37371.13Schristos		DPRINTF("Before exiting of the child process\n");
37381.1Skamil		_exit(exitval);
37391.1Skamil	}
37401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37411.1Skamil
37421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37441.1Skamil
37451.1Skamil	validate_status_stopped(status, sigval);
37461.1Skamil
37471.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37481.1Skamil	    child, getpid());
37491.1Skamil	errno = 0;
37501.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37511.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37521.1Skamil
37531.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37541.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37551.1Skamil
37561.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37571.1Skamil	    child, getpid());
37581.1Skamil	errno = 0;
37591.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37601.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37611.1Skamil
37621.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37631.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37641.1Skamil
37651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37661.1Skamil	    "without signal to be sent\n");
37671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
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_exited(status, exitval);
37731.1Skamil
37741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37761.1Skamil}
37771.1Skamil
37781.1SkamilATF_TC(read_i3);
37791.1SkamilATF_TC_HEAD(read_i3, tc)
37801.1Skamil{
37811.1Skamil	atf_tc_set_md_var(tc, "descr",
37821.1Skamil	    "Verify PT_READ_I called three times");
37831.1Skamil}
37841.1Skamil
37851.1SkamilATF_TC_BODY(read_i3, tc)
37861.1Skamil{
37871.1Skamil	const int exitval = 5;
37881.1Skamil	const int sigval = SIGSTOP;
37891.1Skamil	pid_t child, wpid;
37901.1Skamil	int lookup_me1 = 0;
37911.1Skamil	int lookup_me2 = 0;
37921.1Skamil	int lookup_me3 = 0;
37931.1Skamil	int magic1;
37941.1Skamil	int magic2;
37951.1Skamil	int magic3;
37961.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37971.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37981.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37991.1Skamil#if defined(TWAIT_HAVE_STATUS)
38001.1Skamil	int status;
38011.1Skamil#endif
38021.1Skamil
38031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38051.1Skamil	if (child == 0) {
38061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38081.1Skamil
38091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38111.1Skamil
38121.13Schristos		DPRINTF("Before exiting of the child process\n");
38131.1Skamil		_exit(exitval);
38141.1Skamil	}
38151.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38161.1Skamil
38171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38191.1Skamil
38201.1Skamil	validate_status_stopped(status, sigval);
38211.1Skamil
38221.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38231.1Skamil	    child, getpid());
38241.1Skamil	errno = 0;
38251.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38261.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38271.1Skamil
38281.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38291.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38301.1Skamil
38311.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38321.1Skamil	    child, getpid());
38331.1Skamil	errno = 0;
38341.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38351.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38361.1Skamil
38371.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38381.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38391.1Skamil
38401.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38411.1Skamil	    child, getpid());
38421.1Skamil	errno = 0;
38431.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38441.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38451.1Skamil
38461.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38471.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38481.1Skamil
38491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38501.1Skamil	    "without signal to be sent\n");
38511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38521.1Skamil
38531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38551.1Skamil
38561.1Skamil	validate_status_exited(status, exitval);
38571.1Skamil
38581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38601.1Skamil}
38611.1Skamil
38621.1SkamilATF_TC(read_i4);
38631.1SkamilATF_TC_HEAD(read_i4, tc)
38641.1Skamil{
38651.1Skamil	atf_tc_set_md_var(tc, "descr",
38661.1Skamil	    "Verify PT_READ_I called four times");
38671.1Skamil}
38681.1Skamil
38691.1SkamilATF_TC_BODY(read_i4, tc)
38701.1Skamil{
38711.1Skamil	const int exitval = 5;
38721.1Skamil	const int sigval = SIGSTOP;
38731.1Skamil	pid_t child, wpid;
38741.1Skamil	int lookup_me1 = 0;
38751.1Skamil	int lookup_me2 = 0;
38761.1Skamil	int lookup_me3 = 0;
38771.1Skamil	int lookup_me4 = 0;
38781.1Skamil	int magic1;
38791.1Skamil	int magic2;
38801.1Skamil	int magic3;
38811.1Skamil	int magic4;
38821.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
38831.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
38841.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
38851.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
38861.1Skamil#if defined(TWAIT_HAVE_STATUS)
38871.1Skamil	int status;
38881.1Skamil#endif
38891.1Skamil
38901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38921.1Skamil	if (child == 0) {
38931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38951.1Skamil
38961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38981.1Skamil
38991.13Schristos		DPRINTF("Before exiting of the child process\n");
39001.1Skamil		_exit(exitval);
39011.1Skamil	}
39021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39031.1Skamil
39041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39061.1Skamil
39071.1Skamil	validate_status_stopped(status, sigval);
39081.1Skamil
39091.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
39101.1Skamil	    child, getpid());
39111.1Skamil	errno = 0;
39121.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
39131.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39141.1Skamil
39151.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
39161.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
39171.1Skamil
39181.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
39191.1Skamil	    child, getpid());
39201.1Skamil	errno = 0;
39211.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
39221.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39231.1Skamil
39241.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
39251.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
39261.1Skamil
39271.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
39281.1Skamil	    child, getpid());
39291.1Skamil	errno = 0;
39301.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
39311.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39321.1Skamil
39331.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
39341.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
39351.1Skamil
39361.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
39371.1Skamil	    child, getpid());
39381.1Skamil	errno = 0;
39391.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
39401.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
39411.1Skamil
39421.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
39431.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
39441.1Skamil
39451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39461.1Skamil	    "without signal to be sent\n");
39471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39481.1Skamil
39491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39511.1Skamil
39521.1Skamil	validate_status_exited(status, exitval);
39531.1Skamil
39541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39561.1Skamil}
39571.1Skamil
39581.1Skamil#if defined(HAVE_GPREGS)
39591.1SkamilATF_TC(regs1);
39601.1SkamilATF_TC_HEAD(regs1, tc)
39611.1Skamil{
39621.1Skamil	atf_tc_set_md_var(tc, "descr",
39631.1Skamil	    "Verify plain PT_GETREGS call without further steps");
39641.1Skamil}
39651.1Skamil
39661.1SkamilATF_TC_BODY(regs1, tc)
39671.1Skamil{
39681.1Skamil	const int exitval = 5;
39691.1Skamil	const int sigval = SIGSTOP;
39701.1Skamil	pid_t child, wpid;
39711.1Skamil#if defined(TWAIT_HAVE_STATUS)
39721.1Skamil	int status;
39731.1Skamil#endif
39741.1Skamil	struct reg r;
39751.1Skamil
39761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39781.1Skamil	if (child == 0) {
39791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39811.1Skamil
39821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39841.1Skamil
39851.13Schristos		DPRINTF("Before exiting of the child process\n");
39861.1Skamil		_exit(exitval);
39871.1Skamil	}
39881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39891.1Skamil
39901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39921.1Skamil
39931.1Skamil	validate_status_stopped(status, sigval);
39941.1Skamil
39951.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39971.1Skamil
39981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39991.1Skamil	    "without signal to be sent\n");
40001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40011.1Skamil
40021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40041.1Skamil
40051.1Skamil	validate_status_exited(status, exitval);
40061.1Skamil
40071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40091.1Skamil}
40101.1Skamil#endif
40111.1Skamil
40121.1Skamil#if defined(HAVE_GPREGS)
40131.1SkamilATF_TC(regs2);
40141.1SkamilATF_TC_HEAD(regs2, tc)
40151.1Skamil{
40161.1Skamil	atf_tc_set_md_var(tc, "descr",
40171.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
40181.1Skamil}
40191.1Skamil
40201.1SkamilATF_TC_BODY(regs2, tc)
40211.1Skamil{
40221.1Skamil	const int exitval = 5;
40231.1Skamil	const int sigval = SIGSTOP;
40241.1Skamil	pid_t child, wpid;
40251.1Skamil#if defined(TWAIT_HAVE_STATUS)
40261.1Skamil	int status;
40271.1Skamil#endif
40281.1Skamil	struct reg r;
40291.1Skamil
40301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40321.1Skamil	if (child == 0) {
40331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40351.1Skamil
40361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40381.1Skamil
40391.13Schristos		DPRINTF("Before exiting of the child process\n");
40401.1Skamil		_exit(exitval);
40411.1Skamil	}
40421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40431.1Skamil
40441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40461.1Skamil
40471.1Skamil	validate_status_stopped(status, sigval);
40481.1Skamil
40491.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40511.1Skamil
40521.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
40531.1Skamil
40541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40551.1Skamil	    "without signal to be sent\n");
40561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40571.1Skamil
40581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40601.1Skamil
40611.1Skamil	validate_status_exited(status, exitval);
40621.1Skamil
40631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40651.1Skamil}
40661.1Skamil#endif
40671.1Skamil
40681.1Skamil#if defined(HAVE_GPREGS)
40691.1SkamilATF_TC(regs3);
40701.1SkamilATF_TC_HEAD(regs3, tc)
40711.1Skamil{
40721.1Skamil	atf_tc_set_md_var(tc, "descr",
40731.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
40741.1Skamil}
40751.1Skamil
40761.1SkamilATF_TC_BODY(regs3, tc)
40771.1Skamil{
40781.1Skamil	const int exitval = 5;
40791.1Skamil	const int sigval = SIGSTOP;
40801.1Skamil	pid_t child, wpid;
40811.1Skamil#if defined(TWAIT_HAVE_STATUS)
40821.1Skamil	int status;
40831.1Skamil#endif
40841.1Skamil	struct reg r;
40851.1Skamil
40861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40881.1Skamil	if (child == 0) {
40891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40911.1Skamil
40921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40941.1Skamil
40951.13Schristos		DPRINTF("Before exiting of the child process\n");
40961.1Skamil		_exit(exitval);
40971.1Skamil	}
40981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40991.1Skamil
41001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41021.1Skamil
41031.1Skamil	validate_status_stopped(status, sigval);
41041.1Skamil
41051.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41071.1Skamil
41081.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
41091.1Skamil
41101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41111.1Skamil	    "without signal to be sent\n");
41121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41131.1Skamil
41141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41161.1Skamil
41171.1Skamil	validate_status_exited(status, exitval);
41181.1Skamil
41191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41211.1Skamil}
41221.1Skamil#endif
41231.1Skamil
41241.1Skamil#if defined(HAVE_GPREGS)
41251.1SkamilATF_TC(regs4);
41261.1SkamilATF_TC_HEAD(regs4, tc)
41271.1Skamil{
41281.1Skamil	atf_tc_set_md_var(tc, "descr",
41291.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
41301.1Skamil}
41311.1Skamil
41321.1SkamilATF_TC_BODY(regs4, tc)
41331.1Skamil{
41341.1Skamil	const int exitval = 5;
41351.1Skamil	const int sigval = SIGSTOP;
41361.1Skamil	pid_t child, wpid;
41371.1Skamil#if defined(TWAIT_HAVE_STATUS)
41381.1Skamil	int status;
41391.1Skamil#endif
41401.1Skamil	struct reg r;
41411.1Skamil
41421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41441.1Skamil	if (child == 0) {
41451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41471.1Skamil
41481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41501.1Skamil
41511.13Schristos		DPRINTF("Before exiting of the child process\n");
41521.1Skamil		_exit(exitval);
41531.1Skamil	}
41541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41551.1Skamil
41561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41581.1Skamil
41591.1Skamil	validate_status_stopped(status, sigval);
41601.1Skamil
41611.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41631.1Skamil
41641.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
41651.1Skamil
41661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41671.1Skamil	    "without signal to be sent\n");
41681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41691.1Skamil
41701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41721.1Skamil
41731.1Skamil	validate_status_exited(status, exitval);
41741.1Skamil
41751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41771.1Skamil}
41781.1Skamil#endif
41791.1Skamil
41801.1Skamil#if defined(HAVE_GPREGS)
41811.1SkamilATF_TC(regs5);
41821.1SkamilATF_TC_HEAD(regs5, tc)
41831.1Skamil{
41841.1Skamil	atf_tc_set_md_var(tc, "descr",
41851.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
41861.1Skamil}
41871.1Skamil
41881.1SkamilATF_TC_BODY(regs5, tc)
41891.1Skamil{
41901.1Skamil	const int exitval = 5;
41911.1Skamil	const int sigval = SIGSTOP;
41921.1Skamil	pid_t child, wpid;
41931.1Skamil#if defined(TWAIT_HAVE_STATUS)
41941.1Skamil	int status;
41951.1Skamil#endif
41961.1Skamil	struct reg r;
41971.1Skamil
41981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42001.1Skamil	if (child == 0) {
42011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42031.1Skamil
42041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42061.1Skamil
42071.13Schristos		DPRINTF("Before exiting of the child process\n");
42081.1Skamil		_exit(exitval);
42091.1Skamil	}
42101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42111.1Skamil
42121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42141.1Skamil
42151.1Skamil	validate_status_stopped(status, sigval);
42161.1Skamil
42171.13Schristos	DPRINTF("Call GETREGS for the child process\n");
42181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
42191.1Skamil
42201.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
42211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
42221.1Skamil
42231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42241.1Skamil	    "without signal to be sent\n");
42251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42261.1Skamil
42271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42291.1Skamil
42301.1Skamil	validate_status_exited(status, exitval);
42311.1Skamil
42321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42341.1Skamil}
42351.1Skamil#endif
42361.1Skamil
42371.1Skamil#if defined(HAVE_FPREGS)
42381.1SkamilATF_TC(fpregs1);
42391.1SkamilATF_TC_HEAD(fpregs1, tc)
42401.1Skamil{
42411.1Skamil	atf_tc_set_md_var(tc, "descr",
42421.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
42431.1Skamil}
42441.1Skamil
42451.1SkamilATF_TC_BODY(fpregs1, tc)
42461.1Skamil{
42471.1Skamil	const int exitval = 5;
42481.1Skamil	const int sigval = SIGSTOP;
42491.1Skamil	pid_t child, wpid;
42501.1Skamil#if defined(TWAIT_HAVE_STATUS)
42511.1Skamil	int status;
42521.1Skamil#endif
42531.1Skamil	struct fpreg r;
42541.1Skamil
42551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42571.1Skamil	if (child == 0) {
42581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42601.1Skamil
42611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42631.1Skamil
42641.13Schristos		DPRINTF("Before exiting of the child process\n");
42651.1Skamil		_exit(exitval);
42661.1Skamil	}
42671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42681.1Skamil
42691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42711.1Skamil
42721.1Skamil	validate_status_stopped(status, sigval);
42731.1Skamil
42741.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42761.1Skamil
42771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42781.1Skamil	    "without signal to be sent\n");
42791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42801.1Skamil
42811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42831.1Skamil
42841.1Skamil	validate_status_exited(status, exitval);
42851.1Skamil
42861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42881.1Skamil}
42891.1Skamil#endif
42901.1Skamil
42911.1Skamil#if defined(HAVE_FPREGS)
42921.1SkamilATF_TC(fpregs2);
42931.1SkamilATF_TC_HEAD(fpregs2, tc)
42941.1Skamil{
42951.1Skamil	atf_tc_set_md_var(tc, "descr",
42961.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
42971.1Skamil	    "regs");
42981.1Skamil}
42991.1Skamil
43001.1SkamilATF_TC_BODY(fpregs2, tc)
43011.1Skamil{
43021.1Skamil	const int exitval = 5;
43031.1Skamil	const int sigval = SIGSTOP;
43041.1Skamil	pid_t child, wpid;
43051.1Skamil#if defined(TWAIT_HAVE_STATUS)
43061.1Skamil	int status;
43071.1Skamil#endif
43081.1Skamil	struct fpreg r;
43091.1Skamil
43101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43121.1Skamil	if (child == 0) {
43131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43151.1Skamil
43161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43181.1Skamil
43191.13Schristos		DPRINTF("Before exiting of the child process\n");
43201.1Skamil		_exit(exitval);
43211.1Skamil	}
43221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43231.1Skamil
43241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43261.1Skamil
43271.1Skamil	validate_status_stopped(status, sigval);
43281.1Skamil
43291.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
43301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
43311.1Skamil
43321.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
43331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
43341.1Skamil
43351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43361.1Skamil	    "without signal to be sent\n");
43371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43381.1Skamil
43391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43411.1Skamil
43421.1Skamil	validate_status_exited(status, exitval);
43431.1Skamil
43441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43461.1Skamil}
43471.1Skamil#endif
43481.1Skamil
43491.1Skamil#if defined(PT_STEP)
43501.1Skamilstatic void
43511.2Skamilptrace_step(int N, int setstep)
43521.1Skamil{
43531.1Skamil	const int exitval = 5;
43541.1Skamil	const int sigval = SIGSTOP;
43551.1Skamil	pid_t child, wpid;
43561.1Skamil#if defined(TWAIT_HAVE_STATUS)
43571.1Skamil	int status;
43581.1Skamil#endif
43591.1Skamil	int happy;
43601.1Skamil
43611.1Skamil#if defined(__arm__)
43621.1Skamil	/* PT_STEP not supported on arm 32-bit */
43631.1Skamil	atf_tc_expect_fail("PR kern/52119");
43641.1Skamil#endif
43651.1Skamil
43661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43681.1Skamil	if (child == 0) {
43691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43711.1Skamil
43721.1Skamil		happy = check_happy(999);
43731.1Skamil
43741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43761.1Skamil
43771.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
43781.1Skamil
43791.13Schristos		DPRINTF("Before exiting of the child process\n");
43801.1Skamil		_exit(exitval);
43811.1Skamil	}
43821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43831.1Skamil
43841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43861.1Skamil
43871.1Skamil	validate_status_stopped(status, sigval);
43881.1Skamil
43891.1Skamil	while (N --> 0) {
43901.2Skamil		if (setstep) {
43911.13Schristos			DPRINTF("Before resuming the child process where it "
43921.2Skamil			    "left off and without signal to be sent (use "
43931.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
43941.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
43951.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
43961.2Skamil			    != -1);
43971.2Skamil		} else {
43981.13Schristos			DPRINTF("Before resuming the child process where it "
43991.2Skamil			    "left off and without signal to be sent (use "
44001.2Skamil			    "PT_STEP)\n");
44011.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
44021.2Skamil			    != -1);
44031.2Skamil		}
44041.1Skamil
44051.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44061.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
44071.1Skamil		    child);
44081.1Skamil
44091.1Skamil		validate_status_stopped(status, SIGTRAP);
44101.2Skamil
44111.2Skamil		if (setstep) {
44121.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
44131.2Skamil		}
44141.1Skamil	}
44151.1Skamil
44161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44171.1Skamil	    "without signal to be sent\n");
44181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44191.1Skamil
44201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44221.1Skamil
44231.1Skamil	validate_status_exited(status, exitval);
44241.1Skamil
44251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44271.1Skamil}
44281.1Skamil#endif
44291.1Skamil
44301.1Skamil#if defined(PT_STEP)
44311.1SkamilATF_TC(step1);
44321.1SkamilATF_TC_HEAD(step1, tc)
44331.1Skamil{
44341.1Skamil	atf_tc_set_md_var(tc, "descr",
44351.1Skamil	    "Verify single PT_STEP call");
44361.1Skamil}
44371.1Skamil
44381.1SkamilATF_TC_BODY(step1, tc)
44391.1Skamil{
44401.2Skamil	ptrace_step(1, 0);
44411.1Skamil}
44421.1Skamil#endif
44431.1Skamil
44441.1Skamil#if defined(PT_STEP)
44451.1SkamilATF_TC(step2);
44461.1SkamilATF_TC_HEAD(step2, tc)
44471.1Skamil{
44481.1Skamil	atf_tc_set_md_var(tc, "descr",
44491.1Skamil	    "Verify PT_STEP called twice");
44501.1Skamil}
44511.1Skamil
44521.1SkamilATF_TC_BODY(step2, tc)
44531.1Skamil{
44541.2Skamil	ptrace_step(2, 0);
44551.1Skamil}
44561.1Skamil#endif
44571.1Skamil
44581.1Skamil#if defined(PT_STEP)
44591.1SkamilATF_TC(step3);
44601.1SkamilATF_TC_HEAD(step3, tc)
44611.1Skamil{
44621.1Skamil	atf_tc_set_md_var(tc, "descr",
44631.1Skamil	    "Verify PT_STEP called three times");
44641.1Skamil}
44651.1Skamil
44661.1SkamilATF_TC_BODY(step3, tc)
44671.1Skamil{
44681.2Skamil	ptrace_step(3, 0);
44691.1Skamil}
44701.1Skamil#endif
44711.1Skamil
44721.1Skamil#if defined(PT_STEP)
44731.1SkamilATF_TC(step4);
44741.1SkamilATF_TC_HEAD(step4, tc)
44751.1Skamil{
44761.1Skamil	atf_tc_set_md_var(tc, "descr",
44771.1Skamil	    "Verify PT_STEP called four times");
44781.1Skamil}
44791.1Skamil
44801.1SkamilATF_TC_BODY(step4, tc)
44811.1Skamil{
44821.2Skamil	ptrace_step(4, 0);
44831.2Skamil}
44841.2Skamil#endif
44851.2Skamil
44861.2Skamil#if defined(PT_STEP)
44871.2SkamilATF_TC(setstep1);
44881.2SkamilATF_TC_HEAD(setstep1, tc)
44891.2Skamil{
44901.2Skamil	atf_tc_set_md_var(tc, "descr",
44911.2Skamil	    "Verify single PT_SETSTEP call");
44921.2Skamil}
44931.2Skamil
44941.2SkamilATF_TC_BODY(setstep1, tc)
44951.2Skamil{
44961.2Skamil	ptrace_step(1, 1);
44971.2Skamil}
44981.2Skamil#endif
44991.2Skamil
45001.2Skamil#if defined(PT_STEP)
45011.2SkamilATF_TC(setstep2);
45021.2SkamilATF_TC_HEAD(setstep2, tc)
45031.2Skamil{
45041.2Skamil	atf_tc_set_md_var(tc, "descr",
45051.2Skamil	    "Verify PT_SETSTEP called twice");
45061.2Skamil}
45071.2Skamil
45081.2SkamilATF_TC_BODY(setstep2, tc)
45091.2Skamil{
45101.2Skamil	ptrace_step(2, 1);
45111.2Skamil}
45121.2Skamil#endif
45131.2Skamil
45141.2Skamil#if defined(PT_STEP)
45151.2SkamilATF_TC(setstep3);
45161.2SkamilATF_TC_HEAD(setstep3, tc)
45171.2Skamil{
45181.2Skamil	atf_tc_set_md_var(tc, "descr",
45191.2Skamil	    "Verify PT_SETSTEP called three times");
45201.2Skamil}
45211.2Skamil
45221.2SkamilATF_TC_BODY(setstep3, tc)
45231.2Skamil{
45241.2Skamil	ptrace_step(3, 1);
45251.2Skamil}
45261.2Skamil#endif
45271.2Skamil
45281.2Skamil#if defined(PT_STEP)
45291.2SkamilATF_TC(setstep4);
45301.2SkamilATF_TC_HEAD(setstep4, tc)
45311.2Skamil{
45321.2Skamil	atf_tc_set_md_var(tc, "descr",
45331.2Skamil	    "Verify PT_SETSTEP called four times");
45341.2Skamil}
45351.2Skamil
45361.2SkamilATF_TC_BODY(setstep4, tc)
45371.2Skamil{
45381.2Skamil	ptrace_step(4, 1);
45391.1Skamil}
45401.1Skamil#endif
45411.1Skamil
45421.1SkamilATF_TC(kill1);
45431.1SkamilATF_TC_HEAD(kill1, tc)
45441.1Skamil{
45451.1Skamil	atf_tc_set_md_var(tc, "descr",
45461.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
45471.1Skamil}
45481.1Skamil
45491.1SkamilATF_TC_BODY(kill1, tc)
45501.1Skamil{
45511.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
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_CONTINUE, child, (void *)1, sigsent) != -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, sigsent, 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(kill2);
45911.1SkamilATF_TC_HEAD(kill2, tc)
45921.1Skamil{
45931.1Skamil	atf_tc_set_md_var(tc, "descr",
45941.1Skamil	    "Verify that PT_KILL terminates child");
45951.1Skamil}
45961.1Skamil
45971.1SkamilATF_TC_BODY(kill2, tc)
45981.1Skamil{
45991.1Skamil	const int sigval = SIGSTOP;
46001.1Skamil	pid_t child, wpid;
46011.1Skamil#if defined(TWAIT_HAVE_STATUS)
46021.1Skamil	int status;
46031.1Skamil#endif
46041.1Skamil
46051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46071.1Skamil	if (child == 0) {
46081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46101.1Skamil
46111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46131.1Skamil
46141.1Skamil		/* NOTREACHED */
46151.1Skamil		FORKEE_ASSERTX(0 &&
46161.1Skamil		    "Child should be terminated by a signal from its parent");
46171.1Skamil	}
46181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46191.1Skamil
46201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46221.1Skamil
46231.1Skamil	validate_status_stopped(status, sigval);
46241.1Skamil
46251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46261.1Skamil	    "without signal to be sent\n");
46271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
46281.1Skamil
46291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46311.1Skamil
46321.1Skamil	validate_status_signaled(status, SIGKILL, 0);
46331.1Skamil
46341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46361.1Skamil}
46371.1Skamil
46381.1SkamilATF_TC(lwpinfo1);
46391.1SkamilATF_TC_HEAD(lwpinfo1, tc)
46401.1Skamil{
46411.1Skamil	atf_tc_set_md_var(tc, "descr",
46421.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
46431.1Skamil}
46441.1Skamil
46451.1SkamilATF_TC_BODY(lwpinfo1, tc)
46461.1Skamil{
46471.1Skamil	const int exitval = 5;
46481.1Skamil	const int sigval = SIGSTOP;
46491.1Skamil	pid_t child, wpid;
46501.1Skamil#if defined(TWAIT_HAVE_STATUS)
46511.1Skamil	int status;
46521.1Skamil#endif
46531.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46541.1Skamil
46551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46571.1Skamil	if (child == 0) {
46581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46601.1Skamil
46611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46631.1Skamil
46641.13Schristos		DPRINTF("Before exiting of the child process\n");
46651.1Skamil		_exit(exitval);
46661.1Skamil	}
46671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46681.1Skamil
46691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46711.1Skamil
46721.1Skamil	validate_status_stopped(status, sigval);
46731.1Skamil
46741.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46761.1Skamil
46771.13Schristos	DPRINTF("Assert that there exists a thread\n");
46781.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
46791.1Skamil
46801.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
46811.1Skamil	    info.pl_lwpid);
46821.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
46831.1Skamil	    "Received event %d != expected event %d",
46841.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
46851.1Skamil
46861.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46881.1Skamil
46891.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
46901.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
46911.1Skamil
46921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46931.1Skamil	    "without signal to be sent\n");
46941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46951.1Skamil
46961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46981.1Skamil
46991.1Skamil	validate_status_exited(status, exitval);
47001.1Skamil
47011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47031.1Skamil}
47041.1Skamil
47051.1Skamil#if defined(TWAIT_HAVE_PID)
47061.1SkamilATF_TC(lwpinfo2);
47071.1SkamilATF_TC_HEAD(lwpinfo2, tc)
47081.1Skamil{
47091.1Skamil	atf_tc_set_md_var(tc, "descr",
47101.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
47111.1Skamil	    "tracer)");
47121.1Skamil}
47131.1Skamil
47141.1SkamilATF_TC_BODY(lwpinfo2, tc)
47151.1Skamil{
47161.1Skamil	struct msg_fds parent_tracee, parent_tracer;
47171.1Skamil	const int exitval_tracee = 5;
47181.1Skamil	const int exitval_tracer = 10;
47191.1Skamil	pid_t tracee, tracer, wpid;
47201.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
47211.1Skamil#if defined(TWAIT_HAVE_STATUS)
47221.1Skamil	int status;
47231.1Skamil#endif
47241.1Skamil	struct ptrace_lwpinfo info = {0, 0};
47251.1Skamil
47261.13Schristos	DPRINTF("Spawn tracee\n");
47271.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
47281.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
47291.1Skamil	tracee = atf_utils_fork();
47301.1Skamil	if (tracee == 0) {
47311.1Skamil
47321.1Skamil		/* Wait for message from the parent */
47331.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
47341.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
47351.1Skamil
47361.1Skamil		_exit(exitval_tracee);
47371.1Skamil	}
47381.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
47391.1Skamil
47401.13Schristos	DPRINTF("Spawn debugger\n");
47411.1Skamil	tracer = atf_utils_fork();
47421.1Skamil	if (tracer == 0) {
47431.1Skamil		/* No IPC to communicate with the child */
47441.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
47451.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
47461.1Skamil
47471.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
47481.1Skamil		FORKEE_REQUIRE_SUCCESS(
47491.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47501.1Skamil
47511.1Skamil		forkee_status_stopped(status, SIGSTOP);
47521.1Skamil
47531.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47541.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47551.1Skamil		    != -1);
47561.1Skamil
47571.13Schristos		DPRINTF("Assert that there exists a thread\n");
47581.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
47591.1Skamil
47601.13Schristos		DPRINTF("Assert that lwp thread %d received event "
47611.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
47621.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
47631.1Skamil
47641.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47651.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47661.1Skamil		    != -1);
47671.1Skamil
47681.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
47691.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
47701.1Skamil
47711.1Skamil		/* Resume tracee with PT_CONTINUE */
47721.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
47731.1Skamil
47741.1Skamil		/* Inform parent that tracer has attached to tracee */
47751.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
47761.1Skamil		/* Wait for parent */
47771.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
47781.1Skamil
47791.1Skamil		/* Wait for tracee and assert that it exited */
47801.1Skamil		FORKEE_REQUIRE_SUCCESS(
47811.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47821.1Skamil
47831.1Skamil		forkee_status_exited(status, exitval_tracee);
47841.1Skamil
47851.13Schristos		DPRINTF("Before exiting of the tracer process\n");
47861.1Skamil		_exit(exitval_tracer);
47871.1Skamil	}
47881.1Skamil
47891.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
47901.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
47911.1Skamil
47921.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
47931.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
47941.1Skamil
47951.13Schristos	DPRINTF("Detect that tracee is zombie\n");
47961.1Skamil	await_zombie(tracee);
47971.1Skamil
47981.13Schristos	DPRINTF("Assert that there is no status about tracee - "
47991.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
48001.1Skamil	TWAIT_REQUIRE_SUCCESS(
48011.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
48021.1Skamil
48031.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
48041.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
48051.1Skamil
48061.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
48071.1Skamil	    TWAIT_FNAME);
48081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
48091.1Skamil	    tracer);
48101.1Skamil
48111.1Skamil	validate_status_exited(status, exitval_tracer);
48121.1Skamil
48131.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
48141.1Skamil	    TWAIT_FNAME);
48151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
48161.1Skamil	    tracee);
48171.1Skamil
48181.1Skamil	validate_status_exited(status, exitval_tracee);
48191.1Skamil
48201.1Skamil	msg_close(&parent_tracer);
48211.1Skamil	msg_close(&parent_tracee);
48221.1Skamil}
48231.1Skamil#endif
48241.1Skamil
48251.1SkamilATF_TC(siginfo1);
48261.1SkamilATF_TC_HEAD(siginfo1, tc)
48271.1Skamil{
48281.1Skamil	atf_tc_set_md_var(tc, "descr",
48291.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
48301.1Skamil}
48311.1Skamil
48321.1SkamilATF_TC_BODY(siginfo1, tc)
48331.1Skamil{
48341.1Skamil	const int exitval = 5;
48351.1Skamil	const int sigval = SIGTRAP;
48361.1Skamil	pid_t child, wpid;
48371.1Skamil#if defined(TWAIT_HAVE_STATUS)
48381.1Skamil	int status;
48391.1Skamil#endif
48401.1Skamil	struct ptrace_siginfo info;
48411.1Skamil	memset(&info, 0, sizeof(info));
48421.1Skamil
48431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48451.1Skamil	if (child == 0) {
48461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48481.1Skamil
48491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48511.1Skamil
48521.13Schristos		DPRINTF("Before exiting of the child process\n");
48531.1Skamil		_exit(exitval);
48541.1Skamil	}
48551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48561.1Skamil
48571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48591.1Skamil
48601.1Skamil	validate_status_stopped(status, sigval);
48611.1Skamil
48621.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48641.1Skamil
48651.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48661.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48671.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48681.1Skamil	    info.psi_siginfo.si_errno);
48691.1Skamil
48701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48711.1Skamil	    "without signal to be sent\n");
48721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48731.1Skamil
48741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48761.1Skamil
48771.1Skamil	validate_status_exited(status, exitval);
48781.1Skamil
48791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48811.1Skamil}
48821.1Skamil
48831.1SkamilATF_TC(siginfo2);
48841.1SkamilATF_TC_HEAD(siginfo2, tc)
48851.1Skamil{
48861.1Skamil	atf_tc_set_md_var(tc, "descr",
48871.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
48881.1Skamil	    "modification of SIGINT from tracee");
48891.1Skamil}
48901.1Skamil
48911.1Skamilstatic int siginfo2_caught = 0;
48921.1Skamil
48931.1Skamilstatic void
48941.1Skamilsiginfo2_sighandler(int sig)
48951.1Skamil{
48961.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
48971.1Skamil
48981.1Skamil	++siginfo2_caught;
48991.1Skamil}
49001.1Skamil
49011.1SkamilATF_TC_BODY(siginfo2, tc)
49021.1Skamil{
49031.1Skamil	const int exitval = 5;
49041.1Skamil	const int sigval = SIGINT;
49051.1Skamil	pid_t child, wpid;
49061.1Skamil	struct sigaction sa;
49071.1Skamil#if defined(TWAIT_HAVE_STATUS)
49081.1Skamil	int status;
49091.1Skamil#endif
49101.1Skamil	struct ptrace_siginfo info;
49111.1Skamil	memset(&info, 0, sizeof(info));
49121.1Skamil
49131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49151.1Skamil	if (child == 0) {
49161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49181.1Skamil
49191.1Skamil		sa.sa_handler = siginfo2_sighandler;
49201.1Skamil		sa.sa_flags = SA_SIGINFO;
49211.1Skamil		sigemptyset(&sa.sa_mask);
49221.1Skamil
49231.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
49241.1Skamil
49251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49271.1Skamil
49281.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
49291.1Skamil
49301.13Schristos		DPRINTF("Before exiting of the child process\n");
49311.1Skamil		_exit(exitval);
49321.1Skamil	}
49331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49341.1Skamil
49351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49371.1Skamil
49381.1Skamil	validate_status_stopped(status, sigval);
49391.1Skamil
49401.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49421.1Skamil
49431.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49441.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49451.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49461.1Skamil	    info.psi_siginfo.si_errno);
49471.1Skamil
49481.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49501.1Skamil
49511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49521.1Skamil	    "without signal to be sent\n");
49531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
49541.1Skamil
49551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49571.1Skamil
49581.1Skamil	validate_status_exited(status, exitval);
49591.1Skamil
49601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49621.1Skamil}
49631.1Skamil
49641.1SkamilATF_TC(siginfo3);
49651.1SkamilATF_TC_HEAD(siginfo3, tc)
49661.1Skamil{
49671.1Skamil	atf_tc_set_md_var(tc, "descr",
49681.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
49691.1Skamil	    "setting signal to new value");
49701.1Skamil}
49711.1Skamil
49721.1Skamilstatic int siginfo3_caught = 0;
49731.1Skamil
49741.1Skamilstatic void
49751.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
49761.1Skamil{
49771.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
49781.1Skamil
49791.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
49801.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
49811.1Skamil
49821.1Skamil	++siginfo3_caught;
49831.1Skamil}
49841.1Skamil
49851.1SkamilATF_TC_BODY(siginfo3, tc)
49861.1Skamil{
49871.1Skamil	const int exitval = 5;
49881.1Skamil	const int sigval = SIGINT;
49891.1Skamil	const int sigfaked = SIGTRAP;
49901.1Skamil	const int sicodefaked = TRAP_BRKPT;
49911.1Skamil	pid_t child, wpid;
49921.1Skamil	struct sigaction sa;
49931.1Skamil#if defined(TWAIT_HAVE_STATUS)
49941.1Skamil	int status;
49951.1Skamil#endif
49961.1Skamil	struct ptrace_siginfo info;
49971.1Skamil	memset(&info, 0, sizeof(info));
49981.1Skamil
49991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50011.1Skamil	if (child == 0) {
50021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50041.1Skamil
50051.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
50061.1Skamil		sa.sa_flags = SA_SIGINFO;
50071.1Skamil		sigemptyset(&sa.sa_mask);
50081.1Skamil
50091.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
50101.1Skamil
50111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50131.1Skamil
50141.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
50151.1Skamil
50161.13Schristos		DPRINTF("Before exiting of the child process\n");
50171.1Skamil		_exit(exitval);
50181.1Skamil	}
50191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50201.1Skamil
50211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50231.1Skamil
50241.1Skamil	validate_status_stopped(status, sigval);
50251.1Skamil
50261.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50281.1Skamil
50291.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50301.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50311.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50321.1Skamil	    info.psi_siginfo.si_errno);
50331.1Skamil
50341.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
50351.1Skamil	    sigfaked, sicodefaked);
50361.1Skamil	info.psi_siginfo.si_signo = sigfaked;
50371.1Skamil	info.psi_siginfo.si_code = sicodefaked;
50381.1Skamil
50391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
50401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
50411.1Skamil
50421.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50441.1Skamil
50451.13Schristos	DPRINTF("Before checking siginfo_t\n");
50461.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
50471.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
50481.1Skamil
50491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50501.1Skamil	    "without signal to be sent\n");
50511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
50521.1Skamil
50531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50551.1Skamil
50561.1Skamil	validate_status_exited(status, exitval);
50571.1Skamil
50581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50601.1Skamil}
50611.1Skamil
50621.1SkamilATF_TC(siginfo4);
50631.1SkamilATF_TC_HEAD(siginfo4, tc)
50641.1Skamil{
50651.1Skamil	atf_tc_set_md_var(tc, "descr",
50661.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
50671.1Skamil}
50681.1Skamil
50691.1SkamilATF_TC_BODY(siginfo4, tc)
50701.1Skamil{
50711.1Skamil	const int sigval = SIGTRAP;
50721.1Skamil	pid_t child, wpid;
50731.1Skamil#if defined(TWAIT_HAVE_STATUS)
50741.1Skamil	int status;
50751.1Skamil#endif
50761.1Skamil
50771.1Skamil	struct ptrace_siginfo info;
50781.1Skamil	memset(&info, 0, sizeof(info));
50791.1Skamil
50801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50821.1Skamil	if (child == 0) {
50831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50851.1Skamil
50861.13Schristos		DPRINTF("Before calling execve(2) from child\n");
50871.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
50881.1Skamil
50891.1Skamil		FORKEE_ASSERT(0 && "Not reached");
50901.1Skamil	}
50911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50921.1Skamil
50931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50951.1Skamil
50961.1Skamil	validate_status_stopped(status, sigval);
50971.1Skamil
50981.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51001.1Skamil
51011.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
51021.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
51031.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
51041.1Skamil	    info.psi_siginfo.si_errno);
51051.1Skamil
51061.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51071.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
51081.1Skamil
51091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51101.1Skamil	    "without signal to be sent\n");
51111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51121.1Skamil
51131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51151.1Skamil
51161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51181.1Skamil}
51191.1Skamil
51201.1Skamil#if defined(TWAIT_HAVE_PID)
51211.1SkamilATF_TC(siginfo5);
51221.1SkamilATF_TC_HEAD(siginfo5, tc)
51231.1Skamil{
51241.1Skamil	atf_tc_set_md_var(tc, "descr",
51251.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
51261.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
51271.1Skamil}
51281.1Skamil
51291.1SkamilATF_TC_BODY(siginfo5, tc)
51301.1Skamil{
51311.1Skamil	const int exitval = 5;
51321.1Skamil	const int exitval2 = 15;
51331.1Skamil	const int sigval = SIGSTOP;
51341.1Skamil	pid_t child, child2, wpid;
51351.1Skamil#if defined(TWAIT_HAVE_STATUS)
51361.1Skamil	int status;
51371.1Skamil#endif
51381.1Skamil	ptrace_state_t state;
51391.1Skamil	const int slen = sizeof(state);
51401.1Skamil	ptrace_event_t event;
51411.1Skamil	const int elen = sizeof(event);
51421.1Skamil	struct ptrace_siginfo info;
51431.1Skamil
51441.1Skamil	memset(&info, 0, sizeof(info));
51451.1Skamil
51461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51481.1Skamil	if (child == 0) {
51491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51511.1Skamil
51521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51541.1Skamil
51551.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
51561.1Skamil
51571.1Skamil		if (child2 == 0)
51581.1Skamil			_exit(exitval2);
51591.1Skamil
51601.1Skamil		FORKEE_REQUIRE_SUCCESS
51611.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
51621.1Skamil
51631.1Skamil		forkee_status_exited(status, exitval2);
51641.1Skamil
51651.13Schristos		DPRINTF("Before exiting of the child process\n");
51661.1Skamil		_exit(exitval);
51671.1Skamil	}
51681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51691.1Skamil
51701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51721.1Skamil
51731.1Skamil	validate_status_stopped(status, sigval);
51741.1Skamil
51751.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51771.1Skamil
51781.13Schristos	DPRINTF("Before checking siginfo_t\n");
51791.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51801.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
51811.1Skamil
51821.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
51831.1Skamil	event.pe_set_event = PTRACE_FORK;
51841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -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        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
51891.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
51901.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
51911.1Skamil                "state.pe_other_pid=child)\n", child);
51921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51931.1Skamil
51941.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
51951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51961.1Skamil
51971.1Skamil	validate_status_stopped(status, SIGTRAP);
51981.1Skamil
51991.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52011.1Skamil
52021.13Schristos	DPRINTF("Before checking siginfo_t\n");
52031.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
52041.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
52051.1Skamil
52061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
52071.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
52081.1Skamil
52091.1Skamil	child2 = state.pe_other_pid;
52101.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
52111.1Skamil
52121.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
52131.1Skamil	    TWAIT_FNAME, child2, child);
52141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
52151.1Skamil	    child2);
52161.1Skamil
52171.1Skamil	validate_status_stopped(status, SIGTRAP);
52181.1Skamil
52191.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52211.1Skamil
52221.13Schristos	DPRINTF("Before checking siginfo_t\n");
52231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
52241.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
52251.1Skamil
52261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
52271.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
52281.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
52291.1Skamil
52301.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
52311.1Skamil	    "without signal to be sent\n");
52321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
52331.1Skamil
52341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52351.1Skamil	    "without signal to be sent\n");
52361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52371.1Skamil
52381.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
52391.1Skamil	    TWAIT_FNAME);
52401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
52411.1Skamil	    child2);
52421.1Skamil
52431.1Skamil	validate_status_exited(status, exitval2);
52441.1Skamil
52451.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
52461.1Skamil	    TWAIT_FNAME);
52471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
52481.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
52491.1Skamil
52501.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52511.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
52521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52531.1Skamil
52541.1Skamil	validate_status_stopped(status, SIGCHLD);
52551.1Skamil
52561.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52581.1Skamil
52591.13Schristos	DPRINTF("Before checking siginfo_t\n");
52601.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
52611.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
52621.1Skamil
52631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52641.1Skamil	    "without signal to be sent\n");
52651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52661.1Skamil
52671.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52681.1Skamil	    TWAIT_FNAME);
52691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52701.1Skamil
52711.1Skamil	validate_status_exited(status, exitval);
52721.1Skamil
52731.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52741.1Skamil	    TWAIT_FNAME);
52751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52761.1Skamil}
52771.1Skamil#endif
52781.1Skamil
52791.1Skamil#if defined(PT_STEP)
52801.1SkamilATF_TC(siginfo6);
52811.1SkamilATF_TC_HEAD(siginfo6, tc)
52821.1Skamil{
52831.1Skamil	atf_tc_set_md_var(tc, "descr",
52841.1Skamil	    "Verify single PT_STEP call with signal information check");
52851.1Skamil}
52861.1Skamil
52871.1SkamilATF_TC_BODY(siginfo6, tc)
52881.1Skamil{
52891.1Skamil	const int exitval = 5;
52901.1Skamil	const int sigval = SIGSTOP;
52911.1Skamil	pid_t child, wpid;
52921.1Skamil#if defined(TWAIT_HAVE_STATUS)
52931.1Skamil	int status;
52941.1Skamil#endif
52951.1Skamil	int happy;
52961.1Skamil	struct ptrace_siginfo info;
52971.1Skamil
52981.1Skamil#if defined(__arm__)
52991.1Skamil	/* PT_STEP not supported on arm 32-bit */
53001.1Skamil	atf_tc_expect_fail("PR kern/52119");
53011.1Skamil#endif
53021.1Skamil
53031.1Skamil	memset(&info, 0, sizeof(info));
53041.1Skamil
53051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53071.1Skamil	if (child == 0) {
53081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53101.1Skamil
53111.1Skamil		happy = check_happy(100);
53121.1Skamil
53131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53151.1Skamil
53161.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
53171.1Skamil
53181.13Schristos		DPRINTF("Before exiting of the child process\n");
53191.1Skamil		_exit(exitval);
53201.1Skamil	}
53211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53221.1Skamil
53231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53251.1Skamil
53261.1Skamil	validate_status_stopped(status, sigval);
53271.1Skamil
53281.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53301.1Skamil
53311.13Schristos	DPRINTF("Before checking siginfo_t\n");
53321.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
53331.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
53341.1Skamil
53351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53361.1Skamil	    "without signal to be sent (use PT_STEP)\n");
53371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
53381.1Skamil
53391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53411.1Skamil
53421.1Skamil	validate_status_stopped(status, SIGTRAP);
53431.1Skamil
53441.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
53451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
53461.1Skamil
53471.13Schristos	DPRINTF("Before checking siginfo_t\n");
53481.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
53491.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
53501.1Skamil
53511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53521.1Skamil	    "without signal to be sent\n");
53531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53541.1Skamil
53551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53571.1Skamil
53581.1Skamil	validate_status_exited(status, exitval);
53591.1Skamil
53601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53621.1Skamil}
53631.1Skamil#endif
53641.1Skamil
53651.1Skamilvolatile lwpid_t the_lwp_id = 0;
53661.1Skamil
53671.1Skamilstatic void
53681.1Skamillwp_main_func(void *arg)
53691.1Skamil{
53701.1Skamil	the_lwp_id = _lwp_self();
53711.1Skamil	_lwp_exit();
53721.1Skamil}
53731.1Skamil
53741.1SkamilATF_TC(lwp_create1);
53751.1SkamilATF_TC_HEAD(lwp_create1, tc)
53761.1Skamil{
53771.1Skamil	atf_tc_set_md_var(tc, "descr",
53781.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53791.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
53801.1Skamil}
53811.1Skamil
53821.1SkamilATF_TC_BODY(lwp_create1, tc)
53831.1Skamil{
53841.1Skamil	const int exitval = 5;
53851.1Skamil	const int sigval = SIGSTOP;
53861.1Skamil	pid_t child, wpid;
53871.1Skamil#if defined(TWAIT_HAVE_STATUS)
53881.1Skamil	int status;
53891.1Skamil#endif
53901.1Skamil	ptrace_state_t state;
53911.1Skamil	const int slen = sizeof(state);
53921.1Skamil	ptrace_event_t event;
53931.1Skamil	const int elen = sizeof(event);
53941.1Skamil	ucontext_t uc;
53951.1Skamil	lwpid_t lid;
53961.1Skamil	static const size_t ssize = 16*1024;
53971.1Skamil	void *stack;
53981.1Skamil
53991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54011.1Skamil	if (child == 0) {
54021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54041.1Skamil
54051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54071.1Skamil
54081.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54091.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54101.1Skamil
54111.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54121.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54131.1Skamil
54141.13Schristos		DPRINTF("Before creating new in child\n");
54151.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54161.1Skamil
54171.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54181.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54191.1Skamil
54201.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54211.1Skamil		    "are the same\n", lid, the_lwp_id);
54221.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54231.1Skamil
54241.13Schristos		DPRINTF("Before exiting of the child process\n");
54251.1Skamil		_exit(exitval);
54261.1Skamil	}
54271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54281.1Skamil
54291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54311.1Skamil
54321.1Skamil	validate_status_stopped(status, sigval);
54331.1Skamil
54341.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54351.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
54361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54371.1Skamil
54381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54391.1Skamil	    "without signal to be sent\n");
54401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54411.1Skamil
54421.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54431.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54451.1Skamil
54461.1Skamil	validate_status_stopped(status, SIGTRAP);
54471.1Skamil
54481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54491.1Skamil
54501.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
54511.1Skamil
54521.1Skamil	lid = state.pe_lwp;
54531.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54541.1Skamil
54551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54561.1Skamil	    "without signal to be sent\n");
54571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54581.1Skamil
54591.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54601.1Skamil	    TWAIT_FNAME);
54611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54621.1Skamil
54631.1Skamil	validate_status_exited(status, exitval);
54641.1Skamil
54651.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54661.1Skamil	    TWAIT_FNAME);
54671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54681.1Skamil}
54691.1Skamil
54701.1SkamilATF_TC(lwp_exit1);
54711.1SkamilATF_TC_HEAD(lwp_exit1, tc)
54721.1Skamil{
54731.1Skamil	atf_tc_set_md_var(tc, "descr",
54741.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
54751.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
54761.1Skamil}
54771.1Skamil
54781.1SkamilATF_TC_BODY(lwp_exit1, tc)
54791.1Skamil{
54801.1Skamil	const int exitval = 5;
54811.1Skamil	const int sigval = SIGSTOP;
54821.1Skamil	pid_t child, wpid;
54831.1Skamil#if defined(TWAIT_HAVE_STATUS)
54841.1Skamil	int status;
54851.1Skamil#endif
54861.1Skamil	ptrace_state_t state;
54871.1Skamil	const int slen = sizeof(state);
54881.1Skamil	ptrace_event_t event;
54891.1Skamil	const int elen = sizeof(event);
54901.1Skamil	ucontext_t uc;
54911.1Skamil	lwpid_t lid;
54921.1Skamil	static const size_t ssize = 16*1024;
54931.1Skamil	void *stack;
54941.1Skamil
54951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54971.1Skamil	if (child == 0) {
54981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55001.1Skamil
55011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55031.1Skamil
55041.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
55051.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
55061.1Skamil
55071.13Schristos		DPRINTF("Before making context for new lwp in child\n");
55081.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
55091.1Skamil
55101.13Schristos		DPRINTF("Before creating new in child\n");
55111.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
55121.1Skamil
55131.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
55141.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
55151.1Skamil
55161.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
55171.1Skamil		    "are the same\n", lid, the_lwp_id);
55181.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
55191.1Skamil
55201.13Schristos		DPRINTF("Before exiting of the child process\n");
55211.1Skamil		_exit(exitval);
55221.1Skamil	}
55231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55241.1Skamil
55251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55271.1Skamil
55281.1Skamil	validate_status_stopped(status, sigval);
55291.1Skamil
55301.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
55311.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
55321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
55331.1Skamil
55341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55351.1Skamil	    "without signal to be sent\n");
55361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55371.1Skamil
55381.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
55391.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
55401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55411.1Skamil
55421.1Skamil	validate_status_stopped(status, SIGTRAP);
55431.1Skamil
55441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
55451.1Skamil
55461.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
55471.1Skamil
55481.1Skamil	lid = state.pe_lwp;
55491.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55501.1Skamil
55511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55521.1Skamil	    "without signal to be sent\n");
55531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55541.1Skamil
55551.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55561.1Skamil	    TWAIT_FNAME);
55571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55581.1Skamil
55591.1Skamil	validate_status_exited(status, exitval);
55601.1Skamil
55611.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55621.1Skamil	    TWAIT_FNAME);
55631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55641.1Skamil}
55651.1Skamil
55661.1SkamilATF_TC(signal1);
55671.1SkamilATF_TC_HEAD(signal1, tc)
55681.1Skamil{
55691.1Skamil	atf_tc_set_md_var(tc, "descr",
55701.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
55711.1Skamil	    "from catching other signals");
55721.1Skamil}
55731.1Skamil
55741.1SkamilATF_TC_BODY(signal1, tc)
55751.1Skamil{
55761.1Skamil	const int exitval = 5;
55771.1Skamil	const int sigval = SIGSTOP;
55781.1Skamil	const int sigmasked = SIGTRAP;
55791.1Skamil	const int signotmasked = SIGINT;
55801.1Skamil	pid_t child, wpid;
55811.1Skamil#if defined(TWAIT_HAVE_STATUS)
55821.1Skamil	int status;
55831.1Skamil#endif
55841.1Skamil	sigset_t intmask;
55851.1Skamil
55861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55881.1Skamil	if (child == 0) {
55891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55911.1Skamil
55921.1Skamil		sigemptyset(&intmask);
55931.1Skamil		sigaddset(&intmask, sigmasked);
55941.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55951.1Skamil
55961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55981.1Skamil
55991.13Schristos		DPRINTF("Before raising %s from child\n",
56001.1Skamil		    strsignal(signotmasked));
56011.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
56021.1Skamil
56031.13Schristos		DPRINTF("Before exiting of the child process\n");
56041.1Skamil		_exit(exitval);
56051.1Skamil	}
56061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56071.1Skamil
56081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56101.1Skamil
56111.1Skamil	validate_status_stopped(status, sigval);
56121.1Skamil
56131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56141.1Skamil	    "without signal to be sent\n");
56151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56161.1Skamil
56171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56191.1Skamil
56201.1Skamil	validate_status_stopped(status, signotmasked);
56211.1Skamil
56221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56231.1Skamil	    "without signal to be sent\n");
56241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56251.1Skamil
56261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56281.1Skamil
56291.1Skamil	validate_status_exited(status, exitval);
56301.1Skamil
56311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56331.1Skamil}
56341.1Skamil
56351.1SkamilATF_TC(signal2);
56361.1SkamilATF_TC_HEAD(signal2, tc)
56371.1Skamil{
56381.1Skamil	atf_tc_set_md_var(tc, "descr",
56391.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
56401.1Skamil	    "catching this raised signal");
56411.1Skamil}
56421.1Skamil
56431.1SkamilATF_TC_BODY(signal2, tc)
56441.1Skamil{
56451.1Skamil	const int exitval = 5;
56461.1Skamil	const int sigval = SIGSTOP;
56471.1Skamil	const int sigmasked = SIGTRAP;
56481.1Skamil	pid_t child, wpid;
56491.1Skamil#if defined(TWAIT_HAVE_STATUS)
56501.1Skamil	int status;
56511.1Skamil#endif
56521.1Skamil	sigset_t intmask;
56531.1Skamil
56541.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56551.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56561.1Skamil	if (child == 0) {
56571.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56581.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56591.1Skamil
56601.1Skamil		sigemptyset(&intmask);
56611.1Skamil		sigaddset(&intmask, sigmasked);
56621.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56631.1Skamil
56641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56661.1Skamil
56671.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
56681.1Skamil		    strsignal(sigmasked));
56691.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
56701.1Skamil
56711.13Schristos		DPRINTF("Before exiting of the child process\n");
56721.1Skamil		_exit(exitval);
56731.1Skamil	}
56741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56751.1Skamil
56761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56781.1Skamil
56791.1Skamil	validate_status_stopped(status, sigval);
56801.1Skamil
56811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56821.1Skamil	    "without signal to be sent\n");
56831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56841.1Skamil
56851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56871.1Skamil
56881.1Skamil	validate_status_exited(status, exitval);
56891.1Skamil
56901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56921.1Skamil}
56931.1Skamil
56941.1SkamilATF_TC(signal3);
56951.1SkamilATF_TC_HEAD(signal3, tc)
56961.1Skamil{
56971.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
56981.1Skamil	atf_tc_set_md_var(tc, "descr",
56991.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57001.1Skamil	    "catching software breakpoints");
57011.1Skamil}
57021.1Skamil
57031.1SkamilATF_TC_BODY(signal3, tc)
57041.1Skamil{
57051.1Skamil	const int exitval = 5;
57061.1Skamil	const int sigval = SIGSTOP;
57071.1Skamil	const int sigmasked = SIGTRAP;
57081.1Skamil	pid_t child, wpid;
57091.1Skamil#if defined(TWAIT_HAVE_STATUS)
57101.1Skamil	int status;
57111.1Skamil#endif
57121.1Skamil	sigset_t intmask;
57131.1Skamil
57141.20Skamil	atf_tc_expect_fail("PR kern/51918");
57151.20Skamil
57161.20Skamil	// This test breaks now on some ports, temporarily disable it
57171.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
57181.20Skamil
57191.10Smartin#if defined(__sparc__)
57201.7Skamil	atf_tc_expect_timeout("PR kern/52167");
57211.7Skamil
57221.7Skamil	// timeout wins, failure still valid
57231.7Skamil	// atf_tc_expect_fail("PR kern/51918");
57241.7Skamil#endif
57251.1Skamil
57261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57281.1Skamil	if (child == 0) {
57291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57311.1Skamil
57321.1Skamil		sigemptyset(&intmask);
57331.1Skamil		sigaddset(&intmask, sigmasked);
57341.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57351.1Skamil
57361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57381.1Skamil
57391.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
57401.4Skamil
57411.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
57421.4Skamil		PTRACE_BREAKPOINT_ASM;
57431.1Skamil#else
57441.4Skamil		/* port me */
57451.1Skamil#endif
57461.1Skamil
57471.13Schristos		DPRINTF("Before exiting of the child process\n");
57481.1Skamil		_exit(exitval);
57491.1Skamil	}
57501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57511.1Skamil
57521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57541.1Skamil
57551.1Skamil	validate_status_stopped(status, sigval);
57561.1Skamil
57571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57581.1Skamil	    "without signal to be sent\n");
57591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57601.1Skamil
57611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57631.1Skamil
57641.1Skamil	validate_status_stopped(status, sigmasked);
57651.1Skamil
57661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57671.1Skamil	    "without signal to be sent\n");
57681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57691.1Skamil
57701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57721.1Skamil
57731.1Skamil	validate_status_exited(status, exitval);
57741.1Skamil
57751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57771.1Skamil}
57781.1Skamil
57791.1Skamil#if defined(PT_STEP)
57801.1SkamilATF_TC(signal4);
57811.1SkamilATF_TC_HEAD(signal4, tc)
57821.1Skamil{
57831.1Skamil	atf_tc_set_md_var(tc, "descr",
57841.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57851.1Skamil	    "catching single step trap");
57861.1Skamil}
57871.1Skamil
57881.1SkamilATF_TC_BODY(signal4, tc)
57891.1Skamil{
57901.1Skamil	const int exitval = 5;
57911.1Skamil	const int sigval = SIGSTOP;
57921.1Skamil	const int sigmasked = SIGTRAP;
57931.1Skamil	pid_t child, wpid;
57941.1Skamil#if defined(TWAIT_HAVE_STATUS)
57951.1Skamil	int status;
57961.1Skamil#endif
57971.1Skamil	sigset_t intmask;
57981.1Skamil	int happy;
57991.1Skamil
58001.1Skamil#if defined(__arm__)
58011.5Skamil	/* PT_STEP not supported on arm 32-bit */
58021.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
58031.1Skamil#endif
58041.1Skamil
58051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58071.1Skamil	if (child == 0) {
58081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58101.1Skamil
58111.1Skamil		happy = check_happy(100);
58121.1Skamil
58131.1Skamil		sigemptyset(&intmask);
58141.1Skamil		sigaddset(&intmask, sigmasked);
58151.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58161.1Skamil
58171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58191.1Skamil
58201.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
58211.1Skamil
58221.13Schristos		DPRINTF("Before exiting of the child process\n");
58231.1Skamil		_exit(exitval);
58241.1Skamil	}
58251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58261.1Skamil
58271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58291.1Skamil
58301.1Skamil	validate_status_stopped(status, sigval);
58311.1Skamil
58321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58331.1Skamil	    "without signal to be sent\n");
58341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
58351.1Skamil
58361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58381.1Skamil
58391.1Skamil	validate_status_stopped(status, sigmasked);
58401.1Skamil
58411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58421.1Skamil	    "without signal to be sent\n");
58431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58441.1Skamil
58451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58471.1Skamil
58481.1Skamil	validate_status_exited(status, exitval);
58491.1Skamil
58501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58521.1Skamil}
58531.1Skamil#endif
58541.1Skamil
58551.1SkamilATF_TC(signal5);
58561.1SkamilATF_TC_HEAD(signal5, tc)
58571.1Skamil{
58581.1Skamil	atf_tc_set_md_var(tc, "descr",
58591.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58601.1Skamil	    "catching exec() breakpoint");
58611.1Skamil}
58621.1Skamil
58631.1SkamilATF_TC_BODY(signal5, tc)
58641.1Skamil{
58651.1Skamil	const int exitval = 5;
58661.1Skamil	const int sigval = SIGSTOP;
58671.1Skamil	const int sigmasked = SIGTRAP;
58681.1Skamil	pid_t child, wpid;
58691.1Skamil#if defined(TWAIT_HAVE_STATUS)
58701.1Skamil	int status;
58711.1Skamil#endif
58721.1Skamil	sigset_t intmask;
58731.1Skamil
58741.14Schristos	atf_tc_expect_fail("wrong signal");
58751.14Schristos
58761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58781.1Skamil	if (child == 0) {
58791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58811.1Skamil
58821.1Skamil		sigemptyset(&intmask);
58831.1Skamil		sigaddset(&intmask, sigmasked);
58841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58851.1Skamil
58861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58881.1Skamil
58891.13Schristos		DPRINTF("Before calling execve(2) from child\n");
58901.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
58911.1Skamil
58921.13Schristos		DPRINTF("Before exiting of the child process\n");
58931.1Skamil		_exit(exitval);
58941.1Skamil	}
58951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58961.1Skamil
58971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58991.1Skamil
59001.1Skamil	validate_status_stopped(status, sigval);
59011.1Skamil
59021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59031.1Skamil	    "without signal to be sent\n");
59041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59051.1Skamil
59061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59081.1Skamil
59091.1Skamil	validate_status_stopped(status, sigmasked);
59101.1Skamil
59111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59121.1Skamil	    "without signal to be sent\n");
59131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59141.1Skamil
59151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59171.1Skamil
59181.1Skamil	validate_status_exited(status, exitval);
59191.1Skamil
59201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59221.1Skamil}
59231.1Skamil
59241.1Skamil#if defined(TWAIT_HAVE_PID)
59251.1SkamilATF_TC(signal6);
59261.1SkamilATF_TC_HEAD(signal6, tc)
59271.1Skamil{
59281.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
59291.1Skamil	atf_tc_set_md_var(tc, "descr",
59301.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
59311.1Skamil	    "catching PTRACE_FORK breakpoint");
59321.1Skamil}
59331.1Skamil
59341.1SkamilATF_TC_BODY(signal6, tc)
59351.1Skamil{
59361.1Skamil	const int exitval = 5;
59371.1Skamil	const int exitval2 = 15;
59381.1Skamil	const int sigval = SIGSTOP;
59391.1Skamil	const int sigmasked = SIGTRAP;
59401.1Skamil	pid_t child, child2, wpid;
59411.1Skamil#if defined(TWAIT_HAVE_STATUS)
59421.1Skamil	int status;
59431.1Skamil#endif
59441.1Skamil	sigset_t intmask;
59451.1Skamil	ptrace_state_t state;
59461.1Skamil	const int slen = sizeof(state);
59471.1Skamil	ptrace_event_t event;
59481.1Skamil	const int elen = sizeof(event);
59491.1Skamil
59501.38Skamil	atf_tc_expect_fail("PR kern/51918");
59511.14Schristos
59521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59541.1Skamil	if (child == 0) {
59551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59571.1Skamil
59581.1Skamil		sigemptyset(&intmask);
59591.1Skamil		sigaddset(&intmask, sigmasked);
59601.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59611.1Skamil
59621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59641.1Skamil
59651.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59661.1Skamil
59671.1Skamil		if (child2 == 0)
59681.1Skamil			_exit(exitval2);
59691.1Skamil
59701.1Skamil		FORKEE_REQUIRE_SUCCESS
59711.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59721.1Skamil
59731.1Skamil		forkee_status_exited(status, exitval2);
59741.1Skamil
59751.13Schristos		DPRINTF("Before exiting of the child process\n");
59761.1Skamil		_exit(exitval);
59771.1Skamil	}
59781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59791.1Skamil
59801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59821.1Skamil
59831.1Skamil	validate_status_stopped(status, sigval);
59841.1Skamil
59851.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
59861.1Skamil	event.pe_set_event = PTRACE_FORK;
59871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
59881.1Skamil
59891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59901.1Skamil	    "without signal to be sent\n");
59911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59921.1Skamil
59931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59951.1Skamil
59961.1Skamil	validate_status_stopped(status, sigmasked);
59971.1Skamil
59981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
60001.1Skamil
60011.1Skamil	child2 = state.pe_other_pid;
60021.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
60031.1Skamil
60041.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
60051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60061.1Skamil	    child2);
60071.1Skamil
60081.1Skamil	validate_status_stopped(status, SIGTRAP);
60091.1Skamil
60101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
60111.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
60121.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
60131.1Skamil
60141.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
60151.1Skamil	    "without signal to be sent\n");
60161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
60171.1Skamil
60181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60191.1Skamil	    "without signal to be sent\n");
60201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60211.1Skamil
60221.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
60231.1Skamil	    TWAIT_FNAME);
60241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60251.1Skamil	    child2);
60261.1Skamil
60271.1Skamil	validate_status_exited(status, exitval2);
60281.1Skamil
60291.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
60301.1Skamil	    TWAIT_FNAME);
60311.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
60321.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
60331.1Skamil
60341.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60351.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60371.1Skamil
60381.1Skamil	validate_status_stopped(status, SIGCHLD);
60391.1Skamil
60401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60411.1Skamil	    "without signal to be sent\n");
60421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60431.1Skamil
60441.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60451.1Skamil	    TWAIT_FNAME);
60461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60471.1Skamil
60481.1Skamil	validate_status_exited(status, exitval);
60491.1Skamil
60501.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60511.1Skamil	    TWAIT_FNAME);
60521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60531.1Skamil}
60541.1Skamil#endif
60551.1Skamil
60561.1Skamil#if defined(TWAIT_HAVE_PID)
60571.1SkamilATF_TC(signal7);
60581.1SkamilATF_TC_HEAD(signal7, tc)
60591.1Skamil{
60601.1Skamil	atf_tc_set_md_var(tc, "descr",
60611.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60621.1Skamil	    "catching PTRACE_VFORK breakpoint");
60631.1Skamil}
60641.1Skamil
60651.1SkamilATF_TC_BODY(signal7, tc)
60661.1Skamil{
60671.1Skamil	const int exitval = 5;
60681.1Skamil	const int exitval2 = 15;
60691.1Skamil	const int sigval = SIGSTOP;
60701.1Skamil	const int sigmasked = SIGTRAP;
60711.1Skamil	pid_t child, child2, wpid;
60721.1Skamil#if defined(TWAIT_HAVE_STATUS)
60731.1Skamil	int status;
60741.1Skamil#endif
60751.1Skamil	sigset_t intmask;
60761.1Skamil	ptrace_state_t state;
60771.1Skamil	const int slen = sizeof(state);
60781.1Skamil	ptrace_event_t event;
60791.1Skamil	const int elen = sizeof(event);
60801.1Skamil
60811.38Skamil	atf_tc_expect_fail("PR kern/51918");
60821.14Schristos
60831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60851.1Skamil	if (child == 0) {
60861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60881.1Skamil
60891.1Skamil		sigemptyset(&intmask);
60901.1Skamil		sigaddset(&intmask, sigmasked);
60911.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
60921.1Skamil
60931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60951.1Skamil
60961.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
60971.1Skamil
60981.1Skamil		if (child2 == 0)
60991.1Skamil			_exit(exitval2);
61001.1Skamil
61011.1Skamil		FORKEE_REQUIRE_SUCCESS
61021.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
61031.1Skamil
61041.1Skamil		forkee_status_exited(status, exitval2);
61051.1Skamil
61061.13Schristos		DPRINTF("Before exiting of the child process\n");
61071.1Skamil		_exit(exitval);
61081.1Skamil	}
61091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61101.1Skamil
61111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61131.1Skamil
61141.1Skamil	validate_status_stopped(status, sigval);
61151.1Skamil
61161.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
61171.1Skamil	event.pe_set_event = PTRACE_VFORK;
61181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
61191.1Skamil
61201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61211.1Skamil	    "without signal to be sent\n");
61221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61231.1Skamil
61241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61261.1Skamil
61271.1Skamil	validate_status_stopped(status, sigmasked);
61281.1Skamil
61291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61301.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
61311.1Skamil
61321.1Skamil	child2 = state.pe_other_pid;
61331.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
61341.1Skamil
61351.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
61361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61371.1Skamil	    child2);
61381.1Skamil
61391.1Skamil	validate_status_stopped(status, SIGTRAP);
61401.1Skamil
61411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
61421.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
61431.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
61441.1Skamil
61451.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
61461.1Skamil	    "without signal to be sent\n");
61471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
61481.1Skamil
61491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61501.1Skamil	    "without signal to be sent\n");
61511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61521.1Skamil
61531.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
61541.1Skamil	    TWAIT_FNAME);
61551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61561.1Skamil	    child2);
61571.1Skamil
61581.1Skamil	validate_status_exited(status, exitval2);
61591.1Skamil
61601.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
61611.1Skamil	    TWAIT_FNAME);
61621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
61631.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
61641.1Skamil
61651.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61661.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61681.1Skamil
61691.1Skamil	validate_status_stopped(status, SIGCHLD);
61701.1Skamil
61711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61721.1Skamil	    "without signal to be sent\n");
61731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61741.1Skamil
61751.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61761.1Skamil	    TWAIT_FNAME);
61771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61781.1Skamil
61791.1Skamil	validate_status_exited(status, exitval);
61801.1Skamil
61811.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61821.1Skamil	    TWAIT_FNAME);
61831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61841.1Skamil}
61851.1Skamil#endif
61861.1Skamil
61871.1SkamilATF_TC(signal8);
61881.1SkamilATF_TC_HEAD(signal8, tc)
61891.1Skamil{
61901.1Skamil	atf_tc_set_md_var(tc, "descr",
61911.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61921.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
61931.1Skamil}
61941.1Skamil
61951.1SkamilATF_TC_BODY(signal8, tc)
61961.1Skamil{
61971.1Skamil	const int exitval = 5;
61981.1Skamil	const int exitval2 = 15;
61991.1Skamil	const int sigval = SIGSTOP;
62001.1Skamil	const int sigmasked = SIGTRAP;
62011.1Skamil	pid_t child, child2, wpid;
62021.1Skamil#if defined(TWAIT_HAVE_STATUS)
62031.1Skamil	int status;
62041.1Skamil#endif
62051.1Skamil	sigset_t intmask;
62061.1Skamil	ptrace_state_t state;
62071.1Skamil	const int slen = sizeof(state);
62081.1Skamil	ptrace_event_t event;
62091.1Skamil	const int elen = sizeof(event);
62101.1Skamil
62111.14Schristos	atf_tc_expect_fail("PR kern/51918");
62121.14Schristos
62131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62151.1Skamil	if (child == 0) {
62161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62181.1Skamil
62191.1Skamil		sigemptyset(&intmask);
62201.1Skamil		sigaddset(&intmask, sigmasked);
62211.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62221.1Skamil
62231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62251.1Skamil
62261.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
62271.1Skamil
62281.1Skamil		if (child2 == 0)
62291.1Skamil			_exit(exitval2);
62301.1Skamil
62311.1Skamil		FORKEE_REQUIRE_SUCCESS
62321.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
62331.1Skamil
62341.1Skamil		forkee_status_exited(status, exitval2);
62351.1Skamil
62361.13Schristos		DPRINTF("Before exiting of the child process\n");
62371.1Skamil		_exit(exitval);
62381.1Skamil	}
62391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62401.1Skamil
62411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62431.1Skamil
62441.1Skamil	validate_status_stopped(status, sigval);
62451.1Skamil
62461.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
62471.1Skamil	    child);
62481.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
62491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62501.1Skamil
62511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62521.1Skamil	    "without signal to be sent\n");
62531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62541.1Skamil
62551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62571.1Skamil
62581.1Skamil	validate_status_stopped(status, sigmasked);
62591.1Skamil
62601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62611.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
62621.1Skamil
62631.1Skamil	child2 = state.pe_other_pid;
62641.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
62651.1Skamil
62661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62671.1Skamil	    "without signal to be sent\n");
62681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62691.1Skamil
62701.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62711.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
62721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62731.1Skamil
62741.1Skamil	validate_status_stopped(status, SIGCHLD);
62751.1Skamil
62761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62771.1Skamil	    "without signal to be sent\n");
62781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62791.1Skamil
62801.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62811.1Skamil	    TWAIT_FNAME);
62821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62831.1Skamil
62841.1Skamil	validate_status_exited(status, exitval);
62851.1Skamil
62861.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62871.1Skamil	    TWAIT_FNAME);
62881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62891.1Skamil}
62901.1Skamil
62911.1SkamilATF_TC(signal9);
62921.1SkamilATF_TC_HEAD(signal9, tc)
62931.1Skamil{
62941.1Skamil	atf_tc_set_md_var(tc, "descr",
62951.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62961.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
62971.1Skamil}
62981.1Skamil
62991.1SkamilATF_TC_BODY(signal9, tc)
63001.1Skamil{
63011.1Skamil	const int exitval = 5;
63021.1Skamil	const int sigval = SIGSTOP;
63031.1Skamil	const int sigmasked = SIGTRAP;
63041.1Skamil	pid_t child, wpid;
63051.1Skamil#if defined(TWAIT_HAVE_STATUS)
63061.1Skamil	int status;
63071.1Skamil#endif
63081.1Skamil	sigset_t intmask;
63091.1Skamil	ptrace_state_t state;
63101.1Skamil	const int slen = sizeof(state);
63111.1Skamil	ptrace_event_t event;
63121.1Skamil	const int elen = sizeof(event);
63131.1Skamil	ucontext_t uc;
63141.1Skamil	lwpid_t lid;
63151.1Skamil	static const size_t ssize = 16*1024;
63161.1Skamil	void *stack;
63171.1Skamil
63181.14Schristos	atf_tc_expect_fail("PR kern/51918");
63191.14Schristos
63201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63221.1Skamil	if (child == 0) {
63231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63251.1Skamil
63261.1Skamil		sigemptyset(&intmask);
63271.1Skamil		sigaddset(&intmask, sigmasked);
63281.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63291.1Skamil
63301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63321.1Skamil
63331.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63341.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63351.1Skamil
63361.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63371.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63381.1Skamil
63391.13Schristos		DPRINTF("Before creating new in child\n");
63401.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63411.1Skamil
63421.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63431.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63441.1Skamil
63451.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63461.1Skamil		    "are the same\n", lid, the_lwp_id);
63471.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63481.1Skamil
63491.13Schristos		DPRINTF("Before exiting of the child process\n");
63501.1Skamil		_exit(exitval);
63511.1Skamil	}
63521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63531.1Skamil
63541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63561.1Skamil
63571.1Skamil	validate_status_stopped(status, sigval);
63581.1Skamil
63591.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63601.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
63611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63621.1Skamil
63631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63641.1Skamil	    "without signal to be sent\n");
63651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63661.1Skamil
63671.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63681.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63701.1Skamil
63711.1Skamil	validate_status_stopped(status, sigmasked);
63721.1Skamil
63731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63741.1Skamil
63751.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
63761.1Skamil
63771.1Skamil	lid = state.pe_lwp;
63781.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
63791.1Skamil
63801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63811.1Skamil	    "without signal to be sent\n");
63821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63831.1Skamil
63841.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63851.1Skamil	    TWAIT_FNAME);
63861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63871.1Skamil
63881.1Skamil	validate_status_exited(status, exitval);
63891.1Skamil
63901.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63911.1Skamil	    TWAIT_FNAME);
63921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63931.1Skamil}
63941.1Skamil
63951.1SkamilATF_TC(signal10);
63961.1SkamilATF_TC_HEAD(signal10, tc)
63971.1Skamil{
63981.1Skamil	atf_tc_set_md_var(tc, "descr",
63991.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
64001.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
64011.1Skamil}
64021.1Skamil
64031.1SkamilATF_TC_BODY(signal10, tc)
64041.1Skamil{
64051.1Skamil	const int exitval = 5;
64061.1Skamil	const int sigval = SIGSTOP;
64071.1Skamil	const int sigmasked = SIGTRAP;
64081.1Skamil	pid_t child, wpid;
64091.1Skamil#if defined(TWAIT_HAVE_STATUS)
64101.1Skamil	int status;
64111.1Skamil#endif
64121.1Skamil	sigset_t intmask;
64131.1Skamil	ptrace_state_t state;
64141.1Skamil	const int slen = sizeof(state);
64151.1Skamil	ptrace_event_t event;
64161.1Skamil	const int elen = sizeof(event);
64171.1Skamil	ucontext_t uc;
64181.1Skamil	lwpid_t lid;
64191.1Skamil	static const size_t ssize = 16*1024;
64201.1Skamil	void *stack;
64211.1Skamil
64221.14Schristos	atf_tc_expect_fail("PR kern/51918");
64231.14Schristos
64241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64261.1Skamil	if (child == 0) {
64271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64291.1Skamil
64301.1Skamil		sigemptyset(&intmask);
64311.1Skamil		sigaddset(&intmask, sigmasked);
64321.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
64331.1Skamil
64341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64361.1Skamil
64371.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
64381.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
64391.1Skamil
64401.13Schristos		DPRINTF("Before making context for new lwp in child\n");
64411.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
64421.1Skamil
64431.13Schristos		DPRINTF("Before creating new in child\n");
64441.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
64451.1Skamil
64461.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64471.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64481.1Skamil
64491.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64501.1Skamil		    "are the same\n", lid, the_lwp_id);
64511.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64521.1Skamil
64531.13Schristos		DPRINTF("Before exiting of the child process\n");
64541.1Skamil		_exit(exitval);
64551.1Skamil	}
64561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64571.1Skamil
64581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64601.1Skamil
64611.1Skamil	validate_status_stopped(status, sigval);
64621.1Skamil
64631.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
64641.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
64651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64661.1Skamil
64671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64681.1Skamil	    "without signal to be sent\n");
64691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64701.1Skamil
64711.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64721.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64741.1Skamil
64751.1Skamil	validate_status_stopped(status, sigmasked);
64761.1Skamil
64771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64781.1Skamil
64791.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
64801.1Skamil
64811.1Skamil	lid = state.pe_lwp;
64821.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
64831.1Skamil
64841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64851.1Skamil	    "without signal to be sent\n");
64861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64871.1Skamil
64881.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64891.1Skamil	    TWAIT_FNAME);
64901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64911.1Skamil
64921.1Skamil	validate_status_exited(status, exitval);
64931.1Skamil
64941.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64951.1Skamil	    TWAIT_FNAME);
64961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64971.1Skamil}
64981.1Skamil
64991.1Skamilstatic void
65001.1Skamillwp_main_stop(void *arg)
65011.1Skamil{
65021.1Skamil	the_lwp_id = _lwp_self();
65031.1Skamil
65041.1Skamil	raise(SIGTRAP);
65051.1Skamil
65061.1Skamil	_lwp_exit();
65071.1Skamil}
65081.1Skamil
65091.1SkamilATF_TC(suspend1);
65101.1SkamilATF_TC_HEAD(suspend1, tc)
65111.1Skamil{
65121.1Skamil	atf_tc_set_md_var(tc, "descr",
65131.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
65141.1Skamil	    "resumed by a tracee");
65151.1Skamil}
65161.1Skamil
65171.1SkamilATF_TC_BODY(suspend1, tc)
65181.1Skamil{
65191.1Skamil	const int exitval = 5;
65201.1Skamil	const int sigval = SIGSTOP;
65211.1Skamil	pid_t child, wpid;
65221.1Skamil#if defined(TWAIT_HAVE_STATUS)
65231.1Skamil	int status;
65241.1Skamil#endif
65251.1Skamil	ucontext_t uc;
65261.1Skamil	lwpid_t lid;
65271.1Skamil	static const size_t ssize = 16*1024;
65281.1Skamil	void *stack;
65291.1Skamil	struct ptrace_lwpinfo pl;
65301.1Skamil	struct ptrace_siginfo psi;
65311.1Skamil	volatile int go = 0;
65321.1Skamil
65331.17Skamil	// Feature pending for refactoring
65341.17Skamil	atf_tc_expect_fail("PR kern/51995");
65351.17Skamil
65361.16Skamil	// Hangs with qemu
65371.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
65381.16Skamil
65391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65411.1Skamil	if (child == 0) {
65421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65441.1Skamil
65451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65471.1Skamil
65481.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65491.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65501.1Skamil
65511.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65521.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65531.1Skamil
65541.13Schristos		DPRINTF("Before creating new in child\n");
65551.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65561.1Skamil
65571.1Skamil		while (go == 0)
65581.1Skamil			continue;
65591.1Skamil
65601.1Skamil		raise(SIGINT);
65611.1Skamil
65621.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
65631.1Skamil
65641.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65651.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65661.1Skamil
65671.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65681.1Skamil		    "are the same\n", lid, the_lwp_id);
65691.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65701.1Skamil
65711.13Schristos		DPRINTF("Before exiting of the child process\n");
65721.1Skamil		_exit(exitval);
65731.1Skamil	}
65741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65751.1Skamil
65761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65781.1Skamil
65791.1Skamil	validate_status_stopped(status, sigval);
65801.1Skamil
65811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65821.1Skamil	    "without signal to be sent\n");
65831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65841.1Skamil
65851.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65861.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65881.1Skamil
65891.1Skamil	validate_status_stopped(status, SIGTRAP);
65901.1Skamil
65911.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65931.1Skamil
65941.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65961.1Skamil
65971.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
65981.1Skamil	    child, getpid());
65991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
66001.1Skamil
66011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66021.1Skamil	    "without signal to be sent\n");
66031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66041.1Skamil
66051.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
66061.1Skamil	    "SIGINT\n", TWAIT_FNAME);
66071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66081.1Skamil
66091.1Skamil	validate_status_stopped(status, SIGINT);
66101.1Skamil
66111.1Skamil	pl.pl_lwpid = 0;
66121.1Skamil
66131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66141.1Skamil	while (pl.pl_lwpid != 0) {
66151.1Skamil
66161.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
66171.1Skamil		switch (pl.pl_lwpid) {
66181.1Skamil		case 1:
66191.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
66201.1Skamil			break;
66211.1Skamil		case 2:
66221.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
66231.1Skamil			break;
66241.1Skamil		}
66251.1Skamil	}
66261.1Skamil
66271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66281.1Skamil	    "without signal to be sent\n");
66291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66301.1Skamil
66311.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66321.1Skamil	    TWAIT_FNAME);
66331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66341.1Skamil
66351.1Skamil	validate_status_exited(status, exitval);
66361.1Skamil
66371.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66381.1Skamil	    TWAIT_FNAME);
66391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66401.1Skamil}
66411.1Skamil
66421.1SkamilATF_TC(suspend2);
66431.1SkamilATF_TC_HEAD(suspend2, tc)
66441.1Skamil{
66451.1Skamil	atf_tc_set_md_var(tc, "descr",
66461.1Skamil	    "Verify that the while the only thread within a process is "
66471.1Skamil	    "suspended, the whole process cannot be unstopped");
66481.1Skamil}
66491.1Skamil
66501.1SkamilATF_TC_BODY(suspend2, tc)
66511.1Skamil{
66521.1Skamil	const int exitval = 5;
66531.1Skamil	const int sigval = SIGSTOP;
66541.1Skamil	pid_t child, wpid;
66551.1Skamil#if defined(TWAIT_HAVE_STATUS)
66561.1Skamil	int status;
66571.1Skamil#endif
66581.1Skamil	struct ptrace_siginfo psi;
66591.1Skamil
66601.17Skamil	// Feature pending for refactoring
66611.17Skamil	atf_tc_expect_fail("PR kern/51995");
66621.17Skamil
66631.16Skamil	// Hangs with qemu
66641.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66651.16Skamil
66661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66681.1Skamil	if (child == 0) {
66691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66711.1Skamil
66721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66741.1Skamil
66751.13Schristos		DPRINTF("Before exiting of the child process\n");
66761.1Skamil		_exit(exitval);
66771.1Skamil	}
66781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66791.1Skamil
66801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66821.1Skamil
66831.1Skamil	validate_status_stopped(status, sigval);
66841.1Skamil
66851.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66871.1Skamil
66881.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66901.1Skamil
66911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66921.1Skamil	    "without signal to be sent\n");
66931.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
66941.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
66951.1Skamil
66961.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66981.1Skamil
66991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67001.1Skamil	    "without signal to be sent\n");
67011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67021.1Skamil
67031.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
67041.1Skamil	    TWAIT_FNAME);
67051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67061.1Skamil
67071.1Skamil	validate_status_exited(status, exitval);
67081.1Skamil
67091.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
67101.1Skamil	    TWAIT_FNAME);
67111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67121.1Skamil}
67131.1Skamil
67141.1SkamilATF_TC(resume1);
67151.1SkamilATF_TC_HEAD(resume1, tc)
67161.1Skamil{
67171.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
67181.1Skamil	atf_tc_set_md_var(tc, "descr",
67191.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
67201.1Skamil	    "resumed by the debugger");
67211.1Skamil}
67221.1Skamil
67231.1SkamilATF_TC_BODY(resume1, tc)
67241.1Skamil{
67251.1Skamil	struct msg_fds fds;
67261.1Skamil	const int exitval = 5;
67271.1Skamil	const int sigval = SIGSTOP;
67281.1Skamil	pid_t child, wpid;
67291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
67301.1Skamil#if defined(TWAIT_HAVE_STATUS)
67311.1Skamil	int status;
67321.1Skamil#endif
67331.1Skamil	ucontext_t uc;
67341.1Skamil	lwpid_t lid;
67351.1Skamil	static const size_t ssize = 16*1024;
67361.1Skamil	void *stack;
67371.1Skamil	struct ptrace_lwpinfo pl;
67381.1Skamil	struct ptrace_siginfo psi;
67391.1Skamil
67401.17Skamil	// Feature pending for refactoring
67411.17Skamil	atf_tc_expect_fail("PR kern/51995");
67421.17Skamil
67431.15Schristos	// Hangs with qemu
67441.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
67451.1Skamil
67461.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
67471.1Skamil
67481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67501.1Skamil	if (child == 0) {
67511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67531.1Skamil
67541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67561.1Skamil
67571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
67581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
67591.1Skamil
67601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
67611.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
67621.1Skamil
67631.13Schristos		DPRINTF("Before creating new in child\n");
67641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
67651.1Skamil
67661.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
67671.1Skamil
67681.1Skamil		raise(SIGINT);
67691.1Skamil
67701.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
67711.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
67721.1Skamil
67731.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
67741.1Skamil		    "are the same\n", lid, the_lwp_id);
67751.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
67761.1Skamil
67771.13Schristos		DPRINTF("Before exiting of the child process\n");
67781.1Skamil		_exit(exitval);
67791.1Skamil	}
67801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67811.1Skamil
67821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67841.1Skamil
67851.1Skamil	validate_status_stopped(status, sigval);
67861.1Skamil
67871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67881.1Skamil	    "without signal to be sent\n");
67891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67901.1Skamil
67911.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67921.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
67931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67941.1Skamil
67951.1Skamil	validate_status_stopped(status, SIGTRAP);
67961.1Skamil
67971.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
67981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
67991.1Skamil
68001.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
68011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
68021.1Skamil
68031.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
68041.1Skamil
68051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68061.1Skamil	    "without signal to be sent\n");
68071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68081.1Skamil
68091.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
68101.1Skamil	    "SIGINT\n", TWAIT_FNAME);
68111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68121.1Skamil
68131.1Skamil	validate_status_stopped(status, SIGINT);
68141.1Skamil
68151.1Skamil	pl.pl_lwpid = 0;
68161.1Skamil
68171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
68181.1Skamil	while (pl.pl_lwpid != 0) {
68191.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
68201.1Skamil		switch (pl.pl_lwpid) {
68211.1Skamil		case 1:
68221.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
68231.1Skamil			break;
68241.1Skamil		case 2:
68251.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
68261.1Skamil			break;
68271.1Skamil		}
68281.1Skamil	}
68291.1Skamil
68301.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
68311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
68321.1Skamil
68331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68341.1Skamil	    "without signal to be sent\n");
68351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68361.1Skamil
68371.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
68381.1Skamil	    TWAIT_FNAME);
68391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68401.1Skamil
68411.1Skamil	validate_status_exited(status, exitval);
68421.1Skamil
68431.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
68441.1Skamil	    TWAIT_FNAME);
68451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68461.1Skamil
68471.1Skamil	msg_close(&fds);
68481.1Skamil
68491.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
68501.1Skamil	sleep(10);
68511.1Skamil}
68521.1Skamil
68531.1SkamilATF_TC(syscall1);
68541.1SkamilATF_TC_HEAD(syscall1, tc)
68551.1Skamil{
68561.1Skamil	atf_tc_set_md_var(tc, "descr",
68571.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
68581.1Skamil}
68591.1Skamil
68601.1SkamilATF_TC_BODY(syscall1, tc)
68611.1Skamil{
68621.1Skamil	const int exitval = 5;
68631.1Skamil	const int sigval = SIGSTOP;
68641.1Skamil	pid_t child, wpid;
68651.1Skamil#if defined(TWAIT_HAVE_STATUS)
68661.1Skamil	int status;
68671.1Skamil#endif
68681.1Skamil	struct ptrace_siginfo info;
68691.1Skamil	memset(&info, 0, sizeof(info));
68701.1Skamil
68711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68731.1Skamil	if (child == 0) {
68741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68761.1Skamil
68771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68791.1Skamil
68801.1Skamil		syscall(SYS_getpid);
68811.1Skamil
68821.13Schristos		DPRINTF("Before exiting of the child process\n");
68831.1Skamil		_exit(exitval);
68841.1Skamil	}
68851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68861.1Skamil
68871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68891.1Skamil
68901.1Skamil	validate_status_stopped(status, sigval);
68911.1Skamil
68921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68931.1Skamil	    "without signal to be sent\n");
68941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68951.1Skamil
68961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68981.1Skamil
68991.1Skamil	validate_status_stopped(status, SIGTRAP);
69001.1Skamil
69011.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
69021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
69031.1Skamil
69041.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
69051.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
69061.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
69071.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
69081.1Skamil
69091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69101.1Skamil	    "without signal to be sent\n");
69111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69121.1Skamil
69131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69151.1Skamil
69161.1Skamil	validate_status_stopped(status, SIGTRAP);
69171.1Skamil
69181.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
69191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
69201.1Skamil
69211.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
69221.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
69231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
69241.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
69251.1Skamil
69261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69271.1Skamil	    "without signal to be sent\n");
69281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69291.1Skamil
69301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69321.1Skamil
69331.1Skamil	validate_status_exited(status, exitval);
69341.1Skamil
69351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69371.1Skamil}
69381.1Skamil
69391.1SkamilATF_TC(syscallemu1);
69401.1SkamilATF_TC_HEAD(syscallemu1, tc)
69411.1Skamil{
69421.1Skamil	atf_tc_set_md_var(tc, "descr",
69431.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
69441.1Skamil}
69451.1Skamil
69461.1SkamilATF_TC_BODY(syscallemu1, tc)
69471.1Skamil{
69481.1Skamil	const int exitval = 5;
69491.1Skamil	const int sigval = SIGSTOP;
69501.1Skamil	pid_t child, wpid;
69511.1Skamil#if defined(TWAIT_HAVE_STATUS)
69521.1Skamil	int status;
69531.1Skamil#endif
69541.1Skamil
69551.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
69561.6Skamil	/* syscallemu does not work on sparc (32-bit) */
69571.6Skamil	atf_tc_expect_fail("PR kern/52166");
69581.6Skamil#endif
69591.6Skamil
69601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
69611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
69621.1Skamil	if (child == 0) {
69631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
69641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
69651.1Skamil
69661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
69671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
69681.1Skamil
69691.1Skamil		syscall(SYS_exit, 100);
69701.1Skamil
69711.13Schristos		DPRINTF("Before exiting of the child process\n");
69721.1Skamil		_exit(exitval);
69731.1Skamil	}
69741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
69751.1Skamil
69761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69781.1Skamil
69791.1Skamil	validate_status_stopped(status, sigval);
69801.1Skamil
69811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69821.1Skamil	    "without signal to be sent\n");
69831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69841.1Skamil
69851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69871.1Skamil
69881.1Skamil	validate_status_stopped(status, SIGTRAP);
69891.1Skamil
69901.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
69911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
69921.1Skamil
69931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69941.1Skamil	    "without signal to be sent\n");
69951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69961.1Skamil
69971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69991.1Skamil
70001.1Skamil	validate_status_stopped(status, SIGTRAP);
70011.1Skamil
70021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
70031.1Skamil	    "without signal to be sent\n");
70041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
70051.1Skamil
70061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
70071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
70081.1Skamil
70091.1Skamil	validate_status_exited(status, exitval);
70101.1Skamil
70111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
70121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
70131.1Skamil}
70141.1Skamil
70151.26Skamil#if defined(TWAIT_HAVE_PID)
70161.26SkamilATF_TC(race1);
70171.26SkamilATF_TC_HEAD(race1, tc)
70181.26Skamil{
70191.26Skamil	atf_tc_set_md_var(tc, "descr",
70201.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
70211.26Skamil	    "process and no other error is reported");
70221.26Skamil}
70231.26Skamil
70241.26SkamilATF_TC_BODY(race1, tc)
70251.26Skamil{
70261.26Skamil	time_t start, end;
70271.26Skamil	double diff;
70281.26Skamil	unsigned long N = 0;
70291.26Skamil
70301.26Skamil	/* Reuse this test with attach1 */
70311.26Skamil
70321.26Skamil	start = time(NULL);
70331.26Skamil	while (true) {
70341.26Skamil		DPRINTF("Step: %lu\n", N);
70351.26Skamil		attach1_raw(true);
70361.26Skamil		end = time(NULL);
70371.26Skamil		diff = difftime(end, start);
70381.26Skamil		if (diff >= 5.0)
70391.26Skamil			break;
70401.26Skamil		++N;
70411.26Skamil	}
70421.26Skamil	DPRINTF("Iterations: %lu\n", N);
70431.26Skamil}
70441.26Skamil#endif
70451.26Skamil
70461.1Skamil#include "t_ptrace_amd64_wait.h"
70471.1Skamil#include "t_ptrace_i386_wait.h"
70481.1Skamil#include "t_ptrace_x86_wait.h"
70491.1Skamil
70501.1SkamilATF_TP_ADD_TCS(tp)
70511.1Skamil{
70521.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
70531.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
70541.33Skamil
70551.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
70561.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
70571.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
70581.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
70591.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
70601.33Skamil
70611.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch1);
70621.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch2);
70631.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch3);
70641.34Skamil
70651.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler1);
70661.35Skamil//	ATF_TP_ADD_TC(tp, traceme_signal_nohandler2); // not yet
70671.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler3);
70681.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler4);
70691.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler5);
70701.1Skamil
70711.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
70721.37Skamil
70731.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
70741.40Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_raise2); // not yet
70751.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
70761.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
70771.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
70781.40Skamil
70791.41Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_breakpoint);
70801.41Skamil
70811.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
70821.43Skamil
70831.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
70841.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
70851.1Skamil	ATF_TP_ADD_TC(tp, attach3);
70861.1Skamil	ATF_TP_ADD_TC(tp, attach4);
70871.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
70881.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
70891.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
70901.1Skamil
70911.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
70921.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
70931.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
70941.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
70951.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
70961.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
70971.1Skamil
70981.31Skamil	ATF_TP_ADD_TC(tp, fork1);
70991.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
71001.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
71011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
71021.31Skamil	ATF_TP_ADD_TC(tp, fork5);
71031.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
71041.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
71051.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
71061.31Skamil
71071.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
71081.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
71091.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
71101.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
71111.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
71121.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
71131.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
71141.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
71151.1Skamil
71161.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
71171.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
71181.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
71191.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
71201.1Skamil
71211.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
71221.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
71231.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
71241.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
71251.1Skamil
71261.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
71271.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
71281.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
71291.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
71301.1Skamil
71311.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
71321.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
71331.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
71341.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
71351.1Skamil
71361.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
71371.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
71381.1Skamil
71391.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
71401.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
71411.1Skamil
71421.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
71431.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
71441.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
71451.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
71461.1Skamil
71471.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
71481.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
71491.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
71501.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
71511.1Skamil
71521.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
71531.1Skamil
71541.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
71551.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
71561.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
71571.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
71581.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
71591.1Skamil
71601.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
71611.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
71621.1Skamil
71631.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
71641.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
71651.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
71661.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
71671.1Skamil
71681.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
71691.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
71701.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
71711.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
71721.2Skamil
71731.1Skamil	ATF_TP_ADD_TC(tp, kill1);
71741.1Skamil	ATF_TP_ADD_TC(tp, kill2);
71751.1Skamil
71761.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
71771.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
71781.1Skamil
71791.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
71801.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
71811.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
71821.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
71831.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
71841.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
71851.1Skamil
71861.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
71871.1Skamil
71881.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
71891.1Skamil
71901.1Skamil	ATF_TP_ADD_TC(tp, signal1);
71911.1Skamil	ATF_TP_ADD_TC(tp, signal2);
71921.1Skamil	ATF_TP_ADD_TC(tp, signal3);
71931.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
71941.1Skamil	ATF_TP_ADD_TC(tp, signal5);
71951.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
71961.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
71971.1Skamil	ATF_TP_ADD_TC(tp, signal8);
71981.1Skamil	ATF_TP_ADD_TC(tp, signal9);
71991.1Skamil	ATF_TP_ADD_TC(tp, signal10);
72001.1Skamil
72011.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
72021.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
72031.1Skamil
72041.1Skamil	ATF_TP_ADD_TC(tp, resume1);
72051.1Skamil
72061.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
72071.1Skamil
72081.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
72091.1Skamil
72101.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
72111.26Skamil
72121.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
72131.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
72141.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
72151.1Skamil
72161.1Skamil	return atf_no_error();
72171.1Skamil}
7218