t_ptrace_wait.c revision 1.44
11.44Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.44 2018/05/16 03:18:38 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.44Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.44 2018/05/16 03:18:38 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.1Skamil#include <sched.h>
471.1Skamil#include <signal.h>
481.1Skamil#include <stdint.h>
491.1Skamil#include <stdio.h>
501.1Skamil#include <stdlib.h>
511.1Skamil#include <strings.h>
521.26Skamil#include <time.h>
531.1Skamil#include <unistd.h>
541.1Skamil
551.1Skamil#include <atf-c.h>
561.1Skamil
571.1Skamil#include "h_macros.h"
581.1Skamil
591.1Skamil#include "t_ptrace_wait.h"
601.1Skamil#include "msg.h"
611.1Skamil
621.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
631.13Schristos    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0)
641.1Skamil
651.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
661.1Skamil    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
671.1Skamil
681.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
691.1Skamil    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
721.13Schristos    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
731.13Schristos
741.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
751.13Schristos    strerror(errno))
761.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
771.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
781.13Schristos
791.13Schristosstatic int debug = 0;
801.13Schristos
811.13Schristos#define DPRINTF(a, ...)	do  \
821.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
831.13Schristos    while (/*CONSTCOND*/0)
841.1Skamil
851.34Skamil/// ----------------------------------------------------------------------------
861.34Skamil
871.33Skamilstatic void
881.33Skamiltraceme_raise(int sigval)
891.1Skamil{
901.1Skamil	const int exitval = 5;
911.1Skamil	pid_t child, wpid;
921.1Skamil#if defined(TWAIT_HAVE_STATUS)
931.1Skamil	int status;
941.1Skamil#endif
951.1Skamil
961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
981.1Skamil	if (child == 0) {
991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1011.1Skamil
1021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1041.1Skamil
1051.36Skamil		switch (sigval) {
1061.36Skamil		case SIGKILL:
1071.36Skamil			/* NOTREACHED */
1081.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1091.36Skamil		default:
1101.36Skamil			DPRINTF("Before exiting of the child process\n");
1111.36Skamil			_exit(exitval);
1121.36Skamil		}
1131.1Skamil	}
1141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1151.1Skamil
1161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1181.1Skamil
1191.36Skamil	switch (sigval) {
1201.36Skamil	case SIGKILL:
1211.36Skamil		validate_status_signaled(status, sigval, 0);
1221.36Skamil		break;
1231.36Skamil	default:
1241.36Skamil		validate_status_stopped(status, sigval);
1251.1Skamil
1261.36Skamil		DPRINTF("Before resuming the child process where it left off "
1271.36Skamil		    "and without signal to be sent\n");
1281.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1291.1Skamil
1301.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1311.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1321.36Skamil		                      child);
1331.36Skamil		break;
1341.36Skamil	}
1351.1Skamil
1361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1381.1Skamil}
1391.1Skamil
1401.33Skamil#define TRACEME_RAISE(test, sig)						\
1411.33SkamilATF_TC(test);									\
1421.33SkamilATF_TC_HEAD(test, tc)								\
1431.33Skamil{										\
1441.33Skamil	atf_tc_set_md_var(tc, "descr",						\
1451.33Skamil	    "Verify " #sig " followed by _exit(2) in a child");			\
1461.33Skamil}										\
1471.33Skamil										\
1481.33SkamilATF_TC_BODY(test, tc)								\
1491.33Skamil{										\
1501.33Skamil										\
1511.33Skamil	traceme_raise(sig);							\
1521.33Skamil}
1531.33Skamil
1541.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1551.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1561.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1571.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1581.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1591.33Skamil
1601.34Skamil/// ----------------------------------------------------------------------------
1611.1Skamil
1621.1Skamilstatic void
1631.34Skamiltraceme_sighandler_catch(int sigsent, void (*sah)(int arg), int *traceme_caught)
1641.1Skamil{
1651.1Skamil	const int exitval = 5;
1661.34Skamil	const int sigval = SIGSTOP;
1671.1Skamil	pid_t child, wpid;
1681.1Skamil	struct sigaction sa;
1691.1Skamil#if defined(TWAIT_HAVE_STATUS)
1701.1Skamil	int status;
1711.1Skamil#endif
1721.1Skamil
1731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1751.1Skamil	if (child == 0) {
1761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1781.1Skamil
1791.34Skamil		sa.sa_handler = sah;
1801.1Skamil		sa.sa_flags = SA_SIGINFO;
1811.1Skamil		sigemptyset(&sa.sa_mask);
1821.1Skamil
1831.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
1841.1Skamil
1851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1871.1Skamil
1881.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
1891.1Skamil
1901.13Schristos		DPRINTF("Before exiting of the child process\n");
1911.1Skamil		_exit(exitval);
1921.1Skamil	}
1931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1941.1Skamil
1951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1971.1Skamil
1981.1Skamil	validate_status_stopped(status, sigval);
1991.1Skamil
2001.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2011.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2031.1Skamil
2041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2061.1Skamil
2071.1Skamil	validate_status_exited(status, exitval);
2081.1Skamil
2091.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2111.1Skamil}
2121.1Skamil
2131.34Skamil#define TRACEME_SIGHANDLER_CATCH(test, sig)					\
2141.34SkamilATF_TC(test);									\
2151.34SkamilATF_TC_HEAD(test, tc)								\
2161.34Skamil{										\
2171.34Skamil	atf_tc_set_md_var(tc, "descr",						\
2181.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
2191.34Skamil	    "handled correctly and caught by a signal handler");		\
2201.34Skamil}										\
2211.34Skamil										\
2221.34Skamilstatic int test##_caught = 0;							\
2231.34Skamil										\
2241.34Skamilstatic void									\
2251.34Skamiltest##_sighandler(int arg)							\
2261.34Skamil{										\
2271.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
2281.34Skamil										\
2291.34Skamil	++ test##_caught;							\
2301.34Skamil}										\
2311.34Skamil										\
2321.34SkamilATF_TC_BODY(test, tc)								\
2331.34Skamil{										\
2341.34Skamil										\
2351.34Skamil	traceme_sighandler_catch(sig, test##_sighandler, & test##_caught);	\
2361.34Skamil}
2371.34Skamil
2381.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
2391.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch1, SIGABRT) /* abort trap */
2401.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch2, SIGHUP)  /* hangup */
2411.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch3, SIGCONT) /* continued? */
2421.34Skamil
2431.34Skamil/// ----------------------------------------------------------------------------
2441.34Skamil
2451.35Skamilstatic void
2461.35Skamiltraceme_signal_nohandler(int sigsent)
2471.1Skamil{
2481.35Skamil	const int sigval = SIGSTOP;
2491.35Skamil	int exitval = 0;
2501.1Skamil	pid_t child, wpid;
2511.1Skamil#if defined(TWAIT_HAVE_STATUS)
2521.1Skamil	int status;
2531.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
2541.1Skamil#endif
2551.1Skamil
2561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2581.1Skamil	if (child == 0) {
2591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2611.1Skamil
2621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2641.1Skamil
2651.35Skamil		switch (sigsent) {
2661.35Skamil		case SIGCONT:
2671.35Skamil			_exit(exitval);
2681.35Skamil		default:
2691.35Skamil			/* NOTREACHED */
2701.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2711.35Skamil		}
2721.1Skamil	}
2731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2741.1Skamil
2751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2771.1Skamil
2781.1Skamil	validate_status_stopped(status, sigval);
2791.1Skamil
2801.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2811.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2831.1Skamil
2841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2861.1Skamil
2871.35Skamil	switch (sigsent) {
2881.35Skamil	case SIGCONT:
2891.35Skamil		validate_status_exited(status, exitval);
2901.35Skamil		break;
2911.35Skamil	default:
2921.35Skamil		validate_status_signaled(status, sigsent, expect_core);
2931.35Skamil		break;
2941.35Skamil	}
2951.1Skamil
2961.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2981.1Skamil}
2991.1Skamil
3001.35Skamil#define TRACEME_SIGNAL_NOHANDLER(test, sig)					\
3011.35SkamilATF_TC(test);									\
3021.35SkamilATF_TC_HEAD(test, tc)								\
3031.35Skamil{										\
3041.35Skamil	atf_tc_set_md_var(tc, "descr",						\
3051.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3061.35Skamil	    "handled correctly in a child without a signal handler");		\
3071.35Skamil}										\
3081.35Skamil										\
3091.35SkamilATF_TC_BODY(test, tc)								\
3101.35Skamil{										\
3111.35Skamil										\
3121.35Skamil	traceme_signal_nohandler(sig);						\
3131.35Skamil}
3141.35Skamil
3151.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler1, SIGKILL) /* non-maskable */
3161.35Skamil//TRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler2, SIGSTOP) /* non-maskable */
3171.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler3, SIGABRT) /* abort trap */
3181.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler4, SIGHUP)  /* hangup */
3191.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler5, SIGCONT) /* continued? */
3201.35Skamil
3211.35Skamil/// ----------------------------------------------------------------------------
3221.35Skamil
3231.37SkamilATF_TC(traceme_pid1_parent);
3241.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
3251.37Skamil{
3261.37Skamil	atf_tc_set_md_var(tc, "descr",
3271.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
3281.37Skamil}
3291.37Skamil
3301.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
3311.37Skamil{
3321.37Skamil	struct msg_fds parent_child;
3331.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
3341.37Skamil	pid_t child1, child2, wpid;
3351.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3361.37Skamil#if defined(TWAIT_HAVE_STATUS)
3371.37Skamil	int status;
3381.37Skamil#endif
3391.37Skamil
3401.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
3411.37Skamil
3421.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3431.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
3441.37Skamil	if (child1 == 0) {
3451.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
3461.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
3471.37Skamil		if (child2 != 0) {
3481.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
3491.37Skamil			        getpid(), child2);
3501.37Skamil			_exit(exitval_child1);
3511.37Skamil		}
3521.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
3531.37Skamil
3541.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
3551.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
3561.37Skamil
3571.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3581.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
3591.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
3601.37Skamil
3611.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
3621.37Skamil
3631.37Skamil		_exit(exitval_child2);
3641.37Skamil	}
3651.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
3661.37Skamil
3671.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
3691.37Skamil	                      child1);
3701.37Skamil
3711.37Skamil	validate_status_exited(status, exitval_child1);
3721.37Skamil
3731.37Skamil	DPRINTF("Notify that child1 is dead\n");
3741.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
3751.37Skamil
3761.37Skamil	DPRINTF("Wait for exiting of child2\n");
3771.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
3781.37Skamil}
3791.37Skamil
3801.37Skamil/// ----------------------------------------------------------------------------
3811.37Skamil
3821.40Skamilstatic void
3831.40Skamiltraceme_vfork_raise(int sigval)
3841.40Skamil{
3851.40Skamil	const int exitval = 5;
3861.40Skamil	pid_t child, wpid;
3871.40Skamil#if defined(TWAIT_HAVE_STATUS)
3881.40Skamil	int status;
3891.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
3901.40Skamil#endif
3911.40Skamil
3921.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3931.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
3941.40Skamil	if (child == 0) {
3951.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3961.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3971.40Skamil
3981.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3991.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4001.40Skamil
4011.40Skamil		switch (sigval) {
4021.40Skamil		case SIGKILL:
4031.40Skamil		case SIGABRT:
4041.40Skamil		case SIGHUP:
4051.40Skamil			/* NOTREACHED */
4061.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4071.40Skamil		default:
4081.40Skamil			DPRINTF("Before exiting of the child process\n");
4091.40Skamil			_exit(exitval);
4101.40Skamil		}
4111.40Skamil	}
4121.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4131.40Skamil
4141.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4151.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4161.40Skamil
4171.40Skamil	switch (sigval) {
4181.40Skamil	case SIGKILL:
4191.40Skamil	case SIGABRT:
4201.40Skamil	case SIGHUP:
4211.40Skamil		validate_status_signaled(status, sigval, expect_core);
4221.40Skamil		break;
4231.40Skamil	case SIGSTOP:
4241.40Skamil	case SIGCONT:
4251.40Skamil		validate_status_exited(status, exitval);
4261.40Skamil		break;
4271.40Skamil	default:
4281.40Skamil		/* NOTREACHED */
4291.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
4301.40Skamil		break;
4311.40Skamil	}
4321.40Skamil
4331.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4341.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4351.40Skamil}
4361.40Skamil
4371.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
4381.40SkamilATF_TC(test);									\
4391.40SkamilATF_TC_HEAD(test, tc)								\
4401.40Skamil{										\
4411.40Skamil	atf_tc_set_md_var(tc, "descr",						\
4421.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
4431.42Skamil	    "child");								\
4441.40Skamil}										\
4451.40Skamil										\
4461.40SkamilATF_TC_BODY(test, tc)								\
4471.40Skamil{										\
4481.40Skamil										\
4491.40Skamil	traceme_vfork_raise(sig);						\
4501.40Skamil}
4511.40Skamil
4521.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
4531.40Skamil// TRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ // TODO
4541.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGABRT) /* regular abort trap */
4551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGHUP)  /* hangup */
4561.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGCONT) /* continued? */
4571.40Skamil
4581.40Skamil/// ----------------------------------------------------------------------------
4591.40Skamil
4601.41SkamilATF_TC(traceme_vfork_breakpoint);
4611.41SkamilATF_TC_HEAD(traceme_vfork_breakpoint, tc)
4621.41Skamil{
4631.41Skamil	atf_tc_set_md_var(tc, "descr",
4641.44Skamil	    "Verify PT_TRACE_ME followed by a software breakpoint in a "
4651.44Skamil	    "vfork(2)ed child");
4661.41Skamil}
4671.41Skamil
4681.41SkamilATF_TC_BODY(traceme_vfork_breakpoint, tc)
4691.41Skamil{
4701.41Skamil	pid_t child, wpid;
4711.41Skamil#if defined(TWAIT_HAVE_STATUS)
4721.41Skamil	int status;
4731.41Skamil#endif
4741.41Skamil
4751.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4761.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
4771.41Skamil	if (child == 0) {
4781.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4791.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4801.41Skamil
4811.41Skamil		DPRINTF("Before executing a software breakpoint\n");
4821.41Skamil#ifdef PTRACE_BREAKPOINT_ASM
4831.41Skamil		PTRACE_BREAKPOINT_ASM;
4841.41Skamil#else
4851.41Skamil		/* port me */
4861.41Skamil#endif
4871.41Skamil
4881.41Skamil		/* NOTREACHED */
4891.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4901.41Skamil	}
4911.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4921.41Skamil
4931.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4941.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4951.41Skamil
4961.41Skamil	validate_status_signaled(status, SIGTRAP, 1);
4971.41Skamil
4981.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4991.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5001.41Skamil}
5011.41Skamil
5021.41Skamil/// ----------------------------------------------------------------------------
5031.41Skamil
5041.43SkamilATF_TC(traceme_vfork_exec);
5051.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
5061.43Skamil{
5071.43Skamil	atf_tc_set_md_var(tc, "descr",
5081.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
5091.43Skamil}
5101.43Skamil
5111.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
5121.43Skamil{
5131.43Skamil	const int sigval = SIGTRAP;
5141.43Skamil	pid_t child, wpid;
5151.43Skamil#if defined(TWAIT_HAVE_STATUS)
5161.43Skamil	int status;
5171.43Skamil#endif
5181.43Skamil
5191.43Skamil	struct ptrace_siginfo info;
5201.43Skamil	memset(&info, 0, sizeof(info));
5211.43Skamil
5221.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5231.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
5241.43Skamil	if (child == 0) {
5251.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5261.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5271.43Skamil
5281.43Skamil		DPRINTF("Before calling execve(2) from child\n");
5291.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
5301.43Skamil
5311.43Skamil		/* NOTREACHED */
5321.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
5331.43Skamil	}
5341.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5351.43Skamil
5361.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5371.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5381.43Skamil
5391.43Skamil	validate_status_stopped(status, sigval);
5401.43Skamil
5411.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5421.43Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5431.43Skamil
5441.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5451.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5461.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5471.43Skamil	    info.psi_siginfo.si_errno);
5481.43Skamil
5491.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5501.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
5511.43Skamil
5521.43Skamil	DPRINTF("Before resuming the child process where it left off and "
5531.43Skamil	    "without signal to be sent\n");
5541.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5551.43Skamil
5561.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5571.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5581.43Skamil
5591.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5601.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5611.43Skamil}
5621.43Skamil
5631.43Skamil/// ----------------------------------------------------------------------------
5641.43Skamil
5651.1Skamil#if defined(TWAIT_HAVE_PID)
5661.1SkamilATF_TC(attach1);
5671.1SkamilATF_TC_HEAD(attach1, tc)
5681.1Skamil{
5691.1Skamil	atf_tc_set_md_var(tc, "descr",
5701.1Skamil	    "Assert that tracer sees process termination before the parent");
5711.1Skamil}
5721.1Skamil
5731.26Skamilstatic void
5741.26Skamilattach1_raw(bool raw)
5751.1Skamil{
5761.1Skamil	struct msg_fds parent_tracee, parent_tracer;
5771.1Skamil	const int exitval_tracee = 5;
5781.1Skamil	const int exitval_tracer = 10;
5791.1Skamil	pid_t tracee, tracer, wpid;
5801.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5811.1Skamil#if defined(TWAIT_HAVE_STATUS)
5821.1Skamil	int status;
5831.1Skamil#endif
5841.1Skamil
5851.13Schristos	DPRINTF("Spawn tracee\n");
5861.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
5871.1Skamil	tracee = atf_utils_fork();
5881.1Skamil	if (tracee == 0) {
5891.1Skamil		// Wait for parent to let us exit
5901.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
5911.1Skamil		_exit(exitval_tracee);
5921.1Skamil	}
5931.1Skamil
5941.13Schristos	DPRINTF("Spawn debugger\n");
5951.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
5961.1Skamil	tracer = atf_utils_fork();
5971.1Skamil	if (tracer == 0) {
5981.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
5991.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
6001.1Skamil
6011.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6021.1Skamil		FORKEE_REQUIRE_SUCCESS(
6031.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6041.1Skamil
6051.1Skamil		forkee_status_stopped(status, SIGSTOP);
6061.1Skamil
6071.1Skamil		/* Resume tracee with PT_CONTINUE */
6081.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6091.1Skamil
6101.1Skamil		/* Inform parent that tracer has attached to tracee */
6111.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
6121.1Skamil
6131.1Skamil		/* Wait for parent to tell use that tracee should have exited */
6141.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
6151.1Skamil
6161.1Skamil		/* Wait for tracee and assert that it exited */
6171.1Skamil		FORKEE_REQUIRE_SUCCESS(
6181.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6191.1Skamil
6201.1Skamil		forkee_status_exited(status, exitval_tracee);
6211.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
6221.1Skamil
6231.13Schristos		DPRINTF("Before exiting of the tracer process\n");
6241.1Skamil		_exit(exitval_tracer);
6251.1Skamil	}
6261.1Skamil
6271.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
6281.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
6291.1Skamil
6301.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
6311.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
6321.1Skamil
6331.13Schristos	DPRINTF("Detect that tracee is zombie\n");
6341.26Skamil	if (raw)
6351.26Skamil		await_zombie_raw(tracee, 0);
6361.26Skamil	else
6371.26Skamil		await_zombie(tracee);
6381.1Skamil
6391.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
6401.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
6411.1Skamil	    TWAIT_FNAME);
6421.1Skamil	TWAIT_REQUIRE_SUCCESS(
6431.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
6441.1Skamil
6451.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
6461.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
6471.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
6481.1Skamil	    TWAIT_FNAME);
6491.1Skamil
6501.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
6511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
6521.1Skamil	    tracer);
6531.1Skamil
6541.1Skamil	validate_status_exited(status, exitval_tracer);
6551.1Skamil
6561.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
6571.1Skamil	    TWAIT_FNAME);
6581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
6591.1Skamil	    tracee);
6601.1Skamil
6611.1Skamil	validate_status_exited(status, exitval_tracee);
6621.1Skamil
6631.1Skamil	msg_close(&parent_tracer);
6641.1Skamil	msg_close(&parent_tracee);
6651.1Skamil}
6661.26Skamil
6671.26SkamilATF_TC_BODY(attach1, tc)
6681.26Skamil{
6691.26Skamil
6701.26Skamil	/* Reuse this test with race1 */
6711.26Skamil	attach1_raw(false);
6721.26Skamil}
6731.26Skamil
6741.1Skamil#endif
6751.1Skamil
6761.1Skamil#if defined(TWAIT_HAVE_PID)
6771.1SkamilATF_TC(attach2);
6781.1SkamilATF_TC_HEAD(attach2, tc)
6791.1Skamil{
6801.1Skamil	atf_tc_set_md_var(tc, "descr",
6811.1Skamil	    "Assert that any tracer sees process termination before its "
6821.1Skamil	    "parent");
6831.1Skamil}
6841.1Skamil
6851.1SkamilATF_TC_BODY(attach2, tc)
6861.1Skamil{
6871.1Skamil	struct msg_fds parent_tracer, parent_tracee;
6881.1Skamil	const int exitval_tracee = 5;
6891.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
6901.1Skamil	pid_t tracee, tracer, wpid;
6911.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6921.1Skamil#if defined(TWAIT_HAVE_STATUS)
6931.1Skamil	int status;
6941.1Skamil#endif
6951.1Skamil
6961.13Schristos	DPRINTF("Spawn tracee\n");
6971.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6981.1Skamil	tracee = atf_utils_fork();
6991.1Skamil	if (tracee == 0) {
7001.1Skamil		/* Wait for message from the parent */
7011.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7021.1Skamil		_exit(exitval_tracee);
7031.1Skamil	}
7041.1Skamil
7051.13Schristos	DPRINTF("Spawn debugger\n");
7061.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
7071.1Skamil	tracer = atf_utils_fork();
7081.1Skamil	if (tracer == 0) {
7091.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
7101.1Skamil		tracer = atf_utils_fork();
7111.1Skamil		if (tracer != 0)
7121.1Skamil			_exit(exitval_tracer1);
7131.1Skamil
7141.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
7151.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
7161.1Skamil
7171.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
7181.1Skamil		FORKEE_REQUIRE_SUCCESS(
7191.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7201.1Skamil
7211.1Skamil		forkee_status_stopped(status, SIGSTOP);
7221.1Skamil
7231.1Skamil		/* Resume tracee with PT_CONTINUE */
7241.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
7251.1Skamil
7261.1Skamil		/* Inform parent that tracer has attached to tracee */
7271.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
7281.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
7291.1Skamil
7301.1Skamil		/* Wait for tracee and assert that it exited */
7311.1Skamil		FORKEE_REQUIRE_SUCCESS(
7321.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7331.1Skamil
7341.1Skamil		forkee_status_exited(status, exitval_tracee);
7351.1Skamil
7361.13Schristos		DPRINTF("Before exiting of the tracer process\n");
7371.1Skamil		_exit(exitval_tracer2);
7381.1Skamil	}
7391.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
7401.1Skamil	    "%s()\n", TWAIT_FNAME);
7411.1Skamil	TWAIT_REQUIRE_SUCCESS(
7421.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
7431.1Skamil
7441.1Skamil	validate_status_exited(status, exitval_tracer1);
7451.1Skamil
7461.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
7471.1Skamil	    TWAIT_FNAME);
7481.1Skamil	TWAIT_REQUIRE_SUCCESS(
7491.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
7501.1Skamil
7511.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
7521.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
7531.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
7541.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
7551.1Skamil
7561.13Schristos	DPRINTF("Detect that tracee is zombie\n");
7571.1Skamil	await_zombie(tracee);
7581.1Skamil
7591.13Schristos	DPRINTF("Assert that there is no status about tracee - "
7601.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
7611.1Skamil	TWAIT_REQUIRE_SUCCESS(
7621.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
7631.1Skamil
7641.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
7651.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
7661.1Skamil
7671.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7681.1Skamil	    TWAIT_FNAME);
7691.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
7701.1Skamil	    tracee);
7711.1Skamil
7721.1Skamil	validate_status_exited(status, exitval_tracee);
7731.1Skamil
7741.1Skamil	msg_close(&parent_tracer);
7751.1Skamil	msg_close(&parent_tracee);
7761.1Skamil}
7771.1Skamil#endif
7781.1Skamil
7791.1SkamilATF_TC(attach3);
7801.1SkamilATF_TC_HEAD(attach3, tc)
7811.1Skamil{
7821.1Skamil	atf_tc_set_md_var(tc, "descr",
7831.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
7841.1Skamil}
7851.1Skamil
7861.1SkamilATF_TC_BODY(attach3, tc)
7871.1Skamil{
7881.1Skamil	struct msg_fds parent_tracee;
7891.1Skamil	const int exitval_tracee = 5;
7901.1Skamil	pid_t tracee, wpid;
7911.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7921.1Skamil#if defined(TWAIT_HAVE_STATUS)
7931.1Skamil	int status;
7941.1Skamil#endif
7951.1Skamil
7961.13Schristos	DPRINTF("Spawn tracee\n");
7971.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7981.1Skamil	tracee = atf_utils_fork();
7991.1Skamil	if (tracee == 0) {
8001.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8011.13Schristos		DPRINTF("Parent should now attach to tracee\n");
8021.1Skamil
8031.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
8041.1Skamil		/* Wait for message from the parent */
8051.1Skamil		_exit(exitval_tracee);
8061.1Skamil	}
8071.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8081.1Skamil
8091.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
8101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8111.1Skamil
8121.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
8131.1Skamil	    TWAIT_FNAME);
8141.1Skamil	TWAIT_REQUIRE_SUCCESS(
8151.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8161.1Skamil
8171.1Skamil	validate_status_stopped(status, SIGSTOP);
8181.1Skamil
8191.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
8201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8211.1Skamil
8221.13Schristos	DPRINTF("Let the tracee exit now\n");
8231.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
8241.1Skamil
8251.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
8261.1Skamil	TWAIT_REQUIRE_SUCCESS(
8271.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8281.1Skamil
8291.1Skamil	validate_status_exited(status, exitval_tracee);
8301.1Skamil
8311.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
8321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8331.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
8341.1Skamil
8351.1Skamil	msg_close(&parent_tracee);
8361.1Skamil}
8371.1Skamil
8381.1SkamilATF_TC(attach4);
8391.1SkamilATF_TC_HEAD(attach4, tc)
8401.1Skamil{
8411.1Skamil	atf_tc_set_md_var(tc, "descr",
8421.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
8431.1Skamil}
8441.1Skamil
8451.1SkamilATF_TC_BODY(attach4, tc)
8461.1Skamil{
8471.1Skamil	struct msg_fds parent_tracee;
8481.1Skamil	const int exitval_tracer = 5;
8491.1Skamil	pid_t tracer, wpid;
8501.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8511.1Skamil#if defined(TWAIT_HAVE_STATUS)
8521.1Skamil	int status;
8531.1Skamil#endif
8541.1Skamil
8551.13Schristos	DPRINTF("Spawn tracer\n");
8561.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
8571.1Skamil	tracer = atf_utils_fork();
8581.1Skamil	if (tracer == 0) {
8591.1Skamil
8601.1Skamil		/* Wait for message from the parent */
8611.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8621.1Skamil
8631.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
8641.1Skamil		    getppid());
8651.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
8661.1Skamil
8671.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
8681.1Skamil		    TWAIT_FNAME);
8691.1Skamil		FORKEE_REQUIRE_SUCCESS(
8701.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
8711.1Skamil
8721.1Skamil		forkee_status_stopped(status, SIGSTOP);
8731.1Skamil
8741.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
8751.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
8761.1Skamil		    != -1);
8771.1Skamil
8781.1Skamil		/* Tell parent we are ready */
8791.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
8801.1Skamil
8811.1Skamil		_exit(exitval_tracer);
8821.1Skamil	}
8831.1Skamil
8841.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
8851.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8861.13Schristos	DPRINTF("Allow the tracer to exit now\n");
8871.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
8881.1Skamil
8891.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
8901.1Skamil	TWAIT_REQUIRE_SUCCESS(
8911.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
8921.1Skamil
8931.1Skamil	validate_status_exited(status, exitval_tracer);
8941.1Skamil
8951.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
8961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8971.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
8981.1Skamil
8991.1Skamil	msg_close(&parent_tracee);
9001.1Skamil}
9011.1Skamil
9021.1Skamil#if defined(TWAIT_HAVE_PID)
9031.1SkamilATF_TC(attach5);
9041.1SkamilATF_TC_HEAD(attach5, tc)
9051.1Skamil{
9061.1Skamil	atf_tc_set_md_var(tc, "descr",
9071.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
9081.1Skamil	    "(check getppid(2))");
9091.1Skamil}
9101.1Skamil
9111.1SkamilATF_TC_BODY(attach5, tc)
9121.1Skamil{
9131.1Skamil	struct msg_fds parent_tracer, parent_tracee;
9141.1Skamil	const int exitval_tracee = 5;
9151.1Skamil	const int exitval_tracer = 10;
9161.1Skamil	pid_t parent, tracee, tracer, wpid;
9171.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9181.1Skamil#if defined(TWAIT_HAVE_STATUS)
9191.1Skamil	int status;
9201.1Skamil#endif
9211.1Skamil
9221.13Schristos	DPRINTF("Spawn tracee\n");
9231.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9251.1Skamil	tracee = atf_utils_fork();
9261.1Skamil	if (tracee == 0) {
9271.1Skamil		parent = getppid();
9281.1Skamil
9291.1Skamil		/* Emit message to the parent */
9301.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
9311.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
9321.1Skamil
9331.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
9341.1Skamil
9351.1Skamil		_exit(exitval_tracee);
9361.1Skamil	}
9371.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9381.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
9391.1Skamil
9401.13Schristos	DPRINTF("Spawn debugger\n");
9411.1Skamil	tracer = atf_utils_fork();
9421.1Skamil	if (tracer == 0) {
9431.1Skamil		/* No IPC to communicate with the child */
9441.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
9451.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
9461.1Skamil
9471.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
9481.1Skamil		FORKEE_REQUIRE_SUCCESS(
9491.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9501.1Skamil
9511.1Skamil		forkee_status_stopped(status, SIGSTOP);
9521.1Skamil
9531.1Skamil		/* Resume tracee with PT_CONTINUE */
9541.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
9551.1Skamil
9561.1Skamil		/* Inform parent that tracer has attached to tracee */
9571.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
9581.1Skamil
9591.1Skamil		/* Wait for parent to tell use that tracee should have exited */
9601.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
9611.1Skamil
9621.1Skamil		/* Wait for tracee and assert that it exited */
9631.1Skamil		FORKEE_REQUIRE_SUCCESS(
9641.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9651.1Skamil
9661.1Skamil		forkee_status_exited(status, exitval_tracee);
9671.1Skamil
9681.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9691.1Skamil		_exit(exitval_tracer);
9701.1Skamil	}
9711.1Skamil
9721.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9731.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
9741.1Skamil
9751.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9761.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
9771.1Skamil
9781.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9791.1Skamil	await_zombie(tracee);
9801.1Skamil
9811.13Schristos	DPRINTF("Assert that there is no status about tracee - "
9821.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
9831.1Skamil	TWAIT_REQUIRE_SUCCESS(
9841.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9851.1Skamil
9861.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
9871.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
9881.1Skamil
9891.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
9901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9911.1Skamil	    tracer);
9921.1Skamil
9931.1Skamil	validate_status_exited(status, exitval_tracer);
9941.1Skamil
9951.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
9961.1Skamil	    TWAIT_FNAME);
9971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
9981.1Skamil	    tracee);
9991.1Skamil
10001.1Skamil	validate_status_exited(status, exitval_tracee);
10011.1Skamil
10021.1Skamil	msg_close(&parent_tracer);
10031.1Skamil	msg_close(&parent_tracee);
10041.1Skamil}
10051.1Skamil#endif
10061.1Skamil
10071.1Skamil#if defined(TWAIT_HAVE_PID)
10081.1SkamilATF_TC(attach6);
10091.1SkamilATF_TC_HEAD(attach6, tc)
10101.1Skamil{
10111.1Skamil	atf_tc_set_md_var(tc, "descr",
10121.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
10131.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
10141.1Skamil}
10151.1Skamil
10161.1SkamilATF_TC_BODY(attach6, tc)
10171.1Skamil{
10181.1Skamil	struct msg_fds parent_tracee, parent_tracer;
10191.1Skamil	const int exitval_tracee = 5;
10201.1Skamil	const int exitval_tracer = 10;
10211.1Skamil	pid_t parent, tracee, tracer, wpid;
10221.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10231.1Skamil#if defined(TWAIT_HAVE_STATUS)
10241.1Skamil	int status;
10251.1Skamil#endif
10261.1Skamil	int name[CTL_MAXNAME];
10271.1Skamil	struct kinfo_proc2 kp;
10281.1Skamil	size_t len = sizeof(kp);
10291.1Skamil	unsigned int namelen;
10301.1Skamil
10311.13Schristos	DPRINTF("Spawn tracee\n");
10321.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10341.1Skamil	tracee = atf_utils_fork();
10351.1Skamil	if (tracee == 0) {
10361.1Skamil		parent = getppid();
10371.1Skamil
10381.1Skamil		/* Emit message to the parent */
10391.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
10401.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
10411.1Skamil
10421.1Skamil		namelen = 0;
10431.1Skamil		name[namelen++] = CTL_KERN;
10441.1Skamil		name[namelen++] = KERN_PROC2;
10451.1Skamil		name[namelen++] = KERN_PROC_PID;
10461.1Skamil		name[namelen++] = getpid();
10471.1Skamil		name[namelen++] = len;
10481.1Skamil		name[namelen++] = 1;
10491.1Skamil
10501.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
10511.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
10521.1Skamil
10531.1Skamil		_exit(exitval_tracee);
10541.1Skamil	}
10551.1Skamil
10561.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
10571.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
10581.1Skamil
10591.13Schristos	DPRINTF("Spawn debugger\n");
10601.1Skamil	tracer = atf_utils_fork();
10611.1Skamil	if (tracer == 0) {
10621.1Skamil		/* No IPC to communicate with the child */
10631.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10641.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10651.1Skamil
10661.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10671.1Skamil		FORKEE_REQUIRE_SUCCESS(
10681.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10691.1Skamil
10701.1Skamil		forkee_status_stopped(status, SIGSTOP);
10711.1Skamil
10721.1Skamil		/* Resume tracee with PT_CONTINUE */
10731.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10741.1Skamil
10751.1Skamil		/* Inform parent that tracer has attached to tracee */
10761.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
10771.1Skamil
10781.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
10791.1Skamil
10801.1Skamil		/* Wait for tracee and assert that it exited */
10811.1Skamil		FORKEE_REQUIRE_SUCCESS(
10821.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10831.1Skamil
10841.1Skamil		forkee_status_exited(status, exitval_tracee);
10851.1Skamil
10861.13Schristos		DPRINTF("Before exiting of the tracer process\n");
10871.1Skamil		_exit(exitval_tracer);
10881.1Skamil	}
10891.1Skamil
10901.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
10911.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
10921.1Skamil
10931.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
10941.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
10951.1Skamil
10961.13Schristos	DPRINTF("Detect that tracee is zombie\n");
10971.1Skamil	await_zombie(tracee);
10981.1Skamil
10991.13Schristos	DPRINTF("Assert that there is no status about tracee - "
11001.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
11011.1Skamil	TWAIT_REQUIRE_SUCCESS(
11021.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
11031.1Skamil
11041.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
11051.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11061.1Skamil
11071.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
11081.1Skamil	    TWAIT_FNAME);
11091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
11101.1Skamil	    tracer);
11111.1Skamil
11121.1Skamil	validate_status_exited(status, exitval_tracer);
11131.1Skamil
11141.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11151.1Skamil	    TWAIT_FNAME);
11161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
11171.1Skamil	    tracee);
11181.1Skamil
11191.1Skamil	validate_status_exited(status, exitval_tracee);
11201.1Skamil
11211.1Skamil	msg_close(&parent_tracee);
11221.1Skamil	msg_close(&parent_tracer);
11231.1Skamil}
11241.1Skamil#endif
11251.1Skamil
11261.1Skamil#if defined(TWAIT_HAVE_PID)
11271.1SkamilATF_TC(attach7);
11281.1SkamilATF_TC_HEAD(attach7, tc)
11291.1Skamil{
11301.1Skamil	atf_tc_set_md_var(tc, "descr",
11311.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
11321.1Skamil	    "(check /proc/curproc/status 3rd column)");
11331.1Skamil}
11341.1Skamil
11351.1SkamilATF_TC_BODY(attach7, tc)
11361.1Skamil{
11371.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11381.1Skamil	int rv;
11391.1Skamil	const int exitval_tracee = 5;
11401.1Skamil	const int exitval_tracer = 10;
11411.1Skamil	pid_t parent, tracee, tracer, wpid;
11421.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11431.1Skamil#if defined(TWAIT_HAVE_STATUS)
11441.1Skamil	int status;
11451.1Skamil#endif
11461.1Skamil	FILE *fp;
11471.1Skamil	struct stat st;
11481.1Skamil	const char *fname = "/proc/curproc/status";
11491.1Skamil	char s_executable[MAXPATHLEN];
11501.1Skamil	int s_pid, s_ppid;
11511.1Skamil	/*
11521.1Skamil	 * Format:
11531.1Skamil	 *  EXECUTABLE PID PPID ...
11541.1Skamil	 */
11551.1Skamil
11561.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
11571.1Skamil	if (rv != 0) {
11581.1Skamil		atf_tc_skip("/proc/curproc/status not found");
11591.1Skamil	}
11601.1Skamil
11611.13Schristos	DPRINTF("Spawn tracee\n");
11621.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11631.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11641.1Skamil	tracee = atf_utils_fork();
11651.1Skamil	if (tracee == 0) {
11661.1Skamil		parent = getppid();
11671.1Skamil
11681.1Skamil		// Wait for parent to let us exit
11691.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
11701.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
11711.1Skamil
11721.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
11731.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
11741.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
11751.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
11761.1Skamil
11771.1Skamil		_exit(exitval_tracee);
11781.1Skamil	}
11791.1Skamil
11801.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
11811.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
11821.1Skamil
11831.13Schristos	DPRINTF("Spawn debugger\n");
11841.1Skamil	tracer = atf_utils_fork();
11851.1Skamil	if (tracer == 0) {
11861.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11871.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11881.1Skamil
11891.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11901.1Skamil		FORKEE_REQUIRE_SUCCESS(
11911.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11921.1Skamil
11931.1Skamil		forkee_status_stopped(status, SIGSTOP);
11941.1Skamil
11951.1Skamil		/* Resume tracee with PT_CONTINUE */
11961.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11971.1Skamil
11981.1Skamil		/* Inform parent that tracer has attached to tracee */
11991.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12001.1Skamil
12011.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12021.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12031.1Skamil
12041.1Skamil		/* Wait for tracee and assert that it exited */
12051.1Skamil		FORKEE_REQUIRE_SUCCESS(
12061.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12071.1Skamil
12081.1Skamil		forkee_status_exited(status, exitval_tracee);
12091.1Skamil
12101.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12111.1Skamil		_exit(exitval_tracer);
12121.1Skamil	}
12131.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12141.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12151.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12161.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
12171.1Skamil
12181.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12191.1Skamil	await_zombie(tracee);
12201.1Skamil
12211.13Schristos	DPRINTF("Assert that there is no status about tracee - "
12221.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
12231.1Skamil	TWAIT_REQUIRE_SUCCESS(
12241.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
12251.1Skamil
12261.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
12271.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
12281.1Skamil
12291.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
12301.1Skamil	    TWAIT_FNAME);
12311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
12321.1Skamil	    tracer);
12331.1Skamil
12341.1Skamil	validate_status_exited(status, exitval_tracer);
12351.1Skamil
12361.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
12371.1Skamil	    TWAIT_FNAME);
12381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
12391.1Skamil	    tracee);
12401.1Skamil
12411.1Skamil	validate_status_exited(status, exitval_tracee);
12421.1Skamil
12431.1Skamil	msg_close(&parent_tracee);
12441.1Skamil	msg_close(&parent_tracer);
12451.1Skamil}
12461.1Skamil#endif
12471.1Skamil
12481.1SkamilATF_TC(eventmask1);
12491.1SkamilATF_TC_HEAD(eventmask1, tc)
12501.1Skamil{
12511.1Skamil	atf_tc_set_md_var(tc, "descr",
12521.1Skamil	    "Verify that empty EVENT_MASK is preserved");
12531.1Skamil}
12541.1Skamil
12551.1SkamilATF_TC_BODY(eventmask1, tc)
12561.1Skamil{
12571.1Skamil	const int exitval = 5;
12581.1Skamil	const int sigval = SIGSTOP;
12591.1Skamil	pid_t child, wpid;
12601.1Skamil#if defined(TWAIT_HAVE_STATUS)
12611.1Skamil	int status;
12621.1Skamil#endif
12631.1Skamil	ptrace_event_t set_event, get_event;
12641.1Skamil	const int len = sizeof(ptrace_event_t);
12651.1Skamil
12661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12681.1Skamil	if (child == 0) {
12691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12711.1Skamil
12721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12741.1Skamil
12751.13Schristos		DPRINTF("Before exiting of the child process\n");
12761.1Skamil		_exit(exitval);
12771.1Skamil	}
12781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12791.1Skamil
12801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12821.1Skamil
12831.1Skamil	validate_status_stopped(status, sigval);
12841.1Skamil
12851.1Skamil	set_event.pe_set_event = 0;
12861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12881.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12891.1Skamil
12901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12911.1Skamil	    "without signal to be sent\n");
12921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12931.1Skamil
12941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12961.1Skamil
12971.1Skamil	validate_status_exited(status, exitval);
12981.1Skamil
12991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13011.1Skamil}
13021.1Skamil
13031.1SkamilATF_TC(eventmask2);
13041.1SkamilATF_TC_HEAD(eventmask2, tc)
13051.1Skamil{
13061.1Skamil	atf_tc_set_md_var(tc, "descr",
13071.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
13081.1Skamil}
13091.1Skamil
13101.1SkamilATF_TC_BODY(eventmask2, tc)
13111.1Skamil{
13121.1Skamil	const int exitval = 5;
13131.1Skamil	const int sigval = SIGSTOP;
13141.1Skamil	pid_t child, wpid;
13151.1Skamil#if defined(TWAIT_HAVE_STATUS)
13161.1Skamil	int status;
13171.1Skamil#endif
13181.1Skamil	ptrace_event_t set_event, get_event;
13191.1Skamil	const int len = sizeof(ptrace_event_t);
13201.1Skamil
13211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13231.1Skamil	if (child == 0) {
13241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13261.1Skamil
13271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13291.1Skamil
13301.13Schristos		DPRINTF("Before exiting of the child process\n");
13311.1Skamil		_exit(exitval);
13321.1Skamil	}
13331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13341.1Skamil
13351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13371.1Skamil
13381.1Skamil	validate_status_stopped(status, sigval);
13391.1Skamil
13401.1Skamil	set_event.pe_set_event = PTRACE_FORK;
13411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13431.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13441.1Skamil
13451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13461.1Skamil	    "without signal to be sent\n");
13471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13481.1Skamil
13491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13511.1Skamil
13521.1Skamil	validate_status_exited(status, exitval);
13531.1Skamil
13541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13561.1Skamil}
13571.1Skamil
13581.1SkamilATF_TC(eventmask3);
13591.1SkamilATF_TC_HEAD(eventmask3, tc)
13601.1Skamil{
13611.1Skamil	atf_tc_set_md_var(tc, "descr",
13621.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
13631.1Skamil}
13641.1Skamil
13651.1SkamilATF_TC_BODY(eventmask3, tc)
13661.1Skamil{
13671.1Skamil	const int exitval = 5;
13681.1Skamil	const int sigval = SIGSTOP;
13691.1Skamil	pid_t child, wpid;
13701.1Skamil#if defined(TWAIT_HAVE_STATUS)
13711.1Skamil	int status;
13721.1Skamil#endif
13731.1Skamil	ptrace_event_t set_event, get_event;
13741.1Skamil	const int len = sizeof(ptrace_event_t);
13751.1Skamil
13761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13781.1Skamil	if (child == 0) {
13791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13811.1Skamil
13821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13841.1Skamil
13851.13Schristos		DPRINTF("Before exiting of the child process\n");
13861.1Skamil		_exit(exitval);
13871.1Skamil	}
13881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13891.1Skamil
13901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13921.1Skamil
13931.1Skamil	validate_status_stopped(status, sigval);
13941.1Skamil
13951.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
13961.38Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13981.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13991.1Skamil
14001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14011.1Skamil	    "without signal to be sent\n");
14021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14031.1Skamil
14041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14061.1Skamil
14071.1Skamil	validate_status_exited(status, exitval);
14081.1Skamil
14091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14111.1Skamil}
14121.1Skamil
14131.1SkamilATF_TC(eventmask4);
14141.1SkamilATF_TC_HEAD(eventmask4, tc)
14151.1Skamil{
14161.1Skamil	atf_tc_set_md_var(tc, "descr",
14171.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
14181.1Skamil}
14191.1Skamil
14201.1SkamilATF_TC_BODY(eventmask4, tc)
14211.1Skamil{
14221.1Skamil	const int exitval = 5;
14231.1Skamil	const int sigval = SIGSTOP;
14241.1Skamil	pid_t child, wpid;
14251.1Skamil#if defined(TWAIT_HAVE_STATUS)
14261.1Skamil	int status;
14271.1Skamil#endif
14281.1Skamil	ptrace_event_t set_event, get_event;
14291.1Skamil	const int len = sizeof(ptrace_event_t);
14301.1Skamil
14311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14331.1Skamil	if (child == 0) {
14341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14361.1Skamil
14371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14391.1Skamil
14401.13Schristos		DPRINTF("Before exiting of the child process\n");
14411.1Skamil		_exit(exitval);
14421.1Skamil	}
14431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14441.1Skamil
14451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14471.1Skamil
14481.1Skamil	validate_status_stopped(status, sigval);
14491.1Skamil
14501.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
14511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14531.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14541.1Skamil
14551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14561.1Skamil	    "without signal to be sent\n");
14571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14581.1Skamil
14591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14611.1Skamil
14621.1Skamil	validate_status_exited(status, exitval);
14631.1Skamil
14641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14661.1Skamil}
14671.1Skamil
14681.1SkamilATF_TC(eventmask5);
14691.1SkamilATF_TC_HEAD(eventmask5, tc)
14701.1Skamil{
14711.1Skamil	atf_tc_set_md_var(tc, "descr",
14721.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
14731.1Skamil}
14741.1Skamil
14751.1SkamilATF_TC_BODY(eventmask5, tc)
14761.1Skamil{
14771.1Skamil	const int exitval = 5;
14781.1Skamil	const int sigval = SIGSTOP;
14791.1Skamil	pid_t child, wpid;
14801.1Skamil#if defined(TWAIT_HAVE_STATUS)
14811.1Skamil	int status;
14821.1Skamil#endif
14831.1Skamil	ptrace_event_t set_event, get_event;
14841.1Skamil	const int len = sizeof(ptrace_event_t);
14851.1Skamil
14861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14881.1Skamil	if (child == 0) {
14891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14911.1Skamil
14921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14941.1Skamil
14951.13Schristos		DPRINTF("Before exiting of the child process\n");
14961.1Skamil		_exit(exitval);
14971.1Skamil	}
14981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14991.1Skamil
15001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15021.1Skamil
15031.1Skamil	validate_status_stopped(status, sigval);
15041.1Skamil
15051.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
15061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15081.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15091.1Skamil
15101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15111.1Skamil	    "without signal to be sent\n");
15121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15131.1Skamil
15141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15161.1Skamil
15171.1Skamil	validate_status_exited(status, exitval);
15181.1Skamil
15191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15211.1Skamil}
15221.1Skamil
15231.1SkamilATF_TC(eventmask6);
15241.1SkamilATF_TC_HEAD(eventmask6, tc)
15251.1Skamil{
15261.1Skamil	atf_tc_set_md_var(tc, "descr",
15271.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
15281.1Skamil}
15291.1Skamil
15301.1SkamilATF_TC_BODY(eventmask6, tc)
15311.1Skamil{
15321.1Skamil	const int exitval = 5;
15331.1Skamil	const int sigval = SIGSTOP;
15341.1Skamil	pid_t child, wpid;
15351.1Skamil#if defined(TWAIT_HAVE_STATUS)
15361.1Skamil	int status;
15371.1Skamil#endif
15381.1Skamil	ptrace_event_t set_event, get_event;
15391.1Skamil	const int len = sizeof(ptrace_event_t);
15401.1Skamil
15411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15431.1Skamil	if (child == 0) {
15441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15461.1Skamil
15471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15491.1Skamil
15501.13Schristos		DPRINTF("Before exiting of the child process\n");
15511.1Skamil		_exit(exitval);
15521.1Skamil	}
15531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15541.1Skamil
15551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15571.1Skamil
15581.1Skamil	validate_status_stopped(status, sigval);
15591.1Skamil
15601.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
15611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15631.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15641.1Skamil
15651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15661.1Skamil	    "without signal to be sent\n");
15671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15681.1Skamil
15691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15711.1Skamil
15721.1Skamil	validate_status_exited(status, exitval);
15731.1Skamil
15741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15751.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15761.1Skamil}
15771.1Skamil
15781.28Skamilstatic void
15791.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
15801.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
15811.1Skamil{
15821.1Skamil	const int exitval = 5;
15831.1Skamil	const int exitval2 = 15;
15841.1Skamil	const int sigval = SIGSTOP;
15851.31Skamil	pid_t child, child2 = 0, wpid;
15861.1Skamil#if defined(TWAIT_HAVE_STATUS)
15871.1Skamil	int status;
15881.1Skamil#endif
15891.1Skamil	ptrace_state_t state;
15901.1Skamil	const int slen = sizeof(state);
15911.1Skamil	ptrace_event_t event;
15921.1Skamil	const int elen = sizeof(event);
15931.1Skamil
15941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15961.1Skamil	if (child == 0) {
15971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15991.1Skamil
16001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
16011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
16021.1Skamil
16031.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
16041.1Skamil
16051.1Skamil		if (child2 == 0)
16061.1Skamil			_exit(exitval2);
16071.1Skamil
16081.1Skamil		FORKEE_REQUIRE_SUCCESS
16091.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
16101.1Skamil
16111.1Skamil		forkee_status_exited(status, exitval2);
16121.1Skamil
16131.13Schristos		DPRINTF("Before exiting of the child process\n");
16141.1Skamil		_exit(exitval);
16151.1Skamil	}
16161.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16171.1Skamil
16181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16201.1Skamil
16211.1Skamil	validate_status_stopped(status, sigval);
16221.1Skamil
16231.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
16241.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
16251.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
16261.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
16271.30Skamil	event.pe_set_event = 0;
16281.30Skamil	if (trackfork)
16291.30Skamil		event.pe_set_event |= PTRACE_FORK;
16301.30Skamil	if (trackvfork)
16311.30Skamil		event.pe_set_event |= PTRACE_VFORK;
16321.30Skamil	if (trackvforkdone)
16331.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
16341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
16351.1Skamil
16361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16371.1Skamil	    "without signal to be sent\n");
16381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16391.1Skamil
16401.29Skamil#if defined(TWAIT_HAVE_PID)
16411.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
16421.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16431.29Skamil		        child);
16441.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16451.29Skamil		                      child);
16461.1Skamil
16471.29Skamil		validate_status_stopped(status, SIGTRAP);
16481.1Skamil
16491.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
16501.29Skamil		                       slen) != -1);
16511.31Skamil		if (trackfork && fn == fork) {
16521.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16531.30Skamil			       PTRACE_FORK);
16541.30Skamil		}
16551.31Skamil		if (trackvfork && fn == vfork) {
16561.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16571.30Skamil			       PTRACE_VFORK);
16581.30Skamil		}
16591.29Skamil
16601.29Skamil		child2 = state.pe_other_pid;
16611.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
16621.29Skamil
16631.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
16641.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
16651.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16661.29Skamil		    child2);
16671.1Skamil
16681.29Skamil		validate_status_stopped(status, SIGTRAP);
16691.1Skamil
16701.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
16711.29Skamil		                       slen) != -1);
16721.31Skamil		if (trackfork && fn == fork) {
16731.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16741.30Skamil			       PTRACE_FORK);
16751.30Skamil		}
16761.31Skamil		if (trackvfork && fn == vfork) {
16771.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16781.30Skamil			       PTRACE_VFORK);
16791.30Skamil		}
16801.30Skamil
16811.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
16821.29Skamil
16831.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
16841.29Skamil		    "and without signal to be sent\n");
16851.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
16861.29Skamil		                != -1);
16871.29Skamil
16881.29Skamil		DPRINTF("Before resuming the child process where it left off "
16891.29Skamil		        "and without signal to be sent\n");
16901.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16911.30Skamil	}
16921.30Skamil#endif
16931.30Skamil
16941.31Skamil	if (trackvforkdone && fn == vfork) {
16951.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16961.30Skamil		        child);
16971.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16981.30Skamil		                      child);
16991.30Skamil
17001.30Skamil		validate_status_stopped(status, SIGTRAP);
17011.30Skamil
17021.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
17031.30Skamil		                       slen) != -1);
17041.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
17051.30Skamil
17061.30Skamil		child2 = state.pe_other_pid;
17071.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
17081.30Skamil		        child2);
17091.30Skamil
17101.30Skamil		DPRINTF("Before resuming the child process where it left off "
17111.30Skamil		        "and without signal to be sent\n");
17121.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17131.30Skamil	}
17141.29Skamil
17151.30Skamil#if defined(TWAIT_HAVE_PID)
17161.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
17171.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
17181.29Skamil		        "\n", TWAIT_FNAME);
17191.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
17201.29Skamil		    child2);
17211.29Skamil
17221.29Skamil		validate_status_exited(status, exitval2);
17231.29Skamil
17241.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
17251.29Skamil		        "process\n", TWAIT_FNAME);
17261.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
17271.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
17281.29Skamil	}
17291.29Skamil#endif
17301.1Skamil
17311.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
17321.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
17331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17341.1Skamil
17351.1Skamil	validate_status_stopped(status, SIGCHLD);
17361.1Skamil
17371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17381.1Skamil	    "without signal to be sent\n");
17391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17401.1Skamil
17411.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
17421.1Skamil	    TWAIT_FNAME);
17431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17441.1Skamil
17451.1Skamil	validate_status_exited(status, exitval);
17461.1Skamil
17471.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
17481.1Skamil	    TWAIT_FNAME);
17491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17501.1Skamil}
17511.28Skamil
17521.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
17531.32SkamilATF_TC(name);									\
17541.32SkamilATF_TC_HEAD(name, tc)								\
17551.32Skamil{										\
17561.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
17571.32Skamil}										\
17581.32Skamil										\
17591.32SkamilATF_TC_BODY(name, tc)								\
17601.32Skamil{										\
17611.32Skamil										\
17621.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
17631.32Skamil}
17641.32Skamil
17651.32Skamil#define F false
17661.32Skamil#define T true
17671.32Skamil
17681.32Skamil#define F_IF__0(x)
17691.32Skamil#define F_IF__1(x) x
17701.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
17711.32Skamil#define F_IF_(x,y) F_IF__(x,y)
17721.32Skamil#define F_IF(x,y) F_IF_(x,y)
17731.32Skamil
17741.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
17751.32Skamil        "Verify " #function "(2) called with 0"					\
17761.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
17771.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
17781.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
17791.32Skamil        " in EVENT_MASK."							\
17801.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
17811.32Skamil        F_IF(dparentbit," Detach parent in this test.")
17821.1Skamil
17831.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
17841.31Skamil#if defined(TWAIT_HAVE_PID)
17851.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
17861.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
17871.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
17881.31Skamil#endif
17891.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
17901.31Skamil#if defined(TWAIT_HAVE_PID)
17911.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
17921.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
17931.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
17941.31Skamil#endif
17951.1Skamil
17961.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
17971.31Skamil#if defined(TWAIT_HAVE_PID)
17981.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
17991.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
18001.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
18011.31Skamil#endif
18021.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
18031.31Skamil#if defined(TWAIT_HAVE_PID)
18041.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
18051.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
18061.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
18071.31Skamil#endif
18081.31Skamil
18091.31Skamil
18101.31Skamil
18111.1Skamil
18121.1SkamilATF_TC(io_read_d1);
18131.1SkamilATF_TC_HEAD(io_read_d1, tc)
18141.1Skamil{
18151.1Skamil	atf_tc_set_md_var(tc, "descr",
18161.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
18171.1Skamil}
18181.1Skamil
18191.1SkamilATF_TC_BODY(io_read_d1, tc)
18201.1Skamil{
18211.1Skamil	const int exitval = 5;
18221.1Skamil	const int sigval = SIGSTOP;
18231.1Skamil	pid_t child, wpid;
18241.1Skamil	uint8_t lookup_me = 0;
18251.1Skamil	const uint8_t magic = 0xab;
18261.1Skamil	struct ptrace_io_desc io = {
18271.1Skamil		.piod_op = PIOD_READ_D,
18281.1Skamil		.piod_offs = &lookup_me,
18291.1Skamil		.piod_addr = &lookup_me,
18301.1Skamil		.piod_len = sizeof(lookup_me)
18311.1Skamil	};
18321.1Skamil#if defined(TWAIT_HAVE_STATUS)
18331.1Skamil	int status;
18341.1Skamil#endif
18351.1Skamil
18361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18381.1Skamil	if (child == 0) {
18391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18411.1Skamil
18421.1Skamil		lookup_me = magic;
18431.1Skamil
18441.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18451.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18461.1Skamil
18471.13Schristos		DPRINTF("Before exiting of the child process\n");
18481.1Skamil		_exit(exitval);
18491.1Skamil	}
18501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18511.1Skamil
18521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18541.1Skamil
18551.1Skamil	validate_status_stopped(status, sigval);
18561.1Skamil
18571.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
18581.1Skamil	    child, getpid());
18591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
18601.1Skamil
18611.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18621.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
18631.1Skamil
18641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18651.1Skamil	    "without signal to be sent\n");
18661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18671.1Skamil
18681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18701.1Skamil
18711.1Skamil	validate_status_exited(status, exitval);
18721.1Skamil
18731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18751.1Skamil}
18761.1Skamil
18771.1SkamilATF_TC(io_read_d2);
18781.1SkamilATF_TC_HEAD(io_read_d2, tc)
18791.1Skamil{
18801.1Skamil	atf_tc_set_md_var(tc, "descr",
18811.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
18821.1Skamil}
18831.1Skamil
18841.1SkamilATF_TC_BODY(io_read_d2, tc)
18851.1Skamil{
18861.1Skamil	const int exitval = 5;
18871.1Skamil	const int sigval = SIGSTOP;
18881.1Skamil	pid_t child, wpid;
18891.1Skamil	uint16_t lookup_me = 0;
18901.1Skamil	const uint16_t magic = 0x1234;
18911.1Skamil	struct ptrace_io_desc io = {
18921.1Skamil		.piod_op = PIOD_READ_D,
18931.1Skamil		.piod_offs = &lookup_me,
18941.1Skamil		.piod_addr = &lookup_me,
18951.1Skamil		.piod_len = sizeof(lookup_me)
18961.1Skamil	};
18971.1Skamil#if defined(TWAIT_HAVE_STATUS)
18981.1Skamil	int status;
18991.1Skamil#endif
19001.1Skamil
19011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19031.1Skamil	if (child == 0) {
19041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19061.1Skamil
19071.1Skamil		lookup_me = magic;
19081.1Skamil
19091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19111.1Skamil
19121.13Schristos		DPRINTF("Before exiting of the child process\n");
19131.1Skamil		_exit(exitval);
19141.1Skamil	}
19151.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19161.1Skamil
19171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19191.1Skamil
19201.1Skamil	validate_status_stopped(status, sigval);
19211.1Skamil
19221.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19231.1Skamil	    child, getpid());
19241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19251.1Skamil
19261.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19271.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
19281.1Skamil
19291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19301.1Skamil	    "without signal to be sent\n");
19311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19321.1Skamil
19331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19351.1Skamil
19361.1Skamil	validate_status_exited(status, exitval);
19371.1Skamil
19381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19401.1Skamil}
19411.1Skamil
19421.1SkamilATF_TC(io_read_d3);
19431.1SkamilATF_TC_HEAD(io_read_d3, tc)
19441.1Skamil{
19451.1Skamil	atf_tc_set_md_var(tc, "descr",
19461.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
19471.1Skamil}
19481.1Skamil
19491.1SkamilATF_TC_BODY(io_read_d3, tc)
19501.1Skamil{
19511.1Skamil	const int exitval = 5;
19521.1Skamil	const int sigval = SIGSTOP;
19531.1Skamil	pid_t child, wpid;
19541.1Skamil	uint32_t lookup_me = 0;
19551.1Skamil	const uint32_t magic = 0x1234abcd;
19561.1Skamil	struct ptrace_io_desc io = {
19571.1Skamil		.piod_op = PIOD_READ_D,
19581.1Skamil		.piod_offs = &lookup_me,
19591.1Skamil		.piod_addr = &lookup_me,
19601.1Skamil		.piod_len = sizeof(lookup_me)
19611.1Skamil	};
19621.1Skamil#if defined(TWAIT_HAVE_STATUS)
19631.1Skamil	int status;
19641.1Skamil#endif
19651.1Skamil
19661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19681.1Skamil	if (child == 0) {
19691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19711.1Skamil
19721.1Skamil		lookup_me = magic;
19731.1Skamil
19741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19761.1Skamil
19771.13Schristos		DPRINTF("Before exiting of the child process\n");
19781.1Skamil		_exit(exitval);
19791.1Skamil	}
19801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19811.1Skamil
19821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19841.1Skamil
19851.1Skamil	validate_status_stopped(status, sigval);
19861.1Skamil
19871.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19881.1Skamil	    child, getpid());
19891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19901.1Skamil
19911.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19921.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
19931.1Skamil
19941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19951.1Skamil	    "without signal to be sent\n");
19961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19971.1Skamil
19981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20001.1Skamil
20011.1Skamil	validate_status_exited(status, exitval);
20021.1Skamil
20031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20051.1Skamil}
20061.1Skamil
20071.1SkamilATF_TC(io_read_d4);
20081.1SkamilATF_TC_HEAD(io_read_d4, tc)
20091.1Skamil{
20101.1Skamil	atf_tc_set_md_var(tc, "descr",
20111.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
20121.1Skamil}
20131.1Skamil
20141.1SkamilATF_TC_BODY(io_read_d4, tc)
20151.1Skamil{
20161.1Skamil	const int exitval = 5;
20171.1Skamil	const int sigval = SIGSTOP;
20181.1Skamil	pid_t child, wpid;
20191.1Skamil	uint64_t lookup_me = 0;
20201.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
20211.1Skamil	struct ptrace_io_desc io = {
20221.1Skamil		.piod_op = PIOD_READ_D,
20231.1Skamil		.piod_offs = &lookup_me,
20241.1Skamil		.piod_addr = &lookup_me,
20251.1Skamil		.piod_len = sizeof(lookup_me)
20261.1Skamil	};
20271.1Skamil#if defined(TWAIT_HAVE_STATUS)
20281.1Skamil	int status;
20291.1Skamil#endif
20301.1Skamil
20311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20331.1Skamil	if (child == 0) {
20341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20361.1Skamil
20371.1Skamil		lookup_me = magic;
20381.1Skamil
20391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20411.1Skamil
20421.13Schristos		DPRINTF("Before exiting of the child process\n");
20431.1Skamil		_exit(exitval);
20441.1Skamil	}
20451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20461.1Skamil
20471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20491.1Skamil
20501.1Skamil	validate_status_stopped(status, sigval);
20511.1Skamil
20521.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
20531.1Skamil	    child, getpid());
20541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20551.1Skamil
20561.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
20571.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
20581.1Skamil
20591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20601.1Skamil	    "without signal to be sent\n");
20611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20621.1Skamil
20631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20651.1Skamil
20661.1Skamil	validate_status_exited(status, exitval);
20671.1Skamil
20681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20701.1Skamil}
20711.1Skamil
20721.1SkamilATF_TC(io_write_d1);
20731.1SkamilATF_TC_HEAD(io_write_d1, tc)
20741.1Skamil{
20751.1Skamil	atf_tc_set_md_var(tc, "descr",
20761.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
20771.1Skamil}
20781.1Skamil
20791.1SkamilATF_TC_BODY(io_write_d1, tc)
20801.1Skamil{
20811.1Skamil	const int exitval = 5;
20821.1Skamil	const int sigval = SIGSTOP;
20831.1Skamil	pid_t child, wpid;
20841.1Skamil	uint8_t lookup_me = 0;
20851.1Skamil	const uint8_t magic = 0xab;
20861.1Skamil	struct ptrace_io_desc io = {
20871.1Skamil		.piod_op = PIOD_WRITE_D,
20881.1Skamil		.piod_offs = &lookup_me,
20891.1Skamil		.piod_addr = &lookup_me,
20901.1Skamil		.piod_len = sizeof(lookup_me)
20911.1Skamil	};
20921.1Skamil#if defined(TWAIT_HAVE_STATUS)
20931.1Skamil	int status;
20941.1Skamil#endif
20951.1Skamil
20961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20981.1Skamil	if (child == 0) {
20991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21011.1Skamil
21021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21041.1Skamil
21051.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21061.1Skamil
21071.13Schristos		DPRINTF("Before exiting of the child process\n");
21081.1Skamil		_exit(exitval);
21091.1Skamil	}
21101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21111.1Skamil
21121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21141.1Skamil
21151.1Skamil	validate_status_stopped(status, sigval);
21161.1Skamil
21171.1Skamil	lookup_me = magic;
21181.1Skamil
21191.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21201.1Skamil	    child, getpid());
21211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21221.1Skamil
21231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21241.1Skamil	    "without signal to be sent\n");
21251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21261.1Skamil
21271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21291.1Skamil
21301.1Skamil	validate_status_exited(status, exitval);
21311.1Skamil
21321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21341.1Skamil}
21351.1Skamil
21361.1SkamilATF_TC(io_write_d2);
21371.1SkamilATF_TC_HEAD(io_write_d2, tc)
21381.1Skamil{
21391.1Skamil	atf_tc_set_md_var(tc, "descr",
21401.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
21411.1Skamil}
21421.1Skamil
21431.1SkamilATF_TC_BODY(io_write_d2, tc)
21441.1Skamil{
21451.1Skamil	const int exitval = 5;
21461.1Skamil	const int sigval = SIGSTOP;
21471.1Skamil	pid_t child, wpid;
21481.1Skamil	uint16_t lookup_me = 0;
21491.1Skamil	const uint16_t magic = 0xab12;
21501.1Skamil	struct ptrace_io_desc io = {
21511.1Skamil		.piod_op = PIOD_WRITE_D,
21521.1Skamil		.piod_offs = &lookup_me,
21531.1Skamil		.piod_addr = &lookup_me,
21541.1Skamil		.piod_len = sizeof(lookup_me)
21551.1Skamil	};
21561.1Skamil#if defined(TWAIT_HAVE_STATUS)
21571.1Skamil	int status;
21581.1Skamil#endif
21591.1Skamil
21601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21621.1Skamil	if (child == 0) {
21631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21651.1Skamil
21661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21681.1Skamil
21691.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21701.1Skamil
21711.13Schristos		DPRINTF("Before exiting of the child process\n");
21721.1Skamil		_exit(exitval);
21731.1Skamil	}
21741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21751.1Skamil
21761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21781.1Skamil
21791.1Skamil	validate_status_stopped(status, sigval);
21801.1Skamil
21811.1Skamil	lookup_me = magic;
21821.1Skamil
21831.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21841.1Skamil	    child, getpid());
21851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21861.1Skamil
21871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21881.1Skamil	    "without signal to be sent\n");
21891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21901.1Skamil
21911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21931.1Skamil
21941.1Skamil	validate_status_exited(status, exitval);
21951.1Skamil
21961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21981.1Skamil}
21991.1Skamil
22001.1SkamilATF_TC(io_write_d3);
22011.1SkamilATF_TC_HEAD(io_write_d3, tc)
22021.1Skamil{
22031.1Skamil	atf_tc_set_md_var(tc, "descr",
22041.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
22051.1Skamil}
22061.1Skamil
22071.1SkamilATF_TC_BODY(io_write_d3, tc)
22081.1Skamil{
22091.1Skamil	const int exitval = 5;
22101.1Skamil	const int sigval = SIGSTOP;
22111.1Skamil	pid_t child, wpid;
22121.1Skamil	uint32_t lookup_me = 0;
22131.1Skamil	const uint32_t magic = 0xab127643;
22141.1Skamil	struct ptrace_io_desc io = {
22151.1Skamil		.piod_op = PIOD_WRITE_D,
22161.1Skamil		.piod_offs = &lookup_me,
22171.1Skamil		.piod_addr = &lookup_me,
22181.1Skamil		.piod_len = sizeof(lookup_me)
22191.1Skamil	};
22201.1Skamil#if defined(TWAIT_HAVE_STATUS)
22211.1Skamil	int status;
22221.1Skamil#endif
22231.1Skamil
22241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22261.1Skamil	if (child == 0) {
22271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22291.1Skamil
22301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22321.1Skamil
22331.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22341.1Skamil
22351.13Schristos		DPRINTF("Before exiting of the child process\n");
22361.1Skamil		_exit(exitval);
22371.1Skamil	}
22381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22391.1Skamil
22401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22421.1Skamil
22431.1Skamil	validate_status_stopped(status, sigval);
22441.1Skamil
22451.1Skamil	lookup_me = magic;
22461.1Skamil
22471.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22481.1Skamil	    child, getpid());
22491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22501.1Skamil
22511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22521.1Skamil	    "without signal to be sent\n");
22531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22541.1Skamil
22551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22571.1Skamil
22581.1Skamil	validate_status_exited(status, exitval);
22591.1Skamil
22601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22621.1Skamil}
22631.1Skamil
22641.1SkamilATF_TC(io_write_d4);
22651.1SkamilATF_TC_HEAD(io_write_d4, tc)
22661.1Skamil{
22671.1Skamil	atf_tc_set_md_var(tc, "descr",
22681.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
22691.1Skamil}
22701.1Skamil
22711.1SkamilATF_TC_BODY(io_write_d4, tc)
22721.1Skamil{
22731.1Skamil	const int exitval = 5;
22741.1Skamil	const int sigval = SIGSTOP;
22751.1Skamil	pid_t child, wpid;
22761.1Skamil	uint64_t lookup_me = 0;
22771.1Skamil	const uint64_t magic = 0xab12764376490123;
22781.1Skamil	struct ptrace_io_desc io = {
22791.1Skamil		.piod_op = PIOD_WRITE_D,
22801.1Skamil		.piod_offs = &lookup_me,
22811.1Skamil		.piod_addr = &lookup_me,
22821.1Skamil		.piod_len = sizeof(lookup_me)
22831.1Skamil	};
22841.1Skamil#if defined(TWAIT_HAVE_STATUS)
22851.1Skamil	int status;
22861.1Skamil#endif
22871.1Skamil
22881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22901.1Skamil	if (child == 0) {
22911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22931.1Skamil
22941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22961.1Skamil
22971.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22981.1Skamil
22991.13Schristos		DPRINTF("Before exiting of the child process\n");
23001.1Skamil		_exit(exitval);
23011.1Skamil	}
23021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23031.1Skamil
23041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23061.1Skamil
23071.1Skamil	validate_status_stopped(status, sigval);
23081.1Skamil
23091.1Skamil	lookup_me = magic;
23101.1Skamil
23111.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
23121.1Skamil	    child, getpid());
23131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23141.1Skamil
23151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23161.1Skamil	    "without signal to be sent\n");
23171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23181.1Skamil
23191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23211.1Skamil
23221.1Skamil	validate_status_exited(status, exitval);
23231.1Skamil
23241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23261.1Skamil}
23271.1Skamil
23281.1SkamilATF_TC(io_read_auxv1);
23291.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
23301.1Skamil{
23311.1Skamil	atf_tc_set_md_var(tc, "descr",
23321.1Skamil	    "Verify PT_READ_AUXV called for tracee");
23331.1Skamil}
23341.1Skamil
23351.1SkamilATF_TC_BODY(io_read_auxv1, tc)
23361.1Skamil{
23371.1Skamil	const int exitval = 5;
23381.1Skamil	const int sigval = SIGSTOP;
23391.1Skamil	pid_t child, wpid;
23401.1Skamil#if defined(TWAIT_HAVE_STATUS)
23411.1Skamil	int status;
23421.1Skamil#endif
23431.1Skamil	AuxInfo ai[100], *aip;
23441.1Skamil	struct ptrace_io_desc io = {
23451.1Skamil		.piod_op = PIOD_READ_AUXV,
23461.1Skamil		.piod_offs = 0,
23471.1Skamil		.piod_addr = ai,
23481.1Skamil		.piod_len = sizeof(ai)
23491.1Skamil	};
23501.1Skamil
23511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23531.1Skamil	if (child == 0) {
23541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23561.1Skamil
23571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23591.1Skamil
23601.13Schristos		DPRINTF("Before exiting of the child process\n");
23611.1Skamil		_exit(exitval);
23621.1Skamil	}
23631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23641.1Skamil
23651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23671.1Skamil
23681.1Skamil	validate_status_stopped(status, sigval);
23691.1Skamil
23701.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
23711.1Skamil	    child, getpid());
23721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23731.1Skamil
23741.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
23751.1Skamil	ATF_REQUIRE(io.piod_len > 0);
23761.1Skamil
23771.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
23781.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
23791.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
23801.1Skamil
23811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23821.1Skamil	    "without signal to be sent\n");
23831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23841.1Skamil
23851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23871.1Skamil
23881.1Skamil	validate_status_exited(status, exitval);
23891.1Skamil
23901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23921.1Skamil}
23931.1Skamil
23941.1SkamilATF_TC(read_d1);
23951.1SkamilATF_TC_HEAD(read_d1, tc)
23961.1Skamil{
23971.1Skamil	atf_tc_set_md_var(tc, "descr",
23981.1Skamil	    "Verify PT_READ_D called once");
23991.1Skamil}
24001.1Skamil
24011.1SkamilATF_TC_BODY(read_d1, tc)
24021.1Skamil{
24031.1Skamil	const int exitval = 5;
24041.1Skamil	const int sigval = SIGSTOP;
24051.1Skamil	pid_t child, wpid;
24061.1Skamil	int lookup_me = 0;
24071.1Skamil	const int magic = (int)random();
24081.1Skamil#if defined(TWAIT_HAVE_STATUS)
24091.1Skamil	int status;
24101.1Skamil#endif
24111.1Skamil
24121.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24131.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24141.1Skamil	if (child == 0) {
24151.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24161.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24171.1Skamil
24181.1Skamil		lookup_me = magic;
24191.1Skamil
24201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24221.1Skamil
24231.13Schristos		DPRINTF("Before exiting of the child process\n");
24241.1Skamil		_exit(exitval);
24251.1Skamil	}
24261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24271.1Skamil
24281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24301.1Skamil
24311.1Skamil	validate_status_stopped(status, sigval);
24321.1Skamil
24331.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
24341.1Skamil	    child, getpid());
24351.1Skamil	errno = 0;
24361.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
24371.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24381.1Skamil
24391.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
24401.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
24411.1Skamil
24421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24431.1Skamil	    "without signal to be sent\n");
24441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24451.1Skamil
24461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24481.1Skamil
24491.1Skamil	validate_status_exited(status, exitval);
24501.1Skamil
24511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24531.1Skamil}
24541.1Skamil
24551.1SkamilATF_TC(read_d2);
24561.1SkamilATF_TC_HEAD(read_d2, tc)
24571.1Skamil{
24581.1Skamil	atf_tc_set_md_var(tc, "descr",
24591.1Skamil	    "Verify PT_READ_D called twice");
24601.1Skamil}
24611.1Skamil
24621.1SkamilATF_TC_BODY(read_d2, tc)
24631.1Skamil{
24641.1Skamil	const int exitval = 5;
24651.1Skamil	const int sigval = SIGSTOP;
24661.1Skamil	pid_t child, wpid;
24671.1Skamil	int lookup_me1 = 0;
24681.1Skamil	int lookup_me2 = 0;
24691.1Skamil	const int magic1 = (int)random();
24701.1Skamil	const int magic2 = (int)random();
24711.1Skamil#if defined(TWAIT_HAVE_STATUS)
24721.1Skamil	int status;
24731.1Skamil#endif
24741.1Skamil
24751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24771.1Skamil	if (child == 0) {
24781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24801.1Skamil
24811.1Skamil		lookup_me1 = magic1;
24821.1Skamil		lookup_me2 = magic2;
24831.1Skamil
24841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24861.1Skamil
24871.13Schristos		DPRINTF("Before exiting of the child process\n");
24881.1Skamil		_exit(exitval);
24891.1Skamil	}
24901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24911.1Skamil
24921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24941.1Skamil
24951.1Skamil	validate_status_stopped(status, sigval);
24961.1Skamil
24971.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
24981.1Skamil	    child, getpid());
24991.1Skamil	errno = 0;
25001.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25011.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25021.1Skamil
25031.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25041.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25051.1Skamil
25061.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25071.1Skamil	    child, getpid());
25081.1Skamil	errno = 0;
25091.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25101.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25111.1Skamil
25121.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25131.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25141.1Skamil
25151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25161.1Skamil	    "without signal to be sent\n");
25171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25181.1Skamil
25191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25211.1Skamil
25221.1Skamil	validate_status_exited(status, exitval);
25231.1Skamil
25241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25261.1Skamil}
25271.1Skamil
25281.1SkamilATF_TC(read_d3);
25291.1SkamilATF_TC_HEAD(read_d3, tc)
25301.1Skamil{
25311.1Skamil	atf_tc_set_md_var(tc, "descr",
25321.1Skamil	    "Verify PT_READ_D called three times");
25331.1Skamil}
25341.1Skamil
25351.1SkamilATF_TC_BODY(read_d3, tc)
25361.1Skamil{
25371.1Skamil	const int exitval = 5;
25381.1Skamil	const int sigval = SIGSTOP;
25391.1Skamil	pid_t child, wpid;
25401.1Skamil	int lookup_me1 = 0;
25411.1Skamil	int lookup_me2 = 0;
25421.1Skamil	int lookup_me3 = 0;
25431.1Skamil	const int magic1 = (int)random();
25441.1Skamil	const int magic2 = (int)random();
25451.1Skamil	const int magic3 = (int)random();
25461.1Skamil#if defined(TWAIT_HAVE_STATUS)
25471.1Skamil	int status;
25481.1Skamil#endif
25491.1Skamil
25501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25521.1Skamil	if (child == 0) {
25531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25551.1Skamil
25561.1Skamil		lookup_me1 = magic1;
25571.1Skamil		lookup_me2 = magic2;
25581.1Skamil		lookup_me3 = magic3;
25591.1Skamil
25601.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25611.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25621.1Skamil
25631.13Schristos		DPRINTF("Before exiting of the child process\n");
25641.1Skamil		_exit(exitval);
25651.1Skamil	}
25661.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25671.1Skamil
25681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25701.1Skamil
25711.1Skamil	validate_status_stopped(status, sigval);
25721.1Skamil
25731.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25741.1Skamil	    child, getpid());
25751.1Skamil	errno = 0;
25761.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25771.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25781.1Skamil
25791.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25801.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25811.1Skamil
25821.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25831.1Skamil	    child, getpid());
25841.1Skamil	errno = 0;
25851.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25861.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25871.1Skamil
25881.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25891.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25901.1Skamil
25911.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
25921.1Skamil	    child, getpid());
25931.1Skamil	errno = 0;
25941.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
25951.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25961.1Skamil
25971.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
25981.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
25991.1Skamil
26001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26011.1Skamil	    "without signal to be sent\n");
26021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26031.1Skamil
26041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26061.1Skamil
26071.1Skamil	validate_status_exited(status, exitval);
26081.1Skamil
26091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26111.1Skamil}
26121.1Skamil
26131.1SkamilATF_TC(read_d4);
26141.1SkamilATF_TC_HEAD(read_d4, tc)
26151.1Skamil{
26161.1Skamil	atf_tc_set_md_var(tc, "descr",
26171.1Skamil	    "Verify PT_READ_D called four times");
26181.1Skamil}
26191.1Skamil
26201.1SkamilATF_TC_BODY(read_d4, tc)
26211.1Skamil{
26221.1Skamil	const int exitval = 5;
26231.1Skamil	const int sigval = SIGSTOP;
26241.1Skamil	pid_t child, wpid;
26251.1Skamil	int lookup_me1 = 0;
26261.1Skamil	int lookup_me2 = 0;
26271.1Skamil	int lookup_me3 = 0;
26281.1Skamil	int lookup_me4 = 0;
26291.1Skamil	const int magic1 = (int)random();
26301.1Skamil	const int magic2 = (int)random();
26311.1Skamil	const int magic3 = (int)random();
26321.1Skamil	const int magic4 = (int)random();
26331.1Skamil#if defined(TWAIT_HAVE_STATUS)
26341.1Skamil	int status;
26351.1Skamil#endif
26361.1Skamil
26371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26391.1Skamil	if (child == 0) {
26401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26421.1Skamil
26431.1Skamil		lookup_me1 = magic1;
26441.1Skamil		lookup_me2 = magic2;
26451.1Skamil		lookup_me3 = magic3;
26461.1Skamil		lookup_me4 = magic4;
26471.1Skamil
26481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26501.1Skamil
26511.13Schristos		DPRINTF("Before exiting of the child process\n");
26521.1Skamil		_exit(exitval);
26531.1Skamil	}
26541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26551.1Skamil
26561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26581.1Skamil
26591.1Skamil	validate_status_stopped(status, sigval);
26601.1Skamil
26611.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
26621.1Skamil	    child, getpid());
26631.1Skamil	errno = 0;
26641.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26651.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26661.1Skamil
26671.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26681.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26691.1Skamil
26701.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26711.1Skamil	    child, getpid());
26721.1Skamil	errno = 0;
26731.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26741.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26751.1Skamil
26761.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26771.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26781.1Skamil
26791.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26801.1Skamil	    child, getpid());
26811.1Skamil	errno = 0;
26821.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26831.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26841.1Skamil
26851.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26861.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26871.1Skamil
26881.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
26891.1Skamil	    child, getpid());
26901.1Skamil	errno = 0;
26911.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
26921.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26931.1Skamil
26941.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
26951.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
26961.1Skamil
26971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26981.1Skamil	    "without signal to be sent\n");
26991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27001.1Skamil
27011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27031.1Skamil
27041.1Skamil	validate_status_exited(status, exitval);
27051.1Skamil
27061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27081.1Skamil}
27091.1Skamil
27101.1SkamilATF_TC(write_d1);
27111.1SkamilATF_TC_HEAD(write_d1, tc)
27121.1Skamil{
27131.1Skamil	atf_tc_set_md_var(tc, "descr",
27141.1Skamil	    "Verify PT_WRITE_D called once");
27151.1Skamil}
27161.1Skamil
27171.1SkamilATF_TC_BODY(write_d1, tc)
27181.1Skamil{
27191.1Skamil	const int exitval = 5;
27201.1Skamil	const int sigval = SIGSTOP;
27211.1Skamil	pid_t child, wpid;
27221.1Skamil	int lookup_me = 0;
27231.1Skamil	const int magic = (int)random();
27241.1Skamil#if defined(TWAIT_HAVE_STATUS)
27251.1Skamil	int status;
27261.1Skamil#endif
27271.1Skamil
27281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27301.1Skamil	if (child == 0) {
27311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27331.1Skamil
27341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27361.1Skamil
27371.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
27381.1Skamil
27391.13Schristos		DPRINTF("Before exiting of the child process\n");
27401.1Skamil		_exit(exitval);
27411.1Skamil	}
27421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27431.1Skamil
27441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27461.1Skamil
27471.1Skamil	validate_status_stopped(status, sigval);
27481.1Skamil
27491.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
27501.1Skamil	    child, getpid());
27511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
27521.1Skamil
27531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27541.1Skamil	    "without signal to be sent\n");
27551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27561.1Skamil
27571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27591.1Skamil
27601.1Skamil	validate_status_exited(status, exitval);
27611.1Skamil
27621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27641.1Skamil}
27651.1Skamil
27661.1SkamilATF_TC(write_d2);
27671.1SkamilATF_TC_HEAD(write_d2, tc)
27681.1Skamil{
27691.1Skamil	atf_tc_set_md_var(tc, "descr",
27701.1Skamil	    "Verify PT_WRITE_D called twice");
27711.1Skamil}
27721.1Skamil
27731.1SkamilATF_TC_BODY(write_d2, tc)
27741.1Skamil{
27751.1Skamil	const int exitval = 5;
27761.1Skamil	const int sigval = SIGSTOP;
27771.1Skamil	pid_t child, wpid;
27781.1Skamil	int lookup_me1 = 0;
27791.1Skamil	int lookup_me2 = 0;
27801.1Skamil	const int magic1 = (int)random();
27811.1Skamil	const int magic2 = (int)random();
27821.1Skamil#if defined(TWAIT_HAVE_STATUS)
27831.1Skamil	int status;
27841.1Skamil#endif
27851.1Skamil
27861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27881.1Skamil	if (child == 0) {
27891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27911.1Skamil
27921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27941.1Skamil
27951.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27961.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
27971.1Skamil
27981.13Schristos		DPRINTF("Before exiting of the child process\n");
27991.1Skamil		_exit(exitval);
28001.1Skamil	}
28011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28021.1Skamil
28031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28051.1Skamil
28061.1Skamil	validate_status_stopped(status, sigval);
28071.1Skamil
28081.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28091.1Skamil	    child, getpid());
28101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28111.1Skamil
28121.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28131.1Skamil	    child, getpid());
28141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28151.1Skamil
28161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28171.1Skamil	    "without signal to be sent\n");
28181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28191.1Skamil
28201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28221.1Skamil
28231.1Skamil	validate_status_exited(status, exitval);
28241.1Skamil
28251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28271.1Skamil}
28281.1Skamil
28291.1SkamilATF_TC(write_d3);
28301.1SkamilATF_TC_HEAD(write_d3, tc)
28311.1Skamil{
28321.1Skamil	atf_tc_set_md_var(tc, "descr",
28331.1Skamil	    "Verify PT_WRITE_D called three times");
28341.1Skamil}
28351.1Skamil
28361.1SkamilATF_TC_BODY(write_d3, tc)
28371.1Skamil{
28381.1Skamil	const int exitval = 5;
28391.1Skamil	const int sigval = SIGSTOP;
28401.1Skamil	pid_t child, wpid;
28411.1Skamil	int lookup_me1 = 0;
28421.1Skamil	int lookup_me2 = 0;
28431.1Skamil	int lookup_me3 = 0;
28441.1Skamil	const int magic1 = (int)random();
28451.1Skamil	const int magic2 = (int)random();
28461.1Skamil	const int magic3 = (int)random();
28471.1Skamil#if defined(TWAIT_HAVE_STATUS)
28481.1Skamil	int status;
28491.1Skamil#endif
28501.1Skamil
28511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28531.1Skamil	if (child == 0) {
28541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28561.1Skamil
28571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28591.1Skamil
28601.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28611.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28621.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28631.1Skamil
28641.13Schristos		DPRINTF("Before exiting of the child process\n");
28651.1Skamil		_exit(exitval);
28661.1Skamil	}
28671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28681.1Skamil
28691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28711.1Skamil
28721.1Skamil	validate_status_stopped(status, sigval);
28731.1Skamil
28741.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28751.1Skamil	    child, getpid());
28761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28771.1Skamil
28781.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28791.1Skamil	    child, getpid());
28801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28811.1Skamil
28821.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28831.1Skamil	    child, getpid());
28841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28851.1Skamil
28861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28871.1Skamil	    "without signal to be sent\n");
28881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28891.1Skamil
28901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28921.1Skamil
28931.1Skamil	validate_status_exited(status, exitval);
28941.1Skamil
28951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28971.1Skamil}
28981.1Skamil
28991.1SkamilATF_TC(write_d4);
29001.1SkamilATF_TC_HEAD(write_d4, tc)
29011.1Skamil{
29021.1Skamil	atf_tc_set_md_var(tc, "descr",
29031.1Skamil	    "Verify PT_WRITE_D called four times");
29041.1Skamil}
29051.1Skamil
29061.1SkamilATF_TC_BODY(write_d4, tc)
29071.1Skamil{
29081.1Skamil	const int exitval = 5;
29091.1Skamil	const int sigval = SIGSTOP;
29101.1Skamil	pid_t child, wpid;
29111.1Skamil	int lookup_me1 = 0;
29121.1Skamil	int lookup_me2 = 0;
29131.1Skamil	int lookup_me3 = 0;
29141.1Skamil	int lookup_me4 = 0;
29151.1Skamil	const int magic1 = (int)random();
29161.1Skamil	const int magic2 = (int)random();
29171.1Skamil	const int magic3 = (int)random();
29181.1Skamil	const int magic4 = (int)random();
29191.1Skamil#if defined(TWAIT_HAVE_STATUS)
29201.1Skamil	int status;
29211.1Skamil#endif
29221.1Skamil
29231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29251.1Skamil	if (child == 0) {
29261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29281.1Skamil
29291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29311.1Skamil
29321.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
29331.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
29341.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
29351.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
29361.1Skamil
29371.13Schristos		DPRINTF("Before exiting of the child process\n");
29381.1Skamil		_exit(exitval);
29391.1Skamil	}
29401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29411.1Skamil
29421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29441.1Skamil
29451.1Skamil	validate_status_stopped(status, sigval);
29461.1Skamil
29471.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
29481.1Skamil	    child, getpid());
29491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
29501.1Skamil
29511.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
29521.1Skamil	    child, getpid());
29531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
29541.1Skamil
29551.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
29561.1Skamil	    child, getpid());
29571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
29581.1Skamil
29591.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
29601.1Skamil	    child, getpid());
29611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
29621.1Skamil
29631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29641.1Skamil	    "without signal to be sent\n");
29651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29661.1Skamil
29671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29691.1Skamil
29701.1Skamil	validate_status_exited(status, exitval);
29711.1Skamil
29721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29741.1Skamil}
29751.1Skamil
29761.1SkamilATF_TC(io_read_d_write_d_handshake1);
29771.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
29781.1Skamil{
29791.1Skamil	atf_tc_set_md_var(tc, "descr",
29801.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
29811.1Skamil}
29821.1Skamil
29831.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
29841.1Skamil{
29851.1Skamil	const int exitval = 5;
29861.1Skamil	const int sigval = SIGSTOP;
29871.1Skamil	pid_t child, wpid;
29881.1Skamil	uint8_t lookup_me_fromtracee = 0;
29891.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
29901.1Skamil	uint8_t lookup_me_totracee = 0;
29911.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
29921.1Skamil	struct ptrace_io_desc io_fromtracee = {
29931.1Skamil		.piod_op = PIOD_READ_D,
29941.1Skamil		.piod_offs = &lookup_me_fromtracee,
29951.1Skamil		.piod_addr = &lookup_me_fromtracee,
29961.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
29971.1Skamil	};
29981.1Skamil	struct ptrace_io_desc io_totracee = {
29991.1Skamil		.piod_op = PIOD_WRITE_D,
30001.1Skamil		.piod_offs = &lookup_me_totracee,
30011.1Skamil		.piod_addr = &lookup_me_totracee,
30021.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30031.1Skamil	};
30041.1Skamil#if defined(TWAIT_HAVE_STATUS)
30051.1Skamil	int status;
30061.1Skamil#endif
30071.1Skamil
30081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30101.1Skamil	if (child == 0) {
30111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30131.1Skamil
30141.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30151.1Skamil
30161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30181.1Skamil
30191.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30201.1Skamil
30211.13Schristos		DPRINTF("Before exiting of the child process\n");
30221.1Skamil		_exit(exitval);
30231.1Skamil	}
30241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30251.1Skamil
30261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30281.1Skamil
30291.1Skamil	validate_status_stopped(status, sigval);
30301.1Skamil
30311.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30321.1Skamil	    child, getpid());
30331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30341.1Skamil
30351.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30361.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30371.1Skamil	    magic_fromtracee);
30381.1Skamil
30391.1Skamil	lookup_me_totracee = magic_totracee;
30401.1Skamil
30411.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30421.1Skamil	    child, getpid());
30431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30441.1Skamil
30451.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30461.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30471.1Skamil	    magic_totracee);
30481.1Skamil
30491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30501.1Skamil	    "without signal to be sent\n");
30511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30521.1Skamil
30531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30551.1Skamil
30561.1Skamil	validate_status_exited(status, exitval);
30571.1Skamil
30581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30601.1Skamil}
30611.1Skamil
30621.1SkamilATF_TC(io_read_d_write_d_handshake2);
30631.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
30641.1Skamil{
30651.1Skamil	atf_tc_set_md_var(tc, "descr",
30661.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
30671.1Skamil}
30681.1Skamil
30691.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
30701.1Skamil{
30711.1Skamil	const int exitval = 5;
30721.1Skamil	const int sigval = SIGSTOP;
30731.1Skamil	pid_t child, wpid;
30741.1Skamil	uint8_t lookup_me_fromtracee = 0;
30751.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30761.1Skamil	uint8_t lookup_me_totracee = 0;
30771.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30781.1Skamil	struct ptrace_io_desc io_fromtracee = {
30791.1Skamil		.piod_op = PIOD_READ_D,
30801.1Skamil		.piod_offs = &lookup_me_fromtracee,
30811.1Skamil		.piod_addr = &lookup_me_fromtracee,
30821.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30831.1Skamil	};
30841.1Skamil	struct ptrace_io_desc io_totracee = {
30851.1Skamil		.piod_op = PIOD_WRITE_D,
30861.1Skamil		.piod_offs = &lookup_me_totracee,
30871.1Skamil		.piod_addr = &lookup_me_totracee,
30881.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30891.1Skamil	};
30901.1Skamil#if defined(TWAIT_HAVE_STATUS)
30911.1Skamil	int status;
30921.1Skamil#endif
30931.1Skamil
30941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30961.1Skamil	if (child == 0) {
30971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30991.1Skamil
31001.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31011.1Skamil
31021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31041.1Skamil
31051.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31061.1Skamil
31071.13Schristos		DPRINTF("Before exiting of the child process\n");
31081.1Skamil		_exit(exitval);
31091.1Skamil	}
31101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31111.1Skamil
31121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31141.1Skamil
31151.1Skamil	validate_status_stopped(status, sigval);
31161.1Skamil
31171.1Skamil	lookup_me_totracee = magic_totracee;
31181.1Skamil
31191.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
31201.1Skamil	    child, getpid());
31211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
31221.1Skamil
31231.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
31241.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
31251.1Skamil	    magic_totracee);
31261.1Skamil
31271.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31281.1Skamil	    child, getpid());
31291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
31301.1Skamil
31311.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31321.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
31331.1Skamil	    magic_fromtracee);
31341.1Skamil
31351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31361.1Skamil	    "without signal to be sent\n");
31371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31381.1Skamil
31391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31411.1Skamil
31421.1Skamil	validate_status_exited(status, exitval);
31431.1Skamil
31441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31461.1Skamil}
31471.1Skamil
31481.1SkamilATF_TC(read_d_write_d_handshake1);
31491.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
31501.1Skamil{
31511.1Skamil	atf_tc_set_md_var(tc, "descr",
31521.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
31531.1Skamil}
31541.1Skamil
31551.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
31561.1Skamil{
31571.1Skamil	const int exitval = 5;
31581.1Skamil	const int sigval = SIGSTOP;
31591.1Skamil	pid_t child, wpid;
31601.1Skamil	int lookup_me_fromtracee = 0;
31611.1Skamil	const int magic_fromtracee = (int)random();
31621.1Skamil	int lookup_me_totracee = 0;
31631.1Skamil	const int magic_totracee = (int)random();
31641.1Skamil#if defined(TWAIT_HAVE_STATUS)
31651.1Skamil	int status;
31661.1Skamil#endif
31671.1Skamil
31681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31701.1Skamil	if (child == 0) {
31711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31731.1Skamil
31741.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31751.1Skamil
31761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31781.1Skamil
31791.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31801.1Skamil
31811.13Schristos		DPRINTF("Before exiting of the child process\n");
31821.1Skamil		_exit(exitval);
31831.1Skamil	}
31841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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_stopped(status, sigval);
31901.1Skamil
31911.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31921.1Skamil	    child, getpid());
31931.1Skamil	errno = 0;
31941.1Skamil	lookup_me_fromtracee =
31951.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
31961.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
31971.1Skamil
31981.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31991.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32001.1Skamil	    magic_fromtracee);
32011.1Skamil
32021.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32031.1Skamil	    child, getpid());
32041.1Skamil	ATF_REQUIRE
32051.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32061.1Skamil	    != -1);
32071.1Skamil
32081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32091.1Skamil	    "without signal to be sent\n");
32101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32111.1Skamil
32121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32141.1Skamil
32151.1Skamil	validate_status_exited(status, exitval);
32161.1Skamil
32171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32191.1Skamil}
32201.1Skamil
32211.1SkamilATF_TC(read_d_write_d_handshake2);
32221.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
32231.1Skamil{
32241.1Skamil	atf_tc_set_md_var(tc, "descr",
32251.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
32261.1Skamil}
32271.1Skamil
32281.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
32291.1Skamil{
32301.1Skamil	const int exitval = 5;
32311.1Skamil	const int sigval = SIGSTOP;
32321.1Skamil	pid_t child, wpid;
32331.1Skamil	int lookup_me_fromtracee = 0;
32341.1Skamil	const int magic_fromtracee = (int)random();
32351.1Skamil	int lookup_me_totracee = 0;
32361.1Skamil	const int magic_totracee = (int)random();
32371.1Skamil#if defined(TWAIT_HAVE_STATUS)
32381.1Skamil	int status;
32391.1Skamil#endif
32401.1Skamil
32411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32431.1Skamil	if (child == 0) {
32441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32461.1Skamil
32471.1Skamil		lookup_me_fromtracee = magic_fromtracee;
32481.1Skamil
32491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32511.1Skamil
32521.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
32531.1Skamil
32541.13Schristos		DPRINTF("Before exiting of the child process\n");
32551.1Skamil		_exit(exitval);
32561.1Skamil	}
32571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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_stopped(status, sigval);
32631.1Skamil
32641.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32651.1Skamil	    child, getpid());
32661.1Skamil	ATF_REQUIRE
32671.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32681.1Skamil	    != -1);
32691.1Skamil
32701.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32711.1Skamil	    child, getpid());
32721.1Skamil	errno = 0;
32731.1Skamil	lookup_me_fromtracee =
32741.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32751.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32761.1Skamil
32771.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32781.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32791.1Skamil	    magic_fromtracee);
32801.1Skamil
32811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32821.1Skamil	    "without signal to be sent\n");
32831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32841.1Skamil
32851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32871.1Skamil
32881.1Skamil	validate_status_exited(status, exitval);
32891.1Skamil
32901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32921.1Skamil}
32931.1Skamil
32941.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
32951.1Skamilstatic int __used
32961.1Skamildummy_fn1(int a, int b, int c, int d)
32971.1Skamil{
32981.1Skamil
32991.1Skamil	a *= 1;
33001.1Skamil	b += 2;
33011.1Skamil	c -= 3;
33021.1Skamil	d /= 4;
33031.1Skamil
33041.1Skamil	return a + b * c - d;
33051.1Skamil}
33061.1Skamil
33071.1Skamilstatic int __used
33081.1Skamildummy_fn2(int a, int b, int c, int d)
33091.1Skamil{
33101.1Skamil
33111.1Skamil	a *= 4;
33121.1Skamil	b += 3;
33131.1Skamil	c -= 2;
33141.1Skamil	d /= 1;
33151.1Skamil
33161.1Skamil	return a + b * c - d;
33171.1Skamil}
33181.1Skamil
33191.1Skamilstatic int __used
33201.1Skamildummy_fn3(int a, int b, int c, int d)
33211.1Skamil{
33221.1Skamil
33231.1Skamil	a *= 10;
33241.1Skamil	b += 20;
33251.1Skamil	c -= 30;
33261.1Skamil	d /= 40;
33271.1Skamil
33281.1Skamil	return a + b * c - d;
33291.1Skamil}
33301.1Skamil
33311.1Skamilstatic int __used
33321.1Skamildummy_fn4(int a, int b, int c, int d)
33331.1Skamil{
33341.1Skamil
33351.1Skamil	a *= 40;
33361.1Skamil	b += 30;
33371.1Skamil	c -= 20;
33381.1Skamil	d /= 10;
33391.1Skamil
33401.1Skamil	return a + b * c - d;
33411.1Skamil}
33421.1Skamil
33431.1SkamilATF_TC(io_read_i1);
33441.1SkamilATF_TC_HEAD(io_read_i1, tc)
33451.1Skamil{
33461.1Skamil	atf_tc_set_md_var(tc, "descr",
33471.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
33481.1Skamil}
33491.1Skamil
33501.1SkamilATF_TC_BODY(io_read_i1, tc)
33511.1Skamil{
33521.1Skamil	const int exitval = 5;
33531.1Skamil	const int sigval = SIGSTOP;
33541.1Skamil	pid_t child, wpid;
33551.1Skamil	uint8_t lookup_me = 0;
33561.1Skamil	uint8_t magic;
33571.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
33581.1Skamil	struct ptrace_io_desc io = {
33591.1Skamil		.piod_op = PIOD_READ_I,
33601.1Skamil		.piod_offs = dummy_fn1,
33611.1Skamil		.piod_addr = &lookup_me,
33621.1Skamil		.piod_len = sizeof(lookup_me)
33631.1Skamil	};
33641.1Skamil#if defined(TWAIT_HAVE_STATUS)
33651.1Skamil	int status;
33661.1Skamil#endif
33671.1Skamil
33681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33701.1Skamil	if (child == 0) {
33711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33731.1Skamil
33741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33761.1Skamil
33771.13Schristos		DPRINTF("Before exiting of the child process\n");
33781.1Skamil		_exit(exitval);
33791.1Skamil	}
33801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33811.1Skamil
33821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33841.1Skamil
33851.1Skamil	validate_status_stopped(status, sigval);
33861.1Skamil
33871.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33881.1Skamil	    child, getpid());
33891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33901.1Skamil
33911.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33921.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
33931.1Skamil
33941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33951.1Skamil	    "without signal to be sent\n");
33961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33971.1Skamil
33981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34001.1Skamil
34011.1Skamil	validate_status_exited(status, exitval);
34021.1Skamil
34031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34051.1Skamil}
34061.1Skamil
34071.1SkamilATF_TC(io_read_i2);
34081.1SkamilATF_TC_HEAD(io_read_i2, tc)
34091.1Skamil{
34101.1Skamil	atf_tc_set_md_var(tc, "descr",
34111.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
34121.1Skamil}
34131.1Skamil
34141.1SkamilATF_TC_BODY(io_read_i2, tc)
34151.1Skamil{
34161.1Skamil	const int exitval = 5;
34171.1Skamil	const int sigval = SIGSTOP;
34181.1Skamil	pid_t child, wpid;
34191.1Skamil	uint16_t lookup_me = 0;
34201.1Skamil	uint16_t magic;
34211.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34221.1Skamil	struct ptrace_io_desc io = {
34231.1Skamil		.piod_op = PIOD_READ_I,
34241.1Skamil		.piod_offs = dummy_fn1,
34251.1Skamil		.piod_addr = &lookup_me,
34261.1Skamil		.piod_len = sizeof(lookup_me)
34271.1Skamil	};
34281.1Skamil#if defined(TWAIT_HAVE_STATUS)
34291.1Skamil	int status;
34301.1Skamil#endif
34311.1Skamil
34321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34341.1Skamil	if (child == 0) {
34351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34371.1Skamil
34381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34401.1Skamil
34411.13Schristos		DPRINTF("Before exiting of the child process\n");
34421.1Skamil		_exit(exitval);
34431.1Skamil	}
34441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34451.1Skamil
34461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34481.1Skamil
34491.1Skamil	validate_status_stopped(status, sigval);
34501.1Skamil
34511.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34521.1Skamil	    child, getpid());
34531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34541.1Skamil
34551.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34561.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
34571.1Skamil
34581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34591.1Skamil	    "without signal to be sent\n");
34601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34611.1Skamil
34621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34641.1Skamil
34651.1Skamil	validate_status_exited(status, exitval);
34661.1Skamil
34671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34691.1Skamil}
34701.1Skamil
34711.1SkamilATF_TC(io_read_i3);
34721.1SkamilATF_TC_HEAD(io_read_i3, tc)
34731.1Skamil{
34741.1Skamil	atf_tc_set_md_var(tc, "descr",
34751.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
34761.1Skamil}
34771.1Skamil
34781.1SkamilATF_TC_BODY(io_read_i3, tc)
34791.1Skamil{
34801.1Skamil	const int exitval = 5;
34811.1Skamil	const int sigval = SIGSTOP;
34821.1Skamil	pid_t child, wpid;
34831.1Skamil	uint32_t lookup_me = 0;
34841.1Skamil	uint32_t magic;
34851.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34861.1Skamil	struct ptrace_io_desc io = {
34871.1Skamil		.piod_op = PIOD_READ_I,
34881.1Skamil		.piod_offs = dummy_fn1,
34891.1Skamil		.piod_addr = &lookup_me,
34901.1Skamil		.piod_len = sizeof(lookup_me)
34911.1Skamil	};
34921.1Skamil#if defined(TWAIT_HAVE_STATUS)
34931.1Skamil	int status;
34941.1Skamil#endif
34951.1Skamil
34961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34981.1Skamil	if (child == 0) {
34991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35011.1Skamil
35021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35041.1Skamil
35051.13Schristos		DPRINTF("Before exiting of the child process\n");
35061.1Skamil		_exit(exitval);
35071.1Skamil	}
35081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35091.1Skamil
35101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35121.1Skamil
35131.1Skamil	validate_status_stopped(status, sigval);
35141.1Skamil
35151.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35161.1Skamil	    child, getpid());
35171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35181.1Skamil
35191.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35201.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
35211.1Skamil
35221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35231.1Skamil	    "without signal to be sent\n");
35241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35251.1Skamil
35261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35281.1Skamil
35291.1Skamil	validate_status_exited(status, exitval);
35301.1Skamil
35311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35331.1Skamil}
35341.1Skamil
35351.1SkamilATF_TC(io_read_i4);
35361.1SkamilATF_TC_HEAD(io_read_i4, tc)
35371.1Skamil{
35381.1Skamil	atf_tc_set_md_var(tc, "descr",
35391.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
35401.1Skamil}
35411.1Skamil
35421.1SkamilATF_TC_BODY(io_read_i4, tc)
35431.1Skamil{
35441.1Skamil	const int exitval = 5;
35451.1Skamil	const int sigval = SIGSTOP;
35461.1Skamil	pid_t child, wpid;
35471.1Skamil	uint64_t lookup_me = 0;
35481.1Skamil	uint64_t magic;
35491.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35501.1Skamil	struct ptrace_io_desc io = {
35511.1Skamil		.piod_op = PIOD_READ_I,
35521.1Skamil		.piod_offs = dummy_fn1,
35531.1Skamil		.piod_addr = &lookup_me,
35541.1Skamil		.piod_len = sizeof(lookup_me)
35551.1Skamil	};
35561.1Skamil#if defined(TWAIT_HAVE_STATUS)
35571.1Skamil	int status;
35581.1Skamil#endif
35591.1Skamil
35601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35621.1Skamil	if (child == 0) {
35631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35651.1Skamil
35661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35681.1Skamil
35691.13Schristos		DPRINTF("Before exiting of the child process\n");
35701.1Skamil		_exit(exitval);
35711.1Skamil	}
35721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35731.1Skamil
35741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35761.1Skamil
35771.1Skamil	validate_status_stopped(status, sigval);
35781.1Skamil
35791.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35801.1Skamil	    child, getpid());
35811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35821.1Skamil
35831.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35841.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
35851.1Skamil
35861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35871.1Skamil	    "without signal to be sent\n");
35881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35891.1Skamil
35901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35921.1Skamil
35931.1Skamil	validate_status_exited(status, exitval);
35941.1Skamil
35951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35971.1Skamil}
35981.1Skamil
35991.1SkamilATF_TC(read_i1);
36001.1SkamilATF_TC_HEAD(read_i1, tc)
36011.1Skamil{
36021.1Skamil	atf_tc_set_md_var(tc, "descr",
36031.1Skamil	    "Verify PT_READ_I called once");
36041.1Skamil}
36051.1Skamil
36061.1SkamilATF_TC_BODY(read_i1, tc)
36071.1Skamil{
36081.1Skamil	const int exitval = 5;
36091.1Skamil	const int sigval = SIGSTOP;
36101.1Skamil	pid_t child, wpid;
36111.1Skamil	int lookup_me = 0;
36121.1Skamil	int magic;
36131.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
36141.1Skamil#if defined(TWAIT_HAVE_STATUS)
36151.1Skamil	int status;
36161.1Skamil#endif
36171.1Skamil
36181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36201.1Skamil	if (child == 0) {
36211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36231.1Skamil
36241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36261.1Skamil
36271.13Schristos		DPRINTF("Before exiting of the child process\n");
36281.1Skamil		_exit(exitval);
36291.1Skamil	}
36301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36311.1Skamil
36321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36341.1Skamil
36351.1Skamil	validate_status_stopped(status, sigval);
36361.1Skamil
36371.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
36381.1Skamil	    child, getpid());
36391.1Skamil	errno = 0;
36401.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
36411.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36421.1Skamil
36431.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
36441.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
36451.1Skamil
36461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36471.1Skamil	    "without signal to be sent\n");
36481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36491.1Skamil
36501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36521.1Skamil
36531.1Skamil	validate_status_exited(status, exitval);
36541.1Skamil
36551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36571.1Skamil}
36581.1Skamil
36591.1SkamilATF_TC(read_i2);
36601.1SkamilATF_TC_HEAD(read_i2, tc)
36611.1Skamil{
36621.1Skamil	atf_tc_set_md_var(tc, "descr",
36631.1Skamil	    "Verify PT_READ_I called twice");
36641.1Skamil}
36651.1Skamil
36661.1SkamilATF_TC_BODY(read_i2, tc)
36671.1Skamil{
36681.1Skamil	const int exitval = 5;
36691.1Skamil	const int sigval = SIGSTOP;
36701.1Skamil	pid_t child, wpid;
36711.1Skamil	int lookup_me1 = 0;
36721.1Skamil	int lookup_me2 = 0;
36731.1Skamil	int magic1;
36741.1Skamil	int magic2;
36751.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36761.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36771.1Skamil#if defined(TWAIT_HAVE_STATUS)
36781.1Skamil	int status;
36791.1Skamil#endif
36801.1Skamil
36811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36831.1Skamil	if (child == 0) {
36841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36861.1Skamil
36871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36891.1Skamil
36901.13Schristos		DPRINTF("Before exiting of the child process\n");
36911.1Skamil		_exit(exitval);
36921.1Skamil	}
36931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36941.1Skamil
36951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36971.1Skamil
36981.1Skamil	validate_status_stopped(status, sigval);
36991.1Skamil
37001.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37011.1Skamil	    child, getpid());
37021.1Skamil	errno = 0;
37031.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37041.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37051.1Skamil
37061.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37071.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37081.1Skamil
37091.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37101.1Skamil	    child, getpid());
37111.1Skamil	errno = 0;
37121.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37131.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37141.1Skamil
37151.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37161.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37171.1Skamil
37181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37191.1Skamil	    "without signal to be sent\n");
37201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37211.1Skamil
37221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37241.1Skamil
37251.1Skamil	validate_status_exited(status, exitval);
37261.1Skamil
37271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37291.1Skamil}
37301.1Skamil
37311.1SkamilATF_TC(read_i3);
37321.1SkamilATF_TC_HEAD(read_i3, tc)
37331.1Skamil{
37341.1Skamil	atf_tc_set_md_var(tc, "descr",
37351.1Skamil	    "Verify PT_READ_I called three times");
37361.1Skamil}
37371.1Skamil
37381.1SkamilATF_TC_BODY(read_i3, tc)
37391.1Skamil{
37401.1Skamil	const int exitval = 5;
37411.1Skamil	const int sigval = SIGSTOP;
37421.1Skamil	pid_t child, wpid;
37431.1Skamil	int lookup_me1 = 0;
37441.1Skamil	int lookup_me2 = 0;
37451.1Skamil	int lookup_me3 = 0;
37461.1Skamil	int magic1;
37471.1Skamil	int magic2;
37481.1Skamil	int magic3;
37491.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37501.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37511.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37521.1Skamil#if defined(TWAIT_HAVE_STATUS)
37531.1Skamil	int status;
37541.1Skamil#endif
37551.1Skamil
37561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37581.1Skamil	if (child == 0) {
37591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37611.1Skamil
37621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37641.1Skamil
37651.13Schristos		DPRINTF("Before exiting of the child process\n");
37661.1Skamil		_exit(exitval);
37671.1Skamil	}
37681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37691.1Skamil
37701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37721.1Skamil
37731.1Skamil	validate_status_stopped(status, sigval);
37741.1Skamil
37751.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37761.1Skamil	    child, getpid());
37771.1Skamil	errno = 0;
37781.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37791.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37801.1Skamil
37811.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37821.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37831.1Skamil
37841.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37851.1Skamil	    child, getpid());
37861.1Skamil	errno = 0;
37871.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37881.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37891.1Skamil
37901.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37911.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37921.1Skamil
37931.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
37941.1Skamil	    child, getpid());
37951.1Skamil	errno = 0;
37961.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
37971.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37981.1Skamil
37991.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38001.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38011.1Skamil
38021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38031.1Skamil	    "without signal to be sent\n");
38041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38051.1Skamil
38061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38081.1Skamil
38091.1Skamil	validate_status_exited(status, exitval);
38101.1Skamil
38111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38131.1Skamil}
38141.1Skamil
38151.1SkamilATF_TC(read_i4);
38161.1SkamilATF_TC_HEAD(read_i4, tc)
38171.1Skamil{
38181.1Skamil	atf_tc_set_md_var(tc, "descr",
38191.1Skamil	    "Verify PT_READ_I called four times");
38201.1Skamil}
38211.1Skamil
38221.1SkamilATF_TC_BODY(read_i4, tc)
38231.1Skamil{
38241.1Skamil	const int exitval = 5;
38251.1Skamil	const int sigval = SIGSTOP;
38261.1Skamil	pid_t child, wpid;
38271.1Skamil	int lookup_me1 = 0;
38281.1Skamil	int lookup_me2 = 0;
38291.1Skamil	int lookup_me3 = 0;
38301.1Skamil	int lookup_me4 = 0;
38311.1Skamil	int magic1;
38321.1Skamil	int magic2;
38331.1Skamil	int magic3;
38341.1Skamil	int magic4;
38351.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
38361.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
38371.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
38381.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
38391.1Skamil#if defined(TWAIT_HAVE_STATUS)
38401.1Skamil	int status;
38411.1Skamil#endif
38421.1Skamil
38431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38451.1Skamil	if (child == 0) {
38461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38481.1Skamil
38491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38511.1Skamil
38521.13Schristos		DPRINTF("Before exiting of the child process\n");
38531.1Skamil		_exit(exitval);
38541.1Skamil	}
38551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38561.1Skamil
38571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38591.1Skamil
38601.1Skamil	validate_status_stopped(status, sigval);
38611.1Skamil
38621.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38631.1Skamil	    child, getpid());
38641.1Skamil	errno = 0;
38651.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38661.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38671.1Skamil
38681.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38691.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38701.1Skamil
38711.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38721.1Skamil	    child, getpid());
38731.1Skamil	errno = 0;
38741.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38751.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38761.1Skamil
38771.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38781.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38791.1Skamil
38801.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38811.1Skamil	    child, getpid());
38821.1Skamil	errno = 0;
38831.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38841.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38851.1Skamil
38861.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38871.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38881.1Skamil
38891.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
38901.1Skamil	    child, getpid());
38911.1Skamil	errno = 0;
38921.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
38931.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38941.1Skamil
38951.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
38961.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
38971.1Skamil
38981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38991.1Skamil	    "without signal to be sent\n");
39001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39011.1Skamil
39021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39041.1Skamil
39051.1Skamil	validate_status_exited(status, exitval);
39061.1Skamil
39071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39091.1Skamil}
39101.1Skamil
39111.1Skamil#if defined(HAVE_GPREGS)
39121.1SkamilATF_TC(regs1);
39131.1SkamilATF_TC_HEAD(regs1, tc)
39141.1Skamil{
39151.1Skamil	atf_tc_set_md_var(tc, "descr",
39161.1Skamil	    "Verify plain PT_GETREGS call without further steps");
39171.1Skamil}
39181.1Skamil
39191.1SkamilATF_TC_BODY(regs1, tc)
39201.1Skamil{
39211.1Skamil	const int exitval = 5;
39221.1Skamil	const int sigval = SIGSTOP;
39231.1Skamil	pid_t child, wpid;
39241.1Skamil#if defined(TWAIT_HAVE_STATUS)
39251.1Skamil	int status;
39261.1Skamil#endif
39271.1Skamil	struct reg r;
39281.1Skamil
39291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39311.1Skamil	if (child == 0) {
39321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39341.1Skamil
39351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39371.1Skamil
39381.13Schristos		DPRINTF("Before exiting of the child process\n");
39391.1Skamil		_exit(exitval);
39401.1Skamil	}
39411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39421.1Skamil
39431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39451.1Skamil
39461.1Skamil	validate_status_stopped(status, sigval);
39471.1Skamil
39481.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39501.1Skamil
39511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39521.1Skamil	    "without signal to be sent\n");
39531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39541.1Skamil
39551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39571.1Skamil
39581.1Skamil	validate_status_exited(status, exitval);
39591.1Skamil
39601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39621.1Skamil}
39631.1Skamil#endif
39641.1Skamil
39651.1Skamil#if defined(HAVE_GPREGS)
39661.1SkamilATF_TC(regs2);
39671.1SkamilATF_TC_HEAD(regs2, tc)
39681.1Skamil{
39691.1Skamil	atf_tc_set_md_var(tc, "descr",
39701.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
39711.1Skamil}
39721.1Skamil
39731.1SkamilATF_TC_BODY(regs2, tc)
39741.1Skamil{
39751.1Skamil	const int exitval = 5;
39761.1Skamil	const int sigval = SIGSTOP;
39771.1Skamil	pid_t child, wpid;
39781.1Skamil#if defined(TWAIT_HAVE_STATUS)
39791.1Skamil	int status;
39801.1Skamil#endif
39811.1Skamil	struct reg r;
39821.1Skamil
39831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39851.1Skamil	if (child == 0) {
39861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39881.1Skamil
39891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39911.1Skamil
39921.13Schristos		DPRINTF("Before exiting of the child process\n");
39931.1Skamil		_exit(exitval);
39941.1Skamil	}
39951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39961.1Skamil
39971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39991.1Skamil
40001.1Skamil	validate_status_stopped(status, sigval);
40011.1Skamil
40021.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40041.1Skamil
40051.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
40061.1Skamil
40071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40081.1Skamil	    "without signal to be sent\n");
40091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40101.1Skamil
40111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40131.1Skamil
40141.1Skamil	validate_status_exited(status, exitval);
40151.1Skamil
40161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40181.1Skamil}
40191.1Skamil#endif
40201.1Skamil
40211.1Skamil#if defined(HAVE_GPREGS)
40221.1SkamilATF_TC(regs3);
40231.1SkamilATF_TC_HEAD(regs3, tc)
40241.1Skamil{
40251.1Skamil	atf_tc_set_md_var(tc, "descr",
40261.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
40271.1Skamil}
40281.1Skamil
40291.1SkamilATF_TC_BODY(regs3, tc)
40301.1Skamil{
40311.1Skamil	const int exitval = 5;
40321.1Skamil	const int sigval = SIGSTOP;
40331.1Skamil	pid_t child, wpid;
40341.1Skamil#if defined(TWAIT_HAVE_STATUS)
40351.1Skamil	int status;
40361.1Skamil#endif
40371.1Skamil	struct reg r;
40381.1Skamil
40391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40411.1Skamil	if (child == 0) {
40421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40441.1Skamil
40451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40471.1Skamil
40481.13Schristos		DPRINTF("Before exiting of the child process\n");
40491.1Skamil		_exit(exitval);
40501.1Skamil	}
40511.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40521.1Skamil
40531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40551.1Skamil
40561.1Skamil	validate_status_stopped(status, sigval);
40571.1Skamil
40581.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40601.1Skamil
40611.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
40621.1Skamil
40631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40641.1Skamil	    "without signal to be sent\n");
40651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40661.1Skamil
40671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40691.1Skamil
40701.1Skamil	validate_status_exited(status, exitval);
40711.1Skamil
40721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40741.1Skamil}
40751.1Skamil#endif
40761.1Skamil
40771.1Skamil#if defined(HAVE_GPREGS)
40781.1SkamilATF_TC(regs4);
40791.1SkamilATF_TC_HEAD(regs4, tc)
40801.1Skamil{
40811.1Skamil	atf_tc_set_md_var(tc, "descr",
40821.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
40831.1Skamil}
40841.1Skamil
40851.1SkamilATF_TC_BODY(regs4, tc)
40861.1Skamil{
40871.1Skamil	const int exitval = 5;
40881.1Skamil	const int sigval = SIGSTOP;
40891.1Skamil	pid_t child, wpid;
40901.1Skamil#if defined(TWAIT_HAVE_STATUS)
40911.1Skamil	int status;
40921.1Skamil#endif
40931.1Skamil	struct reg r;
40941.1Skamil
40951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40971.1Skamil	if (child == 0) {
40981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41001.1Skamil
41011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41031.1Skamil
41041.13Schristos		DPRINTF("Before exiting of the child process\n");
41051.1Skamil		_exit(exitval);
41061.1Skamil	}
41071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41081.1Skamil
41091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41111.1Skamil
41121.1Skamil	validate_status_stopped(status, sigval);
41131.1Skamil
41141.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41161.1Skamil
41171.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
41181.1Skamil
41191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41201.1Skamil	    "without signal to be sent\n");
41211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41221.1Skamil
41231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41251.1Skamil
41261.1Skamil	validate_status_exited(status, exitval);
41271.1Skamil
41281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41301.1Skamil}
41311.1Skamil#endif
41321.1Skamil
41331.1Skamil#if defined(HAVE_GPREGS)
41341.1SkamilATF_TC(regs5);
41351.1SkamilATF_TC_HEAD(regs5, tc)
41361.1Skamil{
41371.1Skamil	atf_tc_set_md_var(tc, "descr",
41381.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
41391.1Skamil}
41401.1Skamil
41411.1SkamilATF_TC_BODY(regs5, tc)
41421.1Skamil{
41431.1Skamil	const int exitval = 5;
41441.1Skamil	const int sigval = SIGSTOP;
41451.1Skamil	pid_t child, wpid;
41461.1Skamil#if defined(TWAIT_HAVE_STATUS)
41471.1Skamil	int status;
41481.1Skamil#endif
41491.1Skamil	struct reg r;
41501.1Skamil
41511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41531.1Skamil	if (child == 0) {
41541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41561.1Skamil
41571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41591.1Skamil
41601.13Schristos		DPRINTF("Before exiting of the child process\n");
41611.1Skamil		_exit(exitval);
41621.1Skamil	}
41631.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41641.1Skamil
41651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41671.1Skamil
41681.1Skamil	validate_status_stopped(status, sigval);
41691.1Skamil
41701.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41721.1Skamil
41731.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
41741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41751.1Skamil
41761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41771.1Skamil	    "without signal to be sent\n");
41781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41791.1Skamil
41801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41821.1Skamil
41831.1Skamil	validate_status_exited(status, exitval);
41841.1Skamil
41851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41871.1Skamil}
41881.1Skamil#endif
41891.1Skamil
41901.1Skamil#if defined(HAVE_FPREGS)
41911.1SkamilATF_TC(fpregs1);
41921.1SkamilATF_TC_HEAD(fpregs1, tc)
41931.1Skamil{
41941.1Skamil	atf_tc_set_md_var(tc, "descr",
41951.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
41961.1Skamil}
41971.1Skamil
41981.1SkamilATF_TC_BODY(fpregs1, tc)
41991.1Skamil{
42001.1Skamil	const int exitval = 5;
42011.1Skamil	const int sigval = SIGSTOP;
42021.1Skamil	pid_t child, wpid;
42031.1Skamil#if defined(TWAIT_HAVE_STATUS)
42041.1Skamil	int status;
42051.1Skamil#endif
42061.1Skamil	struct fpreg r;
42071.1Skamil
42081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42101.1Skamil	if (child == 0) {
42111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42131.1Skamil
42141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42161.1Skamil
42171.13Schristos		DPRINTF("Before exiting of the child process\n");
42181.1Skamil		_exit(exitval);
42191.1Skamil	}
42201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42211.1Skamil
42221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42241.1Skamil
42251.1Skamil	validate_status_stopped(status, sigval);
42261.1Skamil
42271.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42291.1Skamil
42301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42311.1Skamil	    "without signal to be sent\n");
42321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42331.1Skamil
42341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42361.1Skamil
42371.1Skamil	validate_status_exited(status, exitval);
42381.1Skamil
42391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42411.1Skamil}
42421.1Skamil#endif
42431.1Skamil
42441.1Skamil#if defined(HAVE_FPREGS)
42451.1SkamilATF_TC(fpregs2);
42461.1SkamilATF_TC_HEAD(fpregs2, tc)
42471.1Skamil{
42481.1Skamil	atf_tc_set_md_var(tc, "descr",
42491.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
42501.1Skamil	    "regs");
42511.1Skamil}
42521.1Skamil
42531.1SkamilATF_TC_BODY(fpregs2, tc)
42541.1Skamil{
42551.1Skamil	const int exitval = 5;
42561.1Skamil	const int sigval = SIGSTOP;
42571.1Skamil	pid_t child, wpid;
42581.1Skamil#if defined(TWAIT_HAVE_STATUS)
42591.1Skamil	int status;
42601.1Skamil#endif
42611.1Skamil	struct fpreg r;
42621.1Skamil
42631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42651.1Skamil	if (child == 0) {
42661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42681.1Skamil
42691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42711.1Skamil
42721.13Schristos		DPRINTF("Before exiting of the child process\n");
42731.1Skamil		_exit(exitval);
42741.1Skamil	}
42751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42761.1Skamil
42771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42791.1Skamil
42801.1Skamil	validate_status_stopped(status, sigval);
42811.1Skamil
42821.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42841.1Skamil
42851.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
42861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
42871.1Skamil
42881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42891.1Skamil	    "without signal to be sent\n");
42901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42911.1Skamil
42921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42941.1Skamil
42951.1Skamil	validate_status_exited(status, exitval);
42961.1Skamil
42971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42991.1Skamil}
43001.1Skamil#endif
43011.1Skamil
43021.1Skamil#if defined(PT_STEP)
43031.1Skamilstatic void
43041.2Skamilptrace_step(int N, int setstep)
43051.1Skamil{
43061.1Skamil	const int exitval = 5;
43071.1Skamil	const int sigval = SIGSTOP;
43081.1Skamil	pid_t child, wpid;
43091.1Skamil#if defined(TWAIT_HAVE_STATUS)
43101.1Skamil	int status;
43111.1Skamil#endif
43121.1Skamil	int happy;
43131.1Skamil
43141.1Skamil#if defined(__arm__)
43151.1Skamil	/* PT_STEP not supported on arm 32-bit */
43161.1Skamil	atf_tc_expect_fail("PR kern/52119");
43171.1Skamil#endif
43181.1Skamil
43191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43211.1Skamil	if (child == 0) {
43221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43241.1Skamil
43251.1Skamil		happy = check_happy(999);
43261.1Skamil
43271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43291.1Skamil
43301.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
43311.1Skamil
43321.13Schristos		DPRINTF("Before exiting of the child process\n");
43331.1Skamil		_exit(exitval);
43341.1Skamil	}
43351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43361.1Skamil
43371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43391.1Skamil
43401.1Skamil	validate_status_stopped(status, sigval);
43411.1Skamil
43421.1Skamil	while (N --> 0) {
43431.2Skamil		if (setstep) {
43441.13Schristos			DPRINTF("Before resuming the child process where it "
43451.2Skamil			    "left off and without signal to be sent (use "
43461.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
43471.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
43481.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
43491.2Skamil			    != -1);
43501.2Skamil		} else {
43511.13Schristos			DPRINTF("Before resuming the child process where it "
43521.2Skamil			    "left off and without signal to be sent (use "
43531.2Skamil			    "PT_STEP)\n");
43541.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
43551.2Skamil			    != -1);
43561.2Skamil		}
43571.1Skamil
43581.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43591.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
43601.1Skamil		    child);
43611.1Skamil
43621.1Skamil		validate_status_stopped(status, SIGTRAP);
43631.2Skamil
43641.2Skamil		if (setstep) {
43651.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43661.2Skamil		}
43671.1Skamil	}
43681.1Skamil
43691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43701.1Skamil	    "without signal to be sent\n");
43711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43721.1Skamil
43731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43751.1Skamil
43761.1Skamil	validate_status_exited(status, exitval);
43771.1Skamil
43781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43801.1Skamil}
43811.1Skamil#endif
43821.1Skamil
43831.1Skamil#if defined(PT_STEP)
43841.1SkamilATF_TC(step1);
43851.1SkamilATF_TC_HEAD(step1, tc)
43861.1Skamil{
43871.1Skamil	atf_tc_set_md_var(tc, "descr",
43881.1Skamil	    "Verify single PT_STEP call");
43891.1Skamil}
43901.1Skamil
43911.1SkamilATF_TC_BODY(step1, tc)
43921.1Skamil{
43931.2Skamil	ptrace_step(1, 0);
43941.1Skamil}
43951.1Skamil#endif
43961.1Skamil
43971.1Skamil#if defined(PT_STEP)
43981.1SkamilATF_TC(step2);
43991.1SkamilATF_TC_HEAD(step2, tc)
44001.1Skamil{
44011.1Skamil	atf_tc_set_md_var(tc, "descr",
44021.1Skamil	    "Verify PT_STEP called twice");
44031.1Skamil}
44041.1Skamil
44051.1SkamilATF_TC_BODY(step2, tc)
44061.1Skamil{
44071.2Skamil	ptrace_step(2, 0);
44081.1Skamil}
44091.1Skamil#endif
44101.1Skamil
44111.1Skamil#if defined(PT_STEP)
44121.1SkamilATF_TC(step3);
44131.1SkamilATF_TC_HEAD(step3, tc)
44141.1Skamil{
44151.1Skamil	atf_tc_set_md_var(tc, "descr",
44161.1Skamil	    "Verify PT_STEP called three times");
44171.1Skamil}
44181.1Skamil
44191.1SkamilATF_TC_BODY(step3, tc)
44201.1Skamil{
44211.2Skamil	ptrace_step(3, 0);
44221.1Skamil}
44231.1Skamil#endif
44241.1Skamil
44251.1Skamil#if defined(PT_STEP)
44261.1SkamilATF_TC(step4);
44271.1SkamilATF_TC_HEAD(step4, tc)
44281.1Skamil{
44291.1Skamil	atf_tc_set_md_var(tc, "descr",
44301.1Skamil	    "Verify PT_STEP called four times");
44311.1Skamil}
44321.1Skamil
44331.1SkamilATF_TC_BODY(step4, tc)
44341.1Skamil{
44351.2Skamil	ptrace_step(4, 0);
44361.2Skamil}
44371.2Skamil#endif
44381.2Skamil
44391.2Skamil#if defined(PT_STEP)
44401.2SkamilATF_TC(setstep1);
44411.2SkamilATF_TC_HEAD(setstep1, tc)
44421.2Skamil{
44431.2Skamil	atf_tc_set_md_var(tc, "descr",
44441.2Skamil	    "Verify single PT_SETSTEP call");
44451.2Skamil}
44461.2Skamil
44471.2SkamilATF_TC_BODY(setstep1, tc)
44481.2Skamil{
44491.2Skamil	ptrace_step(1, 1);
44501.2Skamil}
44511.2Skamil#endif
44521.2Skamil
44531.2Skamil#if defined(PT_STEP)
44541.2SkamilATF_TC(setstep2);
44551.2SkamilATF_TC_HEAD(setstep2, tc)
44561.2Skamil{
44571.2Skamil	atf_tc_set_md_var(tc, "descr",
44581.2Skamil	    "Verify PT_SETSTEP called twice");
44591.2Skamil}
44601.2Skamil
44611.2SkamilATF_TC_BODY(setstep2, tc)
44621.2Skamil{
44631.2Skamil	ptrace_step(2, 1);
44641.2Skamil}
44651.2Skamil#endif
44661.2Skamil
44671.2Skamil#if defined(PT_STEP)
44681.2SkamilATF_TC(setstep3);
44691.2SkamilATF_TC_HEAD(setstep3, tc)
44701.2Skamil{
44711.2Skamil	atf_tc_set_md_var(tc, "descr",
44721.2Skamil	    "Verify PT_SETSTEP called three times");
44731.2Skamil}
44741.2Skamil
44751.2SkamilATF_TC_BODY(setstep3, tc)
44761.2Skamil{
44771.2Skamil	ptrace_step(3, 1);
44781.2Skamil}
44791.2Skamil#endif
44801.2Skamil
44811.2Skamil#if defined(PT_STEP)
44821.2SkamilATF_TC(setstep4);
44831.2SkamilATF_TC_HEAD(setstep4, tc)
44841.2Skamil{
44851.2Skamil	atf_tc_set_md_var(tc, "descr",
44861.2Skamil	    "Verify PT_SETSTEP called four times");
44871.2Skamil}
44881.2Skamil
44891.2SkamilATF_TC_BODY(setstep4, tc)
44901.2Skamil{
44911.2Skamil	ptrace_step(4, 1);
44921.1Skamil}
44931.1Skamil#endif
44941.1Skamil
44951.1SkamilATF_TC(kill1);
44961.1SkamilATF_TC_HEAD(kill1, tc)
44971.1Skamil{
44981.1Skamil	atf_tc_set_md_var(tc, "descr",
44991.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
45001.1Skamil}
45011.1Skamil
45021.1SkamilATF_TC_BODY(kill1, tc)
45031.1Skamil{
45041.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
45051.1Skamil	pid_t child, wpid;
45061.1Skamil#if defined(TWAIT_HAVE_STATUS)
45071.1Skamil	int status;
45081.1Skamil#endif
45091.1Skamil
45101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45121.1Skamil	if (child == 0) {
45131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45151.1Skamil
45161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45181.1Skamil
45191.1Skamil		/* NOTREACHED */
45201.1Skamil		FORKEE_ASSERTX(0 &&
45211.1Skamil		    "Child should be terminated by a signal from its parent");
45221.1Skamil	}
45231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45241.1Skamil
45251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45271.1Skamil
45281.1Skamil	validate_status_stopped(status, sigval);
45291.1Skamil
45301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45311.1Skamil	    "without signal to be sent\n");
45321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
45331.1Skamil
45341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45361.1Skamil
45371.1Skamil	validate_status_signaled(status, sigsent, 0);
45381.1Skamil
45391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45411.1Skamil}
45421.1Skamil
45431.1SkamilATF_TC(kill2);
45441.1SkamilATF_TC_HEAD(kill2, tc)
45451.1Skamil{
45461.1Skamil	atf_tc_set_md_var(tc, "descr",
45471.1Skamil	    "Verify that PT_KILL terminates child");
45481.1Skamil}
45491.1Skamil
45501.1SkamilATF_TC_BODY(kill2, tc)
45511.1Skamil{
45521.1Skamil	const int sigval = SIGSTOP;
45531.1Skamil	pid_t child, wpid;
45541.1Skamil#if defined(TWAIT_HAVE_STATUS)
45551.1Skamil	int status;
45561.1Skamil#endif
45571.1Skamil
45581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45601.1Skamil	if (child == 0) {
45611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45631.1Skamil
45641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45661.1Skamil
45671.1Skamil		/* NOTREACHED */
45681.1Skamil		FORKEE_ASSERTX(0 &&
45691.1Skamil		    "Child should be terminated by a signal from its parent");
45701.1Skamil	}
45711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45721.1Skamil
45731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45751.1Skamil
45761.1Skamil	validate_status_stopped(status, sigval);
45771.1Skamil
45781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45791.1Skamil	    "without signal to be sent\n");
45801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
45811.1Skamil
45821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45841.1Skamil
45851.1Skamil	validate_status_signaled(status, SIGKILL, 0);
45861.1Skamil
45871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45891.1Skamil}
45901.1Skamil
45911.1SkamilATF_TC(lwpinfo1);
45921.1SkamilATF_TC_HEAD(lwpinfo1, tc)
45931.1Skamil{
45941.1Skamil	atf_tc_set_md_var(tc, "descr",
45951.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
45961.1Skamil}
45971.1Skamil
45981.1SkamilATF_TC_BODY(lwpinfo1, tc)
45991.1Skamil{
46001.1Skamil	const int exitval = 5;
46011.1Skamil	const int sigval = SIGSTOP;
46021.1Skamil	pid_t child, wpid;
46031.1Skamil#if defined(TWAIT_HAVE_STATUS)
46041.1Skamil	int status;
46051.1Skamil#endif
46061.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46071.1Skamil
46081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46101.1Skamil	if (child == 0) {
46111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46131.1Skamil
46141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46161.1Skamil
46171.13Schristos		DPRINTF("Before exiting of the child process\n");
46181.1Skamil		_exit(exitval);
46191.1Skamil	}
46201.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46211.1Skamil
46221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46241.1Skamil
46251.1Skamil	validate_status_stopped(status, sigval);
46261.1Skamil
46271.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46291.1Skamil
46301.13Schristos	DPRINTF("Assert that there exists a thread\n");
46311.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
46321.1Skamil
46331.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
46341.1Skamil	    info.pl_lwpid);
46351.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
46361.1Skamil	    "Received event %d != expected event %d",
46371.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
46381.1Skamil
46391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
46411.1Skamil
46421.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
46431.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
46441.1Skamil
46451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46461.1Skamil	    "without signal to be sent\n");
46471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46481.1Skamil
46491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46511.1Skamil
46521.1Skamil	validate_status_exited(status, exitval);
46531.1Skamil
46541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46561.1Skamil}
46571.1Skamil
46581.1Skamil#if defined(TWAIT_HAVE_PID)
46591.1SkamilATF_TC(lwpinfo2);
46601.1SkamilATF_TC_HEAD(lwpinfo2, tc)
46611.1Skamil{
46621.1Skamil	atf_tc_set_md_var(tc, "descr",
46631.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
46641.1Skamil	    "tracer)");
46651.1Skamil}
46661.1Skamil
46671.1SkamilATF_TC_BODY(lwpinfo2, tc)
46681.1Skamil{
46691.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46701.1Skamil	const int exitval_tracee = 5;
46711.1Skamil	const int exitval_tracer = 10;
46721.1Skamil	pid_t tracee, tracer, wpid;
46731.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46741.1Skamil#if defined(TWAIT_HAVE_STATUS)
46751.1Skamil	int status;
46761.1Skamil#endif
46771.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46781.1Skamil
46791.13Schristos	DPRINTF("Spawn tracee\n");
46801.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
46811.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
46821.1Skamil	tracee = atf_utils_fork();
46831.1Skamil	if (tracee == 0) {
46841.1Skamil
46851.1Skamil		/* Wait for message from the parent */
46861.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
46871.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
46881.1Skamil
46891.1Skamil		_exit(exitval_tracee);
46901.1Skamil	}
46911.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
46921.1Skamil
46931.13Schristos	DPRINTF("Spawn debugger\n");
46941.1Skamil	tracer = atf_utils_fork();
46951.1Skamil	if (tracer == 0) {
46961.1Skamil		/* No IPC to communicate with the child */
46971.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
46981.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
46991.1Skamil
47001.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
47011.1Skamil		FORKEE_REQUIRE_SUCCESS(
47021.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47031.1Skamil
47041.1Skamil		forkee_status_stopped(status, SIGSTOP);
47051.1Skamil
47061.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47071.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47081.1Skamil		    != -1);
47091.1Skamil
47101.13Schristos		DPRINTF("Assert that there exists a thread\n");
47111.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
47121.1Skamil
47131.13Schristos		DPRINTF("Assert that lwp thread %d received event "
47141.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
47151.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
47161.1Skamil
47171.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
47181.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
47191.1Skamil		    != -1);
47201.1Skamil
47211.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
47221.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
47231.1Skamil
47241.1Skamil		/* Resume tracee with PT_CONTINUE */
47251.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
47261.1Skamil
47271.1Skamil		/* Inform parent that tracer has attached to tracee */
47281.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
47291.1Skamil		/* Wait for parent */
47301.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
47311.1Skamil
47321.1Skamil		/* Wait for tracee and assert that it exited */
47331.1Skamil		FORKEE_REQUIRE_SUCCESS(
47341.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
47351.1Skamil
47361.1Skamil		forkee_status_exited(status, exitval_tracee);
47371.1Skamil
47381.13Schristos		DPRINTF("Before exiting of the tracer process\n");
47391.1Skamil		_exit(exitval_tracer);
47401.1Skamil	}
47411.1Skamil
47421.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
47431.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
47441.1Skamil
47451.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
47461.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
47471.1Skamil
47481.13Schristos	DPRINTF("Detect that tracee is zombie\n");
47491.1Skamil	await_zombie(tracee);
47501.1Skamil
47511.13Schristos	DPRINTF("Assert that there is no status about tracee - "
47521.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
47531.1Skamil	TWAIT_REQUIRE_SUCCESS(
47541.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
47551.1Skamil
47561.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
47571.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
47581.1Skamil
47591.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
47601.1Skamil	    TWAIT_FNAME);
47611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
47621.1Skamil	    tracer);
47631.1Skamil
47641.1Skamil	validate_status_exited(status, exitval_tracer);
47651.1Skamil
47661.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
47671.1Skamil	    TWAIT_FNAME);
47681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
47691.1Skamil	    tracee);
47701.1Skamil
47711.1Skamil	validate_status_exited(status, exitval_tracee);
47721.1Skamil
47731.1Skamil	msg_close(&parent_tracer);
47741.1Skamil	msg_close(&parent_tracee);
47751.1Skamil}
47761.1Skamil#endif
47771.1Skamil
47781.1SkamilATF_TC(siginfo1);
47791.1SkamilATF_TC_HEAD(siginfo1, tc)
47801.1Skamil{
47811.1Skamil	atf_tc_set_md_var(tc, "descr",
47821.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
47831.1Skamil}
47841.1Skamil
47851.1SkamilATF_TC_BODY(siginfo1, tc)
47861.1Skamil{
47871.1Skamil	const int exitval = 5;
47881.1Skamil	const int sigval = SIGTRAP;
47891.1Skamil	pid_t child, wpid;
47901.1Skamil#if defined(TWAIT_HAVE_STATUS)
47911.1Skamil	int status;
47921.1Skamil#endif
47931.1Skamil	struct ptrace_siginfo info;
47941.1Skamil	memset(&info, 0, sizeof(info));
47951.1Skamil
47961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47981.1Skamil	if (child == 0) {
47991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48011.1Skamil
48021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48041.1Skamil
48051.13Schristos		DPRINTF("Before exiting of the child process\n");
48061.1Skamil		_exit(exitval);
48071.1Skamil	}
48081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48091.1Skamil
48101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48121.1Skamil
48131.1Skamil	validate_status_stopped(status, sigval);
48141.1Skamil
48151.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48171.1Skamil
48181.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48191.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48201.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48211.1Skamil	    info.psi_siginfo.si_errno);
48221.1Skamil
48231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48241.1Skamil	    "without signal to be sent\n");
48251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48261.1Skamil
48271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48291.1Skamil
48301.1Skamil	validate_status_exited(status, exitval);
48311.1Skamil
48321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48341.1Skamil}
48351.1Skamil
48361.1SkamilATF_TC(siginfo2);
48371.1SkamilATF_TC_HEAD(siginfo2, tc)
48381.1Skamil{
48391.1Skamil	atf_tc_set_md_var(tc, "descr",
48401.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
48411.1Skamil	    "modification of SIGINT from tracee");
48421.1Skamil}
48431.1Skamil
48441.1Skamilstatic int siginfo2_caught = 0;
48451.1Skamil
48461.1Skamilstatic void
48471.1Skamilsiginfo2_sighandler(int sig)
48481.1Skamil{
48491.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
48501.1Skamil
48511.1Skamil	++siginfo2_caught;
48521.1Skamil}
48531.1Skamil
48541.1SkamilATF_TC_BODY(siginfo2, tc)
48551.1Skamil{
48561.1Skamil	const int exitval = 5;
48571.1Skamil	const int sigval = SIGINT;
48581.1Skamil	pid_t child, wpid;
48591.1Skamil	struct sigaction sa;
48601.1Skamil#if defined(TWAIT_HAVE_STATUS)
48611.1Skamil	int status;
48621.1Skamil#endif
48631.1Skamil	struct ptrace_siginfo info;
48641.1Skamil	memset(&info, 0, sizeof(info));
48651.1Skamil
48661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48681.1Skamil	if (child == 0) {
48691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48711.1Skamil
48721.1Skamil		sa.sa_handler = siginfo2_sighandler;
48731.1Skamil		sa.sa_flags = SA_SIGINFO;
48741.1Skamil		sigemptyset(&sa.sa_mask);
48751.1Skamil
48761.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48771.1Skamil
48781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48801.1Skamil
48811.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
48821.1Skamil
48831.13Schristos		DPRINTF("Before exiting of the child process\n");
48841.1Skamil		_exit(exitval);
48851.1Skamil	}
48861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48871.1Skamil
48881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48901.1Skamil
48911.1Skamil	validate_status_stopped(status, sigval);
48921.1Skamil
48931.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48951.1Skamil
48961.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48971.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48981.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48991.1Skamil	    info.psi_siginfo.si_errno);
49001.1Skamil
49011.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49031.1Skamil
49041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49051.1Skamil	    "without signal to be sent\n");
49061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
49071.1Skamil
49081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49101.1Skamil
49111.1Skamil	validate_status_exited(status, exitval);
49121.1Skamil
49131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49151.1Skamil}
49161.1Skamil
49171.1SkamilATF_TC(siginfo3);
49181.1SkamilATF_TC_HEAD(siginfo3, tc)
49191.1Skamil{
49201.1Skamil	atf_tc_set_md_var(tc, "descr",
49211.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
49221.1Skamil	    "setting signal to new value");
49231.1Skamil}
49241.1Skamil
49251.1Skamilstatic int siginfo3_caught = 0;
49261.1Skamil
49271.1Skamilstatic void
49281.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
49291.1Skamil{
49301.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
49311.1Skamil
49321.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
49331.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
49341.1Skamil
49351.1Skamil	++siginfo3_caught;
49361.1Skamil}
49371.1Skamil
49381.1SkamilATF_TC_BODY(siginfo3, tc)
49391.1Skamil{
49401.1Skamil	const int exitval = 5;
49411.1Skamil	const int sigval = SIGINT;
49421.1Skamil	const int sigfaked = SIGTRAP;
49431.1Skamil	const int sicodefaked = TRAP_BRKPT;
49441.1Skamil	pid_t child, wpid;
49451.1Skamil	struct sigaction sa;
49461.1Skamil#if defined(TWAIT_HAVE_STATUS)
49471.1Skamil	int status;
49481.1Skamil#endif
49491.1Skamil	struct ptrace_siginfo info;
49501.1Skamil	memset(&info, 0, sizeof(info));
49511.1Skamil
49521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49541.1Skamil	if (child == 0) {
49551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49571.1Skamil
49581.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
49591.1Skamil		sa.sa_flags = SA_SIGINFO;
49601.1Skamil		sigemptyset(&sa.sa_mask);
49611.1Skamil
49621.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
49631.1Skamil
49641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49661.1Skamil
49671.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
49681.1Skamil
49691.13Schristos		DPRINTF("Before exiting of the child process\n");
49701.1Skamil		_exit(exitval);
49711.1Skamil	}
49721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49731.1Skamil
49741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49761.1Skamil
49771.1Skamil	validate_status_stopped(status, sigval);
49781.1Skamil
49791.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49811.1Skamil
49821.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49831.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49841.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49851.1Skamil	    info.psi_siginfo.si_errno);
49861.1Skamil
49871.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
49881.1Skamil	    sigfaked, sicodefaked);
49891.1Skamil	info.psi_siginfo.si_signo = sigfaked;
49901.1Skamil	info.psi_siginfo.si_code = sicodefaked;
49911.1Skamil
49921.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49941.1Skamil
49951.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49971.1Skamil
49981.13Schristos	DPRINTF("Before checking siginfo_t\n");
49991.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
50001.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
50011.1Skamil
50021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50031.1Skamil	    "without signal to be sent\n");
50041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
50051.1Skamil
50061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50081.1Skamil
50091.1Skamil	validate_status_exited(status, exitval);
50101.1Skamil
50111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50131.1Skamil}
50141.1Skamil
50151.1SkamilATF_TC(siginfo4);
50161.1SkamilATF_TC_HEAD(siginfo4, tc)
50171.1Skamil{
50181.1Skamil	atf_tc_set_md_var(tc, "descr",
50191.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
50201.1Skamil}
50211.1Skamil
50221.1SkamilATF_TC_BODY(siginfo4, tc)
50231.1Skamil{
50241.1Skamil	const int sigval = SIGTRAP;
50251.1Skamil	pid_t child, wpid;
50261.1Skamil#if defined(TWAIT_HAVE_STATUS)
50271.1Skamil	int status;
50281.1Skamil#endif
50291.1Skamil
50301.1Skamil	struct ptrace_siginfo info;
50311.1Skamil	memset(&info, 0, sizeof(info));
50321.1Skamil
50331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50351.1Skamil	if (child == 0) {
50361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50381.1Skamil
50391.13Schristos		DPRINTF("Before calling execve(2) from child\n");
50401.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
50411.1Skamil
50421.1Skamil		FORKEE_ASSERT(0 && "Not reached");
50431.1Skamil	}
50441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50451.1Skamil
50461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50481.1Skamil
50491.1Skamil	validate_status_stopped(status, sigval);
50501.1Skamil
50511.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50531.1Skamil
50541.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
50551.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
50561.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
50571.1Skamil	    info.psi_siginfo.si_errno);
50581.1Skamil
50591.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50601.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
50611.1Skamil
50621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50631.1Skamil	    "without signal to be sent\n");
50641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50651.1Skamil
50661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50681.1Skamil
50691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50711.1Skamil}
50721.1Skamil
50731.1Skamil#if defined(TWAIT_HAVE_PID)
50741.1SkamilATF_TC(siginfo5);
50751.1SkamilATF_TC_HEAD(siginfo5, tc)
50761.1Skamil{
50771.1Skamil	atf_tc_set_md_var(tc, "descr",
50781.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
50791.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
50801.1Skamil}
50811.1Skamil
50821.1SkamilATF_TC_BODY(siginfo5, tc)
50831.1Skamil{
50841.1Skamil	const int exitval = 5;
50851.1Skamil	const int exitval2 = 15;
50861.1Skamil	const int sigval = SIGSTOP;
50871.1Skamil	pid_t child, child2, wpid;
50881.1Skamil#if defined(TWAIT_HAVE_STATUS)
50891.1Skamil	int status;
50901.1Skamil#endif
50911.1Skamil	ptrace_state_t state;
50921.1Skamil	const int slen = sizeof(state);
50931.1Skamil	ptrace_event_t event;
50941.1Skamil	const int elen = sizeof(event);
50951.1Skamil	struct ptrace_siginfo info;
50961.1Skamil
50971.1Skamil	memset(&info, 0, sizeof(info));
50981.1Skamil
50991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51011.1Skamil	if (child == 0) {
51021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51041.1Skamil
51051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51071.1Skamil
51081.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
51091.1Skamil
51101.1Skamil		if (child2 == 0)
51111.1Skamil			_exit(exitval2);
51121.1Skamil
51131.1Skamil		FORKEE_REQUIRE_SUCCESS
51141.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
51151.1Skamil
51161.1Skamil		forkee_status_exited(status, exitval2);
51171.1Skamil
51181.13Schristos		DPRINTF("Before exiting of the child process\n");
51191.1Skamil		_exit(exitval);
51201.1Skamil	}
51211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51221.1Skamil
51231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51251.1Skamil
51261.1Skamil	validate_status_stopped(status, sigval);
51271.1Skamil
51281.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51301.1Skamil
51311.13Schristos	DPRINTF("Before checking siginfo_t\n");
51321.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
51331.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
51341.1Skamil
51351.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
51361.1Skamil	event.pe_set_event = PTRACE_FORK;
51371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51381.1Skamil
51391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51401.1Skamil	    "without signal to be sent\n");
51411.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
51421.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
51431.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
51441.1Skamil                "state.pe_other_pid=child)\n", child);
51451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51461.1Skamil
51471.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
51481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51491.1Skamil
51501.1Skamil	validate_status_stopped(status, SIGTRAP);
51511.1Skamil
51521.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51541.1Skamil
51551.13Schristos	DPRINTF("Before checking siginfo_t\n");
51561.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51571.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51581.1Skamil
51591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51601.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51611.1Skamil
51621.1Skamil	child2 = state.pe_other_pid;
51631.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
51641.1Skamil
51651.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
51661.1Skamil	    TWAIT_FNAME, child2, child);
51671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51681.1Skamil	    child2);
51691.1Skamil
51701.1Skamil	validate_status_stopped(status, SIGTRAP);
51711.1Skamil
51721.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51741.1Skamil
51751.13Schristos	DPRINTF("Before checking siginfo_t\n");
51761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51771.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51781.1Skamil
51791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
51801.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51811.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
51821.1Skamil
51831.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
51841.1Skamil	    "without signal to be sent\n");
51851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
51861.1Skamil
51871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51881.1Skamil	    "without signal to be sent\n");
51891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51901.1Skamil
51911.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
51921.1Skamil	    TWAIT_FNAME);
51931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51941.1Skamil	    child2);
51951.1Skamil
51961.1Skamil	validate_status_exited(status, exitval2);
51971.1Skamil
51981.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
51991.1Skamil	    TWAIT_FNAME);
52001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
52011.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
52021.1Skamil
52031.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52041.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
52051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52061.1Skamil
52071.1Skamil	validate_status_stopped(status, SIGCHLD);
52081.1Skamil
52091.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52111.1Skamil
52121.13Schristos	DPRINTF("Before checking siginfo_t\n");
52131.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
52141.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
52151.1Skamil
52161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52171.1Skamil	    "without signal to be sent\n");
52181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52191.1Skamil
52201.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52211.1Skamil	    TWAIT_FNAME);
52221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52231.1Skamil
52241.1Skamil	validate_status_exited(status, exitval);
52251.1Skamil
52261.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52271.1Skamil	    TWAIT_FNAME);
52281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52291.1Skamil}
52301.1Skamil#endif
52311.1Skamil
52321.1Skamil#if defined(PT_STEP)
52331.1SkamilATF_TC(siginfo6);
52341.1SkamilATF_TC_HEAD(siginfo6, tc)
52351.1Skamil{
52361.1Skamil	atf_tc_set_md_var(tc, "descr",
52371.1Skamil	    "Verify single PT_STEP call with signal information check");
52381.1Skamil}
52391.1Skamil
52401.1SkamilATF_TC_BODY(siginfo6, tc)
52411.1Skamil{
52421.1Skamil	const int exitval = 5;
52431.1Skamil	const int sigval = SIGSTOP;
52441.1Skamil	pid_t child, wpid;
52451.1Skamil#if defined(TWAIT_HAVE_STATUS)
52461.1Skamil	int status;
52471.1Skamil#endif
52481.1Skamil	int happy;
52491.1Skamil	struct ptrace_siginfo info;
52501.1Skamil
52511.1Skamil#if defined(__arm__)
52521.1Skamil	/* PT_STEP not supported on arm 32-bit */
52531.1Skamil	atf_tc_expect_fail("PR kern/52119");
52541.1Skamil#endif
52551.1Skamil
52561.1Skamil	memset(&info, 0, sizeof(info));
52571.1Skamil
52581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52601.1Skamil	if (child == 0) {
52611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52631.1Skamil
52641.1Skamil		happy = check_happy(100);
52651.1Skamil
52661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52681.1Skamil
52691.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
52701.1Skamil
52711.13Schristos		DPRINTF("Before exiting of the child process\n");
52721.1Skamil		_exit(exitval);
52731.1Skamil	}
52741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52751.1Skamil
52761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52781.1Skamil
52791.1Skamil	validate_status_stopped(status, sigval);
52801.1Skamil
52811.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52831.1Skamil
52841.13Schristos	DPRINTF("Before checking siginfo_t\n");
52851.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52861.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52871.1Skamil
52881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52891.1Skamil	    "without signal to be sent (use PT_STEP)\n");
52901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
52911.1Skamil
52921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52941.1Skamil
52951.1Skamil	validate_status_stopped(status, SIGTRAP);
52961.1Skamil
52971.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52991.1Skamil
53001.13Schristos	DPRINTF("Before checking siginfo_t\n");
53011.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
53021.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
53031.1Skamil
53041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53051.1Skamil	    "without signal to be sent\n");
53061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53071.1Skamil
53081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53101.1Skamil
53111.1Skamil	validate_status_exited(status, exitval);
53121.1Skamil
53131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53151.1Skamil}
53161.1Skamil#endif
53171.1Skamil
53181.1Skamilvolatile lwpid_t the_lwp_id = 0;
53191.1Skamil
53201.1Skamilstatic void
53211.1Skamillwp_main_func(void *arg)
53221.1Skamil{
53231.1Skamil	the_lwp_id = _lwp_self();
53241.1Skamil	_lwp_exit();
53251.1Skamil}
53261.1Skamil
53271.1SkamilATF_TC(lwp_create1);
53281.1SkamilATF_TC_HEAD(lwp_create1, tc)
53291.1Skamil{
53301.1Skamil	atf_tc_set_md_var(tc, "descr",
53311.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53321.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
53331.1Skamil}
53341.1Skamil
53351.1SkamilATF_TC_BODY(lwp_create1, tc)
53361.1Skamil{
53371.1Skamil	const int exitval = 5;
53381.1Skamil	const int sigval = SIGSTOP;
53391.1Skamil	pid_t child, wpid;
53401.1Skamil#if defined(TWAIT_HAVE_STATUS)
53411.1Skamil	int status;
53421.1Skamil#endif
53431.1Skamil	ptrace_state_t state;
53441.1Skamil	const int slen = sizeof(state);
53451.1Skamil	ptrace_event_t event;
53461.1Skamil	const int elen = sizeof(event);
53471.1Skamil	ucontext_t uc;
53481.1Skamil	lwpid_t lid;
53491.1Skamil	static const size_t ssize = 16*1024;
53501.1Skamil	void *stack;
53511.1Skamil
53521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53541.1Skamil	if (child == 0) {
53551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53571.1Skamil
53581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53601.1Skamil
53611.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53621.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53631.1Skamil
53641.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53651.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53661.1Skamil
53671.13Schristos		DPRINTF("Before creating new in child\n");
53681.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53691.1Skamil
53701.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53711.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53721.1Skamil
53731.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53741.1Skamil		    "are the same\n", lid, the_lwp_id);
53751.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53761.1Skamil
53771.13Schristos		DPRINTF("Before exiting of the child process\n");
53781.1Skamil		_exit(exitval);
53791.1Skamil	}
53801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53811.1Skamil
53821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53841.1Skamil
53851.1Skamil	validate_status_stopped(status, sigval);
53861.1Skamil
53871.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
53881.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
53891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53901.1Skamil
53911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53921.1Skamil	    "without signal to be sent\n");
53931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53941.1Skamil
53951.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53961.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
53971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53981.1Skamil
53991.1Skamil	validate_status_stopped(status, SIGTRAP);
54001.1Skamil
54011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54021.1Skamil
54031.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
54041.1Skamil
54051.1Skamil	lid = state.pe_lwp;
54061.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
54071.1Skamil
54081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54091.1Skamil	    "without signal to be sent\n");
54101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54111.1Skamil
54121.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54131.1Skamil	    TWAIT_FNAME);
54141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54151.1Skamil
54161.1Skamil	validate_status_exited(status, exitval);
54171.1Skamil
54181.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54191.1Skamil	    TWAIT_FNAME);
54201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54211.1Skamil}
54221.1Skamil
54231.1SkamilATF_TC(lwp_exit1);
54241.1SkamilATF_TC_HEAD(lwp_exit1, tc)
54251.1Skamil{
54261.1Skamil	atf_tc_set_md_var(tc, "descr",
54271.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
54281.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
54291.1Skamil}
54301.1Skamil
54311.1SkamilATF_TC_BODY(lwp_exit1, tc)
54321.1Skamil{
54331.1Skamil	const int exitval = 5;
54341.1Skamil	const int sigval = SIGSTOP;
54351.1Skamil	pid_t child, wpid;
54361.1Skamil#if defined(TWAIT_HAVE_STATUS)
54371.1Skamil	int status;
54381.1Skamil#endif
54391.1Skamil	ptrace_state_t state;
54401.1Skamil	const int slen = sizeof(state);
54411.1Skamil	ptrace_event_t event;
54421.1Skamil	const int elen = sizeof(event);
54431.1Skamil	ucontext_t uc;
54441.1Skamil	lwpid_t lid;
54451.1Skamil	static const size_t ssize = 16*1024;
54461.1Skamil	void *stack;
54471.1Skamil
54481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54501.1Skamil	if (child == 0) {
54511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54531.1Skamil
54541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54561.1Skamil
54571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54591.1Skamil
54601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54611.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54621.1Skamil
54631.13Schristos		DPRINTF("Before creating new in child\n");
54641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54651.1Skamil
54661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54681.1Skamil
54691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54701.1Skamil		    "are the same\n", lid, the_lwp_id);
54711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54721.1Skamil
54731.13Schristos		DPRINTF("Before exiting of the child process\n");
54741.1Skamil		_exit(exitval);
54751.1Skamil	}
54761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54771.1Skamil
54781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54801.1Skamil
54811.1Skamil	validate_status_stopped(status, sigval);
54821.1Skamil
54831.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54841.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
54851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54861.1Skamil
54871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54881.1Skamil	    "without signal to be sent\n");
54891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54901.1Skamil
54911.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54921.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54941.1Skamil
54951.1Skamil	validate_status_stopped(status, SIGTRAP);
54961.1Skamil
54971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54981.1Skamil
54991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
55001.1Skamil
55011.1Skamil	lid = state.pe_lwp;
55021.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
55031.1Skamil
55041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55051.1Skamil	    "without signal to be sent\n");
55061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55071.1Skamil
55081.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55091.1Skamil	    TWAIT_FNAME);
55101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55111.1Skamil
55121.1Skamil	validate_status_exited(status, exitval);
55131.1Skamil
55141.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55151.1Skamil	    TWAIT_FNAME);
55161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55171.1Skamil}
55181.1Skamil
55191.1SkamilATF_TC(signal1);
55201.1SkamilATF_TC_HEAD(signal1, tc)
55211.1Skamil{
55221.1Skamil	atf_tc_set_md_var(tc, "descr",
55231.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
55241.1Skamil	    "from catching other signals");
55251.1Skamil}
55261.1Skamil
55271.1SkamilATF_TC_BODY(signal1, tc)
55281.1Skamil{
55291.1Skamil	const int exitval = 5;
55301.1Skamil	const int sigval = SIGSTOP;
55311.1Skamil	const int sigmasked = SIGTRAP;
55321.1Skamil	const int signotmasked = SIGINT;
55331.1Skamil	pid_t child, wpid;
55341.1Skamil#if defined(TWAIT_HAVE_STATUS)
55351.1Skamil	int status;
55361.1Skamil#endif
55371.1Skamil	sigset_t intmask;
55381.1Skamil
55391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55411.1Skamil	if (child == 0) {
55421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55441.1Skamil
55451.1Skamil		sigemptyset(&intmask);
55461.1Skamil		sigaddset(&intmask, sigmasked);
55471.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55481.1Skamil
55491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55511.1Skamil
55521.13Schristos		DPRINTF("Before raising %s from child\n",
55531.1Skamil		    strsignal(signotmasked));
55541.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
55551.1Skamil
55561.13Schristos		DPRINTF("Before exiting of the child process\n");
55571.1Skamil		_exit(exitval);
55581.1Skamil	}
55591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55601.1Skamil
55611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55631.1Skamil
55641.1Skamil	validate_status_stopped(status, sigval);
55651.1Skamil
55661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55671.1Skamil	    "without signal to be sent\n");
55681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55691.1Skamil
55701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55721.1Skamil
55731.1Skamil	validate_status_stopped(status, signotmasked);
55741.1Skamil
55751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55761.1Skamil	    "without signal to be sent\n");
55771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55781.1Skamil
55791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55811.1Skamil
55821.1Skamil	validate_status_exited(status, exitval);
55831.1Skamil
55841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55861.1Skamil}
55871.1Skamil
55881.1SkamilATF_TC(signal2);
55891.1SkamilATF_TC_HEAD(signal2, tc)
55901.1Skamil{
55911.1Skamil	atf_tc_set_md_var(tc, "descr",
55921.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
55931.1Skamil	    "catching this raised signal");
55941.1Skamil}
55951.1Skamil
55961.1SkamilATF_TC_BODY(signal2, tc)
55971.1Skamil{
55981.1Skamil	const int exitval = 5;
55991.1Skamil	const int sigval = SIGSTOP;
56001.1Skamil	const int sigmasked = SIGTRAP;
56011.1Skamil	pid_t child, wpid;
56021.1Skamil#if defined(TWAIT_HAVE_STATUS)
56031.1Skamil	int status;
56041.1Skamil#endif
56051.1Skamil	sigset_t intmask;
56061.1Skamil
56071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56091.1Skamil	if (child == 0) {
56101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56121.1Skamil
56131.1Skamil		sigemptyset(&intmask);
56141.1Skamil		sigaddset(&intmask, sigmasked);
56151.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56161.1Skamil
56171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56191.1Skamil
56201.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
56211.1Skamil		    strsignal(sigmasked));
56221.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
56231.1Skamil
56241.13Schristos		DPRINTF("Before exiting of the child process\n");
56251.1Skamil		_exit(exitval);
56261.1Skamil	}
56271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56281.1Skamil
56291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56311.1Skamil
56321.1Skamil	validate_status_stopped(status, sigval);
56331.1Skamil
56341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56351.1Skamil	    "without signal to be sent\n");
56361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56371.1Skamil
56381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56401.1Skamil
56411.1Skamil	validate_status_exited(status, exitval);
56421.1Skamil
56431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56451.1Skamil}
56461.1Skamil
56471.1SkamilATF_TC(signal3);
56481.1SkamilATF_TC_HEAD(signal3, tc)
56491.1Skamil{
56501.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
56511.1Skamil	atf_tc_set_md_var(tc, "descr",
56521.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56531.1Skamil	    "catching software breakpoints");
56541.1Skamil}
56551.1Skamil
56561.1SkamilATF_TC_BODY(signal3, tc)
56571.1Skamil{
56581.1Skamil	const int exitval = 5;
56591.1Skamil	const int sigval = SIGSTOP;
56601.1Skamil	const int sigmasked = SIGTRAP;
56611.1Skamil	pid_t child, wpid;
56621.1Skamil#if defined(TWAIT_HAVE_STATUS)
56631.1Skamil	int status;
56641.1Skamil#endif
56651.1Skamil	sigset_t intmask;
56661.1Skamil
56671.20Skamil	atf_tc_expect_fail("PR kern/51918");
56681.20Skamil
56691.20Skamil	// This test breaks now on some ports, temporarily disable it
56701.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56711.20Skamil
56721.10Smartin#if defined(__sparc__)
56731.7Skamil	atf_tc_expect_timeout("PR kern/52167");
56741.7Skamil
56751.7Skamil	// timeout wins, failure still valid
56761.7Skamil	// atf_tc_expect_fail("PR kern/51918");
56771.7Skamil#endif
56781.1Skamil
56791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56811.1Skamil	if (child == 0) {
56821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56841.1Skamil
56851.1Skamil		sigemptyset(&intmask);
56861.1Skamil		sigaddset(&intmask, sigmasked);
56871.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56881.1Skamil
56891.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56901.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56911.1Skamil
56921.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
56931.4Skamil
56941.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
56951.4Skamil		PTRACE_BREAKPOINT_ASM;
56961.1Skamil#else
56971.4Skamil		/* port me */
56981.1Skamil#endif
56991.1Skamil
57001.13Schristos		DPRINTF("Before exiting of the child process\n");
57011.1Skamil		_exit(exitval);
57021.1Skamil	}
57031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57041.1Skamil
57051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57071.1Skamil
57081.1Skamil	validate_status_stopped(status, sigval);
57091.1Skamil
57101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57111.1Skamil	    "without signal to be sent\n");
57121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57131.1Skamil
57141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57161.1Skamil
57171.1Skamil	validate_status_stopped(status, sigmasked);
57181.1Skamil
57191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57201.1Skamil	    "without signal to be sent\n");
57211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57221.1Skamil
57231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57251.1Skamil
57261.1Skamil	validate_status_exited(status, exitval);
57271.1Skamil
57281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57301.1Skamil}
57311.1Skamil
57321.1Skamil#if defined(PT_STEP)
57331.1SkamilATF_TC(signal4);
57341.1SkamilATF_TC_HEAD(signal4, tc)
57351.1Skamil{
57361.1Skamil	atf_tc_set_md_var(tc, "descr",
57371.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57381.1Skamil	    "catching single step trap");
57391.1Skamil}
57401.1Skamil
57411.1SkamilATF_TC_BODY(signal4, tc)
57421.1Skamil{
57431.1Skamil	const int exitval = 5;
57441.1Skamil	const int sigval = SIGSTOP;
57451.1Skamil	const int sigmasked = SIGTRAP;
57461.1Skamil	pid_t child, wpid;
57471.1Skamil#if defined(TWAIT_HAVE_STATUS)
57481.1Skamil	int status;
57491.1Skamil#endif
57501.1Skamil	sigset_t intmask;
57511.1Skamil	int happy;
57521.1Skamil
57531.1Skamil#if defined(__arm__)
57541.5Skamil	/* PT_STEP not supported on arm 32-bit */
57551.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
57561.1Skamil#endif
57571.1Skamil
57581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57601.1Skamil	if (child == 0) {
57611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57631.1Skamil
57641.1Skamil		happy = check_happy(100);
57651.1Skamil
57661.1Skamil		sigemptyset(&intmask);
57671.1Skamil		sigaddset(&intmask, sigmasked);
57681.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57691.1Skamil
57701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57721.1Skamil
57731.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
57741.1Skamil
57751.13Schristos		DPRINTF("Before exiting of the child process\n");
57761.1Skamil		_exit(exitval);
57771.1Skamil	}
57781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57791.1Skamil
57801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57821.1Skamil
57831.1Skamil	validate_status_stopped(status, sigval);
57841.1Skamil
57851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57861.1Skamil	    "without signal to be sent\n");
57871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
57881.1Skamil
57891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57911.1Skamil
57921.1Skamil	validate_status_stopped(status, sigmasked);
57931.1Skamil
57941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57951.1Skamil	    "without signal to be sent\n");
57961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57971.1Skamil
57981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58001.1Skamil
58011.1Skamil	validate_status_exited(status, exitval);
58021.1Skamil
58031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58041.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58051.1Skamil}
58061.1Skamil#endif
58071.1Skamil
58081.1SkamilATF_TC(signal5);
58091.1SkamilATF_TC_HEAD(signal5, tc)
58101.1Skamil{
58111.1Skamil	atf_tc_set_md_var(tc, "descr",
58121.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58131.1Skamil	    "catching exec() breakpoint");
58141.1Skamil}
58151.1Skamil
58161.1SkamilATF_TC_BODY(signal5, tc)
58171.1Skamil{
58181.1Skamil	const int exitval = 5;
58191.1Skamil	const int sigval = SIGSTOP;
58201.1Skamil	const int sigmasked = SIGTRAP;
58211.1Skamil	pid_t child, wpid;
58221.1Skamil#if defined(TWAIT_HAVE_STATUS)
58231.1Skamil	int status;
58241.1Skamil#endif
58251.1Skamil	sigset_t intmask;
58261.1Skamil
58271.14Schristos	atf_tc_expect_fail("wrong signal");
58281.14Schristos
58291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58311.1Skamil	if (child == 0) {
58321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58341.1Skamil
58351.1Skamil		sigemptyset(&intmask);
58361.1Skamil		sigaddset(&intmask, sigmasked);
58371.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58381.1Skamil
58391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58411.1Skamil
58421.13Schristos		DPRINTF("Before calling execve(2) from child\n");
58431.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
58441.1Skamil
58451.13Schristos		DPRINTF("Before exiting of the child process\n");
58461.1Skamil		_exit(exitval);
58471.1Skamil	}
58481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58491.1Skamil
58501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58521.1Skamil
58531.1Skamil	validate_status_stopped(status, sigval);
58541.1Skamil
58551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58561.1Skamil	    "without signal to be sent\n");
58571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58581.1Skamil
58591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58611.1Skamil
58621.1Skamil	validate_status_stopped(status, sigmasked);
58631.1Skamil
58641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58651.1Skamil	    "without signal to be sent\n");
58661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58671.1Skamil
58681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58701.1Skamil
58711.1Skamil	validate_status_exited(status, exitval);
58721.1Skamil
58731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58751.1Skamil}
58761.1Skamil
58771.1Skamil#if defined(TWAIT_HAVE_PID)
58781.1SkamilATF_TC(signal6);
58791.1SkamilATF_TC_HEAD(signal6, tc)
58801.1Skamil{
58811.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
58821.1Skamil	atf_tc_set_md_var(tc, "descr",
58831.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58841.1Skamil	    "catching PTRACE_FORK breakpoint");
58851.1Skamil}
58861.1Skamil
58871.1SkamilATF_TC_BODY(signal6, tc)
58881.1Skamil{
58891.1Skamil	const int exitval = 5;
58901.1Skamil	const int exitval2 = 15;
58911.1Skamil	const int sigval = SIGSTOP;
58921.1Skamil	const int sigmasked = SIGTRAP;
58931.1Skamil	pid_t child, child2, wpid;
58941.1Skamil#if defined(TWAIT_HAVE_STATUS)
58951.1Skamil	int status;
58961.1Skamil#endif
58971.1Skamil	sigset_t intmask;
58981.1Skamil	ptrace_state_t state;
58991.1Skamil	const int slen = sizeof(state);
59001.1Skamil	ptrace_event_t event;
59011.1Skamil	const int elen = sizeof(event);
59021.1Skamil
59031.38Skamil	atf_tc_expect_fail("PR kern/51918");
59041.14Schristos
59051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59071.1Skamil	if (child == 0) {
59081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59101.1Skamil
59111.1Skamil		sigemptyset(&intmask);
59121.1Skamil		sigaddset(&intmask, sigmasked);
59131.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59141.1Skamil
59151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59171.1Skamil
59181.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59191.1Skamil
59201.1Skamil		if (child2 == 0)
59211.1Skamil			_exit(exitval2);
59221.1Skamil
59231.1Skamil		FORKEE_REQUIRE_SUCCESS
59241.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59251.1Skamil
59261.1Skamil		forkee_status_exited(status, exitval2);
59271.1Skamil
59281.13Schristos		DPRINTF("Before exiting of the child process\n");
59291.1Skamil		_exit(exitval);
59301.1Skamil	}
59311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
59321.1Skamil
59331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59351.1Skamil
59361.1Skamil	validate_status_stopped(status, sigval);
59371.1Skamil
59381.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
59391.1Skamil	event.pe_set_event = PTRACE_FORK;
59401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
59411.1Skamil
59421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59431.1Skamil	    "without signal to be sent\n");
59441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59451.1Skamil
59461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
59471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59481.1Skamil
59491.1Skamil	validate_status_stopped(status, sigmasked);
59501.1Skamil
59511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
59521.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59531.1Skamil
59541.1Skamil	child2 = state.pe_other_pid;
59551.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
59561.1Skamil
59571.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
59581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59591.1Skamil	    child2);
59601.1Skamil
59611.1Skamil	validate_status_stopped(status, SIGTRAP);
59621.1Skamil
59631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59641.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59651.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
59661.1Skamil
59671.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
59681.1Skamil	    "without signal to be sent\n");
59691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59701.1Skamil
59711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59721.1Skamil	    "without signal to be sent\n");
59731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59741.1Skamil
59751.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
59761.1Skamil	    TWAIT_FNAME);
59771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59781.1Skamil	    child2);
59791.1Skamil
59801.1Skamil	validate_status_exited(status, exitval2);
59811.1Skamil
59821.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
59831.1Skamil	    TWAIT_FNAME);
59841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
59851.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
59861.1Skamil
59871.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59881.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
59891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59901.1Skamil
59911.1Skamil	validate_status_stopped(status, SIGCHLD);
59921.1Skamil
59931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59941.1Skamil	    "without signal to be sent\n");
59951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59961.1Skamil
59971.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59981.1Skamil	    TWAIT_FNAME);
59991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60001.1Skamil
60011.1Skamil	validate_status_exited(status, exitval);
60021.1Skamil
60031.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60041.1Skamil	    TWAIT_FNAME);
60051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60061.1Skamil}
60071.1Skamil#endif
60081.1Skamil
60091.1Skamil#if defined(TWAIT_HAVE_PID)
60101.1SkamilATF_TC(signal7);
60111.1SkamilATF_TC_HEAD(signal7, tc)
60121.1Skamil{
60131.1Skamil	atf_tc_set_md_var(tc, "descr",
60141.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60151.1Skamil	    "catching PTRACE_VFORK breakpoint");
60161.1Skamil}
60171.1Skamil
60181.1SkamilATF_TC_BODY(signal7, tc)
60191.1Skamil{
60201.1Skamil	const int exitval = 5;
60211.1Skamil	const int exitval2 = 15;
60221.1Skamil	const int sigval = SIGSTOP;
60231.1Skamil	const int sigmasked = SIGTRAP;
60241.1Skamil	pid_t child, child2, wpid;
60251.1Skamil#if defined(TWAIT_HAVE_STATUS)
60261.1Skamil	int status;
60271.1Skamil#endif
60281.1Skamil	sigset_t intmask;
60291.1Skamil	ptrace_state_t state;
60301.1Skamil	const int slen = sizeof(state);
60311.1Skamil	ptrace_event_t event;
60321.1Skamil	const int elen = sizeof(event);
60331.1Skamil
60341.38Skamil	atf_tc_expect_fail("PR kern/51918");
60351.14Schristos
60361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
60371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
60381.1Skamil	if (child == 0) {
60391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
60401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
60411.1Skamil
60421.1Skamil		sigemptyset(&intmask);
60431.1Skamil		sigaddset(&intmask, sigmasked);
60441.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
60451.1Skamil
60461.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
60471.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
60481.1Skamil
60491.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
60501.1Skamil
60511.1Skamil		if (child2 == 0)
60521.1Skamil			_exit(exitval2);
60531.1Skamil
60541.1Skamil		FORKEE_REQUIRE_SUCCESS
60551.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
60561.1Skamil
60571.1Skamil		forkee_status_exited(status, exitval2);
60581.1Skamil
60591.13Schristos		DPRINTF("Before exiting of the child process\n");
60601.1Skamil		_exit(exitval);
60611.1Skamil	}
60621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60631.1Skamil
60641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60661.1Skamil
60671.1Skamil	validate_status_stopped(status, sigval);
60681.1Skamil
60691.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
60701.1Skamil	event.pe_set_event = PTRACE_VFORK;
60711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
60721.1Skamil
60731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60741.1Skamil	    "without signal to be sent\n");
60751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60761.1Skamil
60771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60791.1Skamil
60801.1Skamil	validate_status_stopped(status, sigmasked);
60811.1Skamil
60821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60831.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60841.1Skamil
60851.1Skamil	child2 = state.pe_other_pid;
60861.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
60871.1Skamil
60881.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
60891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60901.1Skamil	    child2);
60911.1Skamil
60921.1Skamil	validate_status_stopped(status, SIGTRAP);
60931.1Skamil
60941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
60951.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60961.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
60971.1Skamil
60981.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
60991.1Skamil	    "without signal to be sent\n");
61001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
61011.1Skamil
61021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61031.1Skamil	    "without signal to be sent\n");
61041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61051.1Skamil
61061.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
61071.1Skamil	    TWAIT_FNAME);
61081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
61091.1Skamil	    child2);
61101.1Skamil
61111.1Skamil	validate_status_exited(status, exitval2);
61121.1Skamil
61131.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
61141.1Skamil	    TWAIT_FNAME);
61151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
61161.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
61171.1Skamil
61181.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61191.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61211.1Skamil
61221.1Skamil	validate_status_stopped(status, SIGCHLD);
61231.1Skamil
61241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61251.1Skamil	    "without signal to be sent\n");
61261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61271.1Skamil
61281.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61291.1Skamil	    TWAIT_FNAME);
61301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61311.1Skamil
61321.1Skamil	validate_status_exited(status, exitval);
61331.1Skamil
61341.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61351.1Skamil	    TWAIT_FNAME);
61361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61371.1Skamil}
61381.1Skamil#endif
61391.1Skamil
61401.1SkamilATF_TC(signal8);
61411.1SkamilATF_TC_HEAD(signal8, tc)
61421.1Skamil{
61431.1Skamil	atf_tc_set_md_var(tc, "descr",
61441.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61451.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
61461.1Skamil}
61471.1Skamil
61481.1SkamilATF_TC_BODY(signal8, tc)
61491.1Skamil{
61501.1Skamil	const int exitval = 5;
61511.1Skamil	const int exitval2 = 15;
61521.1Skamil	const int sigval = SIGSTOP;
61531.1Skamil	const int sigmasked = SIGTRAP;
61541.1Skamil	pid_t child, child2, wpid;
61551.1Skamil#if defined(TWAIT_HAVE_STATUS)
61561.1Skamil	int status;
61571.1Skamil#endif
61581.1Skamil	sigset_t intmask;
61591.1Skamil	ptrace_state_t state;
61601.1Skamil	const int slen = sizeof(state);
61611.1Skamil	ptrace_event_t event;
61621.1Skamil	const int elen = sizeof(event);
61631.1Skamil
61641.14Schristos	atf_tc_expect_fail("PR kern/51918");
61651.14Schristos
61661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61681.1Skamil	if (child == 0) {
61691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61711.1Skamil
61721.1Skamil		sigemptyset(&intmask);
61731.1Skamil		sigaddset(&intmask, sigmasked);
61741.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61751.1Skamil
61761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61781.1Skamil
61791.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
61801.1Skamil
61811.1Skamil		if (child2 == 0)
61821.1Skamil			_exit(exitval2);
61831.1Skamil
61841.1Skamil		FORKEE_REQUIRE_SUCCESS
61851.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
61861.1Skamil
61871.1Skamil		forkee_status_exited(status, exitval2);
61881.1Skamil
61891.13Schristos		DPRINTF("Before exiting of the child process\n");
61901.1Skamil		_exit(exitval);
61911.1Skamil	}
61921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61931.1Skamil
61941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61961.1Skamil
61971.1Skamil	validate_status_stopped(status, sigval);
61981.1Skamil
61991.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
62001.1Skamil	    child);
62011.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
62021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62031.1Skamil
62041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62051.1Skamil	    "without signal to be sent\n");
62061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62071.1Skamil
62081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62101.1Skamil
62111.1Skamil	validate_status_stopped(status, sigmasked);
62121.1Skamil
62131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62141.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
62151.1Skamil
62161.1Skamil	child2 = state.pe_other_pid;
62171.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
62181.1Skamil
62191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62201.1Skamil	    "without signal to be sent\n");
62211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62221.1Skamil
62231.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62241.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
62251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62261.1Skamil
62271.1Skamil	validate_status_stopped(status, SIGCHLD);
62281.1Skamil
62291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62301.1Skamil	    "without signal to be sent\n");
62311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62321.1Skamil
62331.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62341.1Skamil	    TWAIT_FNAME);
62351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62361.1Skamil
62371.1Skamil	validate_status_exited(status, exitval);
62381.1Skamil
62391.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62401.1Skamil	    TWAIT_FNAME);
62411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62421.1Skamil}
62431.1Skamil
62441.1SkamilATF_TC(signal9);
62451.1SkamilATF_TC_HEAD(signal9, tc)
62461.1Skamil{
62471.1Skamil	atf_tc_set_md_var(tc, "descr",
62481.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62491.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
62501.1Skamil}
62511.1Skamil
62521.1SkamilATF_TC_BODY(signal9, tc)
62531.1Skamil{
62541.1Skamil	const int exitval = 5;
62551.1Skamil	const int sigval = SIGSTOP;
62561.1Skamil	const int sigmasked = SIGTRAP;
62571.1Skamil	pid_t child, wpid;
62581.1Skamil#if defined(TWAIT_HAVE_STATUS)
62591.1Skamil	int status;
62601.1Skamil#endif
62611.1Skamil	sigset_t intmask;
62621.1Skamil	ptrace_state_t state;
62631.1Skamil	const int slen = sizeof(state);
62641.1Skamil	ptrace_event_t event;
62651.1Skamil	const int elen = sizeof(event);
62661.1Skamil	ucontext_t uc;
62671.1Skamil	lwpid_t lid;
62681.1Skamil	static const size_t ssize = 16*1024;
62691.1Skamil	void *stack;
62701.1Skamil
62711.14Schristos	atf_tc_expect_fail("PR kern/51918");
62721.14Schristos
62731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62751.1Skamil	if (child == 0) {
62761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62781.1Skamil
62791.1Skamil		sigemptyset(&intmask);
62801.1Skamil		sigaddset(&intmask, sigmasked);
62811.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62821.1Skamil
62831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62851.1Skamil
62861.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62871.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62881.1Skamil
62891.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62901.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62911.1Skamil
62921.13Schristos		DPRINTF("Before creating new in child\n");
62931.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62941.1Skamil
62951.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62961.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62971.1Skamil
62981.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62991.1Skamil		    "are the same\n", lid, the_lwp_id);
63001.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63011.1Skamil
63021.13Schristos		DPRINTF("Before exiting of the child process\n");
63031.1Skamil		_exit(exitval);
63041.1Skamil	}
63051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63061.1Skamil
63071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63091.1Skamil
63101.1Skamil	validate_status_stopped(status, sigval);
63111.1Skamil
63121.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63131.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
63141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63151.1Skamil
63161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63171.1Skamil	    "without signal to be sent\n");
63181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63191.1Skamil
63201.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63211.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63231.1Skamil
63241.1Skamil	validate_status_stopped(status, sigmasked);
63251.1Skamil
63261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63271.1Skamil
63281.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
63291.1Skamil
63301.1Skamil	lid = state.pe_lwp;
63311.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
63321.1Skamil
63331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63341.1Skamil	    "without signal to be sent\n");
63351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63361.1Skamil
63371.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63381.1Skamil	    TWAIT_FNAME);
63391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63401.1Skamil
63411.1Skamil	validate_status_exited(status, exitval);
63421.1Skamil
63431.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63441.1Skamil	    TWAIT_FNAME);
63451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63461.1Skamil}
63471.1Skamil
63481.1SkamilATF_TC(signal10);
63491.1SkamilATF_TC_HEAD(signal10, tc)
63501.1Skamil{
63511.1Skamil	atf_tc_set_md_var(tc, "descr",
63521.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
63531.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
63541.1Skamil}
63551.1Skamil
63561.1SkamilATF_TC_BODY(signal10, tc)
63571.1Skamil{
63581.1Skamil	const int exitval = 5;
63591.1Skamil	const int sigval = SIGSTOP;
63601.1Skamil	const int sigmasked = SIGTRAP;
63611.1Skamil	pid_t child, wpid;
63621.1Skamil#if defined(TWAIT_HAVE_STATUS)
63631.1Skamil	int status;
63641.1Skamil#endif
63651.1Skamil	sigset_t intmask;
63661.1Skamil	ptrace_state_t state;
63671.1Skamil	const int slen = sizeof(state);
63681.1Skamil	ptrace_event_t event;
63691.1Skamil	const int elen = sizeof(event);
63701.1Skamil	ucontext_t uc;
63711.1Skamil	lwpid_t lid;
63721.1Skamil	static const size_t ssize = 16*1024;
63731.1Skamil	void *stack;
63741.1Skamil
63751.14Schristos	atf_tc_expect_fail("PR kern/51918");
63761.14Schristos
63771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63791.1Skamil	if (child == 0) {
63801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63821.1Skamil
63831.1Skamil		sigemptyset(&intmask);
63841.1Skamil		sigaddset(&intmask, sigmasked);
63851.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63861.1Skamil
63871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63891.1Skamil
63901.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63911.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63921.1Skamil
63931.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63941.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63951.1Skamil
63961.13Schristos		DPRINTF("Before creating new in child\n");
63971.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63981.1Skamil
63991.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64001.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64011.1Skamil
64021.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64031.1Skamil		    "are the same\n", lid, the_lwp_id);
64041.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64051.1Skamil
64061.13Schristos		DPRINTF("Before exiting of the child process\n");
64071.1Skamil		_exit(exitval);
64081.1Skamil	}
64091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64101.1Skamil
64111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64131.1Skamil
64141.1Skamil	validate_status_stopped(status, sigval);
64151.1Skamil
64161.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
64171.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
64181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
64191.1Skamil
64201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64211.1Skamil	    "without signal to be sent\n");
64221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64231.1Skamil
64241.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64251.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64271.1Skamil
64281.1Skamil	validate_status_stopped(status, sigmasked);
64291.1Skamil
64301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
64311.1Skamil
64321.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
64331.1Skamil
64341.1Skamil	lid = state.pe_lwp;
64351.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
64361.1Skamil
64371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64381.1Skamil	    "without signal to be sent\n");
64391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64401.1Skamil
64411.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
64421.1Skamil	    TWAIT_FNAME);
64431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64441.1Skamil
64451.1Skamil	validate_status_exited(status, exitval);
64461.1Skamil
64471.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
64481.1Skamil	    TWAIT_FNAME);
64491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
64501.1Skamil}
64511.1Skamil
64521.1Skamilstatic void
64531.1Skamillwp_main_stop(void *arg)
64541.1Skamil{
64551.1Skamil	the_lwp_id = _lwp_self();
64561.1Skamil
64571.1Skamil	raise(SIGTRAP);
64581.1Skamil
64591.1Skamil	_lwp_exit();
64601.1Skamil}
64611.1Skamil
64621.1SkamilATF_TC(suspend1);
64631.1SkamilATF_TC_HEAD(suspend1, tc)
64641.1Skamil{
64651.1Skamil	atf_tc_set_md_var(tc, "descr",
64661.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64671.1Skamil	    "resumed by a tracee");
64681.1Skamil}
64691.1Skamil
64701.1SkamilATF_TC_BODY(suspend1, tc)
64711.1Skamil{
64721.1Skamil	const int exitval = 5;
64731.1Skamil	const int sigval = SIGSTOP;
64741.1Skamil	pid_t child, wpid;
64751.1Skamil#if defined(TWAIT_HAVE_STATUS)
64761.1Skamil	int status;
64771.1Skamil#endif
64781.1Skamil	ucontext_t uc;
64791.1Skamil	lwpid_t lid;
64801.1Skamil	static const size_t ssize = 16*1024;
64811.1Skamil	void *stack;
64821.1Skamil	struct ptrace_lwpinfo pl;
64831.1Skamil	struct ptrace_siginfo psi;
64841.1Skamil	volatile int go = 0;
64851.1Skamil
64861.17Skamil	// Feature pending for refactoring
64871.17Skamil	atf_tc_expect_fail("PR kern/51995");
64881.17Skamil
64891.16Skamil	// Hangs with qemu
64901.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
64911.16Skamil
64921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64941.1Skamil	if (child == 0) {
64951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64971.1Skamil
64981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65001.1Skamil
65011.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
65021.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
65031.1Skamil
65041.13Schristos		DPRINTF("Before making context for new lwp in child\n");
65051.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
65061.1Skamil
65071.13Schristos		DPRINTF("Before creating new in child\n");
65081.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
65091.1Skamil
65101.1Skamil		while (go == 0)
65111.1Skamil			continue;
65121.1Skamil
65131.1Skamil		raise(SIGINT);
65141.1Skamil
65151.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
65161.1Skamil
65171.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
65181.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
65191.1Skamil
65201.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
65211.1Skamil		    "are the same\n", lid, the_lwp_id);
65221.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
65231.1Skamil
65241.13Schristos		DPRINTF("Before exiting of the child process\n");
65251.1Skamil		_exit(exitval);
65261.1Skamil	}
65271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65281.1Skamil
65291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65311.1Skamil
65321.1Skamil	validate_status_stopped(status, sigval);
65331.1Skamil
65341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65351.1Skamil	    "without signal to be sent\n");
65361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65371.1Skamil
65381.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65391.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
65401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65411.1Skamil
65421.1Skamil	validate_status_stopped(status, SIGTRAP);
65431.1Skamil
65441.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65461.1Skamil
65471.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65491.1Skamil
65501.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
65511.1Skamil	    child, getpid());
65521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
65531.1Skamil
65541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65551.1Skamil	    "without signal to be sent\n");
65561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65571.1Skamil
65581.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
65591.1Skamil	    "SIGINT\n", TWAIT_FNAME);
65601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65611.1Skamil
65621.1Skamil	validate_status_stopped(status, SIGINT);
65631.1Skamil
65641.1Skamil	pl.pl_lwpid = 0;
65651.1Skamil
65661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65671.1Skamil	while (pl.pl_lwpid != 0) {
65681.1Skamil
65691.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65701.1Skamil		switch (pl.pl_lwpid) {
65711.1Skamil		case 1:
65721.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65731.1Skamil			break;
65741.1Skamil		case 2:
65751.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65761.1Skamil			break;
65771.1Skamil		}
65781.1Skamil	}
65791.1Skamil
65801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65811.1Skamil	    "without signal to be sent\n");
65821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65831.1Skamil
65841.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65851.1Skamil	    TWAIT_FNAME);
65861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65871.1Skamil
65881.1Skamil	validate_status_exited(status, exitval);
65891.1Skamil
65901.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65911.1Skamil	    TWAIT_FNAME);
65921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65931.1Skamil}
65941.1Skamil
65951.1SkamilATF_TC(suspend2);
65961.1SkamilATF_TC_HEAD(suspend2, tc)
65971.1Skamil{
65981.1Skamil	atf_tc_set_md_var(tc, "descr",
65991.1Skamil	    "Verify that the while the only thread within a process is "
66001.1Skamil	    "suspended, the whole process cannot be unstopped");
66011.1Skamil}
66021.1Skamil
66031.1SkamilATF_TC_BODY(suspend2, tc)
66041.1Skamil{
66051.1Skamil	const int exitval = 5;
66061.1Skamil	const int sigval = SIGSTOP;
66071.1Skamil	pid_t child, wpid;
66081.1Skamil#if defined(TWAIT_HAVE_STATUS)
66091.1Skamil	int status;
66101.1Skamil#endif
66111.1Skamil	struct ptrace_siginfo psi;
66121.1Skamil
66131.17Skamil	// Feature pending for refactoring
66141.17Skamil	atf_tc_expect_fail("PR kern/51995");
66151.17Skamil
66161.16Skamil	// Hangs with qemu
66171.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66181.16Skamil
66191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66211.1Skamil	if (child == 0) {
66221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66241.1Skamil
66251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66271.1Skamil
66281.13Schristos		DPRINTF("Before exiting of the child process\n");
66291.1Skamil		_exit(exitval);
66301.1Skamil	}
66311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66321.1Skamil
66331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66351.1Skamil
66361.1Skamil	validate_status_stopped(status, sigval);
66371.1Skamil
66381.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66401.1Skamil
66411.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66431.1Skamil
66441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66451.1Skamil	    "without signal to be sent\n");
66461.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
66471.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
66481.1Skamil
66491.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
66501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
66511.1Skamil
66521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66531.1Skamil	    "without signal to be sent\n");
66541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66551.1Skamil
66561.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
66571.1Skamil	    TWAIT_FNAME);
66581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66591.1Skamil
66601.1Skamil	validate_status_exited(status, exitval);
66611.1Skamil
66621.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66631.1Skamil	    TWAIT_FNAME);
66641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66651.1Skamil}
66661.1Skamil
66671.1SkamilATF_TC(resume1);
66681.1SkamilATF_TC_HEAD(resume1, tc)
66691.1Skamil{
66701.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
66711.1Skamil	atf_tc_set_md_var(tc, "descr",
66721.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
66731.1Skamil	    "resumed by the debugger");
66741.1Skamil}
66751.1Skamil
66761.1SkamilATF_TC_BODY(resume1, tc)
66771.1Skamil{
66781.1Skamil	struct msg_fds fds;
66791.1Skamil	const int exitval = 5;
66801.1Skamil	const int sigval = SIGSTOP;
66811.1Skamil	pid_t child, wpid;
66821.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
66831.1Skamil#if defined(TWAIT_HAVE_STATUS)
66841.1Skamil	int status;
66851.1Skamil#endif
66861.1Skamil	ucontext_t uc;
66871.1Skamil	lwpid_t lid;
66881.1Skamil	static const size_t ssize = 16*1024;
66891.1Skamil	void *stack;
66901.1Skamil	struct ptrace_lwpinfo pl;
66911.1Skamil	struct ptrace_siginfo psi;
66921.1Skamil
66931.17Skamil	// Feature pending for refactoring
66941.17Skamil	atf_tc_expect_fail("PR kern/51995");
66951.17Skamil
66961.15Schristos	// Hangs with qemu
66971.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66981.1Skamil
66991.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
67001.1Skamil
67011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67031.1Skamil	if (child == 0) {
67041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67061.1Skamil
67071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67091.1Skamil
67101.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
67111.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
67121.1Skamil
67131.13Schristos		DPRINTF("Before making context for new lwp in child\n");
67141.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
67151.1Skamil
67161.13Schristos		DPRINTF("Before creating new in child\n");
67171.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
67181.1Skamil
67191.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
67201.1Skamil
67211.1Skamil		raise(SIGINT);
67221.1Skamil
67231.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
67241.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
67251.1Skamil
67261.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
67271.1Skamil		    "are the same\n", lid, the_lwp_id);
67281.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
67291.1Skamil
67301.13Schristos		DPRINTF("Before exiting of the child process\n");
67311.1Skamil		_exit(exitval);
67321.1Skamil	}
67331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67341.1Skamil
67351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67371.1Skamil
67381.1Skamil	validate_status_stopped(status, sigval);
67391.1Skamil
67401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67411.1Skamil	    "without signal to be sent\n");
67421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67431.1Skamil
67441.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67451.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
67461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67471.1Skamil
67481.1Skamil	validate_status_stopped(status, SIGTRAP);
67491.1Skamil
67501.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
67511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
67521.1Skamil
67531.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
67541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
67551.1Skamil
67561.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
67571.1Skamil
67581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67591.1Skamil	    "without signal to be sent\n");
67601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67611.1Skamil
67621.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67631.1Skamil	    "SIGINT\n", TWAIT_FNAME);
67641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67651.1Skamil
67661.1Skamil	validate_status_stopped(status, SIGINT);
67671.1Skamil
67681.1Skamil	pl.pl_lwpid = 0;
67691.1Skamil
67701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67711.1Skamil	while (pl.pl_lwpid != 0) {
67721.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67731.1Skamil		switch (pl.pl_lwpid) {
67741.1Skamil		case 1:
67751.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
67761.1Skamil			break;
67771.1Skamil		case 2:
67781.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
67791.1Skamil			break;
67801.1Skamil		}
67811.1Skamil	}
67821.1Skamil
67831.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
67841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
67851.1Skamil
67861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67871.1Skamil	    "without signal to be sent\n");
67881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67891.1Skamil
67901.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
67911.1Skamil	    TWAIT_FNAME);
67921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67931.1Skamil
67941.1Skamil	validate_status_exited(status, exitval);
67951.1Skamil
67961.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
67971.1Skamil	    TWAIT_FNAME);
67981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67991.1Skamil
68001.1Skamil	msg_close(&fds);
68011.1Skamil
68021.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
68031.1Skamil	sleep(10);
68041.1Skamil}
68051.1Skamil
68061.1SkamilATF_TC(syscall1);
68071.1SkamilATF_TC_HEAD(syscall1, tc)
68081.1Skamil{
68091.1Skamil	atf_tc_set_md_var(tc, "descr",
68101.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
68111.1Skamil}
68121.1Skamil
68131.1SkamilATF_TC_BODY(syscall1, tc)
68141.1Skamil{
68151.1Skamil	const int exitval = 5;
68161.1Skamil	const int sigval = SIGSTOP;
68171.1Skamil	pid_t child, wpid;
68181.1Skamil#if defined(TWAIT_HAVE_STATUS)
68191.1Skamil	int status;
68201.1Skamil#endif
68211.1Skamil	struct ptrace_siginfo info;
68221.1Skamil	memset(&info, 0, sizeof(info));
68231.1Skamil
68241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68261.1Skamil	if (child == 0) {
68271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68291.1Skamil
68301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68321.1Skamil
68331.1Skamil		syscall(SYS_getpid);
68341.1Skamil
68351.13Schristos		DPRINTF("Before exiting of the child process\n");
68361.1Skamil		_exit(exitval);
68371.1Skamil	}
68381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68391.1Skamil
68401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68421.1Skamil
68431.1Skamil	validate_status_stopped(status, sigval);
68441.1Skamil
68451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68461.1Skamil	    "without signal to be sent\n");
68471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68481.1Skamil
68491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68511.1Skamil
68521.1Skamil	validate_status_stopped(status, SIGTRAP);
68531.1Skamil
68541.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68561.1Skamil
68571.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68581.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68591.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68601.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
68611.1Skamil
68621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68631.1Skamil	    "without signal to be sent\n");
68641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68651.1Skamil
68661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68681.1Skamil
68691.1Skamil	validate_status_stopped(status, SIGTRAP);
68701.1Skamil
68711.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68731.1Skamil
68741.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68751.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68771.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
68781.1Skamil
68791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68801.1Skamil	    "without signal to be sent\n");
68811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68821.1Skamil
68831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68851.1Skamil
68861.1Skamil	validate_status_exited(status, exitval);
68871.1Skamil
68881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68901.1Skamil}
68911.1Skamil
68921.1SkamilATF_TC(syscallemu1);
68931.1SkamilATF_TC_HEAD(syscallemu1, tc)
68941.1Skamil{
68951.1Skamil	atf_tc_set_md_var(tc, "descr",
68961.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
68971.1Skamil}
68981.1Skamil
68991.1SkamilATF_TC_BODY(syscallemu1, tc)
69001.1Skamil{
69011.1Skamil	const int exitval = 5;
69021.1Skamil	const int sigval = SIGSTOP;
69031.1Skamil	pid_t child, wpid;
69041.1Skamil#if defined(TWAIT_HAVE_STATUS)
69051.1Skamil	int status;
69061.1Skamil#endif
69071.1Skamil
69081.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
69091.6Skamil	/* syscallemu does not work on sparc (32-bit) */
69101.6Skamil	atf_tc_expect_fail("PR kern/52166");
69111.6Skamil#endif
69121.6Skamil
69131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
69141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
69151.1Skamil	if (child == 0) {
69161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
69171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
69181.1Skamil
69191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
69201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
69211.1Skamil
69221.1Skamil		syscall(SYS_exit, 100);
69231.1Skamil
69241.13Schristos		DPRINTF("Before exiting of the child process\n");
69251.1Skamil		_exit(exitval);
69261.1Skamil	}
69271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
69281.1Skamil
69291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69311.1Skamil
69321.1Skamil	validate_status_stopped(status, sigval);
69331.1Skamil
69341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69351.1Skamil	    "without signal to be sent\n");
69361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69371.1Skamil
69381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69401.1Skamil
69411.1Skamil	validate_status_stopped(status, SIGTRAP);
69421.1Skamil
69431.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
69441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
69451.1Skamil
69461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69471.1Skamil	    "without signal to be sent\n");
69481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
69491.1Skamil
69501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69521.1Skamil
69531.1Skamil	validate_status_stopped(status, SIGTRAP);
69541.1Skamil
69551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
69561.1Skamil	    "without signal to be sent\n");
69571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
69581.1Skamil
69591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
69611.1Skamil
69621.1Skamil	validate_status_exited(status, exitval);
69631.1Skamil
69641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69661.1Skamil}
69671.1Skamil
69681.26Skamil#if defined(TWAIT_HAVE_PID)
69691.26SkamilATF_TC(race1);
69701.26SkamilATF_TC_HEAD(race1, tc)
69711.26Skamil{
69721.26Skamil	atf_tc_set_md_var(tc, "descr",
69731.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
69741.26Skamil	    "process and no other error is reported");
69751.26Skamil}
69761.26Skamil
69771.26SkamilATF_TC_BODY(race1, tc)
69781.26Skamil{
69791.26Skamil	time_t start, end;
69801.26Skamil	double diff;
69811.26Skamil	unsigned long N = 0;
69821.26Skamil
69831.26Skamil	/* Reuse this test with attach1 */
69841.26Skamil
69851.26Skamil	start = time(NULL);
69861.26Skamil	while (true) {
69871.26Skamil		DPRINTF("Step: %lu\n", N);
69881.26Skamil		attach1_raw(true);
69891.26Skamil		end = time(NULL);
69901.26Skamil		diff = difftime(end, start);
69911.26Skamil		if (diff >= 5.0)
69921.26Skamil			break;
69931.26Skamil		++N;
69941.26Skamil	}
69951.26Skamil	DPRINTF("Iterations: %lu\n", N);
69961.26Skamil}
69971.26Skamil#endif
69981.26Skamil
69991.1Skamil#include "t_ptrace_amd64_wait.h"
70001.1Skamil#include "t_ptrace_i386_wait.h"
70011.1Skamil#include "t_ptrace_x86_wait.h"
70021.1Skamil
70031.1SkamilATF_TP_ADD_TCS(tp)
70041.1Skamil{
70051.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
70061.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
70071.33Skamil
70081.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
70091.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
70101.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
70111.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
70121.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
70131.33Skamil
70141.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch1);
70151.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch2);
70161.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch3);
70171.34Skamil
70181.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler1);
70191.35Skamil//	ATF_TP_ADD_TC(tp, traceme_signal_nohandler2); // not yet
70201.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler3);
70211.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler4);
70221.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler5);
70231.1Skamil
70241.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
70251.37Skamil
70261.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
70271.40Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_raise2); // not yet
70281.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
70291.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
70301.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
70311.40Skamil
70321.41Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_breakpoint);
70331.41Skamil
70341.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
70351.43Skamil
70361.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
70371.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
70381.1Skamil	ATF_TP_ADD_TC(tp, attach3);
70391.1Skamil	ATF_TP_ADD_TC(tp, attach4);
70401.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
70411.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
70421.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
70431.1Skamil
70441.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
70451.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
70461.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
70471.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
70481.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
70491.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
70501.1Skamil
70511.31Skamil	ATF_TP_ADD_TC(tp, fork1);
70521.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
70531.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
70541.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
70551.31Skamil	ATF_TP_ADD_TC(tp, fork5);
70561.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
70571.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
70581.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
70591.31Skamil
70601.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
70611.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
70621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
70631.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
70641.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
70651.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
70661.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
70671.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
70681.1Skamil
70691.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
70701.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
70711.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
70721.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
70731.1Skamil
70741.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
70751.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
70761.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
70771.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
70781.1Skamil
70791.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
70801.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
70811.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
70821.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
70831.1Skamil
70841.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
70851.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
70861.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
70871.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
70881.1Skamil
70891.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
70901.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
70911.1Skamil
70921.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
70931.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
70941.1Skamil
70951.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
70961.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
70971.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
70981.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
70991.1Skamil
71001.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
71011.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
71021.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
71031.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
71041.1Skamil
71051.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
71061.1Skamil
71071.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
71081.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
71091.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
71101.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
71111.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
71121.1Skamil
71131.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
71141.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
71151.1Skamil
71161.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
71171.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
71181.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
71191.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
71201.1Skamil
71211.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
71221.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
71231.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
71241.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
71251.2Skamil
71261.1Skamil	ATF_TP_ADD_TC(tp, kill1);
71271.1Skamil	ATF_TP_ADD_TC(tp, kill2);
71281.1Skamil
71291.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
71301.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
71311.1Skamil
71321.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
71331.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
71341.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
71351.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
71361.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
71371.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
71381.1Skamil
71391.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
71401.1Skamil
71411.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
71421.1Skamil
71431.1Skamil	ATF_TP_ADD_TC(tp, signal1);
71441.1Skamil	ATF_TP_ADD_TC(tp, signal2);
71451.1Skamil	ATF_TP_ADD_TC(tp, signal3);
71461.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
71471.1Skamil	ATF_TP_ADD_TC(tp, signal5);
71481.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
71491.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
71501.1Skamil	ATF_TP_ADD_TC(tp, signal8);
71511.1Skamil	ATF_TP_ADD_TC(tp, signal9);
71521.1Skamil	ATF_TP_ADD_TC(tp, signal10);
71531.1Skamil
71541.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
71551.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
71561.1Skamil
71571.1Skamil	ATF_TP_ADD_TC(tp, resume1);
71581.1Skamil
71591.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
71601.1Skamil
71611.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
71621.1Skamil
71631.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
71641.26Skamil
71651.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
71661.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
71671.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
71681.1Skamil
71691.1Skamil	return atf_no_error();
71701.1Skamil}
7171