t_ptrace_wait.c revision 1.41
11.41Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.41 2018/05/16 01:27:27 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.41Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.41 2018/05/16 01:27:27 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.40Skamil	    "Verify " #sig " followed by _exit(2) in a vfork(2)ed child");	\
4431.40Skamil}										\
4441.40Skamil										\
4451.40SkamilATF_TC_BODY(test, tc)								\
4461.40Skamil{										\
4471.40Skamil										\
4481.40Skamil	traceme_vfork_raise(sig);						\
4491.40Skamil}
4501.40Skamil
4511.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
4521.40Skamil// TRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ // TODO
4531.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGABRT) /* regular abort trap */
4541.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGHUP)  /* hangup */
4551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGCONT) /* continued? */
4561.40Skamil
4571.40Skamil/// ----------------------------------------------------------------------------
4581.40Skamil
4591.41SkamilATF_TC(traceme_vfork_breakpoint);
4601.41SkamilATF_TC_HEAD(traceme_vfork_breakpoint, tc)
4611.41Skamil{
4621.41Skamil	atf_tc_set_md_var(tc, "descr",
4631.41Skamil	    "Verify software breakpoint in a vfork(2)ed child");
4641.41Skamil}
4651.41Skamil
4661.41SkamilATF_TC_BODY(traceme_vfork_breakpoint, tc)
4671.41Skamil{
4681.41Skamil	pid_t child, wpid;
4691.41Skamil#if defined(TWAIT_HAVE_STATUS)
4701.41Skamil	int status;
4711.41Skamil#endif
4721.41Skamil
4731.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4741.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
4751.41Skamil	if (child == 0) {
4761.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4771.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4781.41Skamil
4791.41Skamil		DPRINTF("Before executing a software breakpoint\n");
4801.41Skamil#ifdef PTRACE_BREAKPOINT_ASM
4811.41Skamil		PTRACE_BREAKPOINT_ASM;
4821.41Skamil#else
4831.41Skamil		/* port me */
4841.41Skamil#endif
4851.41Skamil
4861.41Skamil		/* NOTREACHED */
4871.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4881.41Skamil	}
4891.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4901.41Skamil
4911.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4921.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4931.41Skamil
4941.41Skamil	validate_status_signaled(status, SIGTRAP, 1);
4951.41Skamil
4961.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4971.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4981.41Skamil}
4991.41Skamil
5001.41Skamil/// ----------------------------------------------------------------------------
5011.41Skamil
5021.1Skamil#if defined(TWAIT_HAVE_PID)
5031.1SkamilATF_TC(attach1);
5041.1SkamilATF_TC_HEAD(attach1, tc)
5051.1Skamil{
5061.1Skamil	atf_tc_set_md_var(tc, "descr",
5071.1Skamil	    "Assert that tracer sees process termination before the parent");
5081.1Skamil}
5091.1Skamil
5101.26Skamilstatic void
5111.26Skamilattach1_raw(bool raw)
5121.1Skamil{
5131.1Skamil	struct msg_fds parent_tracee, parent_tracer;
5141.1Skamil	const int exitval_tracee = 5;
5151.1Skamil	const int exitval_tracer = 10;
5161.1Skamil	pid_t tracee, tracer, wpid;
5171.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5181.1Skamil#if defined(TWAIT_HAVE_STATUS)
5191.1Skamil	int status;
5201.1Skamil#endif
5211.1Skamil
5221.13Schristos	DPRINTF("Spawn tracee\n");
5231.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
5241.1Skamil	tracee = atf_utils_fork();
5251.1Skamil	if (tracee == 0) {
5261.1Skamil		// Wait for parent to let us exit
5271.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
5281.1Skamil		_exit(exitval_tracee);
5291.1Skamil	}
5301.1Skamil
5311.13Schristos	DPRINTF("Spawn debugger\n");
5321.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
5331.1Skamil	tracer = atf_utils_fork();
5341.1Skamil	if (tracer == 0) {
5351.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
5361.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
5371.1Skamil
5381.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
5391.1Skamil		FORKEE_REQUIRE_SUCCESS(
5401.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5411.1Skamil
5421.1Skamil		forkee_status_stopped(status, SIGSTOP);
5431.1Skamil
5441.1Skamil		/* Resume tracee with PT_CONTINUE */
5451.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
5461.1Skamil
5471.1Skamil		/* Inform parent that tracer has attached to tracee */
5481.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
5491.1Skamil
5501.1Skamil		/* Wait for parent to tell use that tracee should have exited */
5511.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
5521.1Skamil
5531.1Skamil		/* Wait for tracee and assert that it exited */
5541.1Skamil		FORKEE_REQUIRE_SUCCESS(
5551.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5561.1Skamil
5571.1Skamil		forkee_status_exited(status, exitval_tracee);
5581.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
5591.1Skamil
5601.13Schristos		DPRINTF("Before exiting of the tracer process\n");
5611.1Skamil		_exit(exitval_tracer);
5621.1Skamil	}
5631.1Skamil
5641.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
5651.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
5661.1Skamil
5671.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
5681.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
5691.1Skamil
5701.13Schristos	DPRINTF("Detect that tracee is zombie\n");
5711.26Skamil	if (raw)
5721.26Skamil		await_zombie_raw(tracee, 0);
5731.26Skamil	else
5741.26Skamil		await_zombie(tracee);
5751.1Skamil
5761.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
5771.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
5781.1Skamil	    TWAIT_FNAME);
5791.1Skamil	TWAIT_REQUIRE_SUCCESS(
5801.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
5811.1Skamil
5821.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
5831.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
5841.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
5851.1Skamil	    TWAIT_FNAME);
5861.1Skamil
5871.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
5881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
5891.1Skamil	    tracer);
5901.1Skamil
5911.1Skamil	validate_status_exited(status, exitval_tracer);
5921.1Skamil
5931.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
5941.1Skamil	    TWAIT_FNAME);
5951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
5961.1Skamil	    tracee);
5971.1Skamil
5981.1Skamil	validate_status_exited(status, exitval_tracee);
5991.1Skamil
6001.1Skamil	msg_close(&parent_tracer);
6011.1Skamil	msg_close(&parent_tracee);
6021.1Skamil}
6031.26Skamil
6041.26SkamilATF_TC_BODY(attach1, tc)
6051.26Skamil{
6061.26Skamil
6071.26Skamil	/* Reuse this test with race1 */
6081.26Skamil	attach1_raw(false);
6091.26Skamil}
6101.26Skamil
6111.1Skamil#endif
6121.1Skamil
6131.1Skamil#if defined(TWAIT_HAVE_PID)
6141.1SkamilATF_TC(attach2);
6151.1SkamilATF_TC_HEAD(attach2, tc)
6161.1Skamil{
6171.1Skamil	atf_tc_set_md_var(tc, "descr",
6181.1Skamil	    "Assert that any tracer sees process termination before its "
6191.1Skamil	    "parent");
6201.1Skamil}
6211.1Skamil
6221.1SkamilATF_TC_BODY(attach2, tc)
6231.1Skamil{
6241.1Skamil	struct msg_fds parent_tracer, parent_tracee;
6251.1Skamil	const int exitval_tracee = 5;
6261.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
6271.1Skamil	pid_t tracee, tracer, wpid;
6281.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6291.1Skamil#if defined(TWAIT_HAVE_STATUS)
6301.1Skamil	int status;
6311.1Skamil#endif
6321.1Skamil
6331.13Schristos	DPRINTF("Spawn tracee\n");
6341.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6351.1Skamil	tracee = atf_utils_fork();
6361.1Skamil	if (tracee == 0) {
6371.1Skamil		/* Wait for message from the parent */
6381.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
6391.1Skamil		_exit(exitval_tracee);
6401.1Skamil	}
6411.1Skamil
6421.13Schristos	DPRINTF("Spawn debugger\n");
6431.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
6441.1Skamil	tracer = atf_utils_fork();
6451.1Skamil	if (tracer == 0) {
6461.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
6471.1Skamil		tracer = atf_utils_fork();
6481.1Skamil		if (tracer != 0)
6491.1Skamil			_exit(exitval_tracer1);
6501.1Skamil
6511.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
6521.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
6531.1Skamil
6541.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6551.1Skamil		FORKEE_REQUIRE_SUCCESS(
6561.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6571.1Skamil
6581.1Skamil		forkee_status_stopped(status, SIGSTOP);
6591.1Skamil
6601.1Skamil		/* Resume tracee with PT_CONTINUE */
6611.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6621.1Skamil
6631.1Skamil		/* Inform parent that tracer has attached to tracee */
6641.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
6651.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
6661.1Skamil
6671.1Skamil		/* Wait for tracee and assert that it exited */
6681.1Skamil		FORKEE_REQUIRE_SUCCESS(
6691.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6701.1Skamil
6711.1Skamil		forkee_status_exited(status, exitval_tracee);
6721.1Skamil
6731.13Schristos		DPRINTF("Before exiting of the tracer process\n");
6741.1Skamil		_exit(exitval_tracer2);
6751.1Skamil	}
6761.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
6771.1Skamil	    "%s()\n", TWAIT_FNAME);
6781.1Skamil	TWAIT_REQUIRE_SUCCESS(
6791.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
6801.1Skamil
6811.1Skamil	validate_status_exited(status, exitval_tracer1);
6821.1Skamil
6831.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
6841.1Skamil	    TWAIT_FNAME);
6851.1Skamil	TWAIT_REQUIRE_SUCCESS(
6861.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
6871.1Skamil
6881.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
6891.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
6901.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
6911.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
6921.1Skamil
6931.13Schristos	DPRINTF("Detect that tracee is zombie\n");
6941.1Skamil	await_zombie(tracee);
6951.1Skamil
6961.13Schristos	DPRINTF("Assert that there is no status about tracee - "
6971.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
6981.1Skamil	TWAIT_REQUIRE_SUCCESS(
6991.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
7001.1Skamil
7011.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
7021.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
7031.1Skamil
7041.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7051.1Skamil	    TWAIT_FNAME);
7061.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
7071.1Skamil	    tracee);
7081.1Skamil
7091.1Skamil	validate_status_exited(status, exitval_tracee);
7101.1Skamil
7111.1Skamil	msg_close(&parent_tracer);
7121.1Skamil	msg_close(&parent_tracee);
7131.1Skamil}
7141.1Skamil#endif
7151.1Skamil
7161.1SkamilATF_TC(attach3);
7171.1SkamilATF_TC_HEAD(attach3, tc)
7181.1Skamil{
7191.1Skamil	atf_tc_set_md_var(tc, "descr",
7201.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
7211.1Skamil}
7221.1Skamil
7231.1SkamilATF_TC_BODY(attach3, tc)
7241.1Skamil{
7251.1Skamil	struct msg_fds parent_tracee;
7261.1Skamil	const int exitval_tracee = 5;
7271.1Skamil	pid_t tracee, wpid;
7281.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7291.1Skamil#if defined(TWAIT_HAVE_STATUS)
7301.1Skamil	int status;
7311.1Skamil#endif
7321.1Skamil
7331.13Schristos	DPRINTF("Spawn tracee\n");
7341.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7351.1Skamil	tracee = atf_utils_fork();
7361.1Skamil	if (tracee == 0) {
7371.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7381.13Schristos		DPRINTF("Parent should now attach to tracee\n");
7391.1Skamil
7401.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
7411.1Skamil		/* Wait for message from the parent */
7421.1Skamil		_exit(exitval_tracee);
7431.1Skamil	}
7441.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
7451.1Skamil
7461.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
7471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
7481.1Skamil
7491.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
7501.1Skamil	    TWAIT_FNAME);
7511.1Skamil	TWAIT_REQUIRE_SUCCESS(
7521.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7531.1Skamil
7541.1Skamil	validate_status_stopped(status, SIGSTOP);
7551.1Skamil
7561.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
7571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
7581.1Skamil
7591.13Schristos	DPRINTF("Let the tracee exit now\n");
7601.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
7611.1Skamil
7621.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
7631.1Skamil	TWAIT_REQUIRE_SUCCESS(
7641.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7651.1Skamil
7661.1Skamil	validate_status_exited(status, exitval_tracee);
7671.1Skamil
7681.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
7691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
7701.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
7711.1Skamil
7721.1Skamil	msg_close(&parent_tracee);
7731.1Skamil}
7741.1Skamil
7751.1SkamilATF_TC(attach4);
7761.1SkamilATF_TC_HEAD(attach4, tc)
7771.1Skamil{
7781.1Skamil	atf_tc_set_md_var(tc, "descr",
7791.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
7801.1Skamil}
7811.1Skamil
7821.1SkamilATF_TC_BODY(attach4, tc)
7831.1Skamil{
7841.1Skamil	struct msg_fds parent_tracee;
7851.1Skamil	const int exitval_tracer = 5;
7861.1Skamil	pid_t tracer, wpid;
7871.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7881.1Skamil#if defined(TWAIT_HAVE_STATUS)
7891.1Skamil	int status;
7901.1Skamil#endif
7911.1Skamil
7921.13Schristos	DPRINTF("Spawn tracer\n");
7931.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7941.1Skamil	tracer = atf_utils_fork();
7951.1Skamil	if (tracer == 0) {
7961.1Skamil
7971.1Skamil		/* Wait for message from the parent */
7981.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7991.1Skamil
8001.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
8011.1Skamil		    getppid());
8021.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
8031.1Skamil
8041.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
8051.1Skamil		    TWAIT_FNAME);
8061.1Skamil		FORKEE_REQUIRE_SUCCESS(
8071.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
8081.1Skamil
8091.1Skamil		forkee_status_stopped(status, SIGSTOP);
8101.1Skamil
8111.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
8121.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
8131.1Skamil		    != -1);
8141.1Skamil
8151.1Skamil		/* Tell parent we are ready */
8161.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
8171.1Skamil
8181.1Skamil		_exit(exitval_tracer);
8191.1Skamil	}
8201.1Skamil
8211.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
8221.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8231.13Schristos	DPRINTF("Allow the tracer to exit now\n");
8241.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
8251.1Skamil
8261.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
8271.1Skamil	TWAIT_REQUIRE_SUCCESS(
8281.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
8291.1Skamil
8301.1Skamil	validate_status_exited(status, exitval_tracer);
8311.1Skamil
8321.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
8331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8341.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
8351.1Skamil
8361.1Skamil	msg_close(&parent_tracee);
8371.1Skamil}
8381.1Skamil
8391.1Skamil#if defined(TWAIT_HAVE_PID)
8401.1SkamilATF_TC(attach5);
8411.1SkamilATF_TC_HEAD(attach5, tc)
8421.1Skamil{
8431.1Skamil	atf_tc_set_md_var(tc, "descr",
8441.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
8451.1Skamil	    "(check getppid(2))");
8461.1Skamil}
8471.1Skamil
8481.1SkamilATF_TC_BODY(attach5, tc)
8491.1Skamil{
8501.1Skamil	struct msg_fds parent_tracer, parent_tracee;
8511.1Skamil	const int exitval_tracee = 5;
8521.1Skamil	const int exitval_tracer = 10;
8531.1Skamil	pid_t parent, tracee, tracer, wpid;
8541.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8551.1Skamil#if defined(TWAIT_HAVE_STATUS)
8561.1Skamil	int status;
8571.1Skamil#endif
8581.1Skamil
8591.13Schristos	DPRINTF("Spawn tracee\n");
8601.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
8611.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
8621.1Skamil	tracee = atf_utils_fork();
8631.1Skamil	if (tracee == 0) {
8641.1Skamil		parent = getppid();
8651.1Skamil
8661.1Skamil		/* Emit message to the parent */
8671.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
8681.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
8691.1Skamil
8701.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
8711.1Skamil
8721.1Skamil		_exit(exitval_tracee);
8731.1Skamil	}
8741.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
8751.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
8761.1Skamil
8771.13Schristos	DPRINTF("Spawn debugger\n");
8781.1Skamil	tracer = atf_utils_fork();
8791.1Skamil	if (tracer == 0) {
8801.1Skamil		/* No IPC to communicate with the child */
8811.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
8821.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8831.1Skamil
8841.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
8851.1Skamil		FORKEE_REQUIRE_SUCCESS(
8861.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8871.1Skamil
8881.1Skamil		forkee_status_stopped(status, SIGSTOP);
8891.1Skamil
8901.1Skamil		/* Resume tracee with PT_CONTINUE */
8911.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8921.1Skamil
8931.1Skamil		/* Inform parent that tracer has attached to tracee */
8941.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
8951.1Skamil
8961.1Skamil		/* Wait for parent to tell use that tracee should have exited */
8971.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
8981.1Skamil
8991.1Skamil		/* Wait for tracee and assert that it exited */
9001.1Skamil		FORKEE_REQUIRE_SUCCESS(
9011.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9021.1Skamil
9031.1Skamil		forkee_status_exited(status, exitval_tracee);
9041.1Skamil
9051.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9061.1Skamil		_exit(exitval_tracer);
9071.1Skamil	}
9081.1Skamil
9091.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9101.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
9111.1Skamil
9121.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9131.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
9141.1Skamil
9151.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9161.1Skamil	await_zombie(tracee);
9171.1Skamil
9181.13Schristos	DPRINTF("Assert that there is no status about tracee - "
9191.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
9201.1Skamil	TWAIT_REQUIRE_SUCCESS(
9211.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9221.1Skamil
9231.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
9241.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
9251.1Skamil
9261.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
9271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9281.1Skamil	    tracer);
9291.1Skamil
9301.1Skamil	validate_status_exited(status, exitval_tracer);
9311.1Skamil
9321.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
9331.1Skamil	    TWAIT_FNAME);
9341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
9351.1Skamil	    tracee);
9361.1Skamil
9371.1Skamil	validate_status_exited(status, exitval_tracee);
9381.1Skamil
9391.1Skamil	msg_close(&parent_tracer);
9401.1Skamil	msg_close(&parent_tracee);
9411.1Skamil}
9421.1Skamil#endif
9431.1Skamil
9441.1Skamil#if defined(TWAIT_HAVE_PID)
9451.1SkamilATF_TC(attach6);
9461.1SkamilATF_TC_HEAD(attach6, tc)
9471.1Skamil{
9481.1Skamil	atf_tc_set_md_var(tc, "descr",
9491.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
9501.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
9511.1Skamil}
9521.1Skamil
9531.1SkamilATF_TC_BODY(attach6, tc)
9541.1Skamil{
9551.1Skamil	struct msg_fds parent_tracee, parent_tracer;
9561.1Skamil	const int exitval_tracee = 5;
9571.1Skamil	const int exitval_tracer = 10;
9581.1Skamil	pid_t parent, tracee, tracer, wpid;
9591.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9601.1Skamil#if defined(TWAIT_HAVE_STATUS)
9611.1Skamil	int status;
9621.1Skamil#endif
9631.1Skamil	int name[CTL_MAXNAME];
9641.1Skamil	struct kinfo_proc2 kp;
9651.1Skamil	size_t len = sizeof(kp);
9661.1Skamil	unsigned int namelen;
9671.1Skamil
9681.13Schristos	DPRINTF("Spawn tracee\n");
9691.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9701.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9711.1Skamil	tracee = atf_utils_fork();
9721.1Skamil	if (tracee == 0) {
9731.1Skamil		parent = getppid();
9741.1Skamil
9751.1Skamil		/* Emit message to the parent */
9761.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
9771.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
9781.1Skamil
9791.1Skamil		namelen = 0;
9801.1Skamil		name[namelen++] = CTL_KERN;
9811.1Skamil		name[namelen++] = KERN_PROC2;
9821.1Skamil		name[namelen++] = KERN_PROC_PID;
9831.1Skamil		name[namelen++] = getpid();
9841.1Skamil		name[namelen++] = len;
9851.1Skamil		name[namelen++] = 1;
9861.1Skamil
9871.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
9881.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
9891.1Skamil
9901.1Skamil		_exit(exitval_tracee);
9911.1Skamil	}
9921.1Skamil
9931.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9941.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
9951.1Skamil
9961.13Schristos	DPRINTF("Spawn debugger\n");
9971.1Skamil	tracer = atf_utils_fork();
9981.1Skamil	if (tracer == 0) {
9991.1Skamil		/* No IPC to communicate with the child */
10001.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10011.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10021.1Skamil
10031.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10041.1Skamil		FORKEE_REQUIRE_SUCCESS(
10051.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10061.1Skamil
10071.1Skamil		forkee_status_stopped(status, SIGSTOP);
10081.1Skamil
10091.1Skamil		/* Resume tracee with PT_CONTINUE */
10101.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10111.1Skamil
10121.1Skamil		/* Inform parent that tracer has attached to tracee */
10131.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
10141.1Skamil
10151.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
10161.1Skamil
10171.1Skamil		/* Wait for tracee and assert that it exited */
10181.1Skamil		FORKEE_REQUIRE_SUCCESS(
10191.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10201.1Skamil
10211.1Skamil		forkee_status_exited(status, exitval_tracee);
10221.1Skamil
10231.13Schristos		DPRINTF("Before exiting of the tracer process\n");
10241.1Skamil		_exit(exitval_tracer);
10251.1Skamil	}
10261.1Skamil
10271.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
10281.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
10291.1Skamil
10301.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
10311.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
10321.1Skamil
10331.13Schristos	DPRINTF("Detect that tracee is zombie\n");
10341.1Skamil	await_zombie(tracee);
10351.1Skamil
10361.13Schristos	DPRINTF("Assert that there is no status about tracee - "
10371.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
10381.1Skamil	TWAIT_REQUIRE_SUCCESS(
10391.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
10401.1Skamil
10411.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
10421.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
10431.1Skamil
10441.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
10451.1Skamil	    TWAIT_FNAME);
10461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
10471.1Skamil	    tracer);
10481.1Skamil
10491.1Skamil	validate_status_exited(status, exitval_tracer);
10501.1Skamil
10511.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
10521.1Skamil	    TWAIT_FNAME);
10531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
10541.1Skamil	    tracee);
10551.1Skamil
10561.1Skamil	validate_status_exited(status, exitval_tracee);
10571.1Skamil
10581.1Skamil	msg_close(&parent_tracee);
10591.1Skamil	msg_close(&parent_tracer);
10601.1Skamil}
10611.1Skamil#endif
10621.1Skamil
10631.1Skamil#if defined(TWAIT_HAVE_PID)
10641.1SkamilATF_TC(attach7);
10651.1SkamilATF_TC_HEAD(attach7, tc)
10661.1Skamil{
10671.1Skamil	atf_tc_set_md_var(tc, "descr",
10681.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
10691.1Skamil	    "(check /proc/curproc/status 3rd column)");
10701.1Skamil}
10711.1Skamil
10721.1SkamilATF_TC_BODY(attach7, tc)
10731.1Skamil{
10741.1Skamil	struct msg_fds parent_tracee, parent_tracer;
10751.1Skamil	int rv;
10761.1Skamil	const int exitval_tracee = 5;
10771.1Skamil	const int exitval_tracer = 10;
10781.1Skamil	pid_t parent, tracee, tracer, wpid;
10791.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10801.1Skamil#if defined(TWAIT_HAVE_STATUS)
10811.1Skamil	int status;
10821.1Skamil#endif
10831.1Skamil	FILE *fp;
10841.1Skamil	struct stat st;
10851.1Skamil	const char *fname = "/proc/curproc/status";
10861.1Skamil	char s_executable[MAXPATHLEN];
10871.1Skamil	int s_pid, s_ppid;
10881.1Skamil	/*
10891.1Skamil	 * Format:
10901.1Skamil	 *  EXECUTABLE PID PPID ...
10911.1Skamil	 */
10921.1Skamil
10931.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
10941.1Skamil	if (rv != 0) {
10951.1Skamil		atf_tc_skip("/proc/curproc/status not found");
10961.1Skamil	}
10971.1Skamil
10981.13Schristos	DPRINTF("Spawn tracee\n");
10991.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11011.1Skamil	tracee = atf_utils_fork();
11021.1Skamil	if (tracee == 0) {
11031.1Skamil		parent = getppid();
11041.1Skamil
11051.1Skamil		// Wait for parent to let us exit
11061.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
11071.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
11081.1Skamil
11091.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
11101.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
11111.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
11121.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
11131.1Skamil
11141.1Skamil		_exit(exitval_tracee);
11151.1Skamil	}
11161.1Skamil
11171.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
11181.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
11191.1Skamil
11201.13Schristos	DPRINTF("Spawn debugger\n");
11211.1Skamil	tracer = atf_utils_fork();
11221.1Skamil	if (tracer == 0) {
11231.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11241.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11251.1Skamil
11261.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11271.1Skamil		FORKEE_REQUIRE_SUCCESS(
11281.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11291.1Skamil
11301.1Skamil		forkee_status_stopped(status, SIGSTOP);
11311.1Skamil
11321.1Skamil		/* Resume tracee with PT_CONTINUE */
11331.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11341.1Skamil
11351.1Skamil		/* Inform parent that tracer has attached to tracee */
11361.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
11371.1Skamil
11381.1Skamil		/* Wait for parent to tell use that tracee should have exited */
11391.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
11401.1Skamil
11411.1Skamil		/* Wait for tracee and assert that it exited */
11421.1Skamil		FORKEE_REQUIRE_SUCCESS(
11431.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11441.1Skamil
11451.1Skamil		forkee_status_exited(status, exitval_tracee);
11461.1Skamil
11471.13Schristos		DPRINTF("Before exiting of the tracer process\n");
11481.1Skamil		_exit(exitval_tracer);
11491.1Skamil	}
11501.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
11511.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11521.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
11531.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
11541.1Skamil
11551.13Schristos	DPRINTF("Detect that tracee is zombie\n");
11561.1Skamil	await_zombie(tracee);
11571.1Skamil
11581.13Schristos	DPRINTF("Assert that there is no status about tracee - "
11591.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
11601.1Skamil	TWAIT_REQUIRE_SUCCESS(
11611.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
11621.1Skamil
11631.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
11641.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11651.1Skamil
11661.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
11671.1Skamil	    TWAIT_FNAME);
11681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
11691.1Skamil	    tracer);
11701.1Skamil
11711.1Skamil	validate_status_exited(status, exitval_tracer);
11721.1Skamil
11731.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11741.1Skamil	    TWAIT_FNAME);
11751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
11761.1Skamil	    tracee);
11771.1Skamil
11781.1Skamil	validate_status_exited(status, exitval_tracee);
11791.1Skamil
11801.1Skamil	msg_close(&parent_tracee);
11811.1Skamil	msg_close(&parent_tracer);
11821.1Skamil}
11831.1Skamil#endif
11841.1Skamil
11851.1SkamilATF_TC(eventmask1);
11861.1SkamilATF_TC_HEAD(eventmask1, tc)
11871.1Skamil{
11881.1Skamil	atf_tc_set_md_var(tc, "descr",
11891.1Skamil	    "Verify that empty EVENT_MASK is preserved");
11901.1Skamil}
11911.1Skamil
11921.1SkamilATF_TC_BODY(eventmask1, tc)
11931.1Skamil{
11941.1Skamil	const int exitval = 5;
11951.1Skamil	const int sigval = SIGSTOP;
11961.1Skamil	pid_t child, wpid;
11971.1Skamil#if defined(TWAIT_HAVE_STATUS)
11981.1Skamil	int status;
11991.1Skamil#endif
12001.1Skamil	ptrace_event_t set_event, get_event;
12011.1Skamil	const int len = sizeof(ptrace_event_t);
12021.1Skamil
12031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12051.1Skamil	if (child == 0) {
12061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12081.1Skamil
12091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12111.1Skamil
12121.13Schristos		DPRINTF("Before exiting of the child process\n");
12131.1Skamil		_exit(exitval);
12141.1Skamil	}
12151.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12161.1Skamil
12171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12191.1Skamil
12201.1Skamil	validate_status_stopped(status, sigval);
12211.1Skamil
12221.1Skamil	set_event.pe_set_event = 0;
12231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12251.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12261.1Skamil
12271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12281.1Skamil	    "without signal to be sent\n");
12291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12301.1Skamil
12311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12331.1Skamil
12341.1Skamil	validate_status_exited(status, exitval);
12351.1Skamil
12361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12381.1Skamil}
12391.1Skamil
12401.1SkamilATF_TC(eventmask2);
12411.1SkamilATF_TC_HEAD(eventmask2, tc)
12421.1Skamil{
12431.1Skamil	atf_tc_set_md_var(tc, "descr",
12441.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
12451.1Skamil}
12461.1Skamil
12471.1SkamilATF_TC_BODY(eventmask2, tc)
12481.1Skamil{
12491.1Skamil	const int exitval = 5;
12501.1Skamil	const int sigval = SIGSTOP;
12511.1Skamil	pid_t child, wpid;
12521.1Skamil#if defined(TWAIT_HAVE_STATUS)
12531.1Skamil	int status;
12541.1Skamil#endif
12551.1Skamil	ptrace_event_t set_event, get_event;
12561.1Skamil	const int len = sizeof(ptrace_event_t);
12571.1Skamil
12581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12601.1Skamil	if (child == 0) {
12611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12631.1Skamil
12641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12661.1Skamil
12671.13Schristos		DPRINTF("Before exiting of the child process\n");
12681.1Skamil		_exit(exitval);
12691.1Skamil	}
12701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12711.1Skamil
12721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12741.1Skamil
12751.1Skamil	validate_status_stopped(status, sigval);
12761.1Skamil
12771.1Skamil	set_event.pe_set_event = PTRACE_FORK;
12781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12801.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12811.1Skamil
12821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12831.1Skamil	    "without signal to be sent\n");
12841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12851.1Skamil
12861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12881.1Skamil
12891.1Skamil	validate_status_exited(status, exitval);
12901.1Skamil
12911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12931.1Skamil}
12941.1Skamil
12951.1SkamilATF_TC(eventmask3);
12961.1SkamilATF_TC_HEAD(eventmask3, tc)
12971.1Skamil{
12981.1Skamil	atf_tc_set_md_var(tc, "descr",
12991.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
13001.1Skamil}
13011.1Skamil
13021.1SkamilATF_TC_BODY(eventmask3, tc)
13031.1Skamil{
13041.1Skamil	const int exitval = 5;
13051.1Skamil	const int sigval = SIGSTOP;
13061.1Skamil	pid_t child, wpid;
13071.1Skamil#if defined(TWAIT_HAVE_STATUS)
13081.1Skamil	int status;
13091.1Skamil#endif
13101.1Skamil	ptrace_event_t set_event, get_event;
13111.1Skamil	const int len = sizeof(ptrace_event_t);
13121.1Skamil
13131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13151.1Skamil	if (child == 0) {
13161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13181.1Skamil
13191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13211.1Skamil
13221.13Schristos		DPRINTF("Before exiting of the child process\n");
13231.1Skamil		_exit(exitval);
13241.1Skamil	}
13251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13261.1Skamil
13271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13291.1Skamil
13301.1Skamil	validate_status_stopped(status, sigval);
13311.1Skamil
13321.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
13331.38Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13351.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13361.1Skamil
13371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13381.1Skamil	    "without signal to be sent\n");
13391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13401.1Skamil
13411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13431.1Skamil
13441.1Skamil	validate_status_exited(status, exitval);
13451.1Skamil
13461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13481.1Skamil}
13491.1Skamil
13501.1SkamilATF_TC(eventmask4);
13511.1SkamilATF_TC_HEAD(eventmask4, tc)
13521.1Skamil{
13531.1Skamil	atf_tc_set_md_var(tc, "descr",
13541.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
13551.1Skamil}
13561.1Skamil
13571.1SkamilATF_TC_BODY(eventmask4, tc)
13581.1Skamil{
13591.1Skamil	const int exitval = 5;
13601.1Skamil	const int sigval = SIGSTOP;
13611.1Skamil	pid_t child, wpid;
13621.1Skamil#if defined(TWAIT_HAVE_STATUS)
13631.1Skamil	int status;
13641.1Skamil#endif
13651.1Skamil	ptrace_event_t set_event, get_event;
13661.1Skamil	const int len = sizeof(ptrace_event_t);
13671.1Skamil
13681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13701.1Skamil	if (child == 0) {
13711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13731.1Skamil
13741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13761.1Skamil
13771.13Schristos		DPRINTF("Before exiting of the child process\n");
13781.1Skamil		_exit(exitval);
13791.1Skamil	}
13801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13811.1Skamil
13821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13841.1Skamil
13851.1Skamil	validate_status_stopped(status, sigval);
13861.1Skamil
13871.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
13881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13901.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13911.1Skamil
13921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13931.1Skamil	    "without signal to be sent\n");
13941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13951.1Skamil
13961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13981.1Skamil
13991.1Skamil	validate_status_exited(status, exitval);
14001.1Skamil
14011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14031.1Skamil}
14041.1Skamil
14051.1SkamilATF_TC(eventmask5);
14061.1SkamilATF_TC_HEAD(eventmask5, tc)
14071.1Skamil{
14081.1Skamil	atf_tc_set_md_var(tc, "descr",
14091.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
14101.1Skamil}
14111.1Skamil
14121.1SkamilATF_TC_BODY(eventmask5, tc)
14131.1Skamil{
14141.1Skamil	const int exitval = 5;
14151.1Skamil	const int sigval = SIGSTOP;
14161.1Skamil	pid_t child, wpid;
14171.1Skamil#if defined(TWAIT_HAVE_STATUS)
14181.1Skamil	int status;
14191.1Skamil#endif
14201.1Skamil	ptrace_event_t set_event, get_event;
14211.1Skamil	const int len = sizeof(ptrace_event_t);
14221.1Skamil
14231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14251.1Skamil	if (child == 0) {
14261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14281.1Skamil
14291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14311.1Skamil
14321.13Schristos		DPRINTF("Before exiting of the child process\n");
14331.1Skamil		_exit(exitval);
14341.1Skamil	}
14351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14361.1Skamil
14371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14391.1Skamil
14401.1Skamil	validate_status_stopped(status, sigval);
14411.1Skamil
14421.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
14431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14451.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14461.1Skamil
14471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14481.1Skamil	    "without signal to be sent\n");
14491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14501.1Skamil
14511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14531.1Skamil
14541.1Skamil	validate_status_exited(status, exitval);
14551.1Skamil
14561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14581.1Skamil}
14591.1Skamil
14601.1SkamilATF_TC(eventmask6);
14611.1SkamilATF_TC_HEAD(eventmask6, tc)
14621.1Skamil{
14631.1Skamil	atf_tc_set_md_var(tc, "descr",
14641.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
14651.1Skamil}
14661.1Skamil
14671.1SkamilATF_TC_BODY(eventmask6, tc)
14681.1Skamil{
14691.1Skamil	const int exitval = 5;
14701.1Skamil	const int sigval = SIGSTOP;
14711.1Skamil	pid_t child, wpid;
14721.1Skamil#if defined(TWAIT_HAVE_STATUS)
14731.1Skamil	int status;
14741.1Skamil#endif
14751.1Skamil	ptrace_event_t set_event, get_event;
14761.1Skamil	const int len = sizeof(ptrace_event_t);
14771.1Skamil
14781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14801.1Skamil	if (child == 0) {
14811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14831.1Skamil
14841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14861.1Skamil
14871.13Schristos		DPRINTF("Before exiting of the child process\n");
14881.1Skamil		_exit(exitval);
14891.1Skamil	}
14901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14911.1Skamil
14921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14941.1Skamil
14951.1Skamil	validate_status_stopped(status, sigval);
14961.1Skamil
14971.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
14981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15001.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15011.1Skamil
15021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15031.1Skamil	    "without signal to be sent\n");
15041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15051.1Skamil
15061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15081.1Skamil
15091.1Skamil	validate_status_exited(status, exitval);
15101.1Skamil
15111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15131.1Skamil}
15141.1Skamil
15151.28Skamilstatic void
15161.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
15171.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
15181.1Skamil{
15191.1Skamil	const int exitval = 5;
15201.1Skamil	const int exitval2 = 15;
15211.1Skamil	const int sigval = SIGSTOP;
15221.31Skamil	pid_t child, child2 = 0, wpid;
15231.1Skamil#if defined(TWAIT_HAVE_STATUS)
15241.1Skamil	int status;
15251.1Skamil#endif
15261.1Skamil	ptrace_state_t state;
15271.1Skamil	const int slen = sizeof(state);
15281.1Skamil	ptrace_event_t event;
15291.1Skamil	const int elen = sizeof(event);
15301.1Skamil
15311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15331.1Skamil	if (child == 0) {
15341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15361.1Skamil
15371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15391.1Skamil
15401.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
15411.1Skamil
15421.1Skamil		if (child2 == 0)
15431.1Skamil			_exit(exitval2);
15441.1Skamil
15451.1Skamil		FORKEE_REQUIRE_SUCCESS
15461.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
15471.1Skamil
15481.1Skamil		forkee_status_exited(status, exitval2);
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.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
15611.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
15621.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
15631.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
15641.30Skamil	event.pe_set_event = 0;
15651.30Skamil	if (trackfork)
15661.30Skamil		event.pe_set_event |= PTRACE_FORK;
15671.30Skamil	if (trackvfork)
15681.30Skamil		event.pe_set_event |= PTRACE_VFORK;
15691.30Skamil	if (trackvforkdone)
15701.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
15711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
15721.1Skamil
15731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15741.1Skamil	    "without signal to be sent\n");
15751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15761.1Skamil
15771.29Skamil#if defined(TWAIT_HAVE_PID)
15781.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
15791.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
15801.29Skamil		        child);
15811.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
15821.29Skamil		                      child);
15831.1Skamil
15841.29Skamil		validate_status_stopped(status, SIGTRAP);
15851.1Skamil
15861.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
15871.29Skamil		                       slen) != -1);
15881.31Skamil		if (trackfork && fn == fork) {
15891.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
15901.30Skamil			       PTRACE_FORK);
15911.30Skamil		}
15921.31Skamil		if (trackvfork && fn == vfork) {
15931.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
15941.30Skamil			       PTRACE_VFORK);
15951.30Skamil		}
15961.29Skamil
15971.29Skamil		child2 = state.pe_other_pid;
15981.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
15991.29Skamil
16001.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
16011.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
16021.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16031.29Skamil		    child2);
16041.1Skamil
16051.29Skamil		validate_status_stopped(status, SIGTRAP);
16061.1Skamil
16071.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
16081.29Skamil		                       slen) != -1);
16091.31Skamil		if (trackfork && fn == fork) {
16101.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16111.30Skamil			       PTRACE_FORK);
16121.30Skamil		}
16131.31Skamil		if (trackvfork && fn == vfork) {
16141.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16151.30Skamil			       PTRACE_VFORK);
16161.30Skamil		}
16171.30Skamil
16181.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
16191.29Skamil
16201.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
16211.29Skamil		    "and without signal to be sent\n");
16221.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
16231.29Skamil		                != -1);
16241.29Skamil
16251.29Skamil		DPRINTF("Before resuming the child process where it left off "
16261.29Skamil		        "and without signal to be sent\n");
16271.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16281.30Skamil	}
16291.30Skamil#endif
16301.30Skamil
16311.31Skamil	if (trackvforkdone && fn == vfork) {
16321.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16331.30Skamil		        child);
16341.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16351.30Skamil		                      child);
16361.30Skamil
16371.30Skamil		validate_status_stopped(status, SIGTRAP);
16381.30Skamil
16391.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
16401.30Skamil		                       slen) != -1);
16411.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
16421.30Skamil
16431.30Skamil		child2 = state.pe_other_pid;
16441.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
16451.30Skamil		        child2);
16461.30Skamil
16471.30Skamil		DPRINTF("Before resuming the child process where it left off "
16481.30Skamil		        "and without signal to be sent\n");
16491.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16501.30Skamil	}
16511.29Skamil
16521.30Skamil#if defined(TWAIT_HAVE_PID)
16531.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
16541.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
16551.29Skamil		        "\n", TWAIT_FNAME);
16561.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16571.29Skamil		    child2);
16581.29Skamil
16591.29Skamil		validate_status_exited(status, exitval2);
16601.29Skamil
16611.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
16621.29Skamil		        "process\n", TWAIT_FNAME);
16631.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
16641.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
16651.29Skamil	}
16661.29Skamil#endif
16671.1Skamil
16681.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
16691.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
16701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16711.1Skamil
16721.1Skamil	validate_status_stopped(status, SIGCHLD);
16731.1Skamil
16741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16751.1Skamil	    "without signal to be sent\n");
16761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16771.1Skamil
16781.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
16791.1Skamil	    TWAIT_FNAME);
16801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16811.1Skamil
16821.1Skamil	validate_status_exited(status, exitval);
16831.1Skamil
16841.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
16851.1Skamil	    TWAIT_FNAME);
16861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16871.1Skamil}
16881.28Skamil
16891.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
16901.32SkamilATF_TC(name);									\
16911.32SkamilATF_TC_HEAD(name, tc)								\
16921.32Skamil{										\
16931.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
16941.32Skamil}										\
16951.32Skamil										\
16961.32SkamilATF_TC_BODY(name, tc)								\
16971.32Skamil{										\
16981.32Skamil										\
16991.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
17001.32Skamil}
17011.32Skamil
17021.32Skamil#define F false
17031.32Skamil#define T true
17041.32Skamil
17051.32Skamil#define F_IF__0(x)
17061.32Skamil#define F_IF__1(x) x
17071.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
17081.32Skamil#define F_IF_(x,y) F_IF__(x,y)
17091.32Skamil#define F_IF(x,y) F_IF_(x,y)
17101.32Skamil
17111.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
17121.32Skamil        "Verify " #function "(2) called with 0"					\
17131.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
17141.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
17151.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
17161.32Skamil        " in EVENT_MASK."							\
17171.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
17181.32Skamil        F_IF(dparentbit," Detach parent in this test.")
17191.1Skamil
17201.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
17211.31Skamil#if defined(TWAIT_HAVE_PID)
17221.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
17231.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
17241.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
17251.31Skamil#endif
17261.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
17271.31Skamil#if defined(TWAIT_HAVE_PID)
17281.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
17291.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
17301.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
17311.31Skamil#endif
17321.1Skamil
17331.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
17341.31Skamil#if defined(TWAIT_HAVE_PID)
17351.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
17361.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
17371.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
17381.31Skamil#endif
17391.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
17401.31Skamil#if defined(TWAIT_HAVE_PID)
17411.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
17421.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
17431.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
17441.31Skamil#endif
17451.31Skamil
17461.31Skamil
17471.31Skamil
17481.1Skamil
17491.1SkamilATF_TC(io_read_d1);
17501.1SkamilATF_TC_HEAD(io_read_d1, tc)
17511.1Skamil{
17521.1Skamil	atf_tc_set_md_var(tc, "descr",
17531.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
17541.1Skamil}
17551.1Skamil
17561.1SkamilATF_TC_BODY(io_read_d1, tc)
17571.1Skamil{
17581.1Skamil	const int exitval = 5;
17591.1Skamil	const int sigval = SIGSTOP;
17601.1Skamil	pid_t child, wpid;
17611.1Skamil	uint8_t lookup_me = 0;
17621.1Skamil	const uint8_t magic = 0xab;
17631.1Skamil	struct ptrace_io_desc io = {
17641.1Skamil		.piod_op = PIOD_READ_D,
17651.1Skamil		.piod_offs = &lookup_me,
17661.1Skamil		.piod_addr = &lookup_me,
17671.1Skamil		.piod_len = sizeof(lookup_me)
17681.1Skamil	};
17691.1Skamil#if defined(TWAIT_HAVE_STATUS)
17701.1Skamil	int status;
17711.1Skamil#endif
17721.1Skamil
17731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
17741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
17751.1Skamil	if (child == 0) {
17761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17781.1Skamil
17791.1Skamil		lookup_me = magic;
17801.1Skamil
17811.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
17821.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
17831.1Skamil
17841.13Schristos		DPRINTF("Before exiting of the child process\n");
17851.1Skamil		_exit(exitval);
17861.1Skamil	}
17871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17881.1Skamil
17891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17911.1Skamil
17921.1Skamil	validate_status_stopped(status, sigval);
17931.1Skamil
17941.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
17951.1Skamil	    child, getpid());
17961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
17971.1Skamil
17981.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
17991.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
18001.1Skamil
18011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18021.1Skamil	    "without signal to be sent\n");
18031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18041.1Skamil
18051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18071.1Skamil
18081.1Skamil	validate_status_exited(status, exitval);
18091.1Skamil
18101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18121.1Skamil}
18131.1Skamil
18141.1SkamilATF_TC(io_read_d2);
18151.1SkamilATF_TC_HEAD(io_read_d2, tc)
18161.1Skamil{
18171.1Skamil	atf_tc_set_md_var(tc, "descr",
18181.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
18191.1Skamil}
18201.1Skamil
18211.1SkamilATF_TC_BODY(io_read_d2, tc)
18221.1Skamil{
18231.1Skamil	const int exitval = 5;
18241.1Skamil	const int sigval = SIGSTOP;
18251.1Skamil	pid_t child, wpid;
18261.1Skamil	uint16_t lookup_me = 0;
18271.1Skamil	const uint16_t magic = 0x1234;
18281.1Skamil	struct ptrace_io_desc io = {
18291.1Skamil		.piod_op = PIOD_READ_D,
18301.1Skamil		.piod_offs = &lookup_me,
18311.1Skamil		.piod_addr = &lookup_me,
18321.1Skamil		.piod_len = sizeof(lookup_me)
18331.1Skamil	};
18341.1Skamil#if defined(TWAIT_HAVE_STATUS)
18351.1Skamil	int status;
18361.1Skamil#endif
18371.1Skamil
18381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18401.1Skamil	if (child == 0) {
18411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18431.1Skamil
18441.1Skamil		lookup_me = magic;
18451.1Skamil
18461.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18471.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18481.1Skamil
18491.13Schristos		DPRINTF("Before exiting of the child process\n");
18501.1Skamil		_exit(exitval);
18511.1Skamil	}
18521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18531.1Skamil
18541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18561.1Skamil
18571.1Skamil	validate_status_stopped(status, sigval);
18581.1Skamil
18591.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
18601.1Skamil	    child, getpid());
18611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
18621.1Skamil
18631.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18641.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
18651.1Skamil
18661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18671.1Skamil	    "without signal to be sent\n");
18681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18691.1Skamil
18701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18721.1Skamil
18731.1Skamil	validate_status_exited(status, exitval);
18741.1Skamil
18751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18771.1Skamil}
18781.1Skamil
18791.1SkamilATF_TC(io_read_d3);
18801.1SkamilATF_TC_HEAD(io_read_d3, tc)
18811.1Skamil{
18821.1Skamil	atf_tc_set_md_var(tc, "descr",
18831.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
18841.1Skamil}
18851.1Skamil
18861.1SkamilATF_TC_BODY(io_read_d3, tc)
18871.1Skamil{
18881.1Skamil	const int exitval = 5;
18891.1Skamil	const int sigval = SIGSTOP;
18901.1Skamil	pid_t child, wpid;
18911.1Skamil	uint32_t lookup_me = 0;
18921.1Skamil	const uint32_t magic = 0x1234abcd;
18931.1Skamil	struct ptrace_io_desc io = {
18941.1Skamil		.piod_op = PIOD_READ_D,
18951.1Skamil		.piod_offs = &lookup_me,
18961.1Skamil		.piod_addr = &lookup_me,
18971.1Skamil		.piod_len = sizeof(lookup_me)
18981.1Skamil	};
18991.1Skamil#if defined(TWAIT_HAVE_STATUS)
19001.1Skamil	int status;
19011.1Skamil#endif
19021.1Skamil
19031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19051.1Skamil	if (child == 0) {
19061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19081.1Skamil
19091.1Skamil		lookup_me = magic;
19101.1Skamil
19111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19131.1Skamil
19141.13Schristos		DPRINTF("Before exiting of the child process\n");
19151.1Skamil		_exit(exitval);
19161.1Skamil	}
19171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19181.1Skamil
19191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19211.1Skamil
19221.1Skamil	validate_status_stopped(status, sigval);
19231.1Skamil
19241.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19251.1Skamil	    child, getpid());
19261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19271.1Skamil
19281.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19291.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
19301.1Skamil
19311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19321.1Skamil	    "without signal to be sent\n");
19331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19341.1Skamil
19351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19371.1Skamil
19381.1Skamil	validate_status_exited(status, exitval);
19391.1Skamil
19401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19421.1Skamil}
19431.1Skamil
19441.1SkamilATF_TC(io_read_d4);
19451.1SkamilATF_TC_HEAD(io_read_d4, tc)
19461.1Skamil{
19471.1Skamil	atf_tc_set_md_var(tc, "descr",
19481.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
19491.1Skamil}
19501.1Skamil
19511.1SkamilATF_TC_BODY(io_read_d4, tc)
19521.1Skamil{
19531.1Skamil	const int exitval = 5;
19541.1Skamil	const int sigval = SIGSTOP;
19551.1Skamil	pid_t child, wpid;
19561.1Skamil	uint64_t lookup_me = 0;
19571.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
19581.1Skamil	struct ptrace_io_desc io = {
19591.1Skamil		.piod_op = PIOD_READ_D,
19601.1Skamil		.piod_offs = &lookup_me,
19611.1Skamil		.piod_addr = &lookup_me,
19621.1Skamil		.piod_len = sizeof(lookup_me)
19631.1Skamil	};
19641.1Skamil#if defined(TWAIT_HAVE_STATUS)
19651.1Skamil	int status;
19661.1Skamil#endif
19671.1Skamil
19681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19701.1Skamil	if (child == 0) {
19711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19731.1Skamil
19741.1Skamil		lookup_me = magic;
19751.1Skamil
19761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19781.1Skamil
19791.13Schristos		DPRINTF("Before exiting of the child process\n");
19801.1Skamil		_exit(exitval);
19811.1Skamil	}
19821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19831.1Skamil
19841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19861.1Skamil
19871.1Skamil	validate_status_stopped(status, sigval);
19881.1Skamil
19891.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19901.1Skamil	    child, getpid());
19911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19921.1Skamil
19931.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19941.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
19951.1Skamil
19961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19971.1Skamil	    "without signal to be sent\n");
19981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19991.1Skamil
20001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20021.1Skamil
20031.1Skamil	validate_status_exited(status, exitval);
20041.1Skamil
20051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20071.1Skamil}
20081.1Skamil
20091.1SkamilATF_TC(io_write_d1);
20101.1SkamilATF_TC_HEAD(io_write_d1, tc)
20111.1Skamil{
20121.1Skamil	atf_tc_set_md_var(tc, "descr",
20131.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
20141.1Skamil}
20151.1Skamil
20161.1SkamilATF_TC_BODY(io_write_d1, tc)
20171.1Skamil{
20181.1Skamil	const int exitval = 5;
20191.1Skamil	const int sigval = SIGSTOP;
20201.1Skamil	pid_t child, wpid;
20211.1Skamil	uint8_t lookup_me = 0;
20221.1Skamil	const uint8_t magic = 0xab;
20231.1Skamil	struct ptrace_io_desc io = {
20241.1Skamil		.piod_op = PIOD_WRITE_D,
20251.1Skamil		.piod_offs = &lookup_me,
20261.1Skamil		.piod_addr = &lookup_me,
20271.1Skamil		.piod_len = sizeof(lookup_me)
20281.1Skamil	};
20291.1Skamil#if defined(TWAIT_HAVE_STATUS)
20301.1Skamil	int status;
20311.1Skamil#endif
20321.1Skamil
20331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20351.1Skamil	if (child == 0) {
20361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20381.1Skamil
20391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20411.1Skamil
20421.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
20431.1Skamil
20441.13Schristos		DPRINTF("Before exiting of the child process\n");
20451.1Skamil		_exit(exitval);
20461.1Skamil	}
20471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20481.1Skamil
20491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20511.1Skamil
20521.1Skamil	validate_status_stopped(status, sigval);
20531.1Skamil
20541.1Skamil	lookup_me = magic;
20551.1Skamil
20561.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
20571.1Skamil	    child, getpid());
20581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20591.1Skamil
20601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20611.1Skamil	    "without signal to be sent\n");
20621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20631.1Skamil
20641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20661.1Skamil
20671.1Skamil	validate_status_exited(status, exitval);
20681.1Skamil
20691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20711.1Skamil}
20721.1Skamil
20731.1SkamilATF_TC(io_write_d2);
20741.1SkamilATF_TC_HEAD(io_write_d2, tc)
20751.1Skamil{
20761.1Skamil	atf_tc_set_md_var(tc, "descr",
20771.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
20781.1Skamil}
20791.1Skamil
20801.1SkamilATF_TC_BODY(io_write_d2, tc)
20811.1Skamil{
20821.1Skamil	const int exitval = 5;
20831.1Skamil	const int sigval = SIGSTOP;
20841.1Skamil	pid_t child, wpid;
20851.1Skamil	uint16_t lookup_me = 0;
20861.1Skamil	const uint16_t magic = 0xab12;
20871.1Skamil	struct ptrace_io_desc io = {
20881.1Skamil		.piod_op = PIOD_WRITE_D,
20891.1Skamil		.piod_offs = &lookup_me,
20901.1Skamil		.piod_addr = &lookup_me,
20911.1Skamil		.piod_len = sizeof(lookup_me)
20921.1Skamil	};
20931.1Skamil#if defined(TWAIT_HAVE_STATUS)
20941.1Skamil	int status;
20951.1Skamil#endif
20961.1Skamil
20971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20991.1Skamil	if (child == 0) {
21001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21021.1Skamil
21031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21051.1Skamil
21061.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21071.1Skamil
21081.13Schristos		DPRINTF("Before exiting of the child process\n");
21091.1Skamil		_exit(exitval);
21101.1Skamil	}
21111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21121.1Skamil
21131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21151.1Skamil
21161.1Skamil	validate_status_stopped(status, sigval);
21171.1Skamil
21181.1Skamil	lookup_me = magic;
21191.1Skamil
21201.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21211.1Skamil	    child, getpid());
21221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21231.1Skamil
21241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21251.1Skamil	    "without signal to be sent\n");
21261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21271.1Skamil
21281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21301.1Skamil
21311.1Skamil	validate_status_exited(status, exitval);
21321.1Skamil
21331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21351.1Skamil}
21361.1Skamil
21371.1SkamilATF_TC(io_write_d3);
21381.1SkamilATF_TC_HEAD(io_write_d3, tc)
21391.1Skamil{
21401.1Skamil	atf_tc_set_md_var(tc, "descr",
21411.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
21421.1Skamil}
21431.1Skamil
21441.1SkamilATF_TC_BODY(io_write_d3, tc)
21451.1Skamil{
21461.1Skamil	const int exitval = 5;
21471.1Skamil	const int sigval = SIGSTOP;
21481.1Skamil	pid_t child, wpid;
21491.1Skamil	uint32_t lookup_me = 0;
21501.1Skamil	const uint32_t magic = 0xab127643;
21511.1Skamil	struct ptrace_io_desc io = {
21521.1Skamil		.piod_op = PIOD_WRITE_D,
21531.1Skamil		.piod_offs = &lookup_me,
21541.1Skamil		.piod_addr = &lookup_me,
21551.1Skamil		.piod_len = sizeof(lookup_me)
21561.1Skamil	};
21571.1Skamil#if defined(TWAIT_HAVE_STATUS)
21581.1Skamil	int status;
21591.1Skamil#endif
21601.1Skamil
21611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21631.1Skamil	if (child == 0) {
21641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21661.1Skamil
21671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21691.1Skamil
21701.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21711.1Skamil
21721.13Schristos		DPRINTF("Before exiting of the child process\n");
21731.1Skamil		_exit(exitval);
21741.1Skamil	}
21751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21761.1Skamil
21771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21791.1Skamil
21801.1Skamil	validate_status_stopped(status, sigval);
21811.1Skamil
21821.1Skamil	lookup_me = magic;
21831.1Skamil
21841.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21851.1Skamil	    child, getpid());
21861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21871.1Skamil
21881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21891.1Skamil	    "without signal to be sent\n");
21901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21911.1Skamil
21921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21941.1Skamil
21951.1Skamil	validate_status_exited(status, exitval);
21961.1Skamil
21971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21991.1Skamil}
22001.1Skamil
22011.1SkamilATF_TC(io_write_d4);
22021.1SkamilATF_TC_HEAD(io_write_d4, tc)
22031.1Skamil{
22041.1Skamil	atf_tc_set_md_var(tc, "descr",
22051.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
22061.1Skamil}
22071.1Skamil
22081.1SkamilATF_TC_BODY(io_write_d4, tc)
22091.1Skamil{
22101.1Skamil	const int exitval = 5;
22111.1Skamil	const int sigval = SIGSTOP;
22121.1Skamil	pid_t child, wpid;
22131.1Skamil	uint64_t lookup_me = 0;
22141.1Skamil	const uint64_t magic = 0xab12764376490123;
22151.1Skamil	struct ptrace_io_desc io = {
22161.1Skamil		.piod_op = PIOD_WRITE_D,
22171.1Skamil		.piod_offs = &lookup_me,
22181.1Skamil		.piod_addr = &lookup_me,
22191.1Skamil		.piod_len = sizeof(lookup_me)
22201.1Skamil	};
22211.1Skamil#if defined(TWAIT_HAVE_STATUS)
22221.1Skamil	int status;
22231.1Skamil#endif
22241.1Skamil
22251.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22261.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22271.1Skamil	if (child == 0) {
22281.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22291.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22301.1Skamil
22311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22331.1Skamil
22341.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22351.1Skamil
22361.13Schristos		DPRINTF("Before exiting of the child process\n");
22371.1Skamil		_exit(exitval);
22381.1Skamil	}
22391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22401.1Skamil
22411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22431.1Skamil
22441.1Skamil	validate_status_stopped(status, sigval);
22451.1Skamil
22461.1Skamil	lookup_me = magic;
22471.1Skamil
22481.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22491.1Skamil	    child, getpid());
22501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22511.1Skamil
22521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22531.1Skamil	    "without signal to be sent\n");
22541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22551.1Skamil
22561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22581.1Skamil
22591.1Skamil	validate_status_exited(status, exitval);
22601.1Skamil
22611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22631.1Skamil}
22641.1Skamil
22651.1SkamilATF_TC(io_read_auxv1);
22661.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
22671.1Skamil{
22681.1Skamil	atf_tc_set_md_var(tc, "descr",
22691.1Skamil	    "Verify PT_READ_AUXV called for tracee");
22701.1Skamil}
22711.1Skamil
22721.1SkamilATF_TC_BODY(io_read_auxv1, tc)
22731.1Skamil{
22741.1Skamil	const int exitval = 5;
22751.1Skamil	const int sigval = SIGSTOP;
22761.1Skamil	pid_t child, wpid;
22771.1Skamil#if defined(TWAIT_HAVE_STATUS)
22781.1Skamil	int status;
22791.1Skamil#endif
22801.1Skamil	AuxInfo ai[100], *aip;
22811.1Skamil	struct ptrace_io_desc io = {
22821.1Skamil		.piod_op = PIOD_READ_AUXV,
22831.1Skamil		.piod_offs = 0,
22841.1Skamil		.piod_addr = ai,
22851.1Skamil		.piod_len = sizeof(ai)
22861.1Skamil	};
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.13Schristos		DPRINTF("Before exiting of the child process\n");
22981.1Skamil		_exit(exitval);
22991.1Skamil	}
23001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23011.1Skamil
23021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23041.1Skamil
23051.1Skamil	validate_status_stopped(status, sigval);
23061.1Skamil
23071.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
23081.1Skamil	    child, getpid());
23091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23101.1Skamil
23111.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
23121.1Skamil	ATF_REQUIRE(io.piod_len > 0);
23131.1Skamil
23141.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
23151.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
23161.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
23171.1Skamil
23181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23191.1Skamil	    "without signal to be sent\n");
23201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23211.1Skamil
23221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23241.1Skamil
23251.1Skamil	validate_status_exited(status, exitval);
23261.1Skamil
23271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23291.1Skamil}
23301.1Skamil
23311.1SkamilATF_TC(read_d1);
23321.1SkamilATF_TC_HEAD(read_d1, tc)
23331.1Skamil{
23341.1Skamil	atf_tc_set_md_var(tc, "descr",
23351.1Skamil	    "Verify PT_READ_D called once");
23361.1Skamil}
23371.1Skamil
23381.1SkamilATF_TC_BODY(read_d1, tc)
23391.1Skamil{
23401.1Skamil	const int exitval = 5;
23411.1Skamil	const int sigval = SIGSTOP;
23421.1Skamil	pid_t child, wpid;
23431.1Skamil	int lookup_me = 0;
23441.1Skamil	const int magic = (int)random();
23451.1Skamil#if defined(TWAIT_HAVE_STATUS)
23461.1Skamil	int status;
23471.1Skamil#endif
23481.1Skamil
23491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23511.1Skamil	if (child == 0) {
23521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23541.1Skamil
23551.1Skamil		lookup_me = magic;
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 lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
23711.1Skamil	    child, getpid());
23721.1Skamil	errno = 0;
23731.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
23741.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
23751.1Skamil
23761.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
23771.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
23781.1Skamil
23791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23801.1Skamil	    "without signal to be sent\n");
23811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23821.1Skamil
23831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23851.1Skamil
23861.1Skamil	validate_status_exited(status, exitval);
23871.1Skamil
23881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23901.1Skamil}
23911.1Skamil
23921.1SkamilATF_TC(read_d2);
23931.1SkamilATF_TC_HEAD(read_d2, tc)
23941.1Skamil{
23951.1Skamil	atf_tc_set_md_var(tc, "descr",
23961.1Skamil	    "Verify PT_READ_D called twice");
23971.1Skamil}
23981.1Skamil
23991.1SkamilATF_TC_BODY(read_d2, tc)
24001.1Skamil{
24011.1Skamil	const int exitval = 5;
24021.1Skamil	const int sigval = SIGSTOP;
24031.1Skamil	pid_t child, wpid;
24041.1Skamil	int lookup_me1 = 0;
24051.1Skamil	int lookup_me2 = 0;
24061.1Skamil	const int magic1 = (int)random();
24071.1Skamil	const int magic2 = (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_me1 = magic1;
24191.1Skamil		lookup_me2 = magic2;
24201.1Skamil
24211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24231.1Skamil
24241.13Schristos		DPRINTF("Before exiting of the child process\n");
24251.1Skamil		_exit(exitval);
24261.1Skamil	}
24271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24281.1Skamil
24291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24311.1Skamil
24321.1Skamil	validate_status_stopped(status, sigval);
24331.1Skamil
24341.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
24351.1Skamil	    child, getpid());
24361.1Skamil	errno = 0;
24371.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
24381.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24391.1Skamil
24401.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
24411.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
24421.1Skamil
24431.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
24441.1Skamil	    child, getpid());
24451.1Skamil	errno = 0;
24461.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
24471.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24481.1Skamil
24491.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
24501.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
24511.1Skamil
24521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24531.1Skamil	    "without signal to be sent\n");
24541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24551.1Skamil
24561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24581.1Skamil
24591.1Skamil	validate_status_exited(status, exitval);
24601.1Skamil
24611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24631.1Skamil}
24641.1Skamil
24651.1SkamilATF_TC(read_d3);
24661.1SkamilATF_TC_HEAD(read_d3, tc)
24671.1Skamil{
24681.1Skamil	atf_tc_set_md_var(tc, "descr",
24691.1Skamil	    "Verify PT_READ_D called three times");
24701.1Skamil}
24711.1Skamil
24721.1SkamilATF_TC_BODY(read_d3, tc)
24731.1Skamil{
24741.1Skamil	const int exitval = 5;
24751.1Skamil	const int sigval = SIGSTOP;
24761.1Skamil	pid_t child, wpid;
24771.1Skamil	int lookup_me1 = 0;
24781.1Skamil	int lookup_me2 = 0;
24791.1Skamil	int lookup_me3 = 0;
24801.1Skamil	const int magic1 = (int)random();
24811.1Skamil	const int magic2 = (int)random();
24821.1Skamil	const int magic3 = (int)random();
24831.1Skamil#if defined(TWAIT_HAVE_STATUS)
24841.1Skamil	int status;
24851.1Skamil#endif
24861.1Skamil
24871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24891.1Skamil	if (child == 0) {
24901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24921.1Skamil
24931.1Skamil		lookup_me1 = magic1;
24941.1Skamil		lookup_me2 = magic2;
24951.1Skamil		lookup_me3 = magic3;
24961.1Skamil
24971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24991.1Skamil
25001.13Schristos		DPRINTF("Before exiting of the child process\n");
25011.1Skamil		_exit(exitval);
25021.1Skamil	}
25031.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25041.1Skamil
25051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25071.1Skamil
25081.1Skamil	validate_status_stopped(status, sigval);
25091.1Skamil
25101.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25111.1Skamil	    child, getpid());
25121.1Skamil	errno = 0;
25131.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25141.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25151.1Skamil
25161.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25171.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25181.1Skamil
25191.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25201.1Skamil	    child, getpid());
25211.1Skamil	errno = 0;
25221.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25231.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25241.1Skamil
25251.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25261.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25271.1Skamil
25281.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
25291.1Skamil	    child, getpid());
25301.1Skamil	errno = 0;
25311.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
25321.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25331.1Skamil
25341.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
25351.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
25361.1Skamil
25371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25381.1Skamil	    "without signal to be sent\n");
25391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25401.1Skamil
25411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25431.1Skamil
25441.1Skamil	validate_status_exited(status, exitval);
25451.1Skamil
25461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25481.1Skamil}
25491.1Skamil
25501.1SkamilATF_TC(read_d4);
25511.1SkamilATF_TC_HEAD(read_d4, tc)
25521.1Skamil{
25531.1Skamil	atf_tc_set_md_var(tc, "descr",
25541.1Skamil	    "Verify PT_READ_D called four times");
25551.1Skamil}
25561.1Skamil
25571.1SkamilATF_TC_BODY(read_d4, tc)
25581.1Skamil{
25591.1Skamil	const int exitval = 5;
25601.1Skamil	const int sigval = SIGSTOP;
25611.1Skamil	pid_t child, wpid;
25621.1Skamil	int lookup_me1 = 0;
25631.1Skamil	int lookup_me2 = 0;
25641.1Skamil	int lookup_me3 = 0;
25651.1Skamil	int lookup_me4 = 0;
25661.1Skamil	const int magic1 = (int)random();
25671.1Skamil	const int magic2 = (int)random();
25681.1Skamil	const int magic3 = (int)random();
25691.1Skamil	const int magic4 = (int)random();
25701.1Skamil#if defined(TWAIT_HAVE_STATUS)
25711.1Skamil	int status;
25721.1Skamil#endif
25731.1Skamil
25741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25761.1Skamil	if (child == 0) {
25771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25791.1Skamil
25801.1Skamil		lookup_me1 = magic1;
25811.1Skamil		lookup_me2 = magic2;
25821.1Skamil		lookup_me3 = magic3;
25831.1Skamil		lookup_me4 = magic4;
25841.1Skamil
25851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25871.1Skamil
25881.13Schristos		DPRINTF("Before exiting of the child process\n");
25891.1Skamil		_exit(exitval);
25901.1Skamil	}
25911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25921.1Skamil
25931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25951.1Skamil
25961.1Skamil	validate_status_stopped(status, sigval);
25971.1Skamil
25981.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25991.1Skamil	    child, getpid());
26001.1Skamil	errno = 0;
26011.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26021.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26031.1Skamil
26041.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26051.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26061.1Skamil
26071.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26081.1Skamil	    child, getpid());
26091.1Skamil	errno = 0;
26101.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26111.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26121.1Skamil
26131.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26141.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26151.1Skamil
26161.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26171.1Skamil	    child, getpid());
26181.1Skamil	errno = 0;
26191.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26201.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26211.1Skamil
26221.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26231.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26241.1Skamil
26251.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
26261.1Skamil	    child, getpid());
26271.1Skamil	errno = 0;
26281.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
26291.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26301.1Skamil
26311.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
26321.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
26331.1Skamil
26341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26351.1Skamil	    "without signal to be sent\n");
26361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26371.1Skamil
26381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26401.1Skamil
26411.1Skamil	validate_status_exited(status, exitval);
26421.1Skamil
26431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26451.1Skamil}
26461.1Skamil
26471.1SkamilATF_TC(write_d1);
26481.1SkamilATF_TC_HEAD(write_d1, tc)
26491.1Skamil{
26501.1Skamil	atf_tc_set_md_var(tc, "descr",
26511.1Skamil	    "Verify PT_WRITE_D called once");
26521.1Skamil}
26531.1Skamil
26541.1SkamilATF_TC_BODY(write_d1, tc)
26551.1Skamil{
26561.1Skamil	const int exitval = 5;
26571.1Skamil	const int sigval = SIGSTOP;
26581.1Skamil	pid_t child, wpid;
26591.1Skamil	int lookup_me = 0;
26601.1Skamil	const int magic = (int)random();
26611.1Skamil#if defined(TWAIT_HAVE_STATUS)
26621.1Skamil	int status;
26631.1Skamil#endif
26641.1Skamil
26651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26671.1Skamil	if (child == 0) {
26681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26701.1Skamil
26711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26731.1Skamil
26741.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
26751.1Skamil
26761.13Schristos		DPRINTF("Before exiting of the child process\n");
26771.1Skamil		_exit(exitval);
26781.1Skamil	}
26791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26801.1Skamil
26811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26831.1Skamil
26841.1Skamil	validate_status_stopped(status, sigval);
26851.1Skamil
26861.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
26871.1Skamil	    child, getpid());
26881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
26891.1Skamil
26901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26911.1Skamil	    "without signal to be sent\n");
26921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26931.1Skamil
26941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26961.1Skamil
26971.1Skamil	validate_status_exited(status, exitval);
26981.1Skamil
26991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27011.1Skamil}
27021.1Skamil
27031.1SkamilATF_TC(write_d2);
27041.1SkamilATF_TC_HEAD(write_d2, tc)
27051.1Skamil{
27061.1Skamil	atf_tc_set_md_var(tc, "descr",
27071.1Skamil	    "Verify PT_WRITE_D called twice");
27081.1Skamil}
27091.1Skamil
27101.1SkamilATF_TC_BODY(write_d2, tc)
27111.1Skamil{
27121.1Skamil	const int exitval = 5;
27131.1Skamil	const int sigval = SIGSTOP;
27141.1Skamil	pid_t child, wpid;
27151.1Skamil	int lookup_me1 = 0;
27161.1Skamil	int lookup_me2 = 0;
27171.1Skamil	const int magic1 = (int)random();
27181.1Skamil	const int magic2 = (int)random();
27191.1Skamil#if defined(TWAIT_HAVE_STATUS)
27201.1Skamil	int status;
27211.1Skamil#endif
27221.1Skamil
27231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27251.1Skamil	if (child == 0) {
27261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27281.1Skamil
27291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27311.1Skamil
27321.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27331.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
27341.1Skamil
27351.13Schristos		DPRINTF("Before exiting of the child process\n");
27361.1Skamil		_exit(exitval);
27371.1Skamil	}
27381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27391.1Skamil
27401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27421.1Skamil
27431.1Skamil	validate_status_stopped(status, sigval);
27441.1Skamil
27451.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
27461.1Skamil	    child, getpid());
27471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
27481.1Skamil
27491.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
27501.1Skamil	    child, getpid());
27511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -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_d3);
27671.1SkamilATF_TC_HEAD(write_d3, tc)
27681.1Skamil{
27691.1Skamil	atf_tc_set_md_var(tc, "descr",
27701.1Skamil	    "Verify PT_WRITE_D called three times");
27711.1Skamil}
27721.1Skamil
27731.1SkamilATF_TC_BODY(write_d3, 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	int lookup_me3 = 0;
27811.1Skamil	const int magic1 = (int)random();
27821.1Skamil	const int magic2 = (int)random();
27831.1Skamil	const int magic3 = (int)random();
27841.1Skamil#if defined(TWAIT_HAVE_STATUS)
27851.1Skamil	int status;
27861.1Skamil#endif
27871.1Skamil
27881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27901.1Skamil	if (child == 0) {
27911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27931.1Skamil
27941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27961.1Skamil
27971.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27981.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
27991.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28001.1Skamil
28011.13Schristos		DPRINTF("Before exiting of the child process\n");
28021.1Skamil		_exit(exitval);
28031.1Skamil	}
28041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28051.1Skamil
28061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28081.1Skamil
28091.1Skamil	validate_status_stopped(status, sigval);
28101.1Skamil
28111.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28121.1Skamil	    child, getpid());
28131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28141.1Skamil
28151.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28161.1Skamil	    child, getpid());
28171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28181.1Skamil
28191.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28201.1Skamil	    child, getpid());
28211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28221.1Skamil
28231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28241.1Skamil	    "without signal to be sent\n");
28251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28261.1Skamil
28271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28291.1Skamil
28301.1Skamil	validate_status_exited(status, exitval);
28311.1Skamil
28321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28341.1Skamil}
28351.1Skamil
28361.1SkamilATF_TC(write_d4);
28371.1SkamilATF_TC_HEAD(write_d4, tc)
28381.1Skamil{
28391.1Skamil	atf_tc_set_md_var(tc, "descr",
28401.1Skamil	    "Verify PT_WRITE_D called four times");
28411.1Skamil}
28421.1Skamil
28431.1SkamilATF_TC_BODY(write_d4, tc)
28441.1Skamil{
28451.1Skamil	const int exitval = 5;
28461.1Skamil	const int sigval = SIGSTOP;
28471.1Skamil	pid_t child, wpid;
28481.1Skamil	int lookup_me1 = 0;
28491.1Skamil	int lookup_me2 = 0;
28501.1Skamil	int lookup_me3 = 0;
28511.1Skamil	int lookup_me4 = 0;
28521.1Skamil	const int magic1 = (int)random();
28531.1Skamil	const int magic2 = (int)random();
28541.1Skamil	const int magic3 = (int)random();
28551.1Skamil	const int magic4 = (int)random();
28561.1Skamil#if defined(TWAIT_HAVE_STATUS)
28571.1Skamil	int status;
28581.1Skamil#endif
28591.1Skamil
28601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28621.1Skamil	if (child == 0) {
28631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28651.1Skamil
28661.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28671.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28681.1Skamil
28691.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28701.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28711.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28721.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
28731.1Skamil
28741.13Schristos		DPRINTF("Before exiting of the child process\n");
28751.1Skamil		_exit(exitval);
28761.1Skamil	}
28771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28781.1Skamil
28791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28811.1Skamil
28821.1Skamil	validate_status_stopped(status, sigval);
28831.1Skamil
28841.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28851.1Skamil	    child, getpid());
28861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28871.1Skamil
28881.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28891.1Skamil	    child, getpid());
28901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28911.1Skamil
28921.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28931.1Skamil	    child, getpid());
28941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28951.1Skamil
28961.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
28971.1Skamil	    child, getpid());
28981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
28991.1Skamil
29001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29011.1Skamil	    "without signal to be sent\n");
29021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29031.1Skamil
29041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29061.1Skamil
29071.1Skamil	validate_status_exited(status, exitval);
29081.1Skamil
29091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29111.1Skamil}
29121.1Skamil
29131.1SkamilATF_TC(io_read_d_write_d_handshake1);
29141.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
29151.1Skamil{
29161.1Skamil	atf_tc_set_md_var(tc, "descr",
29171.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
29181.1Skamil}
29191.1Skamil
29201.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
29211.1Skamil{
29221.1Skamil	const int exitval = 5;
29231.1Skamil	const int sigval = SIGSTOP;
29241.1Skamil	pid_t child, wpid;
29251.1Skamil	uint8_t lookup_me_fromtracee = 0;
29261.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
29271.1Skamil	uint8_t lookup_me_totracee = 0;
29281.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
29291.1Skamil	struct ptrace_io_desc io_fromtracee = {
29301.1Skamil		.piod_op = PIOD_READ_D,
29311.1Skamil		.piod_offs = &lookup_me_fromtracee,
29321.1Skamil		.piod_addr = &lookup_me_fromtracee,
29331.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
29341.1Skamil	};
29351.1Skamil	struct ptrace_io_desc io_totracee = {
29361.1Skamil		.piod_op = PIOD_WRITE_D,
29371.1Skamil		.piod_offs = &lookup_me_totracee,
29381.1Skamil		.piod_addr = &lookup_me_totracee,
29391.1Skamil		.piod_len = sizeof(lookup_me_totracee)
29401.1Skamil	};
29411.1Skamil#if defined(TWAIT_HAVE_STATUS)
29421.1Skamil	int status;
29431.1Skamil#endif
29441.1Skamil
29451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29471.1Skamil	if (child == 0) {
29481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29501.1Skamil
29511.1Skamil		lookup_me_fromtracee = magic_fromtracee;
29521.1Skamil
29531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29551.1Skamil
29561.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
29571.1Skamil
29581.13Schristos		DPRINTF("Before exiting of the child process\n");
29591.1Skamil		_exit(exitval);
29601.1Skamil	}
29611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29621.1Skamil
29631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29651.1Skamil
29661.1Skamil	validate_status_stopped(status, sigval);
29671.1Skamil
29681.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
29691.1Skamil	    child, getpid());
29701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
29711.1Skamil
29721.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
29731.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
29741.1Skamil	    magic_fromtracee);
29751.1Skamil
29761.1Skamil	lookup_me_totracee = magic_totracee;
29771.1Skamil
29781.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
29791.1Skamil	    child, getpid());
29801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
29811.1Skamil
29821.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
29831.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
29841.1Skamil	    magic_totracee);
29851.1Skamil
29861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29871.1Skamil	    "without signal to be sent\n");
29881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29891.1Skamil
29901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29921.1Skamil
29931.1Skamil	validate_status_exited(status, exitval);
29941.1Skamil
29951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29971.1Skamil}
29981.1Skamil
29991.1SkamilATF_TC(io_read_d_write_d_handshake2);
30001.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
30011.1Skamil{
30021.1Skamil	atf_tc_set_md_var(tc, "descr",
30031.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
30041.1Skamil}
30051.1Skamil
30061.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
30071.1Skamil{
30081.1Skamil	const int exitval = 5;
30091.1Skamil	const int sigval = SIGSTOP;
30101.1Skamil	pid_t child, wpid;
30111.1Skamil	uint8_t lookup_me_fromtracee = 0;
30121.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30131.1Skamil	uint8_t lookup_me_totracee = 0;
30141.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30151.1Skamil	struct ptrace_io_desc io_fromtracee = {
30161.1Skamil		.piod_op = PIOD_READ_D,
30171.1Skamil		.piod_offs = &lookup_me_fromtracee,
30181.1Skamil		.piod_addr = &lookup_me_fromtracee,
30191.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30201.1Skamil	};
30211.1Skamil	struct ptrace_io_desc io_totracee = {
30221.1Skamil		.piod_op = PIOD_WRITE_D,
30231.1Skamil		.piod_offs = &lookup_me_totracee,
30241.1Skamil		.piod_addr = &lookup_me_totracee,
30251.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30261.1Skamil	};
30271.1Skamil#if defined(TWAIT_HAVE_STATUS)
30281.1Skamil	int status;
30291.1Skamil#endif
30301.1Skamil
30311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30331.1Skamil	if (child == 0) {
30341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30361.1Skamil
30371.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30381.1Skamil
30391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30411.1Skamil
30421.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30431.1Skamil
30441.13Schristos		DPRINTF("Before exiting of the child process\n");
30451.1Skamil		_exit(exitval);
30461.1Skamil	}
30471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30481.1Skamil
30491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30511.1Skamil
30521.1Skamil	validate_status_stopped(status, sigval);
30531.1Skamil
30541.1Skamil	lookup_me_totracee = magic_totracee;
30551.1Skamil
30561.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30571.1Skamil	    child, getpid());
30581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30591.1Skamil
30601.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30611.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30621.1Skamil	    magic_totracee);
30631.1Skamil
30641.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30651.1Skamil	    child, getpid());
30661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30671.1Skamil
30681.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30691.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30701.1Skamil	    magic_fromtracee);
30711.1Skamil
30721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30731.1Skamil	    "without signal to be sent\n");
30741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30751.1Skamil
30761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30781.1Skamil
30791.1Skamil	validate_status_exited(status, exitval);
30801.1Skamil
30811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30831.1Skamil}
30841.1Skamil
30851.1SkamilATF_TC(read_d_write_d_handshake1);
30861.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
30871.1Skamil{
30881.1Skamil	atf_tc_set_md_var(tc, "descr",
30891.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
30901.1Skamil}
30911.1Skamil
30921.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
30931.1Skamil{
30941.1Skamil	const int exitval = 5;
30951.1Skamil	const int sigval = SIGSTOP;
30961.1Skamil	pid_t child, wpid;
30971.1Skamil	int lookup_me_fromtracee = 0;
30981.1Skamil	const int magic_fromtracee = (int)random();
30991.1Skamil	int lookup_me_totracee = 0;
31001.1Skamil	const int magic_totracee = (int)random();
31011.1Skamil#if defined(TWAIT_HAVE_STATUS)
31021.1Skamil	int status;
31031.1Skamil#endif
31041.1Skamil
31051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31071.1Skamil	if (child == 0) {
31081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31101.1Skamil
31111.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31121.1Skamil
31131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31151.1Skamil
31161.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31171.1Skamil
31181.13Schristos		DPRINTF("Before exiting of the child process\n");
31191.1Skamil		_exit(exitval);
31201.1Skamil	}
31211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31221.1Skamil
31231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31251.1Skamil
31261.1Skamil	validate_status_stopped(status, sigval);
31271.1Skamil
31281.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31291.1Skamil	    child, getpid());
31301.1Skamil	errno = 0;
31311.1Skamil	lookup_me_fromtracee =
31321.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
31331.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
31341.1Skamil
31351.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31361.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
31371.1Skamil	    magic_fromtracee);
31381.1Skamil
31391.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
31401.1Skamil	    child, getpid());
31411.1Skamil	ATF_REQUIRE
31421.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
31431.1Skamil	    != -1);
31441.1Skamil
31451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31461.1Skamil	    "without signal to be sent\n");
31471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31481.1Skamil
31491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31511.1Skamil
31521.1Skamil	validate_status_exited(status, exitval);
31531.1Skamil
31541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31561.1Skamil}
31571.1Skamil
31581.1SkamilATF_TC(read_d_write_d_handshake2);
31591.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
31601.1Skamil{
31611.1Skamil	atf_tc_set_md_var(tc, "descr",
31621.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
31631.1Skamil}
31641.1Skamil
31651.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
31661.1Skamil{
31671.1Skamil	const int exitval = 5;
31681.1Skamil	const int sigval = SIGSTOP;
31691.1Skamil	pid_t child, wpid;
31701.1Skamil	int lookup_me_fromtracee = 0;
31711.1Skamil	const int magic_fromtracee = (int)random();
31721.1Skamil	int lookup_me_totracee = 0;
31731.1Skamil	const int magic_totracee = (int)random();
31741.1Skamil#if defined(TWAIT_HAVE_STATUS)
31751.1Skamil	int status;
31761.1Skamil#endif
31771.1Skamil
31781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31801.1Skamil	if (child == 0) {
31811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31831.1Skamil
31841.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31851.1Skamil
31861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31881.1Skamil
31891.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31901.1Skamil
31911.13Schristos		DPRINTF("Before exiting of the child process\n");
31921.1Skamil		_exit(exitval);
31931.1Skamil	}
31941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31951.1Skamil
31961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31981.1Skamil
31991.1Skamil	validate_status_stopped(status, sigval);
32001.1Skamil
32011.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32021.1Skamil	    child, getpid());
32031.1Skamil	ATF_REQUIRE
32041.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32051.1Skamil	    != -1);
32061.1Skamil
32071.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32081.1Skamil	    child, getpid());
32091.1Skamil	errno = 0;
32101.1Skamil	lookup_me_fromtracee =
32111.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32131.1Skamil
32141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32151.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32161.1Skamil	    magic_fromtracee);
32171.1Skamil
32181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32191.1Skamil	    "without signal to be sent\n");
32201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32211.1Skamil
32221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32241.1Skamil
32251.1Skamil	validate_status_exited(status, exitval);
32261.1Skamil
32271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32291.1Skamil}
32301.1Skamil
32311.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
32321.1Skamilstatic int __used
32331.1Skamildummy_fn1(int a, int b, int c, int d)
32341.1Skamil{
32351.1Skamil
32361.1Skamil	a *= 1;
32371.1Skamil	b += 2;
32381.1Skamil	c -= 3;
32391.1Skamil	d /= 4;
32401.1Skamil
32411.1Skamil	return a + b * c - d;
32421.1Skamil}
32431.1Skamil
32441.1Skamilstatic int __used
32451.1Skamildummy_fn2(int a, int b, int c, int d)
32461.1Skamil{
32471.1Skamil
32481.1Skamil	a *= 4;
32491.1Skamil	b += 3;
32501.1Skamil	c -= 2;
32511.1Skamil	d /= 1;
32521.1Skamil
32531.1Skamil	return a + b * c - d;
32541.1Skamil}
32551.1Skamil
32561.1Skamilstatic int __used
32571.1Skamildummy_fn3(int a, int b, int c, int d)
32581.1Skamil{
32591.1Skamil
32601.1Skamil	a *= 10;
32611.1Skamil	b += 20;
32621.1Skamil	c -= 30;
32631.1Skamil	d /= 40;
32641.1Skamil
32651.1Skamil	return a + b * c - d;
32661.1Skamil}
32671.1Skamil
32681.1Skamilstatic int __used
32691.1Skamildummy_fn4(int a, int b, int c, int d)
32701.1Skamil{
32711.1Skamil
32721.1Skamil	a *= 40;
32731.1Skamil	b += 30;
32741.1Skamil	c -= 20;
32751.1Skamil	d /= 10;
32761.1Skamil
32771.1Skamil	return a + b * c - d;
32781.1Skamil}
32791.1Skamil
32801.1SkamilATF_TC(io_read_i1);
32811.1SkamilATF_TC_HEAD(io_read_i1, tc)
32821.1Skamil{
32831.1Skamil	atf_tc_set_md_var(tc, "descr",
32841.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
32851.1Skamil}
32861.1Skamil
32871.1SkamilATF_TC_BODY(io_read_i1, tc)
32881.1Skamil{
32891.1Skamil	const int exitval = 5;
32901.1Skamil	const int sigval = SIGSTOP;
32911.1Skamil	pid_t child, wpid;
32921.1Skamil	uint8_t lookup_me = 0;
32931.1Skamil	uint8_t magic;
32941.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
32951.1Skamil	struct ptrace_io_desc io = {
32961.1Skamil		.piod_op = PIOD_READ_I,
32971.1Skamil		.piod_offs = dummy_fn1,
32981.1Skamil		.piod_addr = &lookup_me,
32991.1Skamil		.piod_len = sizeof(lookup_me)
33001.1Skamil	};
33011.1Skamil#if defined(TWAIT_HAVE_STATUS)
33021.1Skamil	int status;
33031.1Skamil#endif
33041.1Skamil
33051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33071.1Skamil	if (child == 0) {
33081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33101.1Skamil
33111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33131.1Skamil
33141.13Schristos		DPRINTF("Before exiting of the child process\n");
33151.1Skamil		_exit(exitval);
33161.1Skamil	}
33171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33181.1Skamil
33191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33211.1Skamil
33221.1Skamil	validate_status_stopped(status, sigval);
33231.1Skamil
33241.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33251.1Skamil	    child, getpid());
33261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33271.1Skamil
33281.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33291.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
33301.1Skamil
33311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33321.1Skamil	    "without signal to be sent\n");
33331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33341.1Skamil
33351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33371.1Skamil
33381.1Skamil	validate_status_exited(status, exitval);
33391.1Skamil
33401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33421.1Skamil}
33431.1Skamil
33441.1SkamilATF_TC(io_read_i2);
33451.1SkamilATF_TC_HEAD(io_read_i2, tc)
33461.1Skamil{
33471.1Skamil	atf_tc_set_md_var(tc, "descr",
33481.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
33491.1Skamil}
33501.1Skamil
33511.1SkamilATF_TC_BODY(io_read_i2, tc)
33521.1Skamil{
33531.1Skamil	const int exitval = 5;
33541.1Skamil	const int sigval = SIGSTOP;
33551.1Skamil	pid_t child, wpid;
33561.1Skamil	uint16_t lookup_me = 0;
33571.1Skamil	uint16_t magic;
33581.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
33591.1Skamil	struct ptrace_io_desc io = {
33601.1Skamil		.piod_op = PIOD_READ_I,
33611.1Skamil		.piod_offs = dummy_fn1,
33621.1Skamil		.piod_addr = &lookup_me,
33631.1Skamil		.piod_len = sizeof(lookup_me)
33641.1Skamil	};
33651.1Skamil#if defined(TWAIT_HAVE_STATUS)
33661.1Skamil	int status;
33671.1Skamil#endif
33681.1Skamil
33691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33711.1Skamil	if (child == 0) {
33721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33741.1Skamil
33751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33771.1Skamil
33781.13Schristos		DPRINTF("Before exiting of the child process\n");
33791.1Skamil		_exit(exitval);
33801.1Skamil	}
33811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33821.1Skamil
33831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33851.1Skamil
33861.1Skamil	validate_status_stopped(status, sigval);
33871.1Skamil
33881.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33891.1Skamil	    child, getpid());
33901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33911.1Skamil
33921.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33931.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
33941.1Skamil
33951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33961.1Skamil	    "without signal to be sent\n");
33971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33981.1Skamil
33991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34011.1Skamil
34021.1Skamil	validate_status_exited(status, exitval);
34031.1Skamil
34041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34061.1Skamil}
34071.1Skamil
34081.1SkamilATF_TC(io_read_i3);
34091.1SkamilATF_TC_HEAD(io_read_i3, tc)
34101.1Skamil{
34111.1Skamil	atf_tc_set_md_var(tc, "descr",
34121.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
34131.1Skamil}
34141.1Skamil
34151.1SkamilATF_TC_BODY(io_read_i3, tc)
34161.1Skamil{
34171.1Skamil	const int exitval = 5;
34181.1Skamil	const int sigval = SIGSTOP;
34191.1Skamil	pid_t child, wpid;
34201.1Skamil	uint32_t lookup_me = 0;
34211.1Skamil	uint32_t magic;
34221.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34231.1Skamil	struct ptrace_io_desc io = {
34241.1Skamil		.piod_op = PIOD_READ_I,
34251.1Skamil		.piod_offs = dummy_fn1,
34261.1Skamil		.piod_addr = &lookup_me,
34271.1Skamil		.piod_len = sizeof(lookup_me)
34281.1Skamil	};
34291.1Skamil#if defined(TWAIT_HAVE_STATUS)
34301.1Skamil	int status;
34311.1Skamil#endif
34321.1Skamil
34331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34351.1Skamil	if (child == 0) {
34361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34381.1Skamil
34391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34411.1Skamil
34421.13Schristos		DPRINTF("Before exiting of the child process\n");
34431.1Skamil		_exit(exitval);
34441.1Skamil	}
34451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34461.1Skamil
34471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34491.1Skamil
34501.1Skamil	validate_status_stopped(status, sigval);
34511.1Skamil
34521.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34531.1Skamil	    child, getpid());
34541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34551.1Skamil
34561.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34571.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
34581.1Skamil
34591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34601.1Skamil	    "without signal to be sent\n");
34611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34621.1Skamil
34631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34651.1Skamil
34661.1Skamil	validate_status_exited(status, exitval);
34671.1Skamil
34681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34701.1Skamil}
34711.1Skamil
34721.1SkamilATF_TC(io_read_i4);
34731.1SkamilATF_TC_HEAD(io_read_i4, tc)
34741.1Skamil{
34751.1Skamil	atf_tc_set_md_var(tc, "descr",
34761.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
34771.1Skamil}
34781.1Skamil
34791.1SkamilATF_TC_BODY(io_read_i4, tc)
34801.1Skamil{
34811.1Skamil	const int exitval = 5;
34821.1Skamil	const int sigval = SIGSTOP;
34831.1Skamil	pid_t child, wpid;
34841.1Skamil	uint64_t lookup_me = 0;
34851.1Skamil	uint64_t magic;
34861.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34871.1Skamil	struct ptrace_io_desc io = {
34881.1Skamil		.piod_op = PIOD_READ_I,
34891.1Skamil		.piod_offs = dummy_fn1,
34901.1Skamil		.piod_addr = &lookup_me,
34911.1Skamil		.piod_len = sizeof(lookup_me)
34921.1Skamil	};
34931.1Skamil#if defined(TWAIT_HAVE_STATUS)
34941.1Skamil	int status;
34951.1Skamil#endif
34961.1Skamil
34971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34991.1Skamil	if (child == 0) {
35001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35021.1Skamil
35031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35051.1Skamil
35061.13Schristos		DPRINTF("Before exiting of the child process\n");
35071.1Skamil		_exit(exitval);
35081.1Skamil	}
35091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35101.1Skamil
35111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35131.1Skamil
35141.1Skamil	validate_status_stopped(status, sigval);
35151.1Skamil
35161.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35171.1Skamil	    child, getpid());
35181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35191.1Skamil
35201.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35211.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
35221.1Skamil
35231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35241.1Skamil	    "without signal to be sent\n");
35251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35261.1Skamil
35271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35291.1Skamil
35301.1Skamil	validate_status_exited(status, exitval);
35311.1Skamil
35321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35341.1Skamil}
35351.1Skamil
35361.1SkamilATF_TC(read_i1);
35371.1SkamilATF_TC_HEAD(read_i1, tc)
35381.1Skamil{
35391.1Skamil	atf_tc_set_md_var(tc, "descr",
35401.1Skamil	    "Verify PT_READ_I called once");
35411.1Skamil}
35421.1Skamil
35431.1SkamilATF_TC_BODY(read_i1, tc)
35441.1Skamil{
35451.1Skamil	const int exitval = 5;
35461.1Skamil	const int sigval = SIGSTOP;
35471.1Skamil	pid_t child, wpid;
35481.1Skamil	int lookup_me = 0;
35491.1Skamil	int magic;
35501.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35511.1Skamil#if defined(TWAIT_HAVE_STATUS)
35521.1Skamil	int status;
35531.1Skamil#endif
35541.1Skamil
35551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35571.1Skamil	if (child == 0) {
35581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35601.1Skamil
35611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35631.1Skamil
35641.13Schristos		DPRINTF("Before exiting of the child process\n");
35651.1Skamil		_exit(exitval);
35661.1Skamil	}
35671.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35681.1Skamil
35691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35711.1Skamil
35721.1Skamil	validate_status_stopped(status, sigval);
35731.1Skamil
35741.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35751.1Skamil	    child, getpid());
35761.1Skamil	errno = 0;
35771.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
35781.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
35791.1Skamil
35801.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35811.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
35821.1Skamil
35831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35841.1Skamil	    "without signal to be sent\n");
35851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35861.1Skamil
35871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35891.1Skamil
35901.1Skamil	validate_status_exited(status, exitval);
35911.1Skamil
35921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35941.1Skamil}
35951.1Skamil
35961.1SkamilATF_TC(read_i2);
35971.1SkamilATF_TC_HEAD(read_i2, tc)
35981.1Skamil{
35991.1Skamil	atf_tc_set_md_var(tc, "descr",
36001.1Skamil	    "Verify PT_READ_I called twice");
36011.1Skamil}
36021.1Skamil
36031.1SkamilATF_TC_BODY(read_i2, tc)
36041.1Skamil{
36051.1Skamil	const int exitval = 5;
36061.1Skamil	const int sigval = SIGSTOP;
36071.1Skamil	pid_t child, wpid;
36081.1Skamil	int lookup_me1 = 0;
36091.1Skamil	int lookup_me2 = 0;
36101.1Skamil	int magic1;
36111.1Skamil	int magic2;
36121.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36131.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
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_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
36381.1Skamil	    child, getpid());
36391.1Skamil	errno = 0;
36401.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
36411.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36421.1Skamil
36431.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
36441.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
36451.1Skamil
36461.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
36471.1Skamil	    child, getpid());
36481.1Skamil	errno = 0;
36491.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
36501.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36511.1Skamil
36521.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
36531.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
36541.1Skamil
36551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36561.1Skamil	    "without signal to be sent\n");
36571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36581.1Skamil
36591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36611.1Skamil
36621.1Skamil	validate_status_exited(status, exitval);
36631.1Skamil
36641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36661.1Skamil}
36671.1Skamil
36681.1SkamilATF_TC(read_i3);
36691.1SkamilATF_TC_HEAD(read_i3, tc)
36701.1Skamil{
36711.1Skamil	atf_tc_set_md_var(tc, "descr",
36721.1Skamil	    "Verify PT_READ_I called three times");
36731.1Skamil}
36741.1Skamil
36751.1SkamilATF_TC_BODY(read_i3, tc)
36761.1Skamil{
36771.1Skamil	const int exitval = 5;
36781.1Skamil	const int sigval = SIGSTOP;
36791.1Skamil	pid_t child, wpid;
36801.1Skamil	int lookup_me1 = 0;
36811.1Skamil	int lookup_me2 = 0;
36821.1Skamil	int lookup_me3 = 0;
36831.1Skamil	int magic1;
36841.1Skamil	int magic2;
36851.1Skamil	int magic3;
36861.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36871.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36881.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
36891.1Skamil#if defined(TWAIT_HAVE_STATUS)
36901.1Skamil	int status;
36911.1Skamil#endif
36921.1Skamil
36931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36951.1Skamil	if (child == 0) {
36961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36981.1Skamil
36991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37011.1Skamil
37021.13Schristos		DPRINTF("Before exiting of the child process\n");
37031.1Skamil		_exit(exitval);
37041.1Skamil	}
37051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37061.1Skamil
37071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37091.1Skamil
37101.1Skamil	validate_status_stopped(status, sigval);
37111.1Skamil
37121.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37131.1Skamil	    child, getpid());
37141.1Skamil	errno = 0;
37151.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37161.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37171.1Skamil
37181.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37191.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37201.1Skamil
37211.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37221.1Skamil	    child, getpid());
37231.1Skamil	errno = 0;
37241.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37251.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37261.1Skamil
37271.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37281.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37291.1Skamil
37301.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
37311.1Skamil	    child, getpid());
37321.1Skamil	errno = 0;
37331.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
37341.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37351.1Skamil
37361.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
37371.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
37381.1Skamil
37391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37401.1Skamil	    "without signal to be sent\n");
37411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37421.1Skamil
37431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37451.1Skamil
37461.1Skamil	validate_status_exited(status, exitval);
37471.1Skamil
37481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37501.1Skamil}
37511.1Skamil
37521.1SkamilATF_TC(read_i4);
37531.1SkamilATF_TC_HEAD(read_i4, tc)
37541.1Skamil{
37551.1Skamil	atf_tc_set_md_var(tc, "descr",
37561.1Skamil	    "Verify PT_READ_I called four times");
37571.1Skamil}
37581.1Skamil
37591.1SkamilATF_TC_BODY(read_i4, tc)
37601.1Skamil{
37611.1Skamil	const int exitval = 5;
37621.1Skamil	const int sigval = SIGSTOP;
37631.1Skamil	pid_t child, wpid;
37641.1Skamil	int lookup_me1 = 0;
37651.1Skamil	int lookup_me2 = 0;
37661.1Skamil	int lookup_me3 = 0;
37671.1Skamil	int lookup_me4 = 0;
37681.1Skamil	int magic1;
37691.1Skamil	int magic2;
37701.1Skamil	int magic3;
37711.1Skamil	int magic4;
37721.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37731.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37741.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37751.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
37761.1Skamil#if defined(TWAIT_HAVE_STATUS)
37771.1Skamil	int status;
37781.1Skamil#endif
37791.1Skamil
37801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37821.1Skamil	if (child == 0) {
37831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37851.1Skamil
37861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37881.1Skamil
37891.13Schristos		DPRINTF("Before exiting of the child process\n");
37901.1Skamil		_exit(exitval);
37911.1Skamil	}
37921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37931.1Skamil
37941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37961.1Skamil
37971.1Skamil	validate_status_stopped(status, sigval);
37981.1Skamil
37991.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38001.1Skamil	    child, getpid());
38011.1Skamil	errno = 0;
38021.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38031.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38041.1Skamil
38051.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38061.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38071.1Skamil
38081.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38091.1Skamil	    child, getpid());
38101.1Skamil	errno = 0;
38111.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38131.1Skamil
38141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38151.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38161.1Skamil
38171.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38181.1Skamil	    child, getpid());
38191.1Skamil	errno = 0;
38201.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38211.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38221.1Skamil
38231.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38241.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38251.1Skamil
38261.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
38271.1Skamil	    child, getpid());
38281.1Skamil	errno = 0;
38291.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
38301.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38311.1Skamil
38321.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
38331.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
38341.1Skamil
38351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38361.1Skamil	    "without signal to be sent\n");
38371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38381.1Skamil
38391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38411.1Skamil
38421.1Skamil	validate_status_exited(status, exitval);
38431.1Skamil
38441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38461.1Skamil}
38471.1Skamil
38481.1Skamil#if defined(HAVE_GPREGS)
38491.1SkamilATF_TC(regs1);
38501.1SkamilATF_TC_HEAD(regs1, tc)
38511.1Skamil{
38521.1Skamil	atf_tc_set_md_var(tc, "descr",
38531.1Skamil	    "Verify plain PT_GETREGS call without further steps");
38541.1Skamil}
38551.1Skamil
38561.1SkamilATF_TC_BODY(regs1, tc)
38571.1Skamil{
38581.1Skamil	const int exitval = 5;
38591.1Skamil	const int sigval = SIGSTOP;
38601.1Skamil	pid_t child, wpid;
38611.1Skamil#if defined(TWAIT_HAVE_STATUS)
38621.1Skamil	int status;
38631.1Skamil#endif
38641.1Skamil	struct reg r;
38651.1Skamil
38661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38681.1Skamil	if (child == 0) {
38691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38711.1Skamil
38721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38741.1Skamil
38751.13Schristos		DPRINTF("Before exiting of the child process\n");
38761.1Skamil		_exit(exitval);
38771.1Skamil	}
38781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38791.1Skamil
38801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38821.1Skamil
38831.1Skamil	validate_status_stopped(status, sigval);
38841.1Skamil
38851.13Schristos	DPRINTF("Call GETREGS for the child process\n");
38861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
38871.1Skamil
38881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38891.1Skamil	    "without signal to be sent\n");
38901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38911.1Skamil
38921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38941.1Skamil
38951.1Skamil	validate_status_exited(status, exitval);
38961.1Skamil
38971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38991.1Skamil}
39001.1Skamil#endif
39011.1Skamil
39021.1Skamil#if defined(HAVE_GPREGS)
39031.1SkamilATF_TC(regs2);
39041.1SkamilATF_TC_HEAD(regs2, tc)
39051.1Skamil{
39061.1Skamil	atf_tc_set_md_var(tc, "descr",
39071.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
39081.1Skamil}
39091.1Skamil
39101.1SkamilATF_TC_BODY(regs2, tc)
39111.1Skamil{
39121.1Skamil	const int exitval = 5;
39131.1Skamil	const int sigval = SIGSTOP;
39141.1Skamil	pid_t child, wpid;
39151.1Skamil#if defined(TWAIT_HAVE_STATUS)
39161.1Skamil	int status;
39171.1Skamil#endif
39181.1Skamil	struct reg r;
39191.1Skamil
39201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39221.1Skamil	if (child == 0) {
39231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39251.1Skamil
39261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39281.1Skamil
39291.13Schristos		DPRINTF("Before exiting of the child process\n");
39301.1Skamil		_exit(exitval);
39311.1Skamil	}
39321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39331.1Skamil
39341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39361.1Skamil
39371.1Skamil	validate_status_stopped(status, sigval);
39381.1Skamil
39391.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39411.1Skamil
39421.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
39431.1Skamil
39441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39451.1Skamil	    "without signal to be sent\n");
39461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39471.1Skamil
39481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39501.1Skamil
39511.1Skamil	validate_status_exited(status, exitval);
39521.1Skamil
39531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39551.1Skamil}
39561.1Skamil#endif
39571.1Skamil
39581.1Skamil#if defined(HAVE_GPREGS)
39591.1SkamilATF_TC(regs3);
39601.1SkamilATF_TC_HEAD(regs3, tc)
39611.1Skamil{
39621.1Skamil	atf_tc_set_md_var(tc, "descr",
39631.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
39641.1Skamil}
39651.1Skamil
39661.1SkamilATF_TC_BODY(regs3, tc)
39671.1Skamil{
39681.1Skamil	const int exitval = 5;
39691.1Skamil	const int sigval = SIGSTOP;
39701.1Skamil	pid_t child, wpid;
39711.1Skamil#if defined(TWAIT_HAVE_STATUS)
39721.1Skamil	int status;
39731.1Skamil#endif
39741.1Skamil	struct reg r;
39751.1Skamil
39761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39781.1Skamil	if (child == 0) {
39791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39811.1Skamil
39821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39841.1Skamil
39851.13Schristos		DPRINTF("Before exiting of the child process\n");
39861.1Skamil		_exit(exitval);
39871.1Skamil	}
39881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39891.1Skamil
39901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39921.1Skamil
39931.1Skamil	validate_status_stopped(status, sigval);
39941.1Skamil
39951.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39971.1Skamil
39981.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
39991.1Skamil
40001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40011.1Skamil	    "without signal to be sent\n");
40021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40031.1Skamil
40041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40061.1Skamil
40071.1Skamil	validate_status_exited(status, exitval);
40081.1Skamil
40091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40111.1Skamil}
40121.1Skamil#endif
40131.1Skamil
40141.1Skamil#if defined(HAVE_GPREGS)
40151.1SkamilATF_TC(regs4);
40161.1SkamilATF_TC_HEAD(regs4, tc)
40171.1Skamil{
40181.1Skamil	atf_tc_set_md_var(tc, "descr",
40191.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
40201.1Skamil}
40211.1Skamil
40221.1SkamilATF_TC_BODY(regs4, tc)
40231.1Skamil{
40241.1Skamil	const int exitval = 5;
40251.1Skamil	const int sigval = SIGSTOP;
40261.1Skamil	pid_t child, wpid;
40271.1Skamil#if defined(TWAIT_HAVE_STATUS)
40281.1Skamil	int status;
40291.1Skamil#endif
40301.1Skamil	struct reg r;
40311.1Skamil
40321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40341.1Skamil	if (child == 0) {
40351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40371.1Skamil
40381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40401.1Skamil
40411.13Schristos		DPRINTF("Before exiting of the child process\n");
40421.1Skamil		_exit(exitval);
40431.1Skamil	}
40441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40451.1Skamil
40461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40481.1Skamil
40491.1Skamil	validate_status_stopped(status, sigval);
40501.1Skamil
40511.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40531.1Skamil
40541.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
40551.1Skamil
40561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40571.1Skamil	    "without signal to be sent\n");
40581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40591.1Skamil
40601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40621.1Skamil
40631.1Skamil	validate_status_exited(status, exitval);
40641.1Skamil
40651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40671.1Skamil}
40681.1Skamil#endif
40691.1Skamil
40701.1Skamil#if defined(HAVE_GPREGS)
40711.1SkamilATF_TC(regs5);
40721.1SkamilATF_TC_HEAD(regs5, tc)
40731.1Skamil{
40741.1Skamil	atf_tc_set_md_var(tc, "descr",
40751.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
40761.1Skamil}
40771.1Skamil
40781.1SkamilATF_TC_BODY(regs5, tc)
40791.1Skamil{
40801.1Skamil	const int exitval = 5;
40811.1Skamil	const int sigval = SIGSTOP;
40821.1Skamil	pid_t child, wpid;
40831.1Skamil#if defined(TWAIT_HAVE_STATUS)
40841.1Skamil	int status;
40851.1Skamil#endif
40861.1Skamil	struct reg r;
40871.1Skamil
40881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40901.1Skamil	if (child == 0) {
40911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40931.1Skamil
40941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40961.1Skamil
40971.13Schristos		DPRINTF("Before exiting of the child process\n");
40981.1Skamil		_exit(exitval);
40991.1Skamil	}
41001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41011.1Skamil
41021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41041.1Skamil
41051.1Skamil	validate_status_stopped(status, sigval);
41061.1Skamil
41071.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41091.1Skamil
41101.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
41111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41121.1Skamil
41131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41141.1Skamil	    "without signal to be sent\n");
41151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41161.1Skamil
41171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41191.1Skamil
41201.1Skamil	validate_status_exited(status, exitval);
41211.1Skamil
41221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41241.1Skamil}
41251.1Skamil#endif
41261.1Skamil
41271.1Skamil#if defined(HAVE_FPREGS)
41281.1SkamilATF_TC(fpregs1);
41291.1SkamilATF_TC_HEAD(fpregs1, tc)
41301.1Skamil{
41311.1Skamil	atf_tc_set_md_var(tc, "descr",
41321.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
41331.1Skamil}
41341.1Skamil
41351.1SkamilATF_TC_BODY(fpregs1, tc)
41361.1Skamil{
41371.1Skamil	const int exitval = 5;
41381.1Skamil	const int sigval = SIGSTOP;
41391.1Skamil	pid_t child, wpid;
41401.1Skamil#if defined(TWAIT_HAVE_STATUS)
41411.1Skamil	int status;
41421.1Skamil#endif
41431.1Skamil	struct fpreg r;
41441.1Skamil
41451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41471.1Skamil	if (child == 0) {
41481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41501.1Skamil
41511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41531.1Skamil
41541.13Schristos		DPRINTF("Before exiting of the child process\n");
41551.1Skamil		_exit(exitval);
41561.1Skamil	}
41571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41581.1Skamil
41591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41611.1Skamil
41621.1Skamil	validate_status_stopped(status, sigval);
41631.1Skamil
41641.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
41651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
41661.1Skamil
41671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41681.1Skamil	    "without signal to be sent\n");
41691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41701.1Skamil
41711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41731.1Skamil
41741.1Skamil	validate_status_exited(status, exitval);
41751.1Skamil
41761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41781.1Skamil}
41791.1Skamil#endif
41801.1Skamil
41811.1Skamil#if defined(HAVE_FPREGS)
41821.1SkamilATF_TC(fpregs2);
41831.1SkamilATF_TC_HEAD(fpregs2, tc)
41841.1Skamil{
41851.1Skamil	atf_tc_set_md_var(tc, "descr",
41861.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
41871.1Skamil	    "regs");
41881.1Skamil}
41891.1Skamil
41901.1SkamilATF_TC_BODY(fpregs2, tc)
41911.1Skamil{
41921.1Skamil	const int exitval = 5;
41931.1Skamil	const int sigval = SIGSTOP;
41941.1Skamil	pid_t child, wpid;
41951.1Skamil#if defined(TWAIT_HAVE_STATUS)
41961.1Skamil	int status;
41971.1Skamil#endif
41981.1Skamil	struct fpreg r;
41991.1Skamil
42001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42021.1Skamil	if (child == 0) {
42031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42051.1Skamil
42061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42081.1Skamil
42091.13Schristos		DPRINTF("Before exiting of the child process\n");
42101.1Skamil		_exit(exitval);
42111.1Skamil	}
42121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42131.1Skamil
42141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42161.1Skamil
42171.1Skamil	validate_status_stopped(status, sigval);
42181.1Skamil
42191.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42211.1Skamil
42221.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
42231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
42241.1Skamil
42251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42261.1Skamil	    "without signal to be sent\n");
42271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42281.1Skamil
42291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42311.1Skamil
42321.1Skamil	validate_status_exited(status, exitval);
42331.1Skamil
42341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42361.1Skamil}
42371.1Skamil#endif
42381.1Skamil
42391.1Skamil#if defined(PT_STEP)
42401.1Skamilstatic void
42411.2Skamilptrace_step(int N, int setstep)
42421.1Skamil{
42431.1Skamil	const int exitval = 5;
42441.1Skamil	const int sigval = SIGSTOP;
42451.1Skamil	pid_t child, wpid;
42461.1Skamil#if defined(TWAIT_HAVE_STATUS)
42471.1Skamil	int status;
42481.1Skamil#endif
42491.1Skamil	int happy;
42501.1Skamil
42511.1Skamil#if defined(__arm__)
42521.1Skamil	/* PT_STEP not supported on arm 32-bit */
42531.1Skamil	atf_tc_expect_fail("PR kern/52119");
42541.1Skamil#endif
42551.1Skamil
42561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42581.1Skamil	if (child == 0) {
42591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42611.1Skamil
42621.1Skamil		happy = check_happy(999);
42631.1Skamil
42641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42661.1Skamil
42671.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
42681.1Skamil
42691.13Schristos		DPRINTF("Before exiting of the child process\n");
42701.1Skamil		_exit(exitval);
42711.1Skamil	}
42721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42731.1Skamil
42741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42761.1Skamil
42771.1Skamil	validate_status_stopped(status, sigval);
42781.1Skamil
42791.1Skamil	while (N --> 0) {
42801.2Skamil		if (setstep) {
42811.13Schristos			DPRINTF("Before resuming the child process where it "
42821.2Skamil			    "left off and without signal to be sent (use "
42831.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
42841.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
42851.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
42861.2Skamil			    != -1);
42871.2Skamil		} else {
42881.13Schristos			DPRINTF("Before resuming the child process where it "
42891.2Skamil			    "left off and without signal to be sent (use "
42901.2Skamil			    "PT_STEP)\n");
42911.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
42921.2Skamil			    != -1);
42931.2Skamil		}
42941.1Skamil
42951.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42961.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
42971.1Skamil		    child);
42981.1Skamil
42991.1Skamil		validate_status_stopped(status, SIGTRAP);
43001.2Skamil
43011.2Skamil		if (setstep) {
43021.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43031.2Skamil		}
43041.1Skamil	}
43051.1Skamil
43061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43071.1Skamil	    "without signal to be sent\n");
43081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43091.1Skamil
43101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43121.1Skamil
43131.1Skamil	validate_status_exited(status, exitval);
43141.1Skamil
43151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43171.1Skamil}
43181.1Skamil#endif
43191.1Skamil
43201.1Skamil#if defined(PT_STEP)
43211.1SkamilATF_TC(step1);
43221.1SkamilATF_TC_HEAD(step1, tc)
43231.1Skamil{
43241.1Skamil	atf_tc_set_md_var(tc, "descr",
43251.1Skamil	    "Verify single PT_STEP call");
43261.1Skamil}
43271.1Skamil
43281.1SkamilATF_TC_BODY(step1, tc)
43291.1Skamil{
43301.2Skamil	ptrace_step(1, 0);
43311.1Skamil}
43321.1Skamil#endif
43331.1Skamil
43341.1Skamil#if defined(PT_STEP)
43351.1SkamilATF_TC(step2);
43361.1SkamilATF_TC_HEAD(step2, tc)
43371.1Skamil{
43381.1Skamil	atf_tc_set_md_var(tc, "descr",
43391.1Skamil	    "Verify PT_STEP called twice");
43401.1Skamil}
43411.1Skamil
43421.1SkamilATF_TC_BODY(step2, tc)
43431.1Skamil{
43441.2Skamil	ptrace_step(2, 0);
43451.1Skamil}
43461.1Skamil#endif
43471.1Skamil
43481.1Skamil#if defined(PT_STEP)
43491.1SkamilATF_TC(step3);
43501.1SkamilATF_TC_HEAD(step3, tc)
43511.1Skamil{
43521.1Skamil	atf_tc_set_md_var(tc, "descr",
43531.1Skamil	    "Verify PT_STEP called three times");
43541.1Skamil}
43551.1Skamil
43561.1SkamilATF_TC_BODY(step3, tc)
43571.1Skamil{
43581.2Skamil	ptrace_step(3, 0);
43591.1Skamil}
43601.1Skamil#endif
43611.1Skamil
43621.1Skamil#if defined(PT_STEP)
43631.1SkamilATF_TC(step4);
43641.1SkamilATF_TC_HEAD(step4, tc)
43651.1Skamil{
43661.1Skamil	atf_tc_set_md_var(tc, "descr",
43671.1Skamil	    "Verify PT_STEP called four times");
43681.1Skamil}
43691.1Skamil
43701.1SkamilATF_TC_BODY(step4, tc)
43711.1Skamil{
43721.2Skamil	ptrace_step(4, 0);
43731.2Skamil}
43741.2Skamil#endif
43751.2Skamil
43761.2Skamil#if defined(PT_STEP)
43771.2SkamilATF_TC(setstep1);
43781.2SkamilATF_TC_HEAD(setstep1, tc)
43791.2Skamil{
43801.2Skamil	atf_tc_set_md_var(tc, "descr",
43811.2Skamil	    "Verify single PT_SETSTEP call");
43821.2Skamil}
43831.2Skamil
43841.2SkamilATF_TC_BODY(setstep1, tc)
43851.2Skamil{
43861.2Skamil	ptrace_step(1, 1);
43871.2Skamil}
43881.2Skamil#endif
43891.2Skamil
43901.2Skamil#if defined(PT_STEP)
43911.2SkamilATF_TC(setstep2);
43921.2SkamilATF_TC_HEAD(setstep2, tc)
43931.2Skamil{
43941.2Skamil	atf_tc_set_md_var(tc, "descr",
43951.2Skamil	    "Verify PT_SETSTEP called twice");
43961.2Skamil}
43971.2Skamil
43981.2SkamilATF_TC_BODY(setstep2, tc)
43991.2Skamil{
44001.2Skamil	ptrace_step(2, 1);
44011.2Skamil}
44021.2Skamil#endif
44031.2Skamil
44041.2Skamil#if defined(PT_STEP)
44051.2SkamilATF_TC(setstep3);
44061.2SkamilATF_TC_HEAD(setstep3, tc)
44071.2Skamil{
44081.2Skamil	atf_tc_set_md_var(tc, "descr",
44091.2Skamil	    "Verify PT_SETSTEP called three times");
44101.2Skamil}
44111.2Skamil
44121.2SkamilATF_TC_BODY(setstep3, tc)
44131.2Skamil{
44141.2Skamil	ptrace_step(3, 1);
44151.2Skamil}
44161.2Skamil#endif
44171.2Skamil
44181.2Skamil#if defined(PT_STEP)
44191.2SkamilATF_TC(setstep4);
44201.2SkamilATF_TC_HEAD(setstep4, tc)
44211.2Skamil{
44221.2Skamil	atf_tc_set_md_var(tc, "descr",
44231.2Skamil	    "Verify PT_SETSTEP called four times");
44241.2Skamil}
44251.2Skamil
44261.2SkamilATF_TC_BODY(setstep4, tc)
44271.2Skamil{
44281.2Skamil	ptrace_step(4, 1);
44291.1Skamil}
44301.1Skamil#endif
44311.1Skamil
44321.1SkamilATF_TC(kill1);
44331.1SkamilATF_TC_HEAD(kill1, tc)
44341.1Skamil{
44351.1Skamil	atf_tc_set_md_var(tc, "descr",
44361.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
44371.1Skamil}
44381.1Skamil
44391.1SkamilATF_TC_BODY(kill1, tc)
44401.1Skamil{
44411.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
44421.1Skamil	pid_t child, wpid;
44431.1Skamil#if defined(TWAIT_HAVE_STATUS)
44441.1Skamil	int status;
44451.1Skamil#endif
44461.1Skamil
44471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44491.1Skamil	if (child == 0) {
44501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44521.1Skamil
44531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44551.1Skamil
44561.1Skamil		/* NOTREACHED */
44571.1Skamil		FORKEE_ASSERTX(0 &&
44581.1Skamil		    "Child should be terminated by a signal from its parent");
44591.1Skamil	}
44601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44611.1Skamil
44621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44641.1Skamil
44651.1Skamil	validate_status_stopped(status, sigval);
44661.1Skamil
44671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44681.1Skamil	    "without signal to be sent\n");
44691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
44701.1Skamil
44711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44731.1Skamil
44741.1Skamil	validate_status_signaled(status, sigsent, 0);
44751.1Skamil
44761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44781.1Skamil}
44791.1Skamil
44801.1SkamilATF_TC(kill2);
44811.1SkamilATF_TC_HEAD(kill2, tc)
44821.1Skamil{
44831.1Skamil	atf_tc_set_md_var(tc, "descr",
44841.1Skamil	    "Verify that PT_KILL terminates child");
44851.1Skamil}
44861.1Skamil
44871.1SkamilATF_TC_BODY(kill2, tc)
44881.1Skamil{
44891.1Skamil	const int sigval = SIGSTOP;
44901.1Skamil	pid_t child, wpid;
44911.1Skamil#if defined(TWAIT_HAVE_STATUS)
44921.1Skamil	int status;
44931.1Skamil#endif
44941.1Skamil
44951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44971.1Skamil	if (child == 0) {
44981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45001.1Skamil
45011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45031.1Skamil
45041.1Skamil		/* NOTREACHED */
45051.1Skamil		FORKEE_ASSERTX(0 &&
45061.1Skamil		    "Child should be terminated by a signal from its parent");
45071.1Skamil	}
45081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45091.1Skamil
45101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45121.1Skamil
45131.1Skamil	validate_status_stopped(status, sigval);
45141.1Skamil
45151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45161.1Skamil	    "without signal to be sent\n");
45171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
45181.1Skamil
45191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45211.1Skamil
45221.1Skamil	validate_status_signaled(status, SIGKILL, 0);
45231.1Skamil
45241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45261.1Skamil}
45271.1Skamil
45281.1SkamilATF_TC(lwpinfo1);
45291.1SkamilATF_TC_HEAD(lwpinfo1, tc)
45301.1Skamil{
45311.1Skamil	atf_tc_set_md_var(tc, "descr",
45321.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
45331.1Skamil}
45341.1Skamil
45351.1SkamilATF_TC_BODY(lwpinfo1, tc)
45361.1Skamil{
45371.1Skamil	const int exitval = 5;
45381.1Skamil	const int sigval = SIGSTOP;
45391.1Skamil	pid_t child, wpid;
45401.1Skamil#if defined(TWAIT_HAVE_STATUS)
45411.1Skamil	int status;
45421.1Skamil#endif
45431.1Skamil	struct ptrace_lwpinfo info = {0, 0};
45441.1Skamil
45451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45471.1Skamil	if (child == 0) {
45481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45501.1Skamil
45511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45531.1Skamil
45541.13Schristos		DPRINTF("Before exiting of the child process\n");
45551.1Skamil		_exit(exitval);
45561.1Skamil	}
45571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45581.1Skamil
45591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45611.1Skamil
45621.1Skamil	validate_status_stopped(status, sigval);
45631.1Skamil
45641.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
45661.1Skamil
45671.13Schristos	DPRINTF("Assert that there exists a thread\n");
45681.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
45691.1Skamil
45701.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
45711.1Skamil	    info.pl_lwpid);
45721.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
45731.1Skamil	    "Received event %d != expected event %d",
45741.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
45751.1Skamil
45761.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
45781.1Skamil
45791.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
45801.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
45811.1Skamil
45821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45831.1Skamil	    "without signal to be sent\n");
45841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45851.1Skamil
45861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45881.1Skamil
45891.1Skamil	validate_status_exited(status, exitval);
45901.1Skamil
45911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45921.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45931.1Skamil}
45941.1Skamil
45951.1Skamil#if defined(TWAIT_HAVE_PID)
45961.1SkamilATF_TC(lwpinfo2);
45971.1SkamilATF_TC_HEAD(lwpinfo2, tc)
45981.1Skamil{
45991.1Skamil	atf_tc_set_md_var(tc, "descr",
46001.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
46011.1Skamil	    "tracer)");
46021.1Skamil}
46031.1Skamil
46041.1SkamilATF_TC_BODY(lwpinfo2, tc)
46051.1Skamil{
46061.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46071.1Skamil	const int exitval_tracee = 5;
46081.1Skamil	const int exitval_tracer = 10;
46091.1Skamil	pid_t tracee, tracer, wpid;
46101.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46111.1Skamil#if defined(TWAIT_HAVE_STATUS)
46121.1Skamil	int status;
46131.1Skamil#endif
46141.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46151.1Skamil
46161.13Schristos	DPRINTF("Spawn tracee\n");
46171.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
46181.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
46191.1Skamil	tracee = atf_utils_fork();
46201.1Skamil	if (tracee == 0) {
46211.1Skamil
46221.1Skamil		/* Wait for message from the parent */
46231.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
46241.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
46251.1Skamil
46261.1Skamil		_exit(exitval_tracee);
46271.1Skamil	}
46281.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
46291.1Skamil
46301.13Schristos	DPRINTF("Spawn debugger\n");
46311.1Skamil	tracer = atf_utils_fork();
46321.1Skamil	if (tracer == 0) {
46331.1Skamil		/* No IPC to communicate with the child */
46341.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
46351.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
46361.1Skamil
46371.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
46381.1Skamil		FORKEE_REQUIRE_SUCCESS(
46391.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46401.1Skamil
46411.1Skamil		forkee_status_stopped(status, SIGSTOP);
46421.1Skamil
46431.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46441.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
46451.1Skamil		    != -1);
46461.1Skamil
46471.13Schristos		DPRINTF("Assert that there exists a thread\n");
46481.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
46491.1Skamil
46501.13Schristos		DPRINTF("Assert that lwp thread %d received event "
46511.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
46521.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
46531.1Skamil
46541.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46551.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
46561.1Skamil		    != -1);
46571.1Skamil
46581.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
46591.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
46601.1Skamil
46611.1Skamil		/* Resume tracee with PT_CONTINUE */
46621.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
46631.1Skamil
46641.1Skamil		/* Inform parent that tracer has attached to tracee */
46651.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
46661.1Skamil		/* Wait for parent */
46671.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
46681.1Skamil
46691.1Skamil		/* Wait for tracee and assert that it exited */
46701.1Skamil		FORKEE_REQUIRE_SUCCESS(
46711.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46721.1Skamil
46731.1Skamil		forkee_status_exited(status, exitval_tracee);
46741.1Skamil
46751.13Schristos		DPRINTF("Before exiting of the tracer process\n");
46761.1Skamil		_exit(exitval_tracer);
46771.1Skamil	}
46781.1Skamil
46791.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
46801.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
46811.1Skamil
46821.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
46831.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
46841.1Skamil
46851.13Schristos	DPRINTF("Detect that tracee is zombie\n");
46861.1Skamil	await_zombie(tracee);
46871.1Skamil
46881.13Schristos	DPRINTF("Assert that there is no status about tracee - "
46891.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
46901.1Skamil	TWAIT_REQUIRE_SUCCESS(
46911.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
46921.1Skamil
46931.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
46941.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
46951.1Skamil
46961.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
46971.1Skamil	    TWAIT_FNAME);
46981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
46991.1Skamil	    tracer);
47001.1Skamil
47011.1Skamil	validate_status_exited(status, exitval_tracer);
47021.1Skamil
47031.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
47041.1Skamil	    TWAIT_FNAME);
47051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
47061.1Skamil	    tracee);
47071.1Skamil
47081.1Skamil	validate_status_exited(status, exitval_tracee);
47091.1Skamil
47101.1Skamil	msg_close(&parent_tracer);
47111.1Skamil	msg_close(&parent_tracee);
47121.1Skamil}
47131.1Skamil#endif
47141.1Skamil
47151.1SkamilATF_TC(siginfo1);
47161.1SkamilATF_TC_HEAD(siginfo1, tc)
47171.1Skamil{
47181.1Skamil	atf_tc_set_md_var(tc, "descr",
47191.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
47201.1Skamil}
47211.1Skamil
47221.1SkamilATF_TC_BODY(siginfo1, tc)
47231.1Skamil{
47241.1Skamil	const int exitval = 5;
47251.1Skamil	const int sigval = SIGTRAP;
47261.1Skamil	pid_t child, wpid;
47271.1Skamil#if defined(TWAIT_HAVE_STATUS)
47281.1Skamil	int status;
47291.1Skamil#endif
47301.1Skamil	struct ptrace_siginfo info;
47311.1Skamil	memset(&info, 0, sizeof(info));
47321.1Skamil
47331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47351.1Skamil	if (child == 0) {
47361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47381.1Skamil
47391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47411.1Skamil
47421.13Schristos		DPRINTF("Before exiting of the child process\n");
47431.1Skamil		_exit(exitval);
47441.1Skamil	}
47451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47461.1Skamil
47471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47491.1Skamil
47501.1Skamil	validate_status_stopped(status, sigval);
47511.1Skamil
47521.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
47531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47541.1Skamil
47551.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47561.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47571.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47581.1Skamil	    info.psi_siginfo.si_errno);
47591.1Skamil
47601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47611.1Skamil	    "without signal to be sent\n");
47621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47631.1Skamil
47641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47661.1Skamil
47671.1Skamil	validate_status_exited(status, exitval);
47681.1Skamil
47691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47711.1Skamil}
47721.1Skamil
47731.1SkamilATF_TC(siginfo2);
47741.1SkamilATF_TC_HEAD(siginfo2, tc)
47751.1Skamil{
47761.1Skamil	atf_tc_set_md_var(tc, "descr",
47771.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
47781.1Skamil	    "modification of SIGINT from tracee");
47791.1Skamil}
47801.1Skamil
47811.1Skamilstatic int siginfo2_caught = 0;
47821.1Skamil
47831.1Skamilstatic void
47841.1Skamilsiginfo2_sighandler(int sig)
47851.1Skamil{
47861.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
47871.1Skamil
47881.1Skamil	++siginfo2_caught;
47891.1Skamil}
47901.1Skamil
47911.1SkamilATF_TC_BODY(siginfo2, tc)
47921.1Skamil{
47931.1Skamil	const int exitval = 5;
47941.1Skamil	const int sigval = SIGINT;
47951.1Skamil	pid_t child, wpid;
47961.1Skamil	struct sigaction sa;
47971.1Skamil#if defined(TWAIT_HAVE_STATUS)
47981.1Skamil	int status;
47991.1Skamil#endif
48001.1Skamil	struct ptrace_siginfo info;
48011.1Skamil	memset(&info, 0, sizeof(info));
48021.1Skamil
48031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48051.1Skamil	if (child == 0) {
48061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48081.1Skamil
48091.1Skamil		sa.sa_handler = siginfo2_sighandler;
48101.1Skamil		sa.sa_flags = SA_SIGINFO;
48111.1Skamil		sigemptyset(&sa.sa_mask);
48121.1Skamil
48131.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48141.1Skamil
48151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48171.1Skamil
48181.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
48191.1Skamil
48201.13Schristos		DPRINTF("Before exiting of the child process\n");
48211.1Skamil		_exit(exitval);
48221.1Skamil	}
48231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48241.1Skamil
48251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48271.1Skamil
48281.1Skamil	validate_status_stopped(status, sigval);
48291.1Skamil
48301.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48321.1Skamil
48331.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48341.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48351.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48361.1Skamil	    info.psi_siginfo.si_errno);
48371.1Skamil
48381.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
48391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
48401.1Skamil
48411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48421.1Skamil	    "without signal to be sent\n");
48431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
48441.1Skamil
48451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48471.1Skamil
48481.1Skamil	validate_status_exited(status, exitval);
48491.1Skamil
48501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48521.1Skamil}
48531.1Skamil
48541.1SkamilATF_TC(siginfo3);
48551.1SkamilATF_TC_HEAD(siginfo3, tc)
48561.1Skamil{
48571.1Skamil	atf_tc_set_md_var(tc, "descr",
48581.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
48591.1Skamil	    "setting signal to new value");
48601.1Skamil}
48611.1Skamil
48621.1Skamilstatic int siginfo3_caught = 0;
48631.1Skamil
48641.1Skamilstatic void
48651.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
48661.1Skamil{
48671.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
48681.1Skamil
48691.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
48701.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
48711.1Skamil
48721.1Skamil	++siginfo3_caught;
48731.1Skamil}
48741.1Skamil
48751.1SkamilATF_TC_BODY(siginfo3, tc)
48761.1Skamil{
48771.1Skamil	const int exitval = 5;
48781.1Skamil	const int sigval = SIGINT;
48791.1Skamil	const int sigfaked = SIGTRAP;
48801.1Skamil	const int sicodefaked = TRAP_BRKPT;
48811.1Skamil	pid_t child, wpid;
48821.1Skamil	struct sigaction sa;
48831.1Skamil#if defined(TWAIT_HAVE_STATUS)
48841.1Skamil	int status;
48851.1Skamil#endif
48861.1Skamil	struct ptrace_siginfo info;
48871.1Skamil	memset(&info, 0, sizeof(info));
48881.1Skamil
48891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48911.1Skamil	if (child == 0) {
48921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48941.1Skamil
48951.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
48961.1Skamil		sa.sa_flags = SA_SIGINFO;
48971.1Skamil		sigemptyset(&sa.sa_mask);
48981.1Skamil
48991.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
49001.1Skamil
49011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49031.1Skamil
49041.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
49051.1Skamil
49061.13Schristos		DPRINTF("Before exiting of the child process\n");
49071.1Skamil		_exit(exitval);
49081.1Skamil	}
49091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49101.1Skamil
49111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49131.1Skamil
49141.1Skamil	validate_status_stopped(status, sigval);
49151.1Skamil
49161.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49181.1Skamil
49191.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49201.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49211.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49221.1Skamil	    info.psi_siginfo.si_errno);
49231.1Skamil
49241.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
49251.1Skamil	    sigfaked, sicodefaked);
49261.1Skamil	info.psi_siginfo.si_signo = sigfaked;
49271.1Skamil	info.psi_siginfo.si_code = sicodefaked;
49281.1Skamil
49291.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49311.1Skamil
49321.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49341.1Skamil
49351.13Schristos	DPRINTF("Before checking siginfo_t\n");
49361.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
49371.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
49381.1Skamil
49391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49401.1Skamil	    "without signal to be sent\n");
49411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
49421.1Skamil
49431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49451.1Skamil
49461.1Skamil	validate_status_exited(status, exitval);
49471.1Skamil
49481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49491.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49501.1Skamil}
49511.1Skamil
49521.1SkamilATF_TC(siginfo4);
49531.1SkamilATF_TC_HEAD(siginfo4, tc)
49541.1Skamil{
49551.1Skamil	atf_tc_set_md_var(tc, "descr",
49561.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
49571.1Skamil}
49581.1Skamil
49591.1SkamilATF_TC_BODY(siginfo4, tc)
49601.1Skamil{
49611.1Skamil	const int sigval = SIGTRAP;
49621.1Skamil	pid_t child, wpid;
49631.1Skamil#if defined(TWAIT_HAVE_STATUS)
49641.1Skamil	int status;
49651.1Skamil#endif
49661.1Skamil
49671.1Skamil	struct ptrace_siginfo info;
49681.1Skamil	memset(&info, 0, sizeof(info));
49691.1Skamil
49701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49721.1Skamil	if (child == 0) {
49731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49751.1Skamil
49761.13Schristos		DPRINTF("Before calling execve(2) from child\n");
49771.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
49781.1Skamil
49791.1Skamil		FORKEE_ASSERT(0 && "Not reached");
49801.1Skamil	}
49811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49821.1Skamil
49831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49851.1Skamil
49861.1Skamil	validate_status_stopped(status, sigval);
49871.1Skamil
49881.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49901.1Skamil
49911.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49921.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49931.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49941.1Skamil	    info.psi_siginfo.si_errno);
49951.1Skamil
49961.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
49971.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
49981.1Skamil
49991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50001.1Skamil	    "without signal to be sent\n");
50011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50021.1Skamil
50031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50051.1Skamil
50061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50081.1Skamil}
50091.1Skamil
50101.1Skamil#if defined(TWAIT_HAVE_PID)
50111.1SkamilATF_TC(siginfo5);
50121.1SkamilATF_TC_HEAD(siginfo5, tc)
50131.1Skamil{
50141.1Skamil	atf_tc_set_md_var(tc, "descr",
50151.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
50161.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
50171.1Skamil}
50181.1Skamil
50191.1SkamilATF_TC_BODY(siginfo5, tc)
50201.1Skamil{
50211.1Skamil	const int exitval = 5;
50221.1Skamil	const int exitval2 = 15;
50231.1Skamil	const int sigval = SIGSTOP;
50241.1Skamil	pid_t child, child2, wpid;
50251.1Skamil#if defined(TWAIT_HAVE_STATUS)
50261.1Skamil	int status;
50271.1Skamil#endif
50281.1Skamil	ptrace_state_t state;
50291.1Skamil	const int slen = sizeof(state);
50301.1Skamil	ptrace_event_t event;
50311.1Skamil	const int elen = sizeof(event);
50321.1Skamil	struct ptrace_siginfo info;
50331.1Skamil
50341.1Skamil	memset(&info, 0, sizeof(info));
50351.1Skamil
50361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50381.1Skamil	if (child == 0) {
50391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50411.1Skamil
50421.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50431.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50441.1Skamil
50451.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
50461.1Skamil
50471.1Skamil		if (child2 == 0)
50481.1Skamil			_exit(exitval2);
50491.1Skamil
50501.1Skamil		FORKEE_REQUIRE_SUCCESS
50511.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
50521.1Skamil
50531.1Skamil		forkee_status_exited(status, exitval2);
50541.1Skamil
50551.13Schristos		DPRINTF("Before exiting of the child process\n");
50561.1Skamil		_exit(exitval);
50571.1Skamil	}
50581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50591.1Skamil
50601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50621.1Skamil
50631.1Skamil	validate_status_stopped(status, sigval);
50641.1Skamil
50651.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50671.1Skamil
50681.13Schristos	DPRINTF("Before checking siginfo_t\n");
50691.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50701.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
50711.1Skamil
50721.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
50731.1Skamil	event.pe_set_event = PTRACE_FORK;
50741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50751.1Skamil
50761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50771.1Skamil	    "without signal to be sent\n");
50781.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
50791.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
50801.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
50811.1Skamil                "state.pe_other_pid=child)\n", child);
50821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50831.1Skamil
50841.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
50851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50861.1Skamil
50871.1Skamil	validate_status_stopped(status, SIGTRAP);
50881.1Skamil
50891.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50911.1Skamil
50921.13Schristos	DPRINTF("Before checking siginfo_t\n");
50931.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50941.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
50951.1Skamil
50961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50971.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
50981.1Skamil
50991.1Skamil	child2 = state.pe_other_pid;
51001.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
51011.1Skamil
51021.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
51031.1Skamil	    TWAIT_FNAME, child2, child);
51041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51051.1Skamil	    child2);
51061.1Skamil
51071.1Skamil	validate_status_stopped(status, SIGTRAP);
51081.1Skamil
51091.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51111.1Skamil
51121.13Schristos	DPRINTF("Before checking siginfo_t\n");
51131.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51141.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51151.1Skamil
51161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
51171.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51181.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
51191.1Skamil
51201.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
51211.1Skamil	    "without signal to be sent\n");
51221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
51231.1Skamil
51241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51251.1Skamil	    "without signal to be sent\n");
51261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51271.1Skamil
51281.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
51291.1Skamil	    TWAIT_FNAME);
51301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51311.1Skamil	    child2);
51321.1Skamil
51331.1Skamil	validate_status_exited(status, exitval2);
51341.1Skamil
51351.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
51361.1Skamil	    TWAIT_FNAME);
51371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
51381.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
51391.1Skamil
51401.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51411.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
51421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51431.1Skamil
51441.1Skamil	validate_status_stopped(status, SIGCHLD);
51451.1Skamil
51461.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51481.1Skamil
51491.13Schristos	DPRINTF("Before checking siginfo_t\n");
51501.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
51511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
51521.1Skamil
51531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51541.1Skamil	    "without signal to be sent\n");
51551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51561.1Skamil
51571.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51581.1Skamil	    TWAIT_FNAME);
51591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51601.1Skamil
51611.1Skamil	validate_status_exited(status, exitval);
51621.1Skamil
51631.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51641.1Skamil	    TWAIT_FNAME);
51651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51661.1Skamil}
51671.1Skamil#endif
51681.1Skamil
51691.1Skamil#if defined(PT_STEP)
51701.1SkamilATF_TC(siginfo6);
51711.1SkamilATF_TC_HEAD(siginfo6, tc)
51721.1Skamil{
51731.1Skamil	atf_tc_set_md_var(tc, "descr",
51741.1Skamil	    "Verify single PT_STEP call with signal information check");
51751.1Skamil}
51761.1Skamil
51771.1SkamilATF_TC_BODY(siginfo6, tc)
51781.1Skamil{
51791.1Skamil	const int exitval = 5;
51801.1Skamil	const int sigval = SIGSTOP;
51811.1Skamil	pid_t child, wpid;
51821.1Skamil#if defined(TWAIT_HAVE_STATUS)
51831.1Skamil	int status;
51841.1Skamil#endif
51851.1Skamil	int happy;
51861.1Skamil	struct ptrace_siginfo info;
51871.1Skamil
51881.1Skamil#if defined(__arm__)
51891.1Skamil	/* PT_STEP not supported on arm 32-bit */
51901.1Skamil	atf_tc_expect_fail("PR kern/52119");
51911.1Skamil#endif
51921.1Skamil
51931.1Skamil	memset(&info, 0, sizeof(info));
51941.1Skamil
51951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51971.1Skamil	if (child == 0) {
51981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52001.1Skamil
52011.1Skamil		happy = check_happy(100);
52021.1Skamil
52031.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52041.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52051.1Skamil
52061.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
52071.1Skamil
52081.13Schristos		DPRINTF("Before exiting of the child process\n");
52091.1Skamil		_exit(exitval);
52101.1Skamil	}
52111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52121.1Skamil
52131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52151.1Skamil
52161.1Skamil	validate_status_stopped(status, sigval);
52171.1Skamil
52181.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52201.1Skamil
52211.13Schristos	DPRINTF("Before checking siginfo_t\n");
52221.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52241.1Skamil
52251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52261.1Skamil	    "without signal to be sent (use PT_STEP)\n");
52271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
52281.1Skamil
52291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52311.1Skamil
52321.1Skamil	validate_status_stopped(status, SIGTRAP);
52331.1Skamil
52341.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52361.1Skamil
52371.13Schristos	DPRINTF("Before checking siginfo_t\n");
52381.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
52391.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
52401.1Skamil
52411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52421.1Skamil	    "without signal to be sent\n");
52431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52441.1Skamil
52451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52471.1Skamil
52481.1Skamil	validate_status_exited(status, exitval);
52491.1Skamil
52501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52521.1Skamil}
52531.1Skamil#endif
52541.1Skamil
52551.1Skamilvolatile lwpid_t the_lwp_id = 0;
52561.1Skamil
52571.1Skamilstatic void
52581.1Skamillwp_main_func(void *arg)
52591.1Skamil{
52601.1Skamil	the_lwp_id = _lwp_self();
52611.1Skamil	_lwp_exit();
52621.1Skamil}
52631.1Skamil
52641.1SkamilATF_TC(lwp_create1);
52651.1SkamilATF_TC_HEAD(lwp_create1, tc)
52661.1Skamil{
52671.1Skamil	atf_tc_set_md_var(tc, "descr",
52681.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
52691.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
52701.1Skamil}
52711.1Skamil
52721.1SkamilATF_TC_BODY(lwp_create1, tc)
52731.1Skamil{
52741.1Skamil	const int exitval = 5;
52751.1Skamil	const int sigval = SIGSTOP;
52761.1Skamil	pid_t child, wpid;
52771.1Skamil#if defined(TWAIT_HAVE_STATUS)
52781.1Skamil	int status;
52791.1Skamil#endif
52801.1Skamil	ptrace_state_t state;
52811.1Skamil	const int slen = sizeof(state);
52821.1Skamil	ptrace_event_t event;
52831.1Skamil	const int elen = sizeof(event);
52841.1Skamil	ucontext_t uc;
52851.1Skamil	lwpid_t lid;
52861.1Skamil	static const size_t ssize = 16*1024;
52871.1Skamil	void *stack;
52881.1Skamil
52891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52911.1Skamil	if (child == 0) {
52921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52941.1Skamil
52951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52971.1Skamil
52981.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
52991.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53001.1Skamil
53011.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53021.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53031.1Skamil
53041.13Schristos		DPRINTF("Before creating new in child\n");
53051.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53061.1Skamil
53071.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53081.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53091.1Skamil
53101.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53111.1Skamil		    "are the same\n", lid, the_lwp_id);
53121.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53131.1Skamil
53141.13Schristos		DPRINTF("Before exiting of the child process\n");
53151.1Skamil		_exit(exitval);
53161.1Skamil	}
53171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53181.1Skamil
53191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53211.1Skamil
53221.1Skamil	validate_status_stopped(status, sigval);
53231.1Skamil
53241.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
53251.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
53261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53271.1Skamil
53281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53291.1Skamil	    "without signal to be sent\n");
53301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53311.1Skamil
53321.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53331.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
53341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53351.1Skamil
53361.1Skamil	validate_status_stopped(status, SIGTRAP);
53371.1Skamil
53381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53391.1Skamil
53401.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
53411.1Skamil
53421.1Skamil	lid = state.pe_lwp;
53431.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
53441.1Skamil
53451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53461.1Skamil	    "without signal to be sent\n");
53471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53481.1Skamil
53491.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53501.1Skamil	    TWAIT_FNAME);
53511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53521.1Skamil
53531.1Skamil	validate_status_exited(status, exitval);
53541.1Skamil
53551.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53561.1Skamil	    TWAIT_FNAME);
53571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53581.1Skamil}
53591.1Skamil
53601.1SkamilATF_TC(lwp_exit1);
53611.1SkamilATF_TC_HEAD(lwp_exit1, tc)
53621.1Skamil{
53631.1Skamil	atf_tc_set_md_var(tc, "descr",
53641.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53651.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
53661.1Skamil}
53671.1Skamil
53681.1SkamilATF_TC_BODY(lwp_exit1, tc)
53691.1Skamil{
53701.1Skamil	const int exitval = 5;
53711.1Skamil	const int sigval = SIGSTOP;
53721.1Skamil	pid_t child, wpid;
53731.1Skamil#if defined(TWAIT_HAVE_STATUS)
53741.1Skamil	int status;
53751.1Skamil#endif
53761.1Skamil	ptrace_state_t state;
53771.1Skamil	const int slen = sizeof(state);
53781.1Skamil	ptrace_event_t event;
53791.1Skamil	const int elen = sizeof(event);
53801.1Skamil	ucontext_t uc;
53811.1Skamil	lwpid_t lid;
53821.1Skamil	static const size_t ssize = 16*1024;
53831.1Skamil	void *stack;
53841.1Skamil
53851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53871.1Skamil	if (child == 0) {
53881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53901.1Skamil
53911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53931.1Skamil
53941.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53951.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53961.1Skamil
53971.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53981.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53991.1Skamil
54001.13Schristos		DPRINTF("Before creating new in child\n");
54011.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54021.1Skamil
54031.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54041.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54051.1Skamil
54061.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54071.1Skamil		    "are the same\n", lid, the_lwp_id);
54081.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54091.1Skamil
54101.13Schristos		DPRINTF("Before exiting of the child process\n");
54111.1Skamil		_exit(exitval);
54121.1Skamil	}
54131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54141.1Skamil
54151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54171.1Skamil
54181.1Skamil	validate_status_stopped(status, sigval);
54191.1Skamil
54201.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54211.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
54221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54231.1Skamil
54241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54251.1Skamil	    "without signal to be sent\n");
54261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54271.1Skamil
54281.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54291.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54311.1Skamil
54321.1Skamil	validate_status_stopped(status, SIGTRAP);
54331.1Skamil
54341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54351.1Skamil
54361.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
54371.1Skamil
54381.1Skamil	lid = state.pe_lwp;
54391.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
54401.1Skamil
54411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54421.1Skamil	    "without signal to be sent\n");
54431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54441.1Skamil
54451.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54461.1Skamil	    TWAIT_FNAME);
54471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54481.1Skamil
54491.1Skamil	validate_status_exited(status, exitval);
54501.1Skamil
54511.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54521.1Skamil	    TWAIT_FNAME);
54531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54541.1Skamil}
54551.1Skamil
54561.1SkamilATF_TC(signal1);
54571.1SkamilATF_TC_HEAD(signal1, tc)
54581.1Skamil{
54591.1Skamil	atf_tc_set_md_var(tc, "descr",
54601.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
54611.1Skamil	    "from catching other signals");
54621.1Skamil}
54631.1Skamil
54641.1SkamilATF_TC_BODY(signal1, tc)
54651.1Skamil{
54661.1Skamil	const int exitval = 5;
54671.1Skamil	const int sigval = SIGSTOP;
54681.1Skamil	const int sigmasked = SIGTRAP;
54691.1Skamil	const int signotmasked = SIGINT;
54701.1Skamil	pid_t child, wpid;
54711.1Skamil#if defined(TWAIT_HAVE_STATUS)
54721.1Skamil	int status;
54731.1Skamil#endif
54741.1Skamil	sigset_t intmask;
54751.1Skamil
54761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54781.1Skamil	if (child == 0) {
54791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54811.1Skamil
54821.1Skamil		sigemptyset(&intmask);
54831.1Skamil		sigaddset(&intmask, sigmasked);
54841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
54851.1Skamil
54861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54881.1Skamil
54891.13Schristos		DPRINTF("Before raising %s from child\n",
54901.1Skamil		    strsignal(signotmasked));
54911.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
54921.1Skamil
54931.13Schristos		DPRINTF("Before exiting of the child process\n");
54941.1Skamil		_exit(exitval);
54951.1Skamil	}
54961.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54971.1Skamil
54981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55001.1Skamil
55011.1Skamil	validate_status_stopped(status, sigval);
55021.1Skamil
55031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55041.1Skamil	    "without signal to be sent\n");
55051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55061.1Skamil
55071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55091.1Skamil
55101.1Skamil	validate_status_stopped(status, signotmasked);
55111.1Skamil
55121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55131.1Skamil	    "without signal to be sent\n");
55141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55151.1Skamil
55161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55181.1Skamil
55191.1Skamil	validate_status_exited(status, exitval);
55201.1Skamil
55211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55231.1Skamil}
55241.1Skamil
55251.1SkamilATF_TC(signal2);
55261.1SkamilATF_TC_HEAD(signal2, tc)
55271.1Skamil{
55281.1Skamil	atf_tc_set_md_var(tc, "descr",
55291.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
55301.1Skamil	    "catching this raised signal");
55311.1Skamil}
55321.1Skamil
55331.1SkamilATF_TC_BODY(signal2, tc)
55341.1Skamil{
55351.1Skamil	const int exitval = 5;
55361.1Skamil	const int sigval = SIGSTOP;
55371.1Skamil	const int sigmasked = SIGTRAP;
55381.1Skamil	pid_t child, wpid;
55391.1Skamil#if defined(TWAIT_HAVE_STATUS)
55401.1Skamil	int status;
55411.1Skamil#endif
55421.1Skamil	sigset_t intmask;
55431.1Skamil
55441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55461.1Skamil	if (child == 0) {
55471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55491.1Skamil
55501.1Skamil		sigemptyset(&intmask);
55511.1Skamil		sigaddset(&intmask, sigmasked);
55521.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55531.1Skamil
55541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55561.1Skamil
55571.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
55581.1Skamil		    strsignal(sigmasked));
55591.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
55601.1Skamil
55611.13Schristos		DPRINTF("Before exiting of the child process\n");
55621.1Skamil		_exit(exitval);
55631.1Skamil	}
55641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55651.1Skamil
55661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55681.1Skamil
55691.1Skamil	validate_status_stopped(status, sigval);
55701.1Skamil
55711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55721.1Skamil	    "without signal to be sent\n");
55731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55741.1Skamil
55751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55771.1Skamil
55781.1Skamil	validate_status_exited(status, exitval);
55791.1Skamil
55801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55821.1Skamil}
55831.1Skamil
55841.1SkamilATF_TC(signal3);
55851.1SkamilATF_TC_HEAD(signal3, tc)
55861.1Skamil{
55871.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
55881.1Skamil	atf_tc_set_md_var(tc, "descr",
55891.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
55901.1Skamil	    "catching software breakpoints");
55911.1Skamil}
55921.1Skamil
55931.1SkamilATF_TC_BODY(signal3, tc)
55941.1Skamil{
55951.1Skamil	const int exitval = 5;
55961.1Skamil	const int sigval = SIGSTOP;
55971.1Skamil	const int sigmasked = SIGTRAP;
55981.1Skamil	pid_t child, wpid;
55991.1Skamil#if defined(TWAIT_HAVE_STATUS)
56001.1Skamil	int status;
56011.1Skamil#endif
56021.1Skamil	sigset_t intmask;
56031.1Skamil
56041.20Skamil	atf_tc_expect_fail("PR kern/51918");
56051.20Skamil
56061.20Skamil	// This test breaks now on some ports, temporarily disable it
56071.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56081.20Skamil
56091.10Smartin#if defined(__sparc__)
56101.7Skamil	atf_tc_expect_timeout("PR kern/52167");
56111.7Skamil
56121.7Skamil	// timeout wins, failure still valid
56131.7Skamil	// atf_tc_expect_fail("PR kern/51918");
56141.7Skamil#endif
56151.1Skamil
56161.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56171.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56181.1Skamil	if (child == 0) {
56191.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56201.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56211.1Skamil
56221.1Skamil		sigemptyset(&intmask);
56231.1Skamil		sigaddset(&intmask, sigmasked);
56241.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56251.1Skamil
56261.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56271.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56281.1Skamil
56291.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
56301.4Skamil
56311.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
56321.4Skamil		PTRACE_BREAKPOINT_ASM;
56331.1Skamil#else
56341.4Skamil		/* port me */
56351.1Skamil#endif
56361.1Skamil
56371.13Schristos		DPRINTF("Before exiting of the child process\n");
56381.1Skamil		_exit(exitval);
56391.1Skamil	}
56401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56411.1Skamil
56421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56441.1Skamil
56451.1Skamil	validate_status_stopped(status, sigval);
56461.1Skamil
56471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56481.1Skamil	    "without signal to be sent\n");
56491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56501.1Skamil
56511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56531.1Skamil
56541.1Skamil	validate_status_stopped(status, sigmasked);
56551.1Skamil
56561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56571.1Skamil	    "without signal to be sent\n");
56581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56591.1Skamil
56601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56621.1Skamil
56631.1Skamil	validate_status_exited(status, exitval);
56641.1Skamil
56651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56671.1Skamil}
56681.1Skamil
56691.1Skamil#if defined(PT_STEP)
56701.1SkamilATF_TC(signal4);
56711.1SkamilATF_TC_HEAD(signal4, tc)
56721.1Skamil{
56731.1Skamil	atf_tc_set_md_var(tc, "descr",
56741.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56751.1Skamil	    "catching single step trap");
56761.1Skamil}
56771.1Skamil
56781.1SkamilATF_TC_BODY(signal4, tc)
56791.1Skamil{
56801.1Skamil	const int exitval = 5;
56811.1Skamil	const int sigval = SIGSTOP;
56821.1Skamil	const int sigmasked = SIGTRAP;
56831.1Skamil	pid_t child, wpid;
56841.1Skamil#if defined(TWAIT_HAVE_STATUS)
56851.1Skamil	int status;
56861.1Skamil#endif
56871.1Skamil	sigset_t intmask;
56881.1Skamil	int happy;
56891.1Skamil
56901.1Skamil#if defined(__arm__)
56911.5Skamil	/* PT_STEP not supported on arm 32-bit */
56921.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
56931.1Skamil#endif
56941.1Skamil
56951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56971.1Skamil	if (child == 0) {
56981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57001.1Skamil
57011.1Skamil		happy = check_happy(100);
57021.1Skamil
57031.1Skamil		sigemptyset(&intmask);
57041.1Skamil		sigaddset(&intmask, sigmasked);
57051.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57061.1Skamil
57071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57091.1Skamil
57101.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
57111.1Skamil
57121.13Schristos		DPRINTF("Before exiting of the child process\n");
57131.1Skamil		_exit(exitval);
57141.1Skamil	}
57151.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57161.1Skamil
57171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57191.1Skamil
57201.1Skamil	validate_status_stopped(status, sigval);
57211.1Skamil
57221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57231.1Skamil	    "without signal to be sent\n");
57241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
57251.1Skamil
57261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57281.1Skamil
57291.1Skamil	validate_status_stopped(status, sigmasked);
57301.1Skamil
57311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57321.1Skamil	    "without signal to be sent\n");
57331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57341.1Skamil
57351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57371.1Skamil
57381.1Skamil	validate_status_exited(status, exitval);
57391.1Skamil
57401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57421.1Skamil}
57431.1Skamil#endif
57441.1Skamil
57451.1SkamilATF_TC(signal5);
57461.1SkamilATF_TC_HEAD(signal5, tc)
57471.1Skamil{
57481.1Skamil	atf_tc_set_md_var(tc, "descr",
57491.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57501.1Skamil	    "catching exec() breakpoint");
57511.1Skamil}
57521.1Skamil
57531.1SkamilATF_TC_BODY(signal5, tc)
57541.1Skamil{
57551.1Skamil	const int exitval = 5;
57561.1Skamil	const int sigval = SIGSTOP;
57571.1Skamil	const int sigmasked = SIGTRAP;
57581.1Skamil	pid_t child, wpid;
57591.1Skamil#if defined(TWAIT_HAVE_STATUS)
57601.1Skamil	int status;
57611.1Skamil#endif
57621.1Skamil	sigset_t intmask;
57631.1Skamil
57641.14Schristos	atf_tc_expect_fail("wrong signal");
57651.14Schristos
57661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57681.1Skamil	if (child == 0) {
57691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57711.1Skamil
57721.1Skamil		sigemptyset(&intmask);
57731.1Skamil		sigaddset(&intmask, sigmasked);
57741.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57751.1Skamil
57761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57781.1Skamil
57791.13Schristos		DPRINTF("Before calling execve(2) from child\n");
57801.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
57811.1Skamil
57821.13Schristos		DPRINTF("Before exiting of the child process\n");
57831.1Skamil		_exit(exitval);
57841.1Skamil	}
57851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57861.1Skamil
57871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57891.1Skamil
57901.1Skamil	validate_status_stopped(status, sigval);
57911.1Skamil
57921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57931.1Skamil	    "without signal to be sent\n");
57941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57951.1Skamil
57961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57981.1Skamil
57991.1Skamil	validate_status_stopped(status, sigmasked);
58001.1Skamil
58011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58021.1Skamil	    "without signal to be sent\n");
58031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58041.1Skamil
58051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58071.1Skamil
58081.1Skamil	validate_status_exited(status, exitval);
58091.1Skamil
58101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58121.1Skamil}
58131.1Skamil
58141.1Skamil#if defined(TWAIT_HAVE_PID)
58151.1SkamilATF_TC(signal6);
58161.1SkamilATF_TC_HEAD(signal6, tc)
58171.1Skamil{
58181.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
58191.1Skamil	atf_tc_set_md_var(tc, "descr",
58201.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58211.1Skamil	    "catching PTRACE_FORK breakpoint");
58221.1Skamil}
58231.1Skamil
58241.1SkamilATF_TC_BODY(signal6, tc)
58251.1Skamil{
58261.1Skamil	const int exitval = 5;
58271.1Skamil	const int exitval2 = 15;
58281.1Skamil	const int sigval = SIGSTOP;
58291.1Skamil	const int sigmasked = SIGTRAP;
58301.1Skamil	pid_t child, child2, wpid;
58311.1Skamil#if defined(TWAIT_HAVE_STATUS)
58321.1Skamil	int status;
58331.1Skamil#endif
58341.1Skamil	sigset_t intmask;
58351.1Skamil	ptrace_state_t state;
58361.1Skamil	const int slen = sizeof(state);
58371.1Skamil	ptrace_event_t event;
58381.1Skamil	const int elen = sizeof(event);
58391.1Skamil
58401.38Skamil	atf_tc_expect_fail("PR kern/51918");
58411.14Schristos
58421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58441.1Skamil	if (child == 0) {
58451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58471.1Skamil
58481.1Skamil		sigemptyset(&intmask);
58491.1Skamil		sigaddset(&intmask, sigmasked);
58501.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58511.1Skamil
58521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58541.1Skamil
58551.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
58561.1Skamil
58571.1Skamil		if (child2 == 0)
58581.1Skamil			_exit(exitval2);
58591.1Skamil
58601.1Skamil		FORKEE_REQUIRE_SUCCESS
58611.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
58621.1Skamil
58631.1Skamil		forkee_status_exited(status, exitval2);
58641.1Skamil
58651.13Schristos		DPRINTF("Before exiting of the child process\n");
58661.1Skamil		_exit(exitval);
58671.1Skamil	}
58681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58691.1Skamil
58701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58721.1Skamil
58731.1Skamil	validate_status_stopped(status, sigval);
58741.1Skamil
58751.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
58761.1Skamil	event.pe_set_event = PTRACE_FORK;
58771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58781.1Skamil
58791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58801.1Skamil	    "without signal to be sent\n");
58811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58821.1Skamil
58831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58851.1Skamil
58861.1Skamil	validate_status_stopped(status, sigmasked);
58871.1Skamil
58881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58891.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
58901.1Skamil
58911.1Skamil	child2 = state.pe_other_pid;
58921.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
58931.1Skamil
58941.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
58951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
58961.1Skamil	    child2);
58971.1Skamil
58981.1Skamil	validate_status_stopped(status, SIGTRAP);
58991.1Skamil
59001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59011.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59021.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
59031.1Skamil
59041.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
59051.1Skamil	    "without signal to be sent\n");
59061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59071.1Skamil
59081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59091.1Skamil	    "without signal to be sent\n");
59101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59111.1Skamil
59121.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
59131.1Skamil	    TWAIT_FNAME);
59141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59151.1Skamil	    child2);
59161.1Skamil
59171.1Skamil	validate_status_exited(status, exitval2);
59181.1Skamil
59191.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
59201.1Skamil	    TWAIT_FNAME);
59211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
59221.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
59231.1Skamil
59241.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59251.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
59261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59271.1Skamil
59281.1Skamil	validate_status_stopped(status, SIGCHLD);
59291.1Skamil
59301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59311.1Skamil	    "without signal to be sent\n");
59321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59331.1Skamil
59341.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59351.1Skamil	    TWAIT_FNAME);
59361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59371.1Skamil
59381.1Skamil	validate_status_exited(status, exitval);
59391.1Skamil
59401.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59411.1Skamil	    TWAIT_FNAME);
59421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59431.1Skamil}
59441.1Skamil#endif
59451.1Skamil
59461.1Skamil#if defined(TWAIT_HAVE_PID)
59471.1SkamilATF_TC(signal7);
59481.1SkamilATF_TC_HEAD(signal7, tc)
59491.1Skamil{
59501.1Skamil	atf_tc_set_md_var(tc, "descr",
59511.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
59521.1Skamil	    "catching PTRACE_VFORK breakpoint");
59531.1Skamil}
59541.1Skamil
59551.1SkamilATF_TC_BODY(signal7, tc)
59561.1Skamil{
59571.1Skamil	const int exitval = 5;
59581.1Skamil	const int exitval2 = 15;
59591.1Skamil	const int sigval = SIGSTOP;
59601.1Skamil	const int sigmasked = SIGTRAP;
59611.1Skamil	pid_t child, child2, wpid;
59621.1Skamil#if defined(TWAIT_HAVE_STATUS)
59631.1Skamil	int status;
59641.1Skamil#endif
59651.1Skamil	sigset_t intmask;
59661.1Skamil	ptrace_state_t state;
59671.1Skamil	const int slen = sizeof(state);
59681.1Skamil	ptrace_event_t event;
59691.1Skamil	const int elen = sizeof(event);
59701.1Skamil
59711.38Skamil	atf_tc_expect_fail("PR kern/51918");
59721.14Schristos
59731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59751.1Skamil	if (child == 0) {
59761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59781.1Skamil
59791.1Skamil		sigemptyset(&intmask);
59801.1Skamil		sigaddset(&intmask, sigmasked);
59811.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59821.1Skamil
59831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59851.1Skamil
59861.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59871.1Skamil
59881.1Skamil		if (child2 == 0)
59891.1Skamil			_exit(exitval2);
59901.1Skamil
59911.1Skamil		FORKEE_REQUIRE_SUCCESS
59921.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59931.1Skamil
59941.1Skamil		forkee_status_exited(status, exitval2);
59951.1Skamil
59961.13Schristos		DPRINTF("Before exiting of the child process\n");
59971.1Skamil		_exit(exitval);
59981.1Skamil	}
59991.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60001.1Skamil
60011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60031.1Skamil
60041.1Skamil	validate_status_stopped(status, sigval);
60051.1Skamil
60061.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
60071.1Skamil	event.pe_set_event = PTRACE_VFORK;
60081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
60091.1Skamil
60101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60111.1Skamil	    "without signal to be sent\n");
60121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60131.1Skamil
60141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60161.1Skamil
60171.1Skamil	validate_status_stopped(status, sigmasked);
60181.1Skamil
60191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60201.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60211.1Skamil
60221.1Skamil	child2 = state.pe_other_pid;
60231.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
60241.1Skamil
60251.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
60261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60271.1Skamil	    child2);
60281.1Skamil
60291.1Skamil	validate_status_stopped(status, SIGTRAP);
60301.1Skamil
60311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
60321.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60331.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
60341.1Skamil
60351.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
60361.1Skamil	    "without signal to be sent\n");
60371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
60381.1Skamil
60391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60401.1Skamil	    "without signal to be sent\n");
60411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60421.1Skamil
60431.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
60441.1Skamil	    TWAIT_FNAME);
60451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60461.1Skamil	    child2);
60471.1Skamil
60481.1Skamil	validate_status_exited(status, exitval2);
60491.1Skamil
60501.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
60511.1Skamil	    TWAIT_FNAME);
60521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
60531.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
60541.1Skamil
60551.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60561.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60581.1Skamil
60591.1Skamil	validate_status_stopped(status, SIGCHLD);
60601.1Skamil
60611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60621.1Skamil	    "without signal to be sent\n");
60631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60641.1Skamil
60651.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60661.1Skamil	    TWAIT_FNAME);
60671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60681.1Skamil
60691.1Skamil	validate_status_exited(status, exitval);
60701.1Skamil
60711.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60721.1Skamil	    TWAIT_FNAME);
60731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60741.1Skamil}
60751.1Skamil#endif
60761.1Skamil
60771.1SkamilATF_TC(signal8);
60781.1SkamilATF_TC_HEAD(signal8, tc)
60791.1Skamil{
60801.1Skamil	atf_tc_set_md_var(tc, "descr",
60811.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60821.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
60831.1Skamil}
60841.1Skamil
60851.1SkamilATF_TC_BODY(signal8, tc)
60861.1Skamil{
60871.1Skamil	const int exitval = 5;
60881.1Skamil	const int exitval2 = 15;
60891.1Skamil	const int sigval = SIGSTOP;
60901.1Skamil	const int sigmasked = SIGTRAP;
60911.1Skamil	pid_t child, child2, wpid;
60921.1Skamil#if defined(TWAIT_HAVE_STATUS)
60931.1Skamil	int status;
60941.1Skamil#endif
60951.1Skamil	sigset_t intmask;
60961.1Skamil	ptrace_state_t state;
60971.1Skamil	const int slen = sizeof(state);
60981.1Skamil	ptrace_event_t event;
60991.1Skamil	const int elen = sizeof(event);
61001.1Skamil
61011.14Schristos	atf_tc_expect_fail("PR kern/51918");
61021.14Schristos
61031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61051.1Skamil	if (child == 0) {
61061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61081.1Skamil
61091.1Skamil		sigemptyset(&intmask);
61101.1Skamil		sigaddset(&intmask, sigmasked);
61111.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61121.1Skamil
61131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61151.1Skamil
61161.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
61171.1Skamil
61181.1Skamil		if (child2 == 0)
61191.1Skamil			_exit(exitval2);
61201.1Skamil
61211.1Skamil		FORKEE_REQUIRE_SUCCESS
61221.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
61231.1Skamil
61241.1Skamil		forkee_status_exited(status, exitval2);
61251.1Skamil
61261.13Schristos		DPRINTF("Before exiting of the child process\n");
61271.1Skamil		_exit(exitval);
61281.1Skamil	}
61291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61301.1Skamil
61311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61331.1Skamil
61341.1Skamil	validate_status_stopped(status, sigval);
61351.1Skamil
61361.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
61371.1Skamil	    child);
61381.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
61391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61401.1Skamil
61411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61421.1Skamil	    "without signal to be sent\n");
61431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61441.1Skamil
61451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61471.1Skamil
61481.1Skamil	validate_status_stopped(status, sigmasked);
61491.1Skamil
61501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61511.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
61521.1Skamil
61531.1Skamil	child2 = state.pe_other_pid;
61541.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
61551.1Skamil
61561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61571.1Skamil	    "without signal to be sent\n");
61581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61591.1Skamil
61601.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61611.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61631.1Skamil
61641.1Skamil	validate_status_stopped(status, SIGCHLD);
61651.1Skamil
61661.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61671.1Skamil	    "without signal to be sent\n");
61681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61691.1Skamil
61701.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61711.1Skamil	    TWAIT_FNAME);
61721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61731.1Skamil
61741.1Skamil	validate_status_exited(status, exitval);
61751.1Skamil
61761.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61771.1Skamil	    TWAIT_FNAME);
61781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61791.1Skamil}
61801.1Skamil
61811.1SkamilATF_TC(signal9);
61821.1SkamilATF_TC_HEAD(signal9, tc)
61831.1Skamil{
61841.1Skamil	atf_tc_set_md_var(tc, "descr",
61851.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61861.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
61871.1Skamil}
61881.1Skamil
61891.1SkamilATF_TC_BODY(signal9, tc)
61901.1Skamil{
61911.1Skamil	const int exitval = 5;
61921.1Skamil	const int sigval = SIGSTOP;
61931.1Skamil	const int sigmasked = SIGTRAP;
61941.1Skamil	pid_t child, wpid;
61951.1Skamil#if defined(TWAIT_HAVE_STATUS)
61961.1Skamil	int status;
61971.1Skamil#endif
61981.1Skamil	sigset_t intmask;
61991.1Skamil	ptrace_state_t state;
62001.1Skamil	const int slen = sizeof(state);
62011.1Skamil	ptrace_event_t event;
62021.1Skamil	const int elen = sizeof(event);
62031.1Skamil	ucontext_t uc;
62041.1Skamil	lwpid_t lid;
62051.1Skamil	static const size_t ssize = 16*1024;
62061.1Skamil	void *stack;
62071.1Skamil
62081.14Schristos	atf_tc_expect_fail("PR kern/51918");
62091.14Schristos
62101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62121.1Skamil	if (child == 0) {
62131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62151.1Skamil
62161.1Skamil		sigemptyset(&intmask);
62171.1Skamil		sigaddset(&intmask, sigmasked);
62181.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62191.1Skamil
62201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62221.1Skamil
62231.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62241.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62251.1Skamil
62261.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62271.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62281.1Skamil
62291.13Schristos		DPRINTF("Before creating new in child\n");
62301.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62311.1Skamil
62321.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62331.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62341.1Skamil
62351.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62361.1Skamil		    "are the same\n", lid, the_lwp_id);
62371.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62381.1Skamil
62391.13Schristos		DPRINTF("Before exiting of the child process\n");
62401.1Skamil		_exit(exitval);
62411.1Skamil	}
62421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62431.1Skamil
62441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62461.1Skamil
62471.1Skamil	validate_status_stopped(status, sigval);
62481.1Skamil
62491.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
62501.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
62511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62521.1Skamil
62531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62541.1Skamil	    "without signal to be sent\n");
62551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62561.1Skamil
62571.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62581.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62601.1Skamil
62611.1Skamil	validate_status_stopped(status, sigmasked);
62621.1Skamil
62631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62641.1Skamil
62651.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
62661.1Skamil
62671.1Skamil	lid = state.pe_lwp;
62681.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
62691.1Skamil
62701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62711.1Skamil	    "without signal to be sent\n");
62721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62731.1Skamil
62741.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62751.1Skamil	    TWAIT_FNAME);
62761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62771.1Skamil
62781.1Skamil	validate_status_exited(status, exitval);
62791.1Skamil
62801.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62811.1Skamil	    TWAIT_FNAME);
62821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62831.1Skamil}
62841.1Skamil
62851.1SkamilATF_TC(signal10);
62861.1SkamilATF_TC_HEAD(signal10, tc)
62871.1Skamil{
62881.1Skamil	atf_tc_set_md_var(tc, "descr",
62891.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62901.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
62911.1Skamil}
62921.1Skamil
62931.1SkamilATF_TC_BODY(signal10, tc)
62941.1Skamil{
62951.1Skamil	const int exitval = 5;
62961.1Skamil	const int sigval = SIGSTOP;
62971.1Skamil	const int sigmasked = SIGTRAP;
62981.1Skamil	pid_t child, wpid;
62991.1Skamil#if defined(TWAIT_HAVE_STATUS)
63001.1Skamil	int status;
63011.1Skamil#endif
63021.1Skamil	sigset_t intmask;
63031.1Skamil	ptrace_state_t state;
63041.1Skamil	const int slen = sizeof(state);
63051.1Skamil	ptrace_event_t event;
63061.1Skamil	const int elen = sizeof(event);
63071.1Skamil	ucontext_t uc;
63081.1Skamil	lwpid_t lid;
63091.1Skamil	static const size_t ssize = 16*1024;
63101.1Skamil	void *stack;
63111.1Skamil
63121.14Schristos	atf_tc_expect_fail("PR kern/51918");
63131.14Schristos
63141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63161.1Skamil	if (child == 0) {
63171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63191.1Skamil
63201.1Skamil		sigemptyset(&intmask);
63211.1Skamil		sigaddset(&intmask, sigmasked);
63221.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63231.1Skamil
63241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63261.1Skamil
63271.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63281.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63291.1Skamil
63301.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63311.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63321.1Skamil
63331.13Schristos		DPRINTF("Before creating new in child\n");
63341.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63351.1Skamil
63361.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63371.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63381.1Skamil
63391.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63401.1Skamil		    "are the same\n", lid, the_lwp_id);
63411.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63421.1Skamil
63431.13Schristos		DPRINTF("Before exiting of the child process\n");
63441.1Skamil		_exit(exitval);
63451.1Skamil	}
63461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63471.1Skamil
63481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63501.1Skamil
63511.1Skamil	validate_status_stopped(status, sigval);
63521.1Skamil
63531.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63541.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
63551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63561.1Skamil
63571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63581.1Skamil	    "without signal to be sent\n");
63591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63601.1Skamil
63611.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63621.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63641.1Skamil
63651.1Skamil	validate_status_stopped(status, sigmasked);
63661.1Skamil
63671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63681.1Skamil
63691.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
63701.1Skamil
63711.1Skamil	lid = state.pe_lwp;
63721.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
63731.1Skamil
63741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63751.1Skamil	    "without signal to be sent\n");
63761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63771.1Skamil
63781.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63791.1Skamil	    TWAIT_FNAME);
63801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63811.1Skamil
63821.1Skamil	validate_status_exited(status, exitval);
63831.1Skamil
63841.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63851.1Skamil	    TWAIT_FNAME);
63861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63871.1Skamil}
63881.1Skamil
63891.1Skamilstatic void
63901.1Skamillwp_main_stop(void *arg)
63911.1Skamil{
63921.1Skamil	the_lwp_id = _lwp_self();
63931.1Skamil
63941.1Skamil	raise(SIGTRAP);
63951.1Skamil
63961.1Skamil	_lwp_exit();
63971.1Skamil}
63981.1Skamil
63991.1SkamilATF_TC(suspend1);
64001.1SkamilATF_TC_HEAD(suspend1, tc)
64011.1Skamil{
64021.1Skamil	atf_tc_set_md_var(tc, "descr",
64031.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64041.1Skamil	    "resumed by a tracee");
64051.1Skamil}
64061.1Skamil
64071.1SkamilATF_TC_BODY(suspend1, tc)
64081.1Skamil{
64091.1Skamil	const int exitval = 5;
64101.1Skamil	const int sigval = SIGSTOP;
64111.1Skamil	pid_t child, wpid;
64121.1Skamil#if defined(TWAIT_HAVE_STATUS)
64131.1Skamil	int status;
64141.1Skamil#endif
64151.1Skamil	ucontext_t uc;
64161.1Skamil	lwpid_t lid;
64171.1Skamil	static const size_t ssize = 16*1024;
64181.1Skamil	void *stack;
64191.1Skamil	struct ptrace_lwpinfo pl;
64201.1Skamil	struct ptrace_siginfo psi;
64211.1Skamil	volatile int go = 0;
64221.1Skamil
64231.17Skamil	// Feature pending for refactoring
64241.17Skamil	atf_tc_expect_fail("PR kern/51995");
64251.17Skamil
64261.16Skamil	// Hangs with qemu
64271.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
64281.16Skamil
64291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64311.1Skamil	if (child == 0) {
64321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64341.1Skamil
64351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64371.1Skamil
64381.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
64391.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
64401.1Skamil
64411.13Schristos		DPRINTF("Before making context for new lwp in child\n");
64421.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
64431.1Skamil
64441.13Schristos		DPRINTF("Before creating new in child\n");
64451.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
64461.1Skamil
64471.1Skamil		while (go == 0)
64481.1Skamil			continue;
64491.1Skamil
64501.1Skamil		raise(SIGINT);
64511.1Skamil
64521.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
64531.1Skamil
64541.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64551.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64561.1Skamil
64571.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64581.1Skamil		    "are the same\n", lid, the_lwp_id);
64591.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64601.1Skamil
64611.13Schristos		DPRINTF("Before exiting of the child process\n");
64621.1Skamil		_exit(exitval);
64631.1Skamil	}
64641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64651.1Skamil
64661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64681.1Skamil
64691.1Skamil	validate_status_stopped(status, sigval);
64701.1Skamil
64711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64721.1Skamil	    "without signal to be sent\n");
64731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64741.1Skamil
64751.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64761.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64781.1Skamil
64791.1Skamil	validate_status_stopped(status, SIGTRAP);
64801.1Skamil
64811.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64831.1Skamil
64841.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64861.1Skamil
64871.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
64881.1Skamil	    child, getpid());
64891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
64901.1Skamil
64911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64921.1Skamil	    "without signal to be sent\n");
64931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64941.1Skamil
64951.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64961.1Skamil	    "SIGINT\n", TWAIT_FNAME);
64971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64981.1Skamil
64991.1Skamil	validate_status_stopped(status, SIGINT);
65001.1Skamil
65011.1Skamil	pl.pl_lwpid = 0;
65021.1Skamil
65031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65041.1Skamil	while (pl.pl_lwpid != 0) {
65051.1Skamil
65061.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65071.1Skamil		switch (pl.pl_lwpid) {
65081.1Skamil		case 1:
65091.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65101.1Skamil			break;
65111.1Skamil		case 2:
65121.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65131.1Skamil			break;
65141.1Skamil		}
65151.1Skamil	}
65161.1Skamil
65171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65181.1Skamil	    "without signal to be sent\n");
65191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65201.1Skamil
65211.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65221.1Skamil	    TWAIT_FNAME);
65231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65241.1Skamil
65251.1Skamil	validate_status_exited(status, exitval);
65261.1Skamil
65271.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65281.1Skamil	    TWAIT_FNAME);
65291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65301.1Skamil}
65311.1Skamil
65321.1SkamilATF_TC(suspend2);
65331.1SkamilATF_TC_HEAD(suspend2, tc)
65341.1Skamil{
65351.1Skamil	atf_tc_set_md_var(tc, "descr",
65361.1Skamil	    "Verify that the while the only thread within a process is "
65371.1Skamil	    "suspended, the whole process cannot be unstopped");
65381.1Skamil}
65391.1Skamil
65401.1SkamilATF_TC_BODY(suspend2, tc)
65411.1Skamil{
65421.1Skamil	const int exitval = 5;
65431.1Skamil	const int sigval = SIGSTOP;
65441.1Skamil	pid_t child, wpid;
65451.1Skamil#if defined(TWAIT_HAVE_STATUS)
65461.1Skamil	int status;
65471.1Skamil#endif
65481.1Skamil	struct ptrace_siginfo psi;
65491.1Skamil
65501.17Skamil	// Feature pending for refactoring
65511.17Skamil	atf_tc_expect_fail("PR kern/51995");
65521.17Skamil
65531.16Skamil	// Hangs with qemu
65541.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
65551.16Skamil
65561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65581.1Skamil	if (child == 0) {
65591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65611.1Skamil
65621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65641.1Skamil
65651.13Schristos		DPRINTF("Before exiting of the child process\n");
65661.1Skamil		_exit(exitval);
65671.1Skamil	}
65681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65691.1Skamil
65701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65721.1Skamil
65731.1Skamil	validate_status_stopped(status, sigval);
65741.1Skamil
65751.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65771.1Skamil
65781.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65801.1Skamil
65811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65821.1Skamil	    "without signal to be sent\n");
65831.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
65841.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
65851.1Skamil
65861.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65881.1Skamil
65891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65901.1Skamil	    "without signal to be sent\n");
65911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65921.1Skamil
65931.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65941.1Skamil	    TWAIT_FNAME);
65951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65961.1Skamil
65971.1Skamil	validate_status_exited(status, exitval);
65981.1Skamil
65991.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66001.1Skamil	    TWAIT_FNAME);
66011.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66021.1Skamil}
66031.1Skamil
66041.1SkamilATF_TC(resume1);
66051.1SkamilATF_TC_HEAD(resume1, tc)
66061.1Skamil{
66071.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
66081.1Skamil	atf_tc_set_md_var(tc, "descr",
66091.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
66101.1Skamil	    "resumed by the debugger");
66111.1Skamil}
66121.1Skamil
66131.1SkamilATF_TC_BODY(resume1, tc)
66141.1Skamil{
66151.1Skamil	struct msg_fds fds;
66161.1Skamil	const int exitval = 5;
66171.1Skamil	const int sigval = SIGSTOP;
66181.1Skamil	pid_t child, wpid;
66191.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
66201.1Skamil#if defined(TWAIT_HAVE_STATUS)
66211.1Skamil	int status;
66221.1Skamil#endif
66231.1Skamil	ucontext_t uc;
66241.1Skamil	lwpid_t lid;
66251.1Skamil	static const size_t ssize = 16*1024;
66261.1Skamil	void *stack;
66271.1Skamil	struct ptrace_lwpinfo pl;
66281.1Skamil	struct ptrace_siginfo psi;
66291.1Skamil
66301.17Skamil	// Feature pending for refactoring
66311.17Skamil	atf_tc_expect_fail("PR kern/51995");
66321.17Skamil
66331.15Schristos	// Hangs with qemu
66341.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66351.1Skamil
66361.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
66371.1Skamil
66381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66401.1Skamil	if (child == 0) {
66411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66431.1Skamil
66441.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66451.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66461.1Skamil
66471.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
66481.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
66491.1Skamil
66501.13Schristos		DPRINTF("Before making context for new lwp in child\n");
66511.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
66521.1Skamil
66531.13Schristos		DPRINTF("Before creating new in child\n");
66541.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
66551.1Skamil
66561.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
66571.1Skamil
66581.1Skamil		raise(SIGINT);
66591.1Skamil
66601.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
66611.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
66621.1Skamil
66631.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
66641.1Skamil		    "are the same\n", lid, the_lwp_id);
66651.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
66661.1Skamil
66671.13Schristos		DPRINTF("Before exiting of the child process\n");
66681.1Skamil		_exit(exitval);
66691.1Skamil	}
66701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66711.1Skamil
66721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66741.1Skamil
66751.1Skamil	validate_status_stopped(status, sigval);
66761.1Skamil
66771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66781.1Skamil	    "without signal to be sent\n");
66791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66801.1Skamil
66811.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
66821.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
66831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66841.1Skamil
66851.1Skamil	validate_status_stopped(status, SIGTRAP);
66861.1Skamil
66871.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66891.1Skamil
66901.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66921.1Skamil
66931.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
66941.1Skamil
66951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66961.1Skamil	    "without signal to be sent\n");
66971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66981.1Skamil
66991.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67001.1Skamil	    "SIGINT\n", TWAIT_FNAME);
67011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67021.1Skamil
67031.1Skamil	validate_status_stopped(status, SIGINT);
67041.1Skamil
67051.1Skamil	pl.pl_lwpid = 0;
67061.1Skamil
67071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67081.1Skamil	while (pl.pl_lwpid != 0) {
67091.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67101.1Skamil		switch (pl.pl_lwpid) {
67111.1Skamil		case 1:
67121.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
67131.1Skamil			break;
67141.1Skamil		case 2:
67151.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
67161.1Skamil			break;
67171.1Skamil		}
67181.1Skamil	}
67191.1Skamil
67201.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
67211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
67221.1Skamil
67231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67241.1Skamil	    "without signal to be sent\n");
67251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67261.1Skamil
67271.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
67281.1Skamil	    TWAIT_FNAME);
67291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67301.1Skamil
67311.1Skamil	validate_status_exited(status, exitval);
67321.1Skamil
67331.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
67341.1Skamil	    TWAIT_FNAME);
67351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67361.1Skamil
67371.1Skamil	msg_close(&fds);
67381.1Skamil
67391.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
67401.1Skamil	sleep(10);
67411.1Skamil}
67421.1Skamil
67431.1SkamilATF_TC(syscall1);
67441.1SkamilATF_TC_HEAD(syscall1, tc)
67451.1Skamil{
67461.1Skamil	atf_tc_set_md_var(tc, "descr",
67471.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
67481.1Skamil}
67491.1Skamil
67501.1SkamilATF_TC_BODY(syscall1, tc)
67511.1Skamil{
67521.1Skamil	const int exitval = 5;
67531.1Skamil	const int sigval = SIGSTOP;
67541.1Skamil	pid_t child, wpid;
67551.1Skamil#if defined(TWAIT_HAVE_STATUS)
67561.1Skamil	int status;
67571.1Skamil#endif
67581.1Skamil	struct ptrace_siginfo info;
67591.1Skamil	memset(&info, 0, sizeof(info));
67601.1Skamil
67611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67631.1Skamil	if (child == 0) {
67641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67661.1Skamil
67671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67691.1Skamil
67701.1Skamil		syscall(SYS_getpid);
67711.1Skamil
67721.13Schristos		DPRINTF("Before exiting of the child process\n");
67731.1Skamil		_exit(exitval);
67741.1Skamil	}
67751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67761.1Skamil
67771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67791.1Skamil
67801.1Skamil	validate_status_stopped(status, sigval);
67811.1Skamil
67821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67831.1Skamil	    "without signal to be sent\n");
67841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67851.1Skamil
67861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67881.1Skamil
67891.1Skamil	validate_status_stopped(status, SIGTRAP);
67901.1Skamil
67911.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67931.1Skamil
67941.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
67951.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
67961.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67971.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
67981.1Skamil
67991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68001.1Skamil	    "without signal to be sent\n");
68011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68021.1Skamil
68031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68051.1Skamil
68061.1Skamil	validate_status_stopped(status, SIGTRAP);
68071.1Skamil
68081.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68101.1Skamil
68111.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68121.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68131.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68141.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
68151.1Skamil
68161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68171.1Skamil	    "without signal to be sent\n");
68181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68191.1Skamil
68201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68221.1Skamil
68231.1Skamil	validate_status_exited(status, exitval);
68241.1Skamil
68251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68271.1Skamil}
68281.1Skamil
68291.1SkamilATF_TC(syscallemu1);
68301.1SkamilATF_TC_HEAD(syscallemu1, tc)
68311.1Skamil{
68321.1Skamil	atf_tc_set_md_var(tc, "descr",
68331.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
68341.1Skamil}
68351.1Skamil
68361.1SkamilATF_TC_BODY(syscallemu1, tc)
68371.1Skamil{
68381.1Skamil	const int exitval = 5;
68391.1Skamil	const int sigval = SIGSTOP;
68401.1Skamil	pid_t child, wpid;
68411.1Skamil#if defined(TWAIT_HAVE_STATUS)
68421.1Skamil	int status;
68431.1Skamil#endif
68441.1Skamil
68451.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
68461.6Skamil	/* syscallemu does not work on sparc (32-bit) */
68471.6Skamil	atf_tc_expect_fail("PR kern/52166");
68481.6Skamil#endif
68491.6Skamil
68501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68521.1Skamil	if (child == 0) {
68531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68551.1Skamil
68561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68581.1Skamil
68591.1Skamil		syscall(SYS_exit, 100);
68601.1Skamil
68611.13Schristos		DPRINTF("Before exiting of the child process\n");
68621.1Skamil		_exit(exitval);
68631.1Skamil	}
68641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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, sigval);
68701.1Skamil
68711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68721.1Skamil	    "without signal to be sent\n");
68731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68741.1Skamil
68751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68771.1Skamil
68781.1Skamil	validate_status_stopped(status, SIGTRAP);
68791.1Skamil
68801.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
68811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
68821.1Skamil
68831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68841.1Skamil	    "without signal to be sent\n");
68851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68861.1Skamil
68871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68891.1Skamil
68901.1Skamil	validate_status_stopped(status, SIGTRAP);
68911.1Skamil
68921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68931.1Skamil	    "without signal to be sent\n");
68941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68951.1Skamil
68961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68981.1Skamil
68991.1Skamil	validate_status_exited(status, exitval);
69001.1Skamil
69011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69031.1Skamil}
69041.1Skamil
69051.26Skamil#if defined(TWAIT_HAVE_PID)
69061.26SkamilATF_TC(race1);
69071.26SkamilATF_TC_HEAD(race1, tc)
69081.26Skamil{
69091.26Skamil	atf_tc_set_md_var(tc, "descr",
69101.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
69111.26Skamil	    "process and no other error is reported");
69121.26Skamil}
69131.26Skamil
69141.26SkamilATF_TC_BODY(race1, tc)
69151.26Skamil{
69161.26Skamil	time_t start, end;
69171.26Skamil	double diff;
69181.26Skamil	unsigned long N = 0;
69191.26Skamil
69201.26Skamil	/* Reuse this test with attach1 */
69211.26Skamil
69221.26Skamil	start = time(NULL);
69231.26Skamil	while (true) {
69241.26Skamil		DPRINTF("Step: %lu\n", N);
69251.26Skamil		attach1_raw(true);
69261.26Skamil		end = time(NULL);
69271.26Skamil		diff = difftime(end, start);
69281.26Skamil		if (diff >= 5.0)
69291.26Skamil			break;
69301.26Skamil		++N;
69311.26Skamil	}
69321.26Skamil	DPRINTF("Iterations: %lu\n", N);
69331.26Skamil}
69341.26Skamil#endif
69351.26Skamil
69361.1Skamil#include "t_ptrace_amd64_wait.h"
69371.1Skamil#include "t_ptrace_i386_wait.h"
69381.1Skamil#include "t_ptrace_x86_wait.h"
69391.1Skamil
69401.1SkamilATF_TP_ADD_TCS(tp)
69411.1Skamil{
69421.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
69431.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
69441.33Skamil
69451.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
69461.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
69471.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
69481.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
69491.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
69501.33Skamil
69511.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch1);
69521.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch2);
69531.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch3);
69541.34Skamil
69551.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler1);
69561.35Skamil//	ATF_TP_ADD_TC(tp, traceme_signal_nohandler2); // not yet
69571.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler3);
69581.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler4);
69591.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler5);
69601.1Skamil
69611.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
69621.37Skamil
69631.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
69641.40Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_raise2); // not yet
69651.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
69661.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
69671.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
69681.40Skamil
69691.41Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_breakpoint);
69701.41Skamil
69711.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
69721.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
69731.1Skamil	ATF_TP_ADD_TC(tp, attach3);
69741.1Skamil	ATF_TP_ADD_TC(tp, attach4);
69751.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
69761.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
69771.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
69781.1Skamil
69791.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
69801.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
69811.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
69821.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
69831.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
69841.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
69851.1Skamil
69861.31Skamil	ATF_TP_ADD_TC(tp, fork1);
69871.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
69881.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
69891.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
69901.31Skamil	ATF_TP_ADD_TC(tp, fork5);
69911.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
69921.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
69931.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
69941.31Skamil
69951.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
69961.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
69971.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
69981.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
69991.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
70001.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
70011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
70021.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
70031.1Skamil
70041.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
70051.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
70061.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
70071.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
70081.1Skamil
70091.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
70101.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
70111.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
70121.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
70131.1Skamil
70141.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
70151.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
70161.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
70171.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
70181.1Skamil
70191.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
70201.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
70211.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
70221.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
70231.1Skamil
70241.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
70251.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
70261.1Skamil
70271.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
70281.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
70291.1Skamil
70301.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
70311.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
70321.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
70331.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
70341.1Skamil
70351.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
70361.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
70371.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
70381.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
70391.1Skamil
70401.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
70411.1Skamil
70421.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
70431.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
70441.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
70451.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
70461.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
70471.1Skamil
70481.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
70491.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
70501.1Skamil
70511.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
70521.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
70531.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
70541.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
70551.1Skamil
70561.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
70571.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
70581.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
70591.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
70601.2Skamil
70611.1Skamil	ATF_TP_ADD_TC(tp, kill1);
70621.1Skamil	ATF_TP_ADD_TC(tp, kill2);
70631.1Skamil
70641.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
70651.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
70661.1Skamil
70671.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
70681.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
70691.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
70701.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
70711.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
70721.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
70731.1Skamil
70741.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
70751.1Skamil
70761.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
70771.1Skamil
70781.1Skamil	ATF_TP_ADD_TC(tp, signal1);
70791.1Skamil	ATF_TP_ADD_TC(tp, signal2);
70801.1Skamil	ATF_TP_ADD_TC(tp, signal3);
70811.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
70821.1Skamil	ATF_TP_ADD_TC(tp, signal5);
70831.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
70841.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
70851.1Skamil	ATF_TP_ADD_TC(tp, signal8);
70861.1Skamil	ATF_TP_ADD_TC(tp, signal9);
70871.1Skamil	ATF_TP_ADD_TC(tp, signal10);
70881.1Skamil
70891.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
70901.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
70911.1Skamil
70921.1Skamil	ATF_TP_ADD_TC(tp, resume1);
70931.1Skamil
70941.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
70951.1Skamil
70961.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
70971.1Skamil
70981.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
70991.26Skamil
71001.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
71011.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
71021.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
71031.1Skamil
71041.1Skamil	return atf_no_error();
71051.1Skamil}
7106